23 #include <type_traits>
81 #if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
82 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
84 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
91 #elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
92 #if BYTE_ORDER == LITTLE_ENDIAN
94 #elif BYTE_ORDER == BIG_ENDIAN
101 #elif defined(_WIN32) || defined(_WIN64)
106 #elif defined(__LITTLE_ENDIAN__) || defined(__ARMEL__)
108 #elif defined(__BIG_ENDIAN__) || defined(__ARMEB__)
112 #elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || defined(_M_IX86) || \
113 defined(_M_X64) || defined(_M_AMD64) || defined(__aarch64__) || defined(_M_ARM64)
117 #elif defined(__sparc__) || defined(__sparc) || defined(__MIPSEB__) || defined(_POWER) || \
118 defined(__powerpc__) && defined(__BIG_ENDIAN__)
138 } test = {0x01020304};
140 if (test.bytes[0] == 0x01) {
142 }
else if (test.bytes[0] == 0x04) {
163 return compile_time_order;
213 #if defined(_MSC_VER)
216 return static_cast<uint16_t
>((value << 8) | (value >> 8));
217 #elif defined(__GNUC__) || defined(__clang__)
219 #if __has_builtin(__builtin_bswap16)
220 return __builtin_bswap16(value);
222 return static_cast<uint16_t
>((value << 8) | (value >> 8));
226 return static_cast<uint16_t
>((value << 8) | (value >> 8));
234 #if defined(_MSC_VER)
236 return ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) |
237 ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24);
238 #elif defined(__GNUC__) || defined(__clang__)
239 #if __has_builtin(__builtin_bswap32)
240 return __builtin_bswap32(value);
242 return ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) |
243 ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24);
246 return ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) |
247 ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24);
255 #if defined(_MSC_VER)
257 return ((value & 0xFF00000000000000ULL) >> 56) | ((value & 0x00FF000000000000ULL) >> 40) |
258 ((value & 0x0000FF0000000000ULL) >> 24) | ((value & 0x000000FF00000000ULL) >> 8) |
259 ((value & 0x00000000FF000000ULL) << 8) | ((value & 0x0000000000FF0000ULL) << 24) |
260 ((value & 0x000000000000FF00ULL) << 40) | ((value & 0x00000000000000FFULL) << 56);
261 #elif defined(__GNUC__) || defined(__clang__)
262 #if __has_builtin(__builtin_bswap64)
263 return __builtin_bswap64(value);
265 return ((value & 0xFF00000000000000ULL) >> 56) | ((value & 0x00FF000000000000ULL) >> 40) |
266 ((value & 0x0000FF0000000000ULL) >> 24) | ((value & 0x000000FF00000000ULL) >> 8) |
267 ((value & 0x00000000FF000000ULL) << 8) | ((value & 0x0000000000FF0000ULL) << 24) |
268 ((value & 0x000000000000FF00ULL) << 40) | ((value & 0x00000000000000FFULL) << 56);
271 return ((value & 0xFF00000000000000ULL) >> 56) | ((value & 0x00FF000000000000ULL) >> 40) |
272 ((value & 0x0000FF0000000000ULL) >> 24) | ((value & 0x000000FF00000000ULL) >> 8) |
273 ((value & 0x00000000FF000000ULL) << 8) | ((value & 0x0000000000FF0000ULL) << 24) |
274 ((value & 0x000000000000FF00ULL) << 40) | ((value & 0x00000000000000FFULL) << 56);
320 template <
typename Type>
322 static_assert(std::is_integral_v<Type>,
"byteSwap only supports integral types");
324 if constexpr (
sizeof(Type) == 1) {
327 }
else if constexpr (
sizeof(Type) == 2) {
329 using UnsignedType = std::make_unsigned_t<Type>;
330 auto unsigned_value =
static_cast<UnsignedType
>(value);
331 auto swapped =
byteSwap16(
static_cast<uint16_t
>(unsigned_value));
332 return static_cast<Type
>(swapped);
333 }
else if constexpr (
sizeof(Type) == 4) {
335 using UnsignedType = std::make_unsigned_t<Type>;
336 auto unsigned_value =
static_cast<UnsignedType
>(value);
337 auto swapped =
byteSwap32(
static_cast<uint32_t
>(unsigned_value));
338 return static_cast<Type
>(swapped);
339 }
else if constexpr (
sizeof(Type) == 8) {
341 using UnsignedType = std::make_unsigned_t<Type>;
342 auto unsigned_value =
static_cast<UnsignedType
>(value);
343 auto swapped =
byteSwap64(
static_cast<uint64_t
>(unsigned_value));
344 return static_cast<Type
>(swapped);
346 static_assert(
sizeof(Type) <= 8,
"byteSwap supports types up to 64 bits");
365 template <
typename Type>
367 static_assert(std::is_integral_v<Type>,
"hostToNetwork only supports integral types");
388 template <
typename Type>
390 static_assert(std::is_integral_v<Type>,
"networkToHost only supports integral types");
469 return order1 == order2;
498 template <
typename Type>
500 static_assert(std::is_integral_v<Type>,
"convertByteOrder only supports integral types");
521 #define TRLC_ENDIAN_LITTLE (trlc::platform::isLittleEndian())
528 #define TRLC_ENDIAN_BIG (trlc::platform::isBigEndian())
538 #define TRLC_BYTE_SWAP(x) (trlc::platform::byteSwap(x))
546 #define TRLC_HTON(x) (trlc::platform::hostToNetwork(x))
554 #define TRLC_NTOH(x) (trlc::platform::networkToHost(x))
564 #define TRLC_HTONS(x) (trlc::platform::hostToNetworkShort(x))
574 #define TRLC_HTONL(x) (trlc::platform::hostToNetworkLong(x))
584 #define TRLC_NTOHS(x) (trlc::platform::networkToHostShort(x))
594 #define TRLC_NTOHL(x) (trlc::platform::networkToHostLong(x))
597 #define TRLC_ENDIANNESS_INCLUDED