CharInputStreamBuf.h array streambuf InputArchive.h terse::CharInputStreamBuf terse //CopyrightEpicGames,Inc.AllRightsReserved. #pragmaonce #ifdef_MSC_VER #pragmawarning(push) #pragmawarning(disable:43654987) #endif #include<array> #include<streambuf> #ifdef_MSC_VER #pragmawarning(pop) #endif namespaceterse{ template<classTStream,std::size_tBufferSize=4096ul> classCharInputStreamBuf:publicstd::streambuf{ public: usingPosType=std::streambuf::pos_type; usingOffType=std::streambuf::off_type; usingCharType=std::streambuf::char_type; usingIntType=std::streambuf::int_type; usingTraitsType=std::streambuf::traits_type; public: explicitCharInputStreamBuf(TStream*stream_):stream{stream_},buffer{}{ char*bufferEnd=buffer.data()+buffer.size(); setg(bufferEnd,bufferEnd,bufferEnd); } std::streamsizexsgetn(CharType*destination,std::streamsizesize)override{ if(size<=0){ return0; } std::streamsizebytesNeeded=size; //Exhaustbuffercontentsfirst if(gptr()<egptr()){ conststd::size_tbytesInBuffer=static_cast<std::size_t>(egptr()-gptr()); conststd::size_tbytesToCopy=std::min(static_cast<std::size_t>(bytesNeeded),bytesInBuffer); std::memcpy(destination,gptr(),bytesToCopy); destination+=bytesToCopy; bytesNeeded-=static_cast<std::streamsize>(bytesToCopy); gbump(static_cast<IntType>(bytesToCopy)); } //Iftherearestillbytesneeded(moredatathanbuffercontained),readtherestdirectlyfromthestream if(bytesNeeded>0){ constautobytesRead= static_cast<std::streamsize>(stream->read(destination,static_cast<std::size_t>(bytesNeeded))); bytesNeeded-=bytesRead; } //Refillbufferforsubsequentaccesses(ifpossible) underflow(); returnsize-bytesNeeded; } IntTypeunderflow()override{ if(gptr()<egptr()){ returnTraitsType::to_int_type(*gptr()); } char*base=buffer.data(); char*start=base; //Initiallyeback()==buffer.end(),butifthat'snotthecase,bufferhasalreadybeen //filledbefore,inwhichcasefirstcopythedatafromtheput-backarea(locatedattheendof //thebuffer)intothebeginningofthebuffer,makingthemthenextcharacterstobereadfromit. //Put-backareaisjustonebyteinthisimplementationcurrently. if(eback()==base){ std::memcpy(base,egptr()-1ul,1ul); ++start; } //Nowfilltherestofthebufferaftertheput-backareaismovedtothebeginningofthebuffer conststd::size_tbytesRead=stream->read(start,buffer.size()-static_cast<std::size_t>(start-base)); if(bytesRead==0ul){ returnTraitsType::eof(); } setg(base,start,start+bytesRead); returnTraitsType::to_int_type(*gptr()); } std::streamsizeshowmanyc()override{ returnstatic_cast<std::streamsize>(stream->size()-stream->tell()); } private: TStream*stream; std::array<char,BufferSize>buffer; }; }//namespaceterse