comparison include/core/endian.h @ 369:47c9f8502269

*: clang-format all the things I've edited the formatting a bit. Now pointer asterisks (and reference ampersands) are on the variable instead of the type, as well as having newlines for function braces (but nothing else)
author Paper <paper@tflc.us>
date Fri, 25 Jul 2025 10:16:02 -0400
parents 99c961c91809
children
comparison
equal deleted inserted replaced
368:6d37a998cf91 369:47c9f8502269
10 10
11 class Endian { 11 class Endian {
12 private: 12 private:
13 /* check for compiler builtins for byteswapping */ 13 /* check for compiler builtins for byteswapping */
14 #ifdef __has_builtin 14 #ifdef __has_builtin
15 # if __has_builtin(__builtin_bswap16) 15 # if __has_builtin(__builtin_bswap16)
16 # define COMPILER_BUILTIN_BSWAP16(x) __builtin_bswap16(x) 16 # define COMPILER_BUILTIN_BSWAP16(x) __builtin_bswap16(x)
17 # endif 17 # endif
18 # if __has_builtin(__builtin_bswap32) 18 # if __has_builtin(__builtin_bswap32)
19 # define COMPILER_BUILTIN_BSWAP32(x) __builtin_bswap32(x) 19 # define COMPILER_BUILTIN_BSWAP32(x) __builtin_bswap32(x)
20 # endif 20 # endif
21 # if __has_builtin(__builtin_bswap64) 21 # if __has_builtin(__builtin_bswap64)
22 # define COMPILER_BUILTIN_BSWAP64(x) __builtin_bswap64(x) 22 # define COMPILER_BUILTIN_BSWAP64(x) __builtin_bswap64(x)
23 # endif 23 # endif
24 #endif 24 #endif
25 25
26 static constexpr uint16_t byteswap_16(uint16_t x) { 26 static constexpr uint16_t byteswap_16(uint16_t x)
27 {
27 #ifdef COMPILER_BUILTIN_BSWAP16 28 #ifdef COMPILER_BUILTIN_BSWAP16
28 return COMPILER_BUILTIN_BSWAP16(x); 29 return COMPILER_BUILTIN_BSWAP16(x);
29 #else 30 #else
30 return ( 31 return (((x & UINT16_C(0x00FF)) << 8) | ((x & UINT16_C(0xFF00)) >> 8));
31 ((x & UINT16_C(0x00FF)) << 8)
32 | ((x & UINT16_C(0xFF00)) >> 8)
33 );
34 #endif 32 #endif
35 } 33 }
36 34
37 static constexpr uint32_t byteswap_32(uint32_t x) { 35 static constexpr uint32_t byteswap_32(uint32_t x)
36 {
38 #ifdef COMPILER_BUILTIN_BSWAP32 37 #ifdef COMPILER_BUILTIN_BSWAP32
39 return COMPILER_BUILTIN_BSWAP32(x); 38 return COMPILER_BUILTIN_BSWAP32(x);
40 #else 39 #else
41 return ( 40 return (((x & UINT32_C(0x000000FF)) << 24) | ((x & UINT32_C(0x0000FF00)) << 8) |
42 ((x & UINT32_C(0x000000FF)) << 24) 41 ((x & UINT32_C(0x00FF0000)) >> 8) | ((x & UINT32_C(0xFF000000)) >> 24));
43 | ((x & UINT32_C(0x0000FF00)) << 8)
44 | ((x & UINT32_C(0x00FF0000)) >> 8)
45 | ((x & UINT32_C(0xFF000000)) >> 24)
46 );
47 #endif 42 #endif
48 } 43 }
49 44
50 static constexpr uint64_t byteswap_64(uint64_t x) { 45 static constexpr uint64_t byteswap_64(uint64_t x)
46 {
51 #ifdef COMPILER_BUILTIN_BSWAP64 47 #ifdef COMPILER_BUILTIN_BSWAP64
52 return COMPILER_BUILTIN_BSWAP64(x); 48 return COMPILER_BUILTIN_BSWAP64(x);
53 #else 49 #else
54 return ( 50 return (((x & UINT64_C(0x00000000000000FF)) << 56) | ((x & UINT64_C(0x000000000000FF00)) << 40) |
55 ((x & UINT64_C(0x00000000000000FF)) << 56) 51 ((x & UINT64_C(0x0000000000FF0000)) << 24) | ((x & UINT64_C(0x00000000FF000000)) << 8) |
56 | ((x & UINT64_C(0x000000000000FF00)) << 40) 52 ((x & UINT64_C(0x000000FF00000000)) >> 8) | ((x & UINT64_C(0x0000FF0000000000)) >> 24) |
57 | ((x & UINT64_C(0x0000000000FF0000)) << 24) 53 ((x & UINT64_C(0x00FF000000000000)) >> 40) | ((x & UINT64_C(0xFF00000000000000)) >> 56));
58 | ((x & UINT64_C(0x00000000FF000000)) << 8)
59 | ((x & UINT64_C(0x000000FF00000000)) >> 8)
60 | ((x & UINT64_C(0x0000FF0000000000)) >> 24)
61 | ((x & UINT64_C(0x00FF000000000000)) >> 40)
62 | ((x & UINT64_C(0xFF00000000000000)) >> 56)
63 );
64 #endif 54 #endif
65 } 55 }
66 56
67 #ifdef COMPILER_BUILTIN_BSWAP16 57 #ifdef COMPILER_BUILTIN_BSWAP16
68 # undef COMPILER_BUILTIN_BSWAP16 58 # undef COMPILER_BUILTIN_BSWAP16
69 #endif 59 #endif
70 #ifdef COMPILER_BUILTIN_BSWAP32 60 #ifdef COMPILER_BUILTIN_BSWAP32
71 # undef COMPILER_BUILTIN_BSWAP32 61 # undef COMPILER_BUILTIN_BSWAP32
72 #endif 62 #endif
73 #ifdef COMPILER_BUILTIN_BSWAP64 63 #ifdef COMPILER_BUILTIN_BSWAP64
74 # undef COMPILER_BUILTIN_BSWAP64 64 # undef COMPILER_BUILTIN_BSWAP64
75 #endif 65 #endif
76 public: 66 public:
77 #if defined(BYTE_ORDER_BIG) 67 #if defined(BYTE_ORDER_BIG)
78 static constexpr bool big = true; 68 static constexpr bool big = true;
79 static constexpr bool little = false; 69 static constexpr bool little = false;
80 #elif defined(BYTE_ORDER_LITTLE) 70 #elif defined(BYTE_ORDER_LITTLE)
81 static constexpr bool big = false; 71 static constexpr bool big = false;
82 static constexpr bool little = true; 72 static constexpr bool little = true;
83 #else 73 #else
84 #error "unsupported endianness" 74 # error "unsupported endianness"
85 #endif 75 #endif
86 76
87 template<typename T> 77 template<typename T>
88 static constexpr T byteswap(T x) { 78 static constexpr T byteswap(T x)
79 {
89 static_assert(std::is_integral<T>::value); 80 static_assert(std::is_integral<T>::value);
90 static_assert(std::is_unsigned<T>::value, "use signed_byteswap"); 81 static_assert(std::is_unsigned<T>::value, "use signed_byteswap");
91 82
92 if constexpr (std::is_same<T, uint8_t>::value) { 83 if constexpr (std::is_same<T, uint8_t>::value) {
93 return x; 84 return x;
102 } 93 }
103 } 94 }
104 95
105 /* this can't be constexpr */ 96 /* this can't be constexpr */
106 template<typename T> 97 template<typename T>
107 static T signed_byteswap(T x) { 98 static T signed_byteswap(T x)
99 {
108 static_assert(std::is_integral<T>::value); 100 static_assert(std::is_integral<T>::value);
109 static_assert(std::is_signed<T>::value, "use regular byteswap"); 101 static_assert(std::is_signed<T>::value, "use regular byteswap");
110 102
111 using uT = typename std::make_unsigned<T>::type; 103 using uT = typename std::make_unsigned<T>::type;
112 return minori::BitCast<T, uT>(byteswap<uT>(minori::BitCast<uT, T>(x))); 104 return minori::BitCast<T, uT>(byteswap<uT>(minori::BitCast<uT, T>(x)));
113 } 105 }
114 106
115 template<typename T> 107 template<typename T>
116 static constexpr T byteswap_little_to_host(T x) { 108 static constexpr T byteswap_little_to_host(T x)
109 {
117 if constexpr (little) { 110 if constexpr (little) {
118 return x; 111 return x;
119 } else if constexpr (big) { 112 } else if constexpr (big) {
120 return byteswap(x); 113 return byteswap(x);
121 } 114 }
122 } 115 }
123 116
124 template<typename T> 117 template<typename T>
125 static constexpr T byteswap_big_to_host(T x) { 118 static constexpr T byteswap_big_to_host(T x)
119 {
126 if constexpr (big) { 120 if constexpr (big) {
127 return x; 121 return x;
128 } else if constexpr (little) { 122 } else if constexpr (little) {
129 return byteswap(x); 123 return byteswap(x);
130 } 124 }
131 } 125 }
132 126
133 template<typename T> 127 template<typename T>
134 static T signed_byteswap_little_to_host(T x) { 128 static T signed_byteswap_little_to_host(T x)
129 {
135 if constexpr (little) { 130 if constexpr (little) {
136 return x; 131 return x;
137 } else if constexpr (big) { 132 } else if constexpr (big) {
138 return signed_byteswap(x); 133 return signed_byteswap(x);
139 } 134 }
140 } 135 }
141 136
142 template<typename T> 137 template<typename T>
143 static T signed_byteswap_big_to_host(T x) { 138 static T signed_byteswap_big_to_host(T x)
139 {
144 if constexpr (big) { 140 if constexpr (big) {
145 return x; 141 return x;
146 } else if constexpr (little) { 142 } else if constexpr (little) {
147 return signed_byteswap(x); 143 return signed_byteswap(x);
148 } 144 }
149 } 145 }
146
150 private: 147 private:
151 Endian() = delete; 148 Endian() = delete;
152 }; 149 };
153 150
154 #endif /* MINORI_CORE_ENDIAN_H_ */ 151 #endif /* MINORI_CORE_ENDIAN_H_ */