DNA Calib 1.1
Project brief
Endianness.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include <cstdint>
6
7#if defined(ENABLE_SSE_BSWAP)
8 #include <immintrin.h>
9#endif
10
11#if !defined(NO_ENDIAN_H)
12 #if defined(USE_ENDIAN_H) || defined(USE_MACHINE_ENDIAN_H) || defined(USE_SYS_ENDIAN_H) || defined(USE_SYS_ISA_DEFS_H) || \
13 defined(USE_SYS_PARAM_H)
14 #define OVERRIDDEN_ENDIAN_H
15 #endif
16
17 #if !defined(OVERRIDDEN_ENDIAN_H)
18 #if defined(__linux__) || defined(__GLIBC__) || defined(__CYGWIN__) || defined(__ANDROID__)
19 #define USE_ENDIAN_H
20 #elif defined(__APPLE__)
21 #define USE_MACHINE_ENDIAN_H
22 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
23 #define USE_SYS_ENDIAN_H
24 #elif defined(__sun)
25 #define USE_SYS_ISA_DEFS_H
26 #elif defined(__MINGW32__) || defined(__MINGW64__) || !(defined(_WIN64) || defined(_WIN32))
27 #define USE_SYS_PARAM_H
28 #endif
29 #endif
30
31 #if defined(USE_ENDIAN_H)
32 #include <endian.h>
33 #elif defined(USE_MACHINE_ENDIAN_H)
34 #include <machine/endian.h>
35 #elif defined(USE_SYS_ENDIAN_H)
36 #include <sys/endian.h>
37 #elif defined(USE_SYS_ISA_DEFS_H)
38 #include <sys/isa_defs.h>
39 #elif defined(USE_SYS_PARAM_H)
40 #include <sys/param.h>
41 #endif
42#endif
43
44#if !defined(TARGET_LITTLE_ENDIAN) && !defined(TARGET_BIG_ENDIAN)
45 #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) /*GCC*/ || \
46 (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) /*Linux*/ || \
47 (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) /*xBSD,Sun*/ || \
48 (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /*Apple,MingW*/ || \
49 defined(__LITTLE_ENDIAN__) /*GCC Mac*/ || defined(__ARMEL__) /*GCC,Clang*/ || \
50 defined(__THUMBEL__) /*GCC,Clang*/ || defined(__AARCH64EL__) /*GCC,Clang*/ || \
51 defined(_MIPSEL) /*GCC,Clang*/ || defined(__MIPSEL) /*GCC,Clang*/ || \
52 defined(__MIPSEL__) /*GCC,Clang*/ || defined(_M_IX86) /*MSVC*/ || \
53 defined(_M_X64) /*MSVC*/ || defined(_M_IA64) /*MSVC*/ || \
54 defined(_M_AMD64) /*MSVC*/ || defined(_M_ARM) /*MSVC*/ || \
55 defined(_M_ARM64) /*MSVC*/
56 #define TARGET_LITTLE_ENDIAN
57 #elif (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) /*GCC*/ || \
58 (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) /*Linux*/ || \
59 (defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) /*xBSD,Sun*/ || \
60 (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) /*Apple,MingW*/ || \
61 defined(_M_PPC) /*MSVC for XBox-360*/ || defined(__BIG_ENDIAN__) /*GCC Mac*/ || \
62 defined(__ARMEB__) /*GCC,Clang*/ || defined(__THUMBEB__) /*GCC,Clang*/ || \
63 defined(__AARCH64EB__) /*GCC,Clang*/ || defined(_MIPSEB) /*GCC,Clang*/ || \
64 defined(__MIPSEB) /*GCC,Clang*/ || defined(__MIPSEB__) /*GCC,Clang*/
65 #define TARGET_BIG_ENDIAN
66 #elif defined(_WIN32)
67 #define TARGET_LITTLE_ENDIAN
68 #endif // End of byte order checks
69#endif // End of guard for explicitly defined endianness
70
71/*
72 * Swap intrinsics
73 */
74#if defined(__clang__) || (defined(__GNUC__) && \
75 ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5))
76 #define bswap16(x) __builtin_bswap16((x))
77 #define bswap32(x) __builtin_bswap32((x))
78 #define bswap64(x) __builtin_bswap64((x))
79#elif defined(__linux__) || defined(__GLIBC__)
80 #include <byteswap.h>
81 #define bswap16(x) bswap_16((x))
82 #define bswap32(x) bswap_32((x))
83 #define bswap64(x) bswap_64((x))
84#elif defined(_MSC_VER)
85 #include <stdlib.h>
86 #define bswap16(x) _byteswap_ushort((x))
87 #define bswap32(x) _byteswap_ulong((x))
88 #define bswap64(x) _byteswap_uint64((x))
89#elif defined(__APPLE__)
90 #include <libkern/OSByteOrder.h>
91 #define bswap16(x) OSSwapInt16((x))
92 #define bswap32(x) OSSwapInt32((x))
93 #define bswap64(x) OSSwapInt64((x))
94#elif defined(__FreeBSD__) || defined(__NetBSD__)
95 #include <sys/endian.h> // This defines the intrinsics as per the chosen naming convention
96#elif defined(__OpenBSD__)
97 #include <sys/endian.h>
98 #define bswap16(x) swap16((x))
99 #define bswap32(x) swap32((x))
100 #define bswap64(x) swap64((x))
101#elif defined(__sun) || defined(sun)
102 #include <sys/byteorder.h>
103 #define bswap16(x) BSWAP_16((x))
104 #define bswap32(x) BSWAP_32((x))
105 #define bswap64(x) BSWAP_64((x))
106#else
107 static inline std::uint16_t bswap16(std::uint16_t x) {
108 return (((x& std::uint16_t{0x00FF}) << 8) |
109 ((x& std::uint16_t{0xFF00}) >> 8));
110 }
111
112 static inline std::uint32_t bswap32(std::uint32_t x) {
113 return (((x& std::uint32_t{0x000000FF}) << 24) |
114 ((x& std::uint32_t{0x0000FF00}) << 8) |
115 ((x& std::uint32_t{0x00FF0000}) >> 8) |
116 ((x& std::uint32_t{0xFF000000}) >> 24));
117 }
118
119 static inline std::uint64_t bswap64(std::uint64_t x) {
120 return (((x& std::uint64_t{0x00000000000000FF}) << 56) |
121 ((x& std::uint64_t{0x000000000000FF00}) << 40) |
122 ((x& std::uint64_t{0x0000000000FF0000}) << 24) |
123 ((x& std::uint64_t{0x00000000FF000000}) << 8) |
124 ((x& std::uint64_t{0x000000FF00000000}) >> 8) |
125 ((x& std::uint64_t{0x0000FF0000000000}) >> 24) |
126 ((x& std::uint64_t{0x00FF000000000000}) >> 40) |
127 ((x& std::uint64_t{0xFF00000000000000}) >> 56));
128 }
129
130#endif
131
132#if defined(ENABLE_SSE_BSWAP)
133
134 static inline void bswap16x8(std::uint16_t* source) {
135 const __m128i v = _mm_load_si128(reinterpret_cast<__m128i*>(source));
136 const __m128i swapped = _mm_or_si128(_mm_slli_epi16(v, 8), _mm_srli_epi16(v, 8));
137 _mm_store_si128(reinterpret_cast<__m128i*>(source), swapped);
138 }
139
140 static inline void bswap32x4(std::uint32_t* source) {
141 const __m128i v = _mm_load_si128(reinterpret_cast<__m128i*>(source));
142 const __m128i swapped = _mm_shuffle_epi8(v,
143 _mm_set_epi8(
144 12, 13, 14, 15,
145 8, 9, 10, 11,
146 4, 5, 6, 7,
147 0, 1, 2, 3
148 )
149 );
150 _mm_store_si128(reinterpret_cast<__m128i*>(source), swapped);
151 }
152
153 static inline void bswap64x2(std::uint64_t* source) {
154 const __m128i v = _mm_load_si128(reinterpret_cast<__m128i*>(source));
155 const __m128i swapped = _mm_shuffle_epi8(v,
156 _mm_set_epi8(
157 8, 9, 10, 11,
158 12, 13, 14, 15,
159 0, 1, 2, 3,
160 4, 5, 6, 7
161 )
162 );
163 _mm_store_si128(reinterpret_cast<__m128i*>(source), swapped);
164 }
165
166#else
167
168 static inline void bswap16x8(std::uint16_t* source) {
169 source[0] = bswap16(source[0]);
170 source[1] = bswap16(source[1]);
171 source[2] = bswap16(source[2]);
172 source[3] = bswap16(source[3]);
173 source[4] = bswap16(source[4]);
174 source[5] = bswap16(source[5]);
175 source[6] = bswap16(source[6]);
176 source[7] = bswap16(source[7]);
177 }
178
179 static inline void bswap32x4(std::uint32_t* source) {
180 source[0] = bswap32(source[0]);
181 source[1] = bswap32(source[1]);
182 source[2] = bswap32(source[2]);
183 source[3] = bswap32(source[3]);
184 }
185
186 static inline void bswap64x2(std::uint64_t* source) {
187 source[0] = bswap64(source[0]);
188 source[1] = bswap64(source[1]);
189 }
190
191#endif // ENABLE_SSE_BSWAP
192
193// Target architecture specific ntoh and hton for all relevant sizes
194// In case of big endian architectures this is a noop
195#if defined(TARGET_LITTLE_ENDIAN)
196 #define ntoh8(x) (x)
197 #define hton8(x) (x)
198 #define ntoh16(x) bswap16((x))
199 #define hton16(x) bswap16((x))
200 #define ntoh32(x) bswap32((x))
201 #define hton32(x) bswap32((x))
202 #define ntoh64(x) bswap64((x))
203 #define hton64(x) bswap64((x))
204 // Vectorized swap
205 #define ntoh8x16(x) (x)
206 #define hton8x16(x) (x)
207 #define ntoh16x8(x) bswap16x8((x))
208 #define hton16x8(x) bswap16x8((x))
209 #define ntoh32x4(x) bswap32x4((x))
210 #define hton32x4(x) bswap32x4((x))
211 #define ntoh64x2(x) bswap64x2((x))
212 #define hton64x2(x) bswap64x2((x))
213#elif defined(TARGET_BIG_ENDIAN)
214 #define ntoh8(x) (x)
215 #define hton8(x) (x)
216 #define ntoh16(x) (x)
217 #define hton16(x) (x)
218 #define ntoh32(x) (x)
219 #define hton32(x) (x)
220 #define ntoh64(x) (x)
221 #define hton64(x) (x)
222 // Vectorized swap
223 #define ntoh8x16(x) (x)
224 #define hton8x16(x) (x)
225 #define ntoh16x8(x) (x)
226 #define hton16x8(x) (x)
227 #define ntoh32x4(x) (x)
228 #define hton32x4(x) (x)
229 #define ntoh64x2(x) (x)
230 #define hton64x2(x) (x)
231#else
232 #error "Platform not supported, no byte swap functions defined."
233#endif
234
235#if defined(__clang__) || defined(__GNUC__)
236 #pragma GCC diagnostic push
237 #pragma GCC diagnostic ignored "-Wunused-value"
238#endif
239
240// Process single values
241
242inline std::uint8_t ntoh(std::uint8_t x) {
243 return ntoh8(x);
244}
245
246inline std::uint16_t ntoh(std::uint16_t x) {
247 return ntoh16(x);
248}
249
250inline std::uint32_t ntoh(std::uint32_t x) {
251 return ntoh32(x);
252}
253
254inline std::uint64_t ntoh(std::uint64_t x) {
255 return ntoh64(x);
256}
257
258inline std::uint8_t hton(std::uint8_t x) {
259 return hton8(x);
260}
261
262inline std::uint16_t hton(std::uint16_t x) {
263 return hton16(x);
264}
265
266inline std::uint32_t hton(std::uint32_t x) {
267 return hton32(x);
268}
269
270inline std::uint64_t hton(std::uint64_t x) {
271 return hton64(x);
272}
273
274// Process multiple blocks simultaneously
275
276inline void ntoh(std::uint8_t* x) {
277 ntoh8x16(x);
278}
279
280inline void ntoh(std::uint16_t* x) {
281 ntoh16x8(x);
282}
283
284inline void ntoh(std::uint32_t* x) {
285 ntoh32x4(x);
286}
287
288inline void ntoh(std::uint64_t* x) {
289 ntoh64x2(x);
290}
291
292inline void hton(std::uint8_t* x) {
293 hton8x16(x);
294}
295
296inline void hton(std::uint16_t* x) {
297 hton16x8(x);
298}
299
300inline void hton(std::uint32_t* x) {
301 hton32x4(x);
302}
303
304inline void hton(std::uint64_t* x) {
305 hton64x2(x);
306}
307
308// Byte swap overloads
309
310inline std::uint8_t bswap(std::uint8_t x) {
311 // No operation
312 return x;
313}
314
315inline std::uint16_t bswap(std::uint16_t x) {
316 return bswap16(x);
317}
318
319inline std::uint32_t bswap(std::uint32_t x) {
320 return bswap32(x);
321}
322
323inline std::uint64_t bswap(std::uint64_t x) {
324 return bswap64(x);
325}
326
327inline void bswap(std::uint8_t* x) {
328 // No operation
329 static_cast<void>(x);
330}
331
332inline void bswap(std::uint16_t* x) {
333 bswap16x8(x);
334}
335
336inline void bswap(std::uint32_t* x) {
337 bswap32x4(x);
338}
339
340inline void bswap(std::uint64_t* x) {
341 bswap64x2(x);
342}
343
344#if defined(__clang__) || defined(__GNUC__)
345 #pragma GCC diagnostic pop
346#endif
static std::uint16_t bswap16(std::uint16_t x)
Definition: Endianness.h:107
static void bswap16x8(std::uint16_t *source)
Definition: Endianness.h:168
static std::uint64_t bswap64(std::uint64_t x)
Definition: Endianness.h:119
std::uint8_t ntoh(std::uint8_t x)
Definition: Endianness.h:242
std::uint8_t bswap(std::uint8_t x)
Definition: Endianness.h:310
static void bswap32x4(std::uint32_t *source)
Definition: Endianness.h:179
static std::uint32_t bswap32(std::uint32_t x)
Definition: Endianness.h:112
static void bswap64x2(std::uint64_t *source)
Definition: Endianness.h:186
std::uint8_t hton(std::uint8_t x)
Definition: Endianness.h:258