From 6847ea027d04d5becdbca042e6fbaf501f6fb3d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 12:21:23 +0200 Subject: [PATCH] - updated files.cpp with some new features from Raze. Not really needed for GZDoom but it's convenient to have the files being identical. --- src/utility/files.cpp | 9 +++-- src/utility/files.h | 25 ++++++++---- src/utility/files_decompress.cpp | 65 ++++++++++++++++++++------------ 3 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/utility/files.cpp b/src/utility/files.cpp index e5a17dd4f4..e932622146 100644 --- a/src/utility/files.cpp +++ b/src/utility/files.cpp @@ -34,7 +34,8 @@ */ #include "files.h" -#include "templates.h" +#include "templates.h" // just for 'clamp' +#include "zstring.h" FILE *myfopen(const char *filename, const char *flags) @@ -187,7 +188,7 @@ public: return FilePos - StartPos; } - virtual long Seek(long offset, int origin) + virtual long Seek(long offset, int origin) override { switch (origin) { @@ -212,7 +213,7 @@ public: return -1; } - virtual long Read(void *buffer, long len) + virtual long Read(void *buffer, long len) override { assert(len >= 0); if (len <= 0) return 0; @@ -225,7 +226,7 @@ public: return len; } - virtual char *Gets(char *strbuf, int len) + virtual char *Gets(char *strbuf, int len) override { if (len <= 0 || FilePos >= StartPos + Length) return NULL; char *p = mReader->Gets(strbuf, len); diff --git a/src/utility/files.h b/src/utility/files.h index a5ce834eca..5563f5ce9a 100644 --- a/src/utility/files.h +++ b/src/utility/files.h @@ -304,30 +304,33 @@ public: // They will just error out when called. long Tell() const override; long Seek(long offset, int origin) override; - char *Gets(char *strbuf, int len) override; + char* Gets(char* strbuf, int len) override; void DecompressionError(const char* error, ...) const; void SetErrorCallback(const std::function& cb) { ErrorCallback = cb; } + void SetOwnsReader(); + +protected: + FileReader* File = nullptr; + FileReader OwnedFile; }; - - class FileWriter { protected: bool OpenDirect(const char *filename); - FileWriter() - { - File = NULL; - } public: + FileWriter(FILE *f = nullptr) // if passed, this writer will take over the file. + { + File = f; + } virtual ~FileWriter() { - if (File != NULL) fclose(File); + Close(); } static FileWriter *Open(const char *filename); @@ -336,6 +339,11 @@ public: virtual long Tell(); virtual long Seek(long offset, int mode); size_t Printf(const char *fmt, ...) GCCPRINTF(2,3); + virtual void Close() + { + if (File != NULL) fclose(File); + File = nullptr; + } protected: @@ -354,6 +362,7 @@ public: BufferWriter() {} virtual size_t Write(const void *buffer, size_t len) override; TArray *GetBuffer() { return &mBuffer; } + TArray&& TakeBuffer() { return std::move(mBuffer); } }; diff --git a/src/utility/files_decompress.cpp b/src/utility/files_decompress.cpp index 03be66b7ae..c14079b636 100644 --- a/src/utility/files_decompress.cpp +++ b/src/utility/files_decompress.cpp @@ -33,16 +33,18 @@ ** */ -// This also pulls in windows.h +// Caution: LzmaDec also pulls in windows.h! +#define NOMINMAX #include "LzmaDec.h" #include #include +#include #include "files.h" #include "templates.h" +#include "zstring.h" #include "cmdlib.h" - //========================================================================== // // I_Error @@ -82,6 +84,12 @@ char *DecompressorBase::Gets(char *strbuf, int len) return nullptr; } +void DecompressorBase::SetOwnsReader() +{ + OwnedFile = std::move(*File); + File = &OwnedFile; +} + //========================================================================== // // DecompressorZ @@ -95,17 +103,17 @@ class DecompressorZ : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - FileReader &File; bool SawEOF; z_stream Stream; uint8_t InBuff[BUFF_SIZE]; public: - DecompressorZ (FileReader &file, bool zip, const std::function& cb) - : File(file), SawEOF(false) + DecompressorZ (FileReader *file, bool zip, const std::function& cb) + : SawEOF(false) { int err; + File = file; SetErrorCallback(cb); FillBuffer (); @@ -157,7 +165,7 @@ public: void FillBuffer () { - auto numread = File.Read (InBuff, BUFF_SIZE); + auto numread = File->Read (InBuff, BUFF_SIZE); if (numread < BUFF_SIZE) { @@ -186,17 +194,17 @@ class DecompressorBZ2 : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - FileReader &File; bool SawEOF; bz_stream Stream; uint8_t InBuff[BUFF_SIZE]; public: - DecompressorBZ2 (FileReader &file, const std::function& cb) - : File(file), SawEOF(false) + DecompressorBZ2 (FileReader *file, const std::function& cb) + : SawEOF(false) { int err; + File = file; SetErrorCallback(cb); stupidGlobal = this; FillBuffer (); @@ -251,7 +259,7 @@ public: void FillBuffer () { - auto numread = File.Read(InBuff, BUFF_SIZE); + auto numread = File->Read(InBuff, BUFF_SIZE); if (numread < BUFF_SIZE) { @@ -295,7 +303,6 @@ class DecompressorLZMA : public DecompressorBase { enum { BUFF_SIZE = 4096 }; - FileReader &File; bool SawEOF; CLzmaDec Stream; size_t Size; @@ -305,18 +312,19 @@ class DecompressorLZMA : public DecompressorBase public: - DecompressorLZMA (FileReader &file, size_t uncompressed_size, const std::function& cb) - : File(file), SawEOF(false) + DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function& cb) + : SawEOF(false) { uint8_t header[4 + LZMA_PROPS_SIZE]; int err; + File = file; SetErrorCallback(cb); Size = uncompressed_size; OutProcessed = 0; // Read zip LZMA properties header - if (File.Read(header, sizeof(header)) < (long)sizeof(header)) + if (File->Read(header, sizeof(header)) < (long)sizeof(header)) { DecompressionError("DecompressorLZMA: File too short\n"); } @@ -393,7 +401,7 @@ public: void FillBuffer () { - auto numread = File.Read(InBuff, BUFF_SIZE); + auto numread = File->Read(InBuff, BUFF_SIZE); if (numread < BUFF_SIZE) { @@ -415,7 +423,6 @@ class DecompressorLZSS : public DecompressorBase { enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; - FileReader &File; bool SawEOF; uint8_t InBuff[BUFF_SIZE]; @@ -446,7 +453,7 @@ class DecompressorLZSS : public DecompressorBase if(Stream.AvailIn) memmove(InBuff, Stream.In, Stream.AvailIn); - auto numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); + auto numread = File->Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); if (numread < BUFF_SIZE) { @@ -501,7 +508,7 @@ class DecompressorLZSS : public DecompressorBase // Partial overlap: Copy in 2 or 3 chunks. do { - unsigned int copy = MIN(len, pos+1); + unsigned int copy = std::min(len, pos+1); memcpy(Stream.InternalBuffer, copyStart, copy); Stream.InternalBuffer += copy; Stream.InternalOut += copy; @@ -533,8 +540,9 @@ class DecompressorLZSS : public DecompressorBase } public: - DecompressorLZSS(FileReader &file, const std::function& cb) : File(file), SawEOF(false) + DecompressorLZSS(FileReader *file, const std::function& cb) : SawEOF(false) { + File = file; SetErrorCallback(cb); Stream.State = STREAM_EMPTY; Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; @@ -566,7 +574,7 @@ public: break; } - unsigned int copy = MIN(Stream.InternalOut, AvailOut); + unsigned int copy = std::min(Stream.InternalOut, AvailOut); if(copy > 0) { memcpy(Out, Stream.WindowData, copy); @@ -599,29 +607,35 @@ public: bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function& cb) { DecompressorBase *dec = nullptr; - switch (method) + FileReader *p = &parent; + switch (method & ~METHOD_TRANSFEROWNER) { case METHOD_DEFLATE: case METHOD_ZLIB: - dec = new DecompressorZ(parent, method == METHOD_DEFLATE, cb); + dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb); break; case METHOD_BZIP2: - dec = new DecompressorBZ2(parent, cb); + dec = new DecompressorBZ2(p, cb); break; case METHOD_LZMA: - dec = new DecompressorLZMA(parent, length, cb); + dec = new DecompressorLZMA(p, length, cb); break; case METHOD_LZSS: - dec = new DecompressorLZSS(parent, cb); + dec = new DecompressorLZSS(p, cb); break; // todo: METHOD_IMPLODE, METHOD_SHRINK default: return false; } + if (method & METHOD_TRANSFEROWNER) + { + dec->SetOwnsReader(); + } + dec->Length = (long)length; if (!seekable) { @@ -636,3 +650,4 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b return false; } } +