binary/InputArchive.h terse/Archive.h terse/archives/Common.h terse/archives/Traits.h terse/types/Anchor.h terse/types/ArchiveOffset.h terse/types/ArchiveSize.h terse/types/Blob.h terse/types/DynArray.h terse/types/Transparent.h terse/utils/ByteSwap.h array cassert cstddef cstdint cstring memory string tuple type_traits utility vector FilteredInputArchive.h terse::ExtendableBinaryInputArchive terse::BinaryInputArchive terse //CopyrightEpicGames,Inc.AllRightsReserved. #pragmaonce #include"terse/Archive.h" #include"terse/archives/Common.h" #include"terse/archives/Traits.h" #include"terse/types/Anchor.h" #include"terse/types/ArchiveOffset.h" #include"terse/types/ArchiveSize.h" #include"terse/types/Blob.h" #include"terse/types/DynArray.h" #include"terse/types/Transparent.h" #include"terse/utils/ByteSwap.h" #ifdef_MSC_VER #pragmawarning(push) #pragmawarning(disable:43654987) #endif #include<array> #include<cassert> #include<cstddef> #include<cstdint> #include<cstring> #include<memory> #include<string> #include<tuple> #include<type_traits> #include<utility> #include<vector> #ifdef_MSC_VER #pragmawarning(pop) #endif namespaceterse{ template<classTExtender,classTStream,typenameTSize,typenameTOffset,EndiannessEByteOrder> classExtendableBinaryInputArchive:publicArchive<TExtender>{ public: //Giventhepossibilityofboth32and64bitplatforms,useafixedwidthtypeduringserialization usingSizeType=TSize; usingOffsetType=TOffset; staticconstexprEndiannessendianness(){ returnEByteOrder; } private: usingBaseArchive=Archive<TExtender>; public: ExtendableBinaryInputArchive(TExtender*extender,TStream*stream_):BaseArchive{extender},stream{stream_}{ } boolisOk(){ returntrue; } voidsync(){ } voidlabel(constchar*/*unused*/){ } protected: template<typenameT> voidprocess(Transparent<T>&&dest){ process(dest.data); } voidprocess(Anchor<OffsetType>&dest){ dest.value=static_cast<OffsetType>(stream->tell()); } voidprocess(ArchiveOffset<OffsetType>&dest){ //Loadtheoffsetvalueitself(thispointsforwardwithinthestreamtothepositionof //thedatawithwhichtheoffsetisassociated) process(dest.value); } voidprocess(typenameArchiveOffset<OffsetType>::Proxy&dest){ //Relyontheoffsetvaluestoredintheassociated`ArchiveOffset`andseektoit stream->seek(dest.target->value); } voidprocess(typenameArchiveOffset<OffsetType>::Proxy&&dest){ process(dest); } voidprocess(ArchiveSize<SizeType, OffsetType>&dest){ //Loadthesizevalueitself(thisvaluecanbecombinedwithanoffsettogettheendofadataregion) process(dest.value); } voidprocess(typenameArchiveSize<SizeType, OffsetType>::Proxy&dest){ //Calculatetheoffset+sizevaluestoredintheassociated`ArchiveSize`and`Anchor`andseektoit assert(dest.base!=nullptr); stream->seek(dest.base->value+dest.target->value); } voidprocess(typenameArchiveSize<SizeType, OffsetType>::Proxy&&dest){ process(dest); } template<typenameT,typename...Args> voidprocess(Blob<T, Args...>&dest){ usingValueType=typenameBlob<T,Args...>::value_type; //Blobreliesonapredetermined(userspecified)sizeofhowmuchdataitshouldconsume if(dest.size()!=0ul){ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) stream->read(reinterpret_cast<char*>(dest.data()),dest.size()*sizeof(ValueType)); } } template<typenameT> typenamestd::enable_if<traits::has_load_member<T>::value, void>::typeprocess(T&dest){ dest.load(*static_cast<TExtender*>(this)); } template<typenameT> typenamestd::enable_if<traits::has_serialize_member<T>::value, void>::typeprocess(T&dest){ dest.serialize(*static_cast<TExtender*>(this)); } template<typenameT> typenamestd::enable_if<traits::has_load_function<T>::value, void>::typeprocess(T&dest){ load(*static_cast<TExtender*>(this),dest); } template<typenameT> typenamestd::enable_if<traits::has_serialize_function<T>::value, void>::typeprocess(T&dest){ serialize(*static_cast<TExtender*>(this),dest); } template<typenameT> typenamestd::enable_if<!traits::has_load_member<T>::value&&!traits::has_serialize_member<T>::value&& !traits::has_load_function<T>::value&&!traits::has_serialize_function<T>::value, void>::typeprocess(T&dest){ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) stream->read(reinterpret_cast<char*>(&dest),sizeof(T)); SwapFrom<EByteOrder>::swap(dest); } template<typenameT,std::size_tN> voidprocess(std::array<T,N>&dest){ for(auto&element:dest){ BaseArchive::dispatch(element); } } template<typenameT,typename...Args> voidprocess(std::vector<T,Args...>&dest){ constautosize=processSize(); processElements(dest,size); } template<typenameT,typename...Args> voidprocess(DynArray<T, Args...>&dest){ constautosize=processSize(); processElements(dest,size); } template<typenameT,typename...Args> voidprocess(std::basic_string<T,Args...>&dest){ constautosize=processSize(); processElements(dest,size); } template<typenameK,typenameV> voidprocess(std::pair<K,V>&dest){ BaseArchive::dispatch(dest.first); BaseArchive::dispatch(dest.second); } template<typenameK,typenameV> voidprocess(std::tuple<K,V>&dest){ BaseArchive::dispatch(std::get<0>(dest)); BaseArchive::dispatch(std::get<1>(dest)); } std::size_tprocessSize(){ SizeTypesize{}; process(size); returnstatic_cast<std::size_t>(size); } template<classTContainer> typenamestd::enable_if<!traits::is_batchable<TContainer>::value &&traits::has_reserve_member<TContainer>::value &&traits::has_push_back_member<TContainer>::value >::type processElements(TContainer&dest,std::size_tsize){ usingValueType=typenameTContainer::value_type; dest.clear(); dest.reserve(size); for(std::size_ti=0ul;i<size;++i){ dest.push_back(impl::ValueFactory<ValueType>::create(dest.get_allocator())); BaseArchive::dispatch(dest.back()); } } template<classTContainer> typenamestd::enable_if<!traits::is_batchable<TContainer>::value &&!traits::has_reserve_member<TContainer>::value &&!traits::has_push_back_member<TContainer>::value>::type processElements(TContainer&dest,std::size_tsize){ resize(dest,size); for(auto&element:dest){ BaseArchive::dispatch(element); } } template<classTContainer> typenamestd::enable_if<traits::is_batchable<TContainer>::value&&traits::has_wide_elements<TContainer>::value>::type processElements(TContainer&dest,std::size_tsize){ usingValueType=typenameTContainer::value_type; if(size!=0ul){ resize(dest,size); //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) stream->read(reinterpret_cast<char*>(&dest[0]),size*sizeof(ValueType)); conststd::size_tblockWidth=16ul/sizeof(ValueType); conststd::size_talignedSize=size-(size%blockWidth); for(std::size_ti=0ul;i<alignedSize;i+=blockWidth){ SwapFrom<EByteOrder>::swap(&dest[i]); } for(std::size_ti=alignedSize;i<size;++i){ SwapFrom<EByteOrder>::swap(dest[i]); } } } template<classTContainer> typenamestd::enable_if<traits::is_batchable<TContainer>::value&&!traits::has_wide_elements<TContainer>::value>::type processElements(TContainer&dest,std::size_tsize){ usingValueType=typenameTContainer::value_type; if(size!=0ul){ resize(dest,size); //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) stream->read(reinterpret_cast<char*>(&dest[0]),size*sizeof(ValueType)); } } private: template<classTContainer> voidresize(TContainer&dest,std::size_tsize){ dest.resize(size); } template<typenameT,classTAllocator> voidresize(DynArray<T, TAllocator>&dest,std::size_tsize){ dest.resize_uninitialized(size); } private: TStream*stream; }; template<classTStream,typenameTSize=std::uint32_t,typenameTOffset=TSize,EndiannessEByteOrder=Endianness::Network> classBinaryInputArchive:publicExtendableBinaryInputArchive<BinaryInputArchive<TStream,TSize,TOffset,EByteOrder>, TStream, TSize, TOffset, EByteOrder>{ private: usingBaseArchive=ExtendableBinaryInputArchive<BinaryInputArchive, TStream, TSize, TOffset, EByteOrder>; friendArchive<BinaryInputArchive>; public: explicitBinaryInputArchive(TStream*stream_):BaseArchive{this,stream_}{ } private: template<typenameT> voidprocess(T&&dest){ BaseArchive::process(std::forward<T>(dest)); } }; }//namespaceterse