#pragma once #include #include #include #include #include namespace Utility::Endian { enum struct Type { Big = 0, Little = 1 }; #ifdef __cpp_lib_endian //use the c++20 api if possible constexpr Type target = std::endian::native == std::endian::big ? Type::Big : Type::Little; constexpr inline bool isBE() { return target == Type::Big; } #else //do a runtime check otherwise Type getEndian(); const Type target = getEndian(); inline bool isBE() { return target == Type::Big; } #endif uint64_t byteswap(const uint64_t& value); uint32_t byteswap(const uint32_t& value); uint32_t byteswap24(const uint32_t& value); //used in FST files uint16_t byteswap(const uint16_t& value); int64_t byteswap(const int64_t& value); int32_t byteswap(const int32_t& value); int16_t byteswap(const int16_t& value); [[deprecated("Platform may silently set NaN bits, bit_cast to uint32_t first if possible.")]] float byteswap(const float& value); [[deprecated("Platform may silently set NaN bits, bit_cast to uint64_t first if possible.")]] double byteswap(const double& value); char16_t byteswap(const char16_t& value); std::u16string byteswap(const std::u16string& value); template concept CanByteswap = sizeof(T) > 1; template requires CanByteswap && (!std::is_enum_v) constexpr T toPlatform(const Type& src, const T& value) { if (src != target) return byteswap(value); return value; } //for enums template> requires CanByteswap && std::is_enum_v constexpr T toPlatform(const Type& src, const T& value) { if (src != target) return static_cast(byteswap(static_cast(value))); return value; } //doesn't work for enums template requires CanByteswap && (!std::is_enum_v) constexpr void toPlatform_inplace(const Type& src, T& value) { if (src != target) value = byteswap(value); } //for enums template> requires CanByteswap && std::is_enum_v constexpr void toPlatform_inplace(const Type& src, T& value) { if (src != target) value = static_cast(byteswap(static_cast(value))); } }