#pragma once #include #include #include #include #include namespace IntegerLiterals { using u8 = uint8_t; using ub = u8; using u16 = uint16_t; using us = u16; using u32 = uint32_t; //using ul = u32; using u64 = uint64_t; using ud = u64; using s8 = int8_t; using sb = s8; using s16 = int16_t; using ss = s16; using s32 = int32_t; using sl = s32; using s64 = int64_t; using sd = s64; } /// https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html /// Platform-independent functions for swapping the byte order of common data types. namespace Endianness { using namespace IntegerLiterals; /// Returns true if the host machine is big-endian. constexpr bool IsBigEndian() noexcept { return (std::endian::native == std::endian::big); } /// Returns true if the host machine is little-endian. constexpr bool IsLittleEndian() noexcept { return (std::endian::native == std::endian::little); } template T ReverseByteOrder(T val) { T retVal; char* pVal = (char*)&val; char* pRetVal = (char*)&retVal; int size = sizeof(T); for (int i = 0; i < size; i++) { pRetVal[size - 1 - i] = pVal[i]; } return retVal; } #pragma region Template Specializations /// This function simply returns the input value, as no byte order can be swapped on a single-byte-length value. template <> u8 ReverseByteOrder(u8 val); /// This function simply returns the input value, as no byte order can be swapped on a single-byte-length value. template <> s8 ReverseByteOrder(s8 val);; template <> u16 ReverseByteOrder(u16 val); template <> u32 ReverseByteOrder(u32 val); template <> u64 ReverseByteOrder(u64 val); template <> s16 ReverseByteOrder(s16 val); template <> s32 ReverseByteOrder(s32 val); template <> s64 ReverseByteOrder(s64 val); #pragma endregion template T ReverseByteOrderIfLittleEndian(T val) { if (IsLittleEndian()) return ReverseByteOrder(val); else return val; } template T HostToNetworkOrder(T host) { return ReverseByteOrderIfLittleEndian(host);} template T NetworkToHostOrder(T network) { return ReverseByteOrderIfLittleEndian(network);} }