1 | //===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file declares generic and optimized functions to swap the byte order of |
10 | // an integral type. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_SWAPBYTEORDER_H |
15 | #define LLVM_SUPPORT_SWAPBYTEORDER_H |
16 | |
17 | #include "llvm/ADT/bit.h" |
18 | #include <cstddef> |
19 | #include <cstdint> |
20 | #include <type_traits> |
21 | |
22 | #if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \ |
23 | defined(__Fuchsia__) || defined(__EMSCRIPTEN__) |
24 | #include <endian.h> |
25 | #elif defined(_AIX) |
26 | #include <sys/machine.h> |
27 | #elif defined(__sun) |
28 | /* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */ |
29 | #include <sys/types.h> |
30 | #define BIG_ENDIAN 4321 |
31 | #define LITTLE_ENDIAN 1234 |
32 | #if defined(_BIG_ENDIAN) |
33 | #define BYTE_ORDER BIG_ENDIAN |
34 | #else |
35 | #define BYTE_ORDER LITTLE_ENDIAN |
36 | #endif |
37 | #elif defined(__MVS__) |
38 | #define BIG_ENDIAN 4321 |
39 | #define LITTLE_ENDIAN 1234 |
40 | #define BYTE_ORDER BIG_ENDIAN |
41 | #else |
42 | #if !defined(BYTE_ORDER) && !defined(_WIN32) |
43 | #include <machine/endian.h> |
44 | #endif |
45 | #endif |
46 | |
47 | namespace llvm { |
48 | |
49 | namespace sys { |
50 | |
51 | #if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN |
52 | constexpr bool IsBigEndianHost = true; |
53 | #else |
54 | constexpr bool IsBigEndianHost = false; |
55 | #endif |
56 | |
57 | static const bool IsLittleEndianHost = !IsBigEndianHost; |
58 | |
59 | inline unsigned char getSwappedBytes(unsigned char C) { return llvm::byteswap(V: C); } |
60 | inline signed char getSwappedBytes( signed char C) { return llvm::byteswap(V: C); } |
61 | inline char getSwappedBytes( char C) { return llvm::byteswap(V: C); } |
62 | |
63 | inline unsigned short getSwappedBytes(unsigned short C) { return llvm::byteswap(V: C); } |
64 | inline signed short getSwappedBytes( signed short C) { return llvm::byteswap(V: C); } |
65 | |
66 | inline unsigned int getSwappedBytes(unsigned int C) { return llvm::byteswap(V: C); } |
67 | inline signed int getSwappedBytes( signed int C) { return llvm::byteswap(V: C); } |
68 | |
69 | inline unsigned long getSwappedBytes(unsigned long C) { return llvm::byteswap(V: C); } |
70 | inline signed long getSwappedBytes( signed long C) { return llvm::byteswap(V: C); } |
71 | |
72 | inline unsigned long long getSwappedBytes(unsigned long long C) { return llvm::byteswap(V: C); } |
73 | inline signed long long getSwappedBytes( signed long long C) { return llvm::byteswap(V: C); } |
74 | |
75 | inline float getSwappedBytes(float C) { |
76 | union { |
77 | uint32_t i; |
78 | float f; |
79 | } in, out; |
80 | in.f = C; |
81 | out.i = llvm::byteswap(V: in.i); |
82 | return out.f; |
83 | } |
84 | |
85 | inline double getSwappedBytes(double C) { |
86 | union { |
87 | uint64_t i; |
88 | double d; |
89 | } in, out; |
90 | in.d = C; |
91 | out.i = llvm::byteswap(V: in.i); |
92 | return out.d; |
93 | } |
94 | |
95 | template <typename T> |
96 | inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) { |
97 | return static_cast<T>( |
98 | llvm::byteswap(static_cast<std::underlying_type_t<T>>(C))); |
99 | } |
100 | |
101 | template<typename T> |
102 | inline void swapByteOrder(T &Value) { |
103 | Value = getSwappedBytes(Value); |
104 | } |
105 | |
106 | } // end namespace sys |
107 | } // end namespace llvm |
108 | |
109 | #endif |
110 | |