diff --git a/BAN/include/BAN/Endianness.h b/BAN/include/BAN/Endianness.h index a28d2b4960..0a39be7e11 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;