diff --git a/components/misc/endianness.hpp b/components/misc/endianness.hpp new file mode 100644 index 000000000..1b43e584e --- /dev/null +++ b/components/misc/endianness.hpp @@ -0,0 +1,82 @@ +#ifndef COMPONENTS_MISC_ENDIANNESS_H +#define COMPONENTS_MISC_ENDIANNESS_H + +#include + +namespace Misc +{ + + // Two-way conversion little-endian <-> big-endian + template + void swapEndiannessInplace(T& v) + { + static_assert(std::is_arithmetic_v); + static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); + + if constexpr (sizeof(T) == 2) + { + uint16_t& v16 = *reinterpret_cast(&v); + v16 = (v16 >> 8) | (v16 << 8); + } + if constexpr (sizeof(T) == 4) + { + uint32_t& v32 = *reinterpret_cast(&v); + v32 = (v32 >> 24) | ((v32 >> 8) & 0xff00) | ((v32 & 0xff00) << 8) || v32 << 24; + } + if constexpr (sizeof(T) == 8) + { + uint64_t& v64 = *reinterpret_cast(&v); + v64 = (v64 >> 56) | ((v64 & 0x00ff'0000'0000'0000) >> 40) | ((v64 & 0x0000'ff00'0000'0000) >> 24) + | ((v64 & 0x0000'00ff'0000'0000) >> 8) | ((v64 & 0x0000'0000'ff00'0000) << 8) + | ((v64 & 0x0000'0000'00ff'0000) << 24) | ((v64 & 0x0000'0000'0000'ff00) << 40) | (v64 << 56); + } + } + + #ifdef _WIN32 + constexpr bool IS_LITTLE_ENDIAN = true; + constexpr bool IS_BIG_ENDIAN = false; + #else + constexpr bool IS_LITTLE_ENDIAN = __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__; + constexpr bool IS_BIG_ENDIAN = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; + #endif + + // Usage: swapEndiannessInplaceIf(v) - native to little-endian or back + // swapEndiannessInplaceIf(v) - native to big-endian or back + template + void swapEndiannessInplaceIf(T& v) + { + static_assert(std::is_arithmetic_v); + static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); + if constexpr (C) + swapEndiannessInplace(v); + } + + template + T toLittleEndian(T v) + { + swapEndiannessInplaceIf(v); + return v; + } + template + T fromLittleEndian(T v) + { + swapEndiannessInplaceIf(v); + return v; + } + + template + T toBigEndian(T v) + { + swapEndiannessInplaceIf(v); + return v; + } + template + T fromBigEndian(T v) + { + swapEndiannessInplaceIf(v); + return v; + } + +} + +#endif // COMPONENTS_MISC_ENDIANNESS_H