#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; } template void ReverseByteOrder(T* buffer, size_t length) { // Compile-time check to ensure T is an integral type and not bool // (single-byte types like char, int8_t don't need byte reversal) static_assert(std::is_integral_v, "ReverseByteOrder (buffer): Type T must be an integral type."); static_assert(sizeof(T) > 1, "ReverseByteOrder (buffer): Type T must be larger than 1 byte for byte reversal."); if (!buffer || length == 0) { return; // Nothing to do } for (size_t i = 0; i < length; ++i) { buffer[i] = ReverseByteOrder(buffer[i]); // Call the single-value function } } #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);} }