From 27adb9486bd4a13c992e08b38cc3a0b9ed69a3a1 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 27 Sep 2023 22:33:38 +0300 Subject: [PATCH] BAN: Update Endiannes API Add functions to swap endiannes or convert host to big/little endian This code should be very compiler friendly and should be optimized to single bswap instruction on x86. --- BAN/include/BAN/Endianness.h | 67 +++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/BAN/include/BAN/Endianness.h b/BAN/include/BAN/Endianness.h index a28d2b49..0a39be7e 100644 --- a/BAN/include/BAN/Endianness.h +++ b/BAN/include/BAN/Endianness.h @@ -7,20 +7,62 @@ namespace BAN { + template + constexpr T swap_endianness(T value) + { + if constexpr(sizeof(T) == 1) + return value; + if constexpr(sizeof(T) == 2) + return (((value >> 8) & 0xFF) << 0) + | (((value >> 0) & 0xFF) << 8); + if constexpr(sizeof(T) == 4) + return (((value >> 24) & 0xFF) << 0) + | (((value >> 16) & 0xFF) << 8) + | (((value >> 8) & 0xFF) << 16) + | (((value >> 0) & 0xFF) << 24); + if constexpr(sizeof(T) == 8) + return (((value >> 56) & 0xFF) << 0) + | (((value >> 48) & 0xFF) << 8) + | (((value >> 40) & 0xFF) << 16) + | (((value >> 32) & 0xFF) << 24) + | (((value >> 24) & 0xFF) << 32) + | (((value >> 16) & 0xFF) << 40) + | (((value >> 8) & 0xFF) << 48) + | (((value >> 0) & 0xFF) << 56); + T result { 0 }; + for (size_t i = 0; i < sizeof(T); i++) + result |= ((value >> (i * 8)) & 0xFF) << ((sizeof(T) - i - 1) * 8); + return result; + } + + template + constexpr T host_to_little_endian(T value) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return value; +#else + return swap_endianness(value); +#endif + } + + template + constexpr T host_to_big_endian(T value) + { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + return value; +#else + return swap_endianness(value); +#endif + } + template struct LittleEndian { constexpr operator T() const { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - return raw; -#else - T result { 0 }; - for (size_t i = 0; i < sizeof(T); i++) - result = (result << 8) | ((raw >> (sizeof(T) - i - 1) * 8) & 0xFF); - return result; -#endif + return host_to_little_endian(raw); } + private: T raw; }; @@ -29,14 +71,7 @@ namespace BAN { constexpr operator T() const { -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - return raw; -#else - T result { 0 }; - for (size_t i = 0; i < sizeof(T); i++) - result = (result << 8) | ((raw >> (i * 8)) & 0xFF); - return result; -#endif + return host_to_big_endian(raw); } private: T raw;