ByteSwap.h terse/utils/Endianness.h cstddef cstdint cstring type_traits InputArchive.h OutputArchive.h terse::traits::uint_of_size terse::impl::block128 terse::ByteSwapper< Endianness::Little > terse::ByteSwapper< Endianness::Big > terse terse::traits terse::impl //CopyrightEpicGames,Inc.AllRightsReserved. #pragmaonce #ifdefTERSE_ENABLE_SSE #defineENABLE_SSE_BSWAP #endif//TERSE_ENABLE_SSE #include"terse/utils/Endianness.h" #ifdef_MSC_VER #pragmawarning(push) #pragmawarning(disable:43654987) #endif #include<cstddef> #include<cstdint> #include<cstring> #include<type_traits> #ifdef_MSC_VER #pragmawarning(pop) #endif namespaceterse{ namespacetraits{ template<std::size_tsize> structuint_of_size{ usingtype=typenamestd::conditional<(size==1ul),std::uint8_t, typenamestd::conditional<(size==2ul),std::uint16_t, typenamestd::conditional<(size<=4ul),std::uint32_t, std::uint64_t>::type>::type>::type; }; }//namespacetraits namespaceimpl{ structblock128{ staticconstexprstd::size_talignment(){ #ifdefined(__arm__)||defined(__aarch64__)||defined(_M_ARM)||defined(_M_ARM64) returnstd::alignment_of<std::max_align_t>::value; #else return16ul; #endif } }; }//namespaceimpl enumclassEndianness{ Little, Big, Network=Big }; template<EndiannessEByteOrder> structByteSwapper; template<> structByteSwapper<Endianness::Little>{ template<typenameT> staticvoidswap(T&value){ #ifdefTARGET_LITTLE_ENDIAN static_cast<void>(value); #else usingUIntType=typenametraits::uint_of_size<sizeof(T)>::type; static_assert(sizeof(T)==sizeof(UIntType),"Nomatchingunsignedintegraltypefoundforthegiventype."); //Usingmemcpyistheonlywell-definedwayofreconstructingarbitrarytypesfromrawbytes. //Theseeminglyunnecessarycopiesandmemcpycallsarealloptimizedaway, //compilerknowswhat'sup. UIntTypeswapped; std::memcpy(&swapped,&value,sizeof(T)); swapped=bswap(swapped); std::memcpy(&value,&swapped,sizeof(T)); #endif//TARGET_LITTLE_ENDIAN } template<typenameT> staticvoidswap(T*values){ #ifdefTARGET_LITTLE_ENDIAN static_cast<void>(values); #else usingUIntType=typenametraits::uint_of_size<sizeof(T)>::type; static_assert(sizeof(T)==sizeof(UIntType),"Nomatchingunsignedintegraltypefoundforthegiventype."); //Usingmemcpyistheonlywell-definedwayofreconstructingarbitrarytypesfromrawbytes. //Theseeminglyunnecessarycopiesandmemcpycallsarealloptimizedaway, //compilerknowswhat'sup. alignas(impl::block128::alignment())UIntTypeswapped[16ul/sizeof(T)]; std::memcpy(static_cast<UIntType*>(swapped),values,16ul); bswap(static_cast<UIntType*>(swapped)); std::memcpy(values,static_cast<UIntType*>(swapped),16ul); #endif//TARGET_LITTLE_ENDIAN } }; template<> structByteSwapper<Endianness::Big>{ template<typenameT> staticvoidswap(T&value){ #ifdefTARGET_LITTLE_ENDIAN usingUIntType=typenametraits::uint_of_size<sizeof(T)>::type; static_assert(sizeof(T)==sizeof(UIntType),"Nomatchingunsignedintegraltypefoundforthegiventype."); //Usingmemcpyistheonlywell-definedwayofreconstructingarbitrarytypesfromrawbytes. //Theseeminglyunnecessarycopiesandmemcpycallsarealloptimizedaway, //compilerknowswhat'sup. UIntTypeswapped; std::memcpy(&swapped,&value,sizeof(T)); swapped=bswap(swapped); std::memcpy(&value,&swapped,sizeof(T)); #else static_cast<void>(value); #endif//TARGET_LITTLE_ENDIAN } template<typenameT> staticvoidswap(T*values){ #ifdefTARGET_LITTLE_ENDIAN usingUIntType=typenametraits::uint_of_size<sizeof(T)>::type; static_assert(sizeof(T)==sizeof(UIntType),"Nomatchingunsignedintegraltypefoundforthegiventype."); //Usingmemcpyistheonlywell-definedwayofreconstructingarbitrarytypesfromrawbytes. //Theseeminglyunnecessarycopiesandmemcpycallsarealloptimizedaway, //compilerknowswhat'sup. alignas(impl::block128::alignment())UIntTypeswapped[16ul/sizeof(T)]; std::memcpy(static_cast<UIntType*>(swapped),values,16ul); bswap(static_cast<UIntType*>(swapped)); std::memcpy(values,static_cast<UIntType*>(swapped),16ul); #else static_cast<void>(values); #endif//TARGET_LITTLE_ENDIAN } }; template<EndiannessEByteOrder> usingSwapTo=ByteSwapper<EByteOrder>; template<EndiannessEByteOrder> usingSwapFrom=ByteSwapper<EByteOrder>; template<typenameT> inlinevoidnetworkToHost(T&value){ SwapFrom<Endianness::Network>::swap(value); } template<typenameT> inlinevoidnetworkToHost128(T*values){ SwapFrom<Endianness::Network>::swap(values); } template<typenameT> inlinevoidhostToNetwork(T&value){ SwapTo<Endianness::Network>::swap(value); } template<typenameT> inlinevoidhostToNetwork128(T*values){ SwapTo<Endianness::Network>::swap(values); } }//namespaceterse