#pragma once #include #include 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 little_endian_to_host(T value) { return host_to_little_endian(value); } template constexpr T host_to_big_endian(T value) { #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ return value; #else return swap_endianness(value); #endif } template constexpr T big_endian_to_host(T value) { return host_to_big_endian(value); } template struct LittleEndian { constexpr LittleEndian() : raw(0) { } constexpr LittleEndian(T value) : raw(host_to_little_endian(value)) { } constexpr operator T() const { return host_to_little_endian(raw); } private: T raw; }; template struct BigEndian { constexpr BigEndian() : raw(0) { } constexpr BigEndian(T value) : raw(host_to_big_endian(value)) { } constexpr operator T() const { return host_to_big_endian(raw); } private: T raw; }; template using NetworkEndian = BigEndian; template constexpr T host_to_network_endian(T value) { return host_to_big_endian(value); } template constexpr T network_endian_to_host(T value) { return big_endian_to_host(value); } }