FileStreamImpl.cpp trio/streams/FileStreamImpl.h trio/utils/NativeString.h trio/utils/ScopedEnumEx.h pma/PolyAllocator.h algorithm cassert cstddef cstdint cstring ios type_traits trio trio::anonymous_namespace{FileStreamImpl.cpp} //CopyrightEpicGames,Inc.AllRightsReserved. #include"trio/streams/FileStreamImpl.h" #include"trio/utils/NativeString.h" #include"trio/utils/ScopedEnumEx.h" #include<pma/PolyAllocator.h> #ifdef_MSC_VER #pragmawarning(push) #pragmawarning(disable:43654987) #endif #include<algorithm> #include<cassert> #include<cstddef> #include<cstdint> #include<cstring> #include<ios> #include<type_traits> #ifdef_MSC_VER #pragmawarning(pop) #endif namespacetrio{ namespace{ constexprstd::size_tbufferSize=4096ul; inlinestd::uint64_tgetFileSizeStd(constNativeCharacter*path){ std::streamofffileSize=std::ifstream(path,std::ios_base::ate|std::ios_base::binary).tellg(); return(fileSize>0?static_cast<std::uint64_t>(fileSize):0ul); } inlinevoidensureFileExistsStd(constNativeCharacter*path){ std::fstreamfile; file.open(path); if(file.fail()){ //Filedoesnotexist,createit file.open(path,std::ios_base::out); } } }//namespace FileStream::~FileStream()=default; FileStream*FileStream::create(constchar*path,AccessModeaccessMode,OpenModeopenMode,MemoryResource*memRes){ pma::PolyAllocator<FileStreamImpl>alloc{memRes}; returnalloc.newObject(path,accessMode,openMode,memRes); } voidFileStream::destroy(FileStream*instance){ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) autostream=static_cast<FileStreamImpl*>(instance); pma::PolyAllocator<FileStreamImpl>alloc{stream->getMemoryResource()}; alloc.deleteObject(stream); } FileStreamImpl::FileStreamImpl(constchar*path_,AccessModeaccessMode_,OpenModeopenMode_,MemoryResource*memRes_): filePath{NativeStringConverter::from(path_,memRes_)}, fileAccessMode{accessMode_}, fileOpenMode{openMode_}, fileSize{getFileSizeStd(filePath.c_str())}, memRes{memRes_}{ } voidFileStreamImpl::open(){ status->reset(); if(file.is_open()){ status->set(AlreadyOpenError,filePath.c_str()); return; } std::ios_base::openmodeflags{}; flags|=(contains(fileAccessMode,AccessMode::Read)?std::ios_base::in:flags); flags|=(contains(fileAccessMode,AccessMode::Write)?std::ios_base::out:flags); flags|=(contains(fileOpenMode,OpenMode::Binary)?std::ios_base::binary:flags); flags|=std::ios_base::ate; if(fileAccessMode==AccessMode::ReadWrite){ ensureFileExistsStd(filePath.c_str()); } file.open(filePath.c_str(),flags); if(!file.good()){ status->set(OpenError,filePath.c_str()); return; } fileSize=static_cast<std::uint64_t>(file.tellg()); seek(0ul); } voidFileStreamImpl::close(){ file.close(); } std::uint64_tFileStreamImpl::tell(){ returnstatic_cast<std::uint64_t>(file.tellp()); } voidFileStreamImpl::seek(std::uint64_tposition){ constboolseekable=(position==0ul||position<=size())&&file.good(); if(!seekable){ status->set(SeekError,filePath.c_str()); return; } file.seekp(static_cast<std::streamoff>(position)); if(!file.good()){ status->set(SeekError,filePath.c_str()); } } std::size_tFileStreamImpl::read(char*destination,std::size_tsize){ if((destination==nullptr)||file.fail()||!file.is_open()||!contains(fileAccessMode,AccessMode::Read)){ status->set(ReadError,filePath.c_str()); return0ul; } file.read(destination,static_cast<std::streamsize>(size)); if(!file.good()&&!file.eof()){ status->set(ReadError,filePath.c_str()); } constautobytesRead=file.gcount(); return(bytesRead>0?static_cast<std::size_t>(bytesRead):0ul); } std::size_tFileStreamImpl::read(Writable*destination,std::size_tsize){ if((destination==nullptr)||file.fail()||!file.is_open()||!contains(fileAccessMode,AccessMode::Read)){ status->set(ReadError,filePath.c_str()); return0ul; } charbuffer[bufferSize]; while(size>bufferSize){ file.read(buffer,static_cast<std::streamsize>(bufferSize)); destination->write(buffer,bufferSize); size-=bufferSize; } file.read(buffer,static_cast<std::streamsize>(size)); destination->write(buffer,size); if(!file.good()&&!file.eof()){ status->set(ReadError,filePath.c_str()); } constautobytesRead=file.gcount(); return(bytesRead>0?static_cast<std::size_t>(bytesRead):0ul); } std::size_tFileStreamImpl::write(constchar*source,std::size_tsize){ if((source==nullptr)||file.fail()||!file.is_open()||!contains(fileAccessMode,AccessMode::Write)){ status->set(WriteError,filePath.c_str()); return0ul; } constautopreWritePos=file.tellp(); file.write(source,static_cast<std::streamsize>(size)); constautopostWritePos=file.tellp(); if(!file.good()){ status->set(WriteError,filePath.c_str()); }else{ fileSize=std::max(static_cast<std::uint64_t>(postWritePos),fileSize); } return(postWritePos>preWritePos?static_cast<std::size_t>(postWritePos-preWritePos):0ul); } std::size_tFileStreamImpl::write(Readable*source,std::size_tsize){ if((source==nullptr)||file.fail()||!file.is_open()||!contains(fileAccessMode,AccessMode::Write)){ status->set(WriteError,filePath.c_str()); return0ul; } constautopreWritePos=file.tellp(); charbuffer[bufferSize]; while(size>bufferSize){ source->read(buffer,bufferSize); file.write(buffer,static_cast<std::streamsize>(bufferSize)); size-=bufferSize; } source->read(buffer,size); file.write(buffer,static_cast<std::streamsize>(size)); constautopostWritePos=file.tellp(); if(!file.good()){ status->set(WriteError,filePath.c_str()); }else{ fileSize=std::max(static_cast<std::uint64_t>(postWritePos),fileSize); } return(postWritePos>preWritePos?static_cast<std::size_t>(postWritePos-preWritePos):0ul); } std::uint64_tFileStreamImpl::size(){ returnfileSize; } MemoryResource*FileStreamImpl::getMemoryResource(){ returnmemRes; } }//namespacetrio