From b14ee50d0d0fad3e2de236a01d7d2dfdab83d3c9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 Mar 2018 12:33:46 +0100 Subject: [PATCH] - transition to new FileReader interface complete, but untested. --- src/CMakeLists.txt | 1 + src/d_iwad.cpp | 6 +- src/d_main.cpp | 10 +- src/files.cpp | 822 +++++++++------------------ src/files.h | 628 +++++--------------- src/files_decompress.cpp | 607 ++++++++++++++++++++ src/g_game.cpp | 4 +- src/md5.cpp | 4 +- src/menu/loadsavemenu.cpp | 4 +- src/p_conversation.h | 2 +- src/p_glnodes.cpp | 52 +- src/p_setup.cpp | 34 +- src/resourcefiles/ancientzip.cpp | 10 +- src/resourcefiles/ancientzip.h | 6 +- src/resourcefiles/file_7z.cpp | 42 +- src/resourcefiles/file_directory.cpp | 26 +- src/resourcefiles/file_grp.cpp | 20 +- src/resourcefiles/file_lump.cpp | 10 +- src/resourcefiles/file_pak.cpp | 23 +- src/resourcefiles/file_rff.cpp | 26 +- src/resourcefiles/file_wad.cpp | 232 +------- src/resourcefiles/file_zip.cpp | 82 ++- src/resourcefiles/file_zip.h | 4 +- src/resourcefiles/resourcefile.cpp | 90 ++- src/resourcefiles/resourcefile.h | 24 +- src/sound/i_soundfont.cpp | 6 +- src/textures/texture.cpp | 1 - src/textures/textures.h | 2 - src/w_wad.cpp | 326 ++--------- src/w_wad.h | 47 +- src/w_zip.h | 8 - 31 files changed, 1352 insertions(+), 1807 deletions(-) create mode 100644 src/files_decompress.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 924896439..7dfaa9e53 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -886,6 +886,7 @@ set (PCH_SOURCES edata.cpp f_wipe.cpp files.cpp + files_decompress.cpp g_doomedmap.cpp g_game.cpp g_hub.cpp diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index fadb9e65b..29c3ea98b 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -243,7 +243,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, FIWadManager::FIWadManager(const char *fn) { - FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); + FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true); if (resfile != NULL) { uint32_t cnt = resfile->LumpCount(); @@ -276,7 +276,7 @@ FIWadManager::FIWadManager(const char *fn) int FIWadManager::ScanIWAD (const char *iwad) { - FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, NULL, true); + FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, true); mLumpsFound.Resize(mIWadInfos.Size()); @@ -332,7 +332,7 @@ int FIWadManager::ScanIWAD (const char *iwad) int FIWadManager::CheckIWADInfo(const char *fn) { - FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); + FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, true); if (resfile != NULL) { uint32_t cnt = resfile->LumpCount(); diff --git a/src/d_main.cpp b/src/d_main.cpp index 0b03cf098..9ec546d56 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1947,7 +1947,6 @@ static FString CheckGameInfo(TArray & pwads) for(int i=pwads.Size()-1; i>=0; i--) { bool isdir = false; - FileReader *wadinfo; FResourceFile *resfile; const char *filename = pwads[i]; @@ -1960,16 +1959,13 @@ static FString CheckGameInfo(TArray & pwads) if (!isdir) { - try - { - wadinfo = new FileReader(filename); - } - catch (CRecoverableError &) + FileRdr fr; + if (!fr.OpenFile(filename)) { // Didn't find file continue; } - resfile = FResourceFile::OpenResourceFile(filename, wadinfo, true); + resfile = FResourceFile::OpenResourceFile(filename, fr, true); } else resfile = FResourceFile::OpenDirectory(filename, true); diff --git a/src/files.cpp b/src/files.cpp index cfd13cb7f..b445c2789 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -33,150 +33,252 @@ ** */ -// This also pulls in windows.h -#include "LzmaDec.h" - #include "files.h" #include "i_system.h" #include "templates.h" #include "m_misc.h" + //========================================================================== // -// FileReader +// StdFileReader // -// reads data from an uncompressed file or part of it +// reads data from an stdio FILE* or part of it. // //========================================================================== -FILE *FileReader::openfd(const char *filename) +class StdFileReader : public FileReaderInterface { - return fopen(filename, "rb"); -} + FILE *File = nullptr; + long Length = 0; + long StartPos = 0; + long FilePos = 0; -FileReader::FileReader () -: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ -} +public: + StdFileReader() + {} -FileReader::FileReader (const FileReader &other, long length) -: File(other.File), Length(length), CloseOnDestruct(false) -{ - FilePos = StartPos = ftell (other.File); -} - -FileReader::FileReader (const char *filename) -: File(NULL), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ - if (!Open(filename)) + ~StdFileReader() { - I_Error ("Could not open %s", filename); + if (File != nullptr) + { + fclose(File); + } + File = nullptr; } -} -FileReader::FileReader (FILE *file) -: File(file), Length(0), StartPos(0), FilePos(0), CloseOnDestruct(false) -{ - Length = CalcFileLen(); -} - -FileReader::FileReader (FILE *file, long length) -: File(file), Length(length), CloseOnDestruct(true) -{ - FilePos = StartPos = ftell (file); -} - -FileReader::~FileReader() -{ - Close(); -} - -void FileReader::Close() -{ - if (CloseOnDestruct && File != NULL) + bool Open(const char *filename, long startpos = 0, long len = -1) { - fclose (File); + File = fopen(filename, "rb"); + if (File == nullptr) return false; + FilePos = startpos; + StartPos = startpos; + Length = CalcFileLen(); + if (len >= 0 && len < Length) Length = len; + if (startpos > 0) Seek(startpos, SEEK_SET); + return true; } - File = NULL; -} -bool FileReader::Open (const char *filename) -{ - File = openfd (filename); - if (File == NULL) return false; - FilePos = 0; - StartPos = 0; - CloseOnDestruct = true; - Length = CalcFileLen(); - return true; -} - - -void FileReader::ResetFilePtr () -{ - FilePos = ftell (File); -} - -long FileReader::Tell () const -{ - return FilePos - StartPos; -} - -long FileReader::Seek (long offset, int origin) -{ - if (origin == SEEK_SET) + long Tell() const override { - offset += StartPos; + return FilePos - StartPos; } - else if (origin == SEEK_CUR) + + long Seek(long offset, int origin) override { + if (origin == SEEK_SET) + { + offset += StartPos; + } + else if (origin == SEEK_CUR) + { + offset += FilePos; + } + else if (origin == SEEK_END) + { + offset += StartPos + Length; + } + if (offset < StartPos || offset >= StartPos + Length) return -1; // out of scope + + if (0 == fseek(File, offset, SEEK_SET)) + { + FilePos = offset; + return 0; + } + return -1; + } + + long Read(void *buffer, long len) override + { + assert(len >= 0); + if (len <= 0) return 0; + if (FilePos + len > StartPos + Length) + { + len = Length - FilePos + StartPos; + } + len = (long)fread(buffer, 1, len, File); + FilePos += len; + return len; + } + + char *Gets(char *strbuf, int len) override + { + if (len <= 0 || FilePos >= StartPos + Length) return NULL; + char *p = fgets(strbuf, len, File); + if (p != NULL) + { + int old = FilePos; + FilePos = ftell(File); + if (FilePos - StartPos > Length) + { + strbuf[Length - old + StartPos] = 0; + } + } + return p; + } + +private: + long CalcFileLen() const + { + long endpos; + + fseek(File, 0, SEEK_END); + endpos = ftell(File); + fseek(File, 0, SEEK_SET); + return endpos; + } +}; + +//========================================================================== +// +// FileReaderRedirect +// +// like the above, but uses another File reader as its backing data +// +//========================================================================== + +class FileReaderRedirect : public FileReaderInterface +{ + FileRdr *mReader = nullptr; + long Length = 0; + long StartPos = 0; + long FilePos = 0; + +public: + FileReaderRedirect(FileRdr &parent, long start, long length) + { + mReader = &parent; + FilePos = start; + StartPos = start; + Length = length; + Seek(0, SEEK_SET); + } + + virtual long Tell() const override + { + return FilePos - StartPos; + } + + virtual long Seek(long offset, int origin) + { + switch (origin) + { + case SEEK_SET: + offset += StartPos; + break; + + case SEEK_END: + offset += StartPos + Length; + break; + + case SEEK_CUR: + offset += (long)mReader->Tell(); + break; + } + if (offset < StartPos || offset >= StartPos + Length) return -1; // out of scope + if (mReader->Seek(offset, FileRdr::SeekSet) == 0) + { + FilePos = offset; + return 0; + } + return -1; + } + + virtual long Read(void *buffer, long len) + { + assert(len >= 0); + if (len <= 0) return 0; + if (FilePos + len > StartPos + Length) + { + len = Length - FilePos + StartPos; + } + len = (long)mReader->Read(buffer, len); + FilePos += len; + return len; + } + + virtual char *Gets(char *strbuf, int len) + { + if (len <= 0 || FilePos >= StartPos + Length) return NULL; + char *p = mReader->Gets(strbuf, len); + if (p != NULL) + { + int old = FilePos; + FilePos = (long)mReader->Tell(); + if (FilePos - StartPos > Length) + { + strbuf[Length - old + StartPos] = 0; + } + } + return p; + } + +}; + +//========================================================================== +// +// MemoryReader +// +// reads data from a block of memory +// +//========================================================================== + +long MemoryReader::Tell() const +{ + return FilePos; +} + +long MemoryReader::Seek(long offset, int origin) +{ + switch (origin) + { + case SEEK_CUR: offset += FilePos; + break; + + case SEEK_END: + offset += Length; + break; + } - else if (origin == SEEK_END) - { - offset += StartPos + Length; - } - if (0 == fseek (File, offset, SEEK_SET)) - { - FilePos = offset; - return 0; - } - return -1; + if (offset < 0 || offset >= Length) return -1; + FilePos = clamp(offset, 0, Length); + return 0; } -long FileReader::Read (void *buffer, long len) +long MemoryReader::Read(void *buffer, long len) { - assert(len >= 0); - if (len <= 0) return 0; - if (FilePos + len > StartPos + Length) - { - len = Length - FilePos + StartPos; - } - len = (long)fread (buffer, 1, len, File); + if (len>Length - FilePos) len = Length - FilePos; + if (len<0) len = 0; + memcpy(buffer, bufptr + FilePos, len); FilePos += len; return len; } -char *FileReader::Gets(char *strbuf, int len) +char *MemoryReader::Gets(char *strbuf, int len) { - if (len <= 0 || FilePos >= StartPos + Length) return NULL; - char *p = fgets(strbuf, len, File); - if (p != NULL) - { - int old = FilePos; - FilePos = ftell(File); - if (FilePos - StartPos > Length) - { - strbuf[Length - old + StartPos] = 0; - } - } - return p; -} - -char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) -{ - if (len>Length-FilePos) len=Length-FilePos; + if (len>Length - FilePos) len = Length - FilePos; if (len <= 0) return NULL; char *p = strbuf; @@ -191,7 +293,7 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) { *p++ = bufptr[FilePos]; len--; - if (bufptr[FilePos] == '\n') + if (bufptr[FilePos] == '\n') { FilePos++; break; @@ -199,360 +301,11 @@ char *FileReader::GetsFromBuffer(const char * bufptr, char *strbuf, int len) } FilePos++; } - if (p==strbuf) return NULL; - *p++=0; + if (p == strbuf) return NULL; + *p++ = 0; return strbuf; } -long FileReader::CalcFileLen() const -{ - long endpos; - - fseek (File, 0, SEEK_END); - endpos = ftell (File); - fseek (File, 0, SEEK_SET); - return endpos; -} - -//========================================================================== -// -// FileReaderZ -// -// The zlib wrapper -// reads data from a ZLib compressed stream -// -//========================================================================== - -FileReaderZ::FileReaderZ (FileReader &file, bool zip) -: File(file), SawEOF(false) -{ - int err; - - FillBuffer (); - - Stream.zalloc = Z_NULL; - Stream.zfree = Z_NULL; - - if (!zip) err = inflateInit (&Stream); - else err = inflateInit2 (&Stream, -MAX_WBITS); - - if (err != Z_OK) - { - I_Error ("FileReaderZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); - } -} - -FileReaderZ::~FileReaderZ () -{ - inflateEnd (&Stream); -} - -long FileReaderZ::Read (void *buffer, long len) -{ - int err; - - Stream.next_out = (Bytef *)buffer; - Stream.avail_out = len; - - do - { - err = inflate (&Stream, Z_SYNC_FLUSH); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == Z_OK && Stream.avail_out != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - I_Error ("Corrupt zlib stream"); - } - - if (Stream.avail_out != 0) - { - I_Error ("Ran out of data in zlib stream"); - } - - return len - Stream.avail_out; -} - -void FileReaderZ::FillBuffer () -{ - long numread = File.Read (InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = InBuff; - Stream.avail_in = numread; -} - -//========================================================================== -// -// FileReaderZ -// -// The bzip2 wrapper -// reads data from a libbzip2 compressed stream -// -//========================================================================== - -FileReaderBZ2::FileReaderBZ2 (FileReader &file) -: File(file), SawEOF(false) -{ - int err; - - FillBuffer (); - - Stream.bzalloc = NULL; - Stream.bzfree = NULL; - Stream.opaque = NULL; - - err = BZ2_bzDecompressInit(&Stream, 0, 0); - - if (err != BZ_OK) - { - I_Error ("FileReaderBZ2: bzDecompressInit failed: %d\n", err); - } -} - -FileReaderBZ2::~FileReaderBZ2 () -{ - BZ2_bzDecompressEnd (&Stream); -} - -long FileReaderBZ2::Read (void *buffer, long len) -{ - int err; - - Stream.next_out = (char *)buffer; - Stream.avail_out = len; - - do - { - err = BZ2_bzDecompress(&Stream); - if (Stream.avail_in == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == BZ_OK && Stream.avail_out != 0); - - if (err != BZ_OK && err != BZ_STREAM_END) - { - I_Error ("Corrupt bzip2 stream"); - } - - if (Stream.avail_out != 0) - { - I_Error ("Ran out of data in bzip2 stream"); - } - - return len - Stream.avail_out; -} - -void FileReaderBZ2::FillBuffer () -{ - long numread = File.Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.next_in = (char *)InBuff; - Stream.avail_in = numread; -} - -//========================================================================== -// -// bz_internal_error -// -// libbzip2 wants this, since we build it with BZ_NO_STDIO set. -// -//========================================================================== - -extern "C" void bz_internal_error (int errcode) -{ - I_FatalError("libbzip2: internal error number %d\n", errcode); -} - -//========================================================================== -// -// FileReaderLZMA -// -// The lzma wrapper -// reads data from a LZMA compressed stream -// -//========================================================================== - -// This is retarded but necessary to work around the inclusion of windows.h in recent -// LZMA versions, meaning it's no longer possible to include the LZMA headers in files.h. -// As a result we cannot declare the CLzmaDec member in the header so we work around -// it my wrapping it into another struct that can be declared anonymously in the header. -struct FileReaderLZMA::StreamPointer -{ - CLzmaDec Stream; -}; - -static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); } -static void SzFree(ISzAllocPtr, void *address) { free(address); } -ISzAlloc g_Alloc = { SzAlloc, SzFree }; - -FileReaderLZMA::FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip) -: File(file), SawEOF(false) -{ - uint8_t header[4 + LZMA_PROPS_SIZE]; - int err; - - assert(zip == true); - - Size = uncompressed_size; - OutProcessed = 0; - - // Read zip LZMA properties header - if (File.Read(header, sizeof(header)) < (long)sizeof(header)) - { - I_Error("FileReaderLZMA: File too shart\n"); - } - if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) - { - I_Error("FileReaderLZMA: LZMA props size is %d (expected %d)\n", - header[2] + header[3] * 256, LZMA_PROPS_SIZE); - } - - FillBuffer(); - - Streamp = new StreamPointer; - LzmaDec_Construct(&Streamp->Stream); - err = LzmaDec_Allocate(&Streamp->Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); - - if (err != SZ_OK) - { - I_Error("FileReaderLZMA: LzmaDec_Allocate failed: %d\n", err); - } - - LzmaDec_Init(&Streamp->Stream); -} - -FileReaderLZMA::~FileReaderLZMA () -{ - LzmaDec_Free(&Streamp->Stream, &g_Alloc); - delete Streamp; -} - -long FileReaderLZMA::Read (void *buffer, long len) -{ - int err; - Byte *next_out = (Byte *)buffer; - - do - { - ELzmaFinishMode finish_mode = LZMA_FINISH_ANY; - ELzmaStatus status; - size_t out_processed = len; - size_t in_processed = InSize; - - err = LzmaDec_DecodeToBuf(&Streamp->Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); - InPos += in_processed; - InSize -= in_processed; - next_out += out_processed; - len = (long)(len - out_processed); - if (err != SZ_OK) - { - I_Error ("Corrupt LZMA stream"); - } - if (in_processed == 0 && out_processed == 0) - { - if (status != LZMA_STATUS_FINISHED_WITH_MARK) - { - I_Error ("Corrupt LZMA stream"); - } - } - if (InSize == 0 && !SawEOF) - { - FillBuffer (); - } - } while (err == SZ_OK && len != 0); - - if (err != Z_OK && err != Z_STREAM_END) - { - I_Error ("Corrupt LZMA stream"); - } - - if (len != 0) - { - I_Error ("Ran out of data in LZMA stream"); - } - - return (long)(next_out - (Byte *)buffer); -} - -void FileReaderLZMA::FillBuffer () -{ - long numread = File.Read(InBuff, BUFF_SIZE); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - InPos = 0; - InSize = numread; -} - -//========================================================================== -// -// MemoryReader -// -// reads data from a block of memory -// -//========================================================================== - -MemoryReader::MemoryReader (const char *buffer, long length) -{ - bufptr=buffer; - Length=length; - FilePos=0; -} - -MemoryReader::~MemoryReader () -{ -} - -long MemoryReader::Tell () const -{ - return FilePos; -} - -long MemoryReader::Seek (long offset, int origin) -{ - switch (origin) - { - case SEEK_CUR: - offset+=FilePos; - break; - - case SEEK_END: - offset+=Length; - break; - - } - FilePos=clamp(offset,0,Length); - return 0; -} - -long MemoryReader::Read (void *buffer, long len) -{ - if (len>Length-FilePos) len=Length-FilePos; - if (len<0) len=0; - memcpy(buffer,bufptr+FilePos,len); - FilePos+=len; - return len; -} - -char *MemoryReader::Gets(char *strbuf, int len) -{ - return GetsFromBuffer(bufptr, strbuf, len); -} - //========================================================================== // // MemoryArrayReader @@ -561,57 +314,88 @@ char *MemoryReader::Gets(char *strbuf, int len) // //========================================================================== -MemoryArrayReader::MemoryArrayReader (const char *buffer, long length) +class MemoryArrayReader : public MemoryReader { - if (length > 0) + TArray buf; + +public: + MemoryArrayReader(const char *buffer, long length) { - buf.Resize(length); - memcpy(&buf[0], buffer, length); + if (length > 0) + { + buf.Resize(length); + memcpy(&buf[0], buffer, length); + } + Length = length; + FilePos = 0; + bufptr = (const char *)&buf[0]; } - Length = length; - FilePos=0; -} -MemoryArrayReader::~MemoryArrayReader () + TArray &GetArray() { return buf; } + + void UpdateLength() { Length = buf.Size(); } +}; + + + +//========================================================================== +// +// FileReader +// +// this wraps the different reader types in an object with value semantics. +// +//========================================================================== + +bool FileRdr::OpenFile(const char *filename, FileRdr::Size start, FileRdr::Size length) { + auto reader = new StdFileReader; + if (!reader->Open(filename, (long)start, (long)length)) return false; + Close(); + mReader = reader; + return true; } -long MemoryArrayReader::Tell () const +bool FileRdr::OpenFilePart(FileRdr &parent, FileRdr::Size start, FileRdr::Size length) { - return FilePos; + auto reader = new FileReaderRedirect(parent, (long)start, (long)length); + Close(); + mReader = reader; + return true; } -long MemoryArrayReader::Seek (long offset, int origin) +bool FileRdr::OpenMemory(const void *mem, FileRdr::Size length) { - switch (origin) - { - case SEEK_CUR: - offset+=FilePos; - break; - - case SEEK_END: - offset+=Length; - break; - - } - FilePos=clamp(offset,0,Length); - return 0; + Close(); + mReader = new MemoryReader((const char *)mem, (long)length); + return true; } -long MemoryArrayReader::Read (void *buffer, long len) +bool FileRdr::OpenMemoryArray(const void *mem, FileRdr::Size length) { - if (len>Length-FilePos) len=Length-FilePos; - if (len<0) len=0; - memcpy(buffer,&buf[FilePos],len); - FilePos+=len; - return len; + Close(); + mReader = new MemoryArrayReader((const char *)mem, (long)length); + return true; } -char *MemoryArrayReader::Gets(char *strbuf, int len) +bool FileRdr::OpenMemoryArray(std::function&)> getter) { - return GetsFromBuffer((char*)&buf[0], strbuf, len); + auto reader = new MemoryArrayReader(nullptr, 0); + if (getter(reader->GetArray())) + { + Close(); + reader->UpdateLength(); + mReader = reader; + return true; + } + else + { + // This will keep the old buffer, if one existed + delete reader; + return false; + } } + //========================================================================== // // FileWriter (the motivation here is to have a buffer writing subclass) @@ -671,7 +455,6 @@ long FileWriter::Seek(long offset, int mode) } } - size_t FileWriter::Printf(const char *fmt, ...) { va_list ap; @@ -689,52 +472,3 @@ size_t BufferWriter::Write(const void *buffer, size_t len) memcpy(&mBuffer[ofs], buffer, len); return len; } - - -////////////////////////////////////// -// -// The new wrapper -// -////////////////////////////////////// - -bool FileRdr::OpenFile(const char *filename) -{ - auto reader = new FileReader; - if (!reader->Open(filename)) return false; - Close(); - mReader = reader; - return true; -} - -bool FileRdr::OpenMemory(const void *mem, FileRdr::Size length) -{ - Close(); - mReader = new MemoryReader((const char *)mem, (long)length); - return true; -} - -bool FileRdr::OpenMemoryArray(const void *mem, FileRdr::Size length) -{ - Close(); - mReader = new MemoryArrayReader((const char *)mem, (long)length); - return true; -} - -bool FileRdr::OpenMemoryArray(std::function&)> getter) -{ - auto reader = new MemoryArrayReader(nullptr, 0); - if (getter(reader->GetArray())) - { - Close(); - reader->UpdateLength(); - mReader = reader; - return true; - } - else - { - // This will keep the old - delete reader; - return false; - } -} - diff --git a/src/files.h b/src/files.h index dc7022882..c567baac8 100644 --- a/src/files.h +++ b/src/files.h @@ -43,411 +43,197 @@ #include "doomtype.h" #include "m_swap.h" -class FileReaderBase +// Zip compression methods, extended by some internal types to be passed to FileReader::OpenDecompressor +enum +{ + METHOD_STORED = 0, + METHOD_SHRINK = 1, + METHOD_IMPLODE = 6, + METHOD_DEFLATE = 8, + METHOD_BZIP2 = 12, + METHOD_LZMA = 14, + METHOD_PPMD = 98, + METHOD_LZSS = 1337, // not used in Zips - this is for Console Doom compression + METHOD_ZLIB = 1338, // Zlib stream with header, used by compressed nodes. +}; + +class FileReaderInterface { public: - virtual ~FileReaderBase() {} + long Length = -1; + virtual ~FileReaderInterface() {} + virtual long Tell () const = 0; + virtual long Seek (long offset, int origin) = 0; virtual long Read (void *buffer, long len) = 0; - - FileReaderBase &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBase &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBase &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBase &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBase &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderBase &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -}; - - -class FileReader : public FileReaderBase -{ -protected: - FILE *openfd(const char *filename); -public: - FileReader (); - FileReader (const char *filename); - FileReader (FILE *file); - FileReader (FILE *file, long length); - bool Open (const char *filename); - void Close(); - virtual ~FileReader (); - - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); + virtual char *Gets(char *strbuf, int len) = 0; + virtual const char *GetBuffer() const { return nullptr; } long GetLength () const { return Length; } - - // If you use the underlying FILE without going through this class, - // you must call ResetFilePtr() before using this class again. - void ResetFilePtr (); - - FILE *GetFile () const { return File; } - virtual const char *GetBuffer() const { return NULL; } - - FileReader &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReader &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReader &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReader &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReader &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - -protected: - FileReader (const FileReader &other, long length); - - char *GetsFromBuffer(const char * bufptr, char *strbuf, int len); - - FILE *File; - long Length; - long StartPos; - long FilePos; - -private: - long CalcFileLen () const; -protected: - bool CloseOnDestruct; }; -// This will need a cleaner implementation once the outer interface is done. -// As a first step this only needs to work properly in the non-error case. -class FileReaderRedirect : public FileReader +class MemoryReader : public FileReaderInterface { - FileReader *mReader; +protected: + const char * bufptr = nullptr; + long FilePos = 0; + + MemoryReader() + {} + public: - FileReaderRedirect(FileReader *parent, long start, long length) + MemoryReader(const char *buffer, long length) { - mReader = parent; - StartPos = start; + bufptr = buffer; Length = length; + FilePos = 0; } - virtual long Tell() const - { - auto l = mReader->Tell() - StartPos; - if (l < StartPos || l >= StartPos + Length) return -1; // out of scope - return l - StartPos; - } - - virtual long Seek(long offset, int origin) - { - switch (origin) - { - case SEEK_SET: - offset += StartPos; - break; - - case SEEK_END: - offset += StartPos + Length; - break; - - case SEEK_CUR: - offset += mReader->Tell(); - break; - } - if (offset < StartPos || offset >= StartPos + Length) return -1; // out of scope - return mReader->Seek(offset, SEEK_SET); - } - - virtual long Read(void *buffer, long len) - { - // This still needs better range checks - return mReader->Read(buffer, len); - } - virtual char *Gets(char *strbuf, int len) - { - return mReader->Gets(strbuf, len); - } - - long GetLength() const { return Length; } + long Tell() const override; + long Seek(long offset, int origin) override; + long Read(void *buffer, long len) override; + char *Gets(char *strbuf, int len) override; + virtual const char *GetBuffer() const override { return bufptr; } }; -// Wraps around a FileReader to decompress a zlib stream -class FileReaderZ : public FileReaderBase +class FileRdr // this is just a temporary name, until the old FileReader hierarchy can be made private. { -public: - FileReaderZ (FileReader &file, bool zip=false); - ~FileReaderZ (); + FileReaderInterface *mReader = nullptr; - virtual long Read (void *buffer, long len); - - FileReaderZ &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderZ &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderZ &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderZ &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderZ &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderZ &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - z_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderZ &operator= (const FileReaderZ &) { return *this; } -}; - -// Wraps around a FileReader to decompress a bzip2 stream -class FileReaderBZ2 : public FileReaderBase -{ -public: - FileReaderBZ2 (FileReader &file); - ~FileReaderBZ2 (); - - long Read (void *buffer, long len); - - FileReaderBZ2 &operator>> (uint8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBZ2 &operator>> (int8_t &v) - { - Read (&v, 1); - return *this; - } - - FileReaderBZ2 &operator>> (uint16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBZ2 &operator>> (int16_t &v) - { - Read (&v, 2); - v = LittleShort(v); - return *this; - } - - FileReaderBZ2 &operator>> (uint32_t &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - - FileReaderBZ2 &operator>> (int &v) - { - Read (&v, 4); - v = LittleLong(v); - return *this; - } - -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - bz_stream Stream; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderBZ2 &operator= (const FileReaderBZ2 &) { return *this; } -}; - -// Wraps around a FileReader to decompress a lzma stream -class FileReaderLZMA : public FileReaderBase -{ - struct StreamPointer; + FileRdr(const FileRdr &r) = delete; + FileRdr &operator=(const FileRdr &r) = delete; public: - FileReaderLZMA (FileReader &file, size_t uncompressed_size, bool zip); - ~FileReaderLZMA (); - - long Read (void *buffer, long len); - - FileReaderLZMA &operator>> (uint8_t &v) + enum ESeek { - Read (&v, 1); + SeekSet = SEEK_SET, + SeekCur = SEEK_CUR, + SeekEnd = SEEK_END + }; + + typedef ptrdiff_t Size; // let's not use 'long' here. + + FileRdr() {} + + // These two functions are only needed as long as the FileReader has not been fully replaced throughout the code. + explicit FileRdr(FileReaderInterface *r) + { + mReader = r; + } + + FileRdr(FileRdr &&r) + { + mReader = r.mReader; + r.mReader = nullptr; + } + + FileRdr& operator =(FileRdr &&r) + { + Close(); + mReader = r.mReader; + r.mReader = nullptr; return *this; } - FileReaderLZMA &operator>> (int8_t &v) + + ~FileRdr() { - Read (&v, 1); + Close(); + } + + bool isOpen() const + { + return mReader != nullptr; + } + + void Close() + { + if (mReader != nullptr) delete mReader; + mReader = nullptr; + } + + bool OpenFile(const char *filename, Size start = 0, Size length = -1); + bool OpenFilePart(FileRdr &parent, Size start, Size length); + bool OpenMemory(const void *mem, Size length); // read directly from the buffer + bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer. + bool OpenMemoryArray(std::function&)> getter); // read contents to a buffer and return a reader to it + bool OpenDecompressor(FileRdr &parent, Size length, int method, bool seekable); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used. + + Size Tell() const + { + return mReader->Tell(); + } + + Size Seek(Size offset, ESeek origin) + { + return mReader->Seek((long)offset, origin); + } + + Size Read(void *buffer, Size len) + { + return mReader->Read(buffer, (long)len); + } + + char *Gets(char *strbuf, Size len) + { + return mReader->Gets(strbuf, (int)len); + } + + const char *GetBuffer() + { + return mReader->GetBuffer(); + } + + Size GetLength() const + { + return mReader->GetLength(); + } + + // Note: These need to go because they are fundamentally unsafe to use on a binary stream. + FileRdr &operator>> (uint8_t &v) + { + mReader->Read(&v, 1); return *this; } - FileReaderLZMA &operator>> (uint16_t &v) + FileRdr &operator>> (int8_t &v) { - Read (&v, 2); + mReader->Read(&v, 1); + return *this; + } + + FileRdr &operator>> (uint16_t &v) + { + mReader->Read(&v, 2); v = LittleShort(v); return *this; } - FileReaderLZMA &operator>> (int16_t &v) + FileRdr &operator>> (int16_t &v) { - Read (&v, 2); + mReader->Read(&v, 2); v = LittleShort(v); return *this; } - FileReaderLZMA &operator>> (uint32_t &v) + FileRdr &operator>> (uint32_t &v) { - Read (&v, 4); + mReader->Read(&v, 4); v = LittleLong(v); return *this; } - FileReaderLZMA &operator>> (int &v) + FileRdr &operator>> (int32_t &v) { - Read (&v, 4); + mReader->Read(&v, 4); v = LittleLong(v); return *this; } -private: - enum { BUFF_SIZE = 4096 }; - - FileReader &File; - bool SawEOF; - StreamPointer *Streamp; // anonymous pointer to LKZA decoder struct - to avoid including the LZMA headers globally - size_t Size; - size_t InPos, InSize; - size_t OutProcessed; - uint8_t InBuff[BUFF_SIZE]; - - void FillBuffer (); - - FileReaderLZMA &operator= (const FileReaderLZMA &) { return *this; } + friend class FWadCollection; }; -class MemoryReader : public FileReader -{ -public: - MemoryReader (const char *buffer, long length); - ~MemoryReader (); - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); - virtual const char *GetBuffer() const { return bufptr; } - -protected: - const char * bufptr; -}; - -class MemoryArrayReader : public FileReader -{ -public: - MemoryArrayReader (const char *buffer, long length); - ~MemoryArrayReader (); - - virtual long Tell () const; - virtual long Seek (long offset, int origin); - virtual long Read (void *buffer, long len); - virtual char *Gets(char *strbuf, int len); - virtual const char *GetBuffer() const { return (char*)&buf[0]; } - TArray &GetArray() { return buf; } - - void UpdateLength() { Length = buf.Size(); } - -protected: - TArray buf; -}; class FileWriter @@ -491,138 +277,4 @@ public: TArray *GetBuffer() { return &mBuffer; } }; - - - - -class FileRdr // this is just a temporary name, until the old FileReader hierarchy can be made private. -{ - FileReader *mReader = nullptr; - - FileRdr(const FileRdr &r) = delete; - FileRdr &operator=(const FileRdr &r) = delete; -public: - enum ESeek - { - SeekSet = SEEK_SET, - SeekCur = SEEK_CUR, - SeekEnd = SEEK_END - }; - - typedef ptrdiff_t Size; // let's not use 'long' here. - - FileRdr() {} - - // These two functions are only needed as long as the FileReader has not been fully replaced throughout the code. - explicit FileRdr(FileReader *r) - { - mReader = r; - } - FileReader *Reader() - { - auto r = mReader; - mReader = nullptr; - return r; - } - - FileRdr(FileRdr &&r) - { - mReader = r.mReader; - r.mReader = nullptr; - } - - FileRdr& operator =(FileRdr &&r) - { - Close(); - mReader = r.mReader; - r.mReader = nullptr; - return *this; - } - - - ~FileRdr() - { - Close(); - } - - bool isOpen() const - { - return mReader != nullptr; - } - - void Close() - { - if (mReader != nullptr) delete mReader; - mReader = nullptr; - } - - bool OpenFile(const char *filename); - bool OpenFilePart(FileReader *parent, Size start, Size length); // later - bool OpenMemory(const void *mem, Size length); // read directly from the buffer - bool OpenMemoryArray(const void *mem, Size length); // read from a copy of the buffer. - bool OpenMemoryArray(std::function&)> getter); // read contents to a buffer and return a reader to it - - Size Tell() const - { - return mReader->Tell(); - } - - Size Seek(Size offset, ESeek origin) - { - return mReader->Seek((long)offset, origin); - } - - Size Read(void *buffer, Size len) - { - return mReader->Read(buffer, (long)len); - } - - char *Gets(char *strbuf, Size len) - { - return mReader->Gets(strbuf, (int)len); - } - - Size GetLength() const - { - return mReader->GetLength(); - } - - FileRdr &operator>> (uint8_t &v) - { - mReader->Read(&v, 1); - return *this; - } - - FileRdr &operator>> (int8_t &v) - { - mReader->Read(&v, 1); - return *this; - } - - FileRdr &operator>> (uint16_t &v) - { - mReader->Read(&v, 2); - v = LittleShort(v); - return *this; - } - - FileRdr &operator>> (int16_t &v) - { - mReader->Read(&v, 2); - v = LittleShort(v); - return *this; - } - - FileRdr &operator>> (uint32_t &v) - { - mReader->Read(&v, 4); - v = LittleLong(v); - return *this; - } - - friend class FWadCollection; -}; - - - #endif diff --git a/src/files_decompress.cpp b/src/files_decompress.cpp new file mode 100644 index 000000000..4b295fe38 --- /dev/null +++ b/src/files_decompress.cpp @@ -0,0 +1,607 @@ +/* +** files.cpp +** Implements classes for reading from files or memory blocks +** +**--------------------------------------------------------------------------- +** Copyright 1998-2008 Randy Heit +** Copyright 2005-2008 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +// This also pulls in windows.h +#include "LzmaDec.h" + +#include "files.h" +#include "i_system.h" +#include "templates.h" +#include "m_misc.h" + + +class DecompressorBase : public FileReaderInterface +{ +public: + // These do not work but need to be defined to satisfy the FileReader interface + long Tell () const override + { + I_Error("Cannot get position of decompressor stream"); + return 0; + } + virtual long Seek (long offset, int origin) override + { + I_Error("Cannot seek in decompressor stream"); + return 0; + } + virtual char *Gets(char *strbuf, int len) override + { + I_Error("Cannot use Gets on decompressor stream"); + return nullptr; + } +}; + +//========================================================================== +// +// DecompressorZ +// +// The zlib wrapper +// reads data from a ZLib compressed stream +// +//========================================================================== + +class DecompressorZ : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileRdr &File; + bool SawEOF; + z_stream Stream; + uint8_t InBuff[BUFF_SIZE]; + +public: + DecompressorZ (FileRdr &file, bool zip) + : File(file), SawEOF(false) + { + int err; + + FillBuffer (); + + Stream.zalloc = Z_NULL; + Stream.zfree = Z_NULL; + + if (!zip) err = inflateInit (&Stream); + else err = inflateInit2 (&Stream, -MAX_WBITS); + + if (err != Z_OK) + { + I_Error ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars()); + } + } + + ~DecompressorZ () + { + inflateEnd (&Stream); + } + + long Read (void *buffer, long len) override + { + int err; + + Stream.next_out = (Bytef *)buffer; + Stream.avail_out = len; + + do + { + err = inflate (&Stream, Z_SYNC_FLUSH); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == Z_OK && Stream.avail_out != 0); + + if (err != Z_OK && err != Z_STREAM_END) + { + I_Error ("Corrupt zlib stream"); + } + + if (Stream.avail_out != 0) + { + I_Error ("Ran out of data in zlib stream"); + } + + return len - Stream.avail_out; + } + + void FillBuffer () + { + auto numread = File.Read (InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.next_in = InBuff; + Stream.avail_in = (uInt)numread; + } +}; + + +//========================================================================== +// +// DecompressorZ +// +// The bzip2 wrapper +// reads data from a libbzip2 compressed stream +// +//========================================================================== + +class DecompressorBZ2 : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileRdr &File; + bool SawEOF; + bz_stream Stream; + uint8_t InBuff[BUFF_SIZE]; + +public: + DecompressorBZ2 (FileRdr &file) + : File(file), SawEOF(false) + { + int err; + + FillBuffer (); + + Stream.bzalloc = NULL; + Stream.bzfree = NULL; + Stream.opaque = NULL; + + err = BZ2_bzDecompressInit(&Stream, 0, 0); + + if (err != BZ_OK) + { + I_Error ("DecompressorBZ2: bzDecompressInit failed: %d\n", err); + } + } + + ~DecompressorBZ2 () + { + BZ2_bzDecompressEnd (&Stream); + } + + long Read (void *buffer, long len) override + { + int err; + + Stream.next_out = (char *)buffer; + Stream.avail_out = len; + + do + { + err = BZ2_bzDecompress(&Stream); + if (Stream.avail_in == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == BZ_OK && Stream.avail_out != 0); + + if (err != BZ_OK && err != BZ_STREAM_END) + { + I_Error ("Corrupt bzip2 stream"); + } + + if (Stream.avail_out != 0) + { + I_Error ("Ran out of data in bzip2 stream"); + } + + return len - Stream.avail_out; + } + + void FillBuffer () + { + auto numread = File.Read(InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.next_in = (char *)InBuff; + Stream.avail_in = (unsigned)numread; + } + +}; + +//========================================================================== +// +// bz_internal_error +// +// libbzip2 wants this, since we build it with BZ_NO_STDIO set. +// +//========================================================================== + +extern "C" void bz_internal_error (int errcode) +{ + I_FatalError("libbzip2: internal error number %d\n", errcode); +} + +//========================================================================== +// +// DecompressorLZMA +// +// The lzma wrapper +// reads data from a LZMA compressed stream +// +//========================================================================== + +static void *SzAlloc(ISzAllocPtr, size_t size) { return malloc(size); } +static void SzFree(ISzAllocPtr, void *address) { free(address); } +ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +// Wraps around a Decompressor to decompress a lzma stream +class DecompressorLZMA : public DecompressorBase +{ + enum { BUFF_SIZE = 4096 }; + + FileRdr &File; + bool SawEOF; + CLzmaDec Stream; + size_t Size; + size_t InPos, InSize; + size_t OutProcessed; + uint8_t InBuff[BUFF_SIZE]; + +public: + + DecompressorLZMA (FileRdr &file, size_t uncompressed_size) + : File(file), SawEOF(false) + { + uint8_t header[4 + LZMA_PROPS_SIZE]; + int err; + + Size = uncompressed_size; + OutProcessed = 0; + + // Read zip LZMA properties header + if (File.Read(header, sizeof(header)) < (long)sizeof(header)) + { + I_Error("DecompressorLZMA: File too short\n"); + } + if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE) + { + I_Error("DecompressorLZMA: LZMA props size is %d (expected %d)\n", + header[2] + header[3] * 256, LZMA_PROPS_SIZE); + } + + FillBuffer(); + + LzmaDec_Construct(&Stream); + err = LzmaDec_Allocate(&Stream, header + 4, LZMA_PROPS_SIZE, &g_Alloc); + + if (err != SZ_OK) + { + I_Error("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err); + } + + LzmaDec_Init(&Stream); + } + + ~DecompressorLZMA () + { + LzmaDec_Free(&Stream, &g_Alloc); + } + + long Read (void *buffer, long len) override + { + int err; + Byte *next_out = (Byte *)buffer; + + do + { + ELzmaFinishMode finish_mode = LZMA_FINISH_ANY; + ELzmaStatus status; + size_t out_processed = len; + size_t in_processed = InSize; + + err = LzmaDec_DecodeToBuf(&Stream, next_out, &out_processed, InBuff + InPos, &in_processed, finish_mode, &status); + InPos += in_processed; + InSize -= in_processed; + next_out += out_processed; + len = (long)(len - out_processed); + if (err != SZ_OK) + { + I_Error ("Corrupt LZMA stream"); + } + if (in_processed == 0 && out_processed == 0) + { + if (status != LZMA_STATUS_FINISHED_WITH_MARK) + { + I_Error ("Corrupt LZMA stream"); + } + } + if (InSize == 0 && !SawEOF) + { + FillBuffer (); + } + } while (err == SZ_OK && len != 0); + + if (err != Z_OK && err != Z_STREAM_END) + { + I_Error ("Corrupt LZMA stream"); + } + + if (len != 0) + { + I_Error ("Ran out of data in LZMA stream"); + } + + return (long)(next_out - (Byte *)buffer); + } + + void FillBuffer () + { + auto numread = File.Read(InBuff, BUFF_SIZE); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + InPos = 0; + InSize = numread; + } + +}; + +//========================================================================== +// +// Console Doom LZSS wrapper. +// +//========================================================================== + +class DecompressorLZSS : public DecompressorBase +{ + enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; + + FileRdr &File; + bool SawEOF; + uint8_t InBuff[BUFF_SIZE]; + + enum StreamState + { + STREAM_EMPTY, + STREAM_BITS, + STREAM_FLUSH, + STREAM_FINAL + }; + struct + { + StreamState State; + + uint8_t *In; + unsigned int AvailIn; + unsigned int InternalOut; + + uint8_t CFlags, Bits; + + uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE]; + const uint8_t *WindowData; + uint8_t *InternalBuffer; + } Stream; + + void FillBuffer() + { + if(Stream.AvailIn) + memmove(InBuff, Stream.In, Stream.AvailIn); + + auto numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); + + if (numread < BUFF_SIZE) + { + SawEOF = true; + } + Stream.In = InBuff; + Stream.AvailIn = (unsigned)numread+Stream.AvailIn; + } + + // Reads a flag byte. + void PrepareBlocks() + { + assert(Stream.InternalBuffer == Stream.WindowData); + Stream.CFlags = *Stream.In++; + --Stream.AvailIn; + Stream.Bits = 0xFF; + Stream.State = STREAM_BITS; + } + + // Reads the next chunk in the block. Returns true if successful and + // returns false if it ran out of input data. + bool UncompressBlock() + { + if(Stream.CFlags & 1) + { + // Check to see if we have enough input + if(Stream.AvailIn < 2) + return false; + Stream.AvailIn -= 2; + + uint16_t pos = BigShort(*(uint16_t*)Stream.In); + uint8_t len = (pos & 0xF)+1; + pos >>= 4; + Stream.In += 2; + if(len == 1) + { + // We've reached the end of the stream. + Stream.State = STREAM_FINAL; + return true; + } + + const uint8_t* copyStart = Stream.InternalBuffer-pos-1; + + // Complete overlap: Single byte repeated + if(pos == 0) + memset(Stream.InternalBuffer, *copyStart, len); + // No overlap: One copy + else if(pos >= len) + memcpy(Stream.InternalBuffer, copyStart, len); + else + { + // Partial overlap: Copy in 2 or 3 chunks. + do + { + unsigned int copy = MIN(len, pos+1); + memcpy(Stream.InternalBuffer, copyStart, copy); + Stream.InternalBuffer += copy; + Stream.InternalOut += copy; + len -= copy; + pos += copy; // Increase our position since we can copy twice as much the next round. + } + while(len); + } + + Stream.InternalOut += len; + Stream.InternalBuffer += len; + } + else + { + // Uncompressed byte. + *Stream.InternalBuffer++ = *Stream.In++; + --Stream.AvailIn; + ++Stream.InternalOut; + } + + Stream.CFlags >>= 1; + Stream.Bits >>= 1; + + // If we're done with this block, flush the output + if(Stream.Bits == 0) + Stream.State = STREAM_FLUSH; + + return true; + } + +public: + DecompressorLZSS(FileRdr &file) : File(file), SawEOF(false) + { + Stream.State = STREAM_EMPTY; + Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; + Stream.InternalOut = 0; + Stream.AvailIn = 0; + + FillBuffer(); + } + + ~DecompressorLZSS() + { + } + + long Read(void *buffer, long len) override + { + + uint8_t *Out = (uint8_t*)buffer; + long AvailOut = len; + + do + { + while(Stream.AvailIn) + { + if(Stream.State == STREAM_EMPTY) + PrepareBlocks(); + else if(Stream.State == STREAM_BITS && !UncompressBlock()) + break; + else + break; + } + + unsigned int copy = MIN(Stream.InternalOut, AvailOut); + if(copy > 0) + { + memcpy(Out, Stream.WindowData, copy); + Out += copy; + AvailOut -= copy; + + // Slide our window + memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy); + Stream.InternalBuffer -= copy; + Stream.InternalOut -= copy; + } + + if(Stream.State == STREAM_FINAL) + break; + + if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH) + Stream.State = STREAM_EMPTY; + + if(Stream.AvailIn < 2) + FillBuffer(); + } + while(AvailOut && Stream.State != STREAM_FINAL); + + assert(AvailOut == 0); + return (long)(Out - (uint8_t*)buffer); + } +}; + + +bool FileRdr::OpenDecompressor(FileRdr &parent, Size length, int method, bool seekable) +{ + DecompressorBase *dec = nullptr; + switch (method) + { + case METHOD_DEFLATE: + case METHOD_ZLIB: + dec = new DecompressorZ(parent, method == METHOD_DEFLATE); + break; + + case METHOD_BZIP2: + dec = new DecompressorBZ2(parent); + break; + + case METHOD_LZMA: + dec = new DecompressorLZMA(parent, length); + break; + + case METHOD_LZSS: + dec = new DecompressorLZSS(parent); + break; + + // todo: METHOD_IMPLODE, METHOD_SHRINK + default: + return false; + } + dec->Length = (long)length; + if (!seekable) + { + Close(); + mReader = dec; + return true; + } + else + { + // todo: create a wrapper. for now this fails + delete dec; + return false; + } +} diff --git a/src/g_game.cpp b/src/g_game.cpp index 836805677..e61c440fd 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1930,7 +1930,7 @@ void G_DoLoadGame () hidecon = gameaction == ga_loadgamehidecon; gameaction = ga_nothing; - std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), nullptr, true, true)); + std::unique_ptr resfile(FResourceFile::OpenResourceFile(savename.GetChars(), true, true)); if (resfile == nullptr) { Printf ("Could not read savegame '%s'\n", savename.GetChars()); @@ -2372,7 +2372,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio savegame_content[2].Clean(); // Check whether the file is ok by trying to open it. - FResourceFile *test = FResourceFile::OpenResourceFile(filename, nullptr, true); + FResourceFile *test = FResourceFile::OpenResourceFile(filename, true); if (test != nullptr) { delete test; diff --git a/src/md5.cpp b/src/md5.cpp index e8257b597..f5d8ba604 100644 --- a/src/md5.cpp +++ b/src/md5.cpp @@ -269,8 +269,8 @@ CCMD (md5sum) } for (int i = 1; i < argv.argc(); ++i) { - FileReader fr; - if (!fr.Open(argv[i])) + FileRdr fr; + if (!fr.OpenFile(argv[i])) { Printf("%s: %s\n", argv[i], strerror(errno)); } diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index d66a3ab07..424073ba5 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -174,7 +174,7 @@ void FSavegameManager::ReadSaveStrings() // I_FindName only returns the file's name and not its full path FString filepath = G_BuildSaveName(I_FindName(&c_file), -1); - FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, nullptr, true, true); + FResourceFile *savegame = FResourceFile::OpenResourceFile(filepath, true, true); if (savegame != nullptr) { bool oldVer = false; @@ -469,7 +469,7 @@ unsigned FSavegameManager::ExtractSaveData(int index) (node = SaveGames[index]) && !node->Filename.IsEmpty() && !node->bOldVersion && - (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), nullptr, true)) != nullptr) + (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) { FResourceLump *info = resf->FindLump("info.json"); if (info == nullptr) diff --git a/src/p_conversation.h b/src/p_conversation.h index 620b6f4e8..90423ffe3 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -77,7 +77,7 @@ void P_ResumeConversation (); void P_ConversationCommand (int netcode, int player, uint8_t **stream); -class FileReader; +class FileRdr; bool P_ParseUSDF(int lumpnum, FileRdr &lump, int lumplen); diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 096eaf904..09e9ef28d 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -215,18 +215,18 @@ bool P_CheckForGLNodes() static int firstglvertex; static bool format5; -static bool LoadGLVertexes(FileReader * lump) +static bool LoadGLVertexes(FileRdr &lump) { uint8_t *gldata; int i; firstglvertex = level.vertexes.Size(); - int gllen=lump->GetLength(); + auto gllen=lump.GetLength(); gldata = new uint8_t[gllen]; - lump->Seek(0, SEEK_SET); - lump->Read(gldata, gllen); + lump.Seek(0, FileRdr::SeekSet); + lump.Read(gldata, gllen); if (*(int *)gldata == gNd5) { @@ -246,7 +246,7 @@ static bool LoadGLVertexes(FileReader * lump) else format5=false; mapglvertex_t* mgl = (mapglvertex_t *)(gldata + GL_VERT_OFFSET); - unsigned numvertexes = firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t); + unsigned numvertexes = (unsigned)(firstglvertex + (gllen - GL_VERT_OFFSET)/sizeof(mapglvertex_t)); auto oldvertexes = &level.vertexes[0]; level.vertexes.Resize(numvertexes); @@ -293,16 +293,16 @@ static inline int checkGLVertex3(int num) // //========================================================================== -static bool LoadGLSegs(FileReader * lump) +static bool LoadGLSegs(FileRdr &lump) { char *data; int i; line_t *ldef=NULL; - int numsegs = lump->GetLength(); + int numsegs = (int)lump.GetLength(); data= new char[numsegs]; - lump->Seek(0, SEEK_SET); - lump->Read(data, numsegs); + lump.Seek(0, FileRdr::SeekSet); + lump.Read(data, numsegs); auto &segs = level.segs; #ifdef _MSC_VER @@ -437,15 +437,15 @@ static bool LoadGLSegs(FileReader * lump) // //========================================================================== -static bool LoadGLSubsectors(FileReader * lump) +static bool LoadGLSubsectors(FileRdr &lump) { char * datab; int i; - auto numsubsectors = lump->GetLength(); + int numsubsectors = (int)lump.GetLength(); datab = new char[numsubsectors]; - lump->Seek(0, SEEK_SET); - lump->Read(datab, numsubsectors); + lump.Seek(0, FileRdr::SeekSet); + lump.Read(datab, numsubsectors); if (numsubsectors == 0) { @@ -521,7 +521,7 @@ static bool LoadGLSubsectors(FileReader * lump) // //========================================================================== -static bool LoadNodes (FileReader * lump) +static bool LoadNodes (FileRdr &lump) { const int NF_SUBSECTOR = 0x8000; const int GL5_NF_SUBSECTOR = (1 << 31); @@ -534,15 +534,15 @@ static bool LoadNodes (FileReader * lump) if (!format5) { mapnode_t* mn, * basemn; - unsigned numnodes = unsigned(lump->GetLength() / sizeof(mapnode_t)); + unsigned numnodes = unsigned(lump.GetLength() / sizeof(mapnode_t)); if (numnodes == 0) return false; level.nodes.Alloc(numnodes); - lump->Seek(0, SEEK_SET); + lump.Seek(0, FileRdr::SeekSet); basemn = mn = new mapnode_t[numnodes]; - lump->Read(mn, lump->GetLength()); + lump.Read(mn, lump.GetLength()); used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); @@ -594,15 +594,15 @@ static bool LoadNodes (FileReader * lump) else { gl5_mapnode_t* mn, * basemn; - auto numnodes = unsigned(lump->GetLength() / sizeof(gl5_mapnode_t)); + auto numnodes = unsigned(lump.GetLength() / sizeof(gl5_mapnode_t)); if (numnodes == 0) return false; level.nodes.Alloc(numnodes); - lump->Seek(0, SEEK_SET); + lump.Seek(0, FileRdr::SeekSet); basemn = mn = new gl5_mapnode_t[numnodes]; - lump->Read(mn, lump->GetLength()); + lump.Read(mn, lump.GetLength()); used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); @@ -660,7 +660,7 @@ static bool LoadNodes (FileReader * lump) // //========================================================================== -static bool DoLoadGLNodes(FileReader ** lumps) +static bool DoLoadGLNodes(FileRdr * lumps) { int missing = 0; @@ -803,7 +803,7 @@ static int FindGLNodesInFile(FResourceFile * f, const char * label) if (mustcheck) { char check[16]={0}; - FileReader *fr = f->GetLump(i)->GetReader(); + auto fr = f->GetLump(i)->GetReader(); fr->Read(check, 16); if (MatchHeader(label, check)) return i; } @@ -857,7 +857,7 @@ bool P_LoadGLNodes(MapData * map) if (!CheckCachedNodes(map)) { - FileReader *gwalumps[4] = { NULL, NULL, NULL, NULL }; + FileRdr gwalumps[4]; char path[256]; int li; int lumpfile = Wads.GetLumpFile(map->lumpnum); @@ -875,7 +875,7 @@ bool P_LoadGLNodes(MapData * map) // GL nodes are loaded with a WAD for(int i=0;i<4;i++) { - gwalumps[i]=Wads.ReopenLumpNum(li+i+1); + gwalumps[i]=Wads.ReopenLumpReader(li+i+1); } return DoLoadGLNodes(gwalumps); } @@ -889,7 +889,7 @@ bool P_LoadGLNodes(MapData * map) strcpy(ext, ".gwa"); // Todo: Compare file dates - f_gwa = FResourceFile::OpenResourceFile(path, NULL, true); + f_gwa = FResourceFile::OpenResourceFile(path, true); if (f_gwa==NULL) return false; strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(map->lumpnum), 8); @@ -918,8 +918,6 @@ bool P_LoadGLNodes(MapData * map) if (f_gwa != map->resource) delete f_gwa; - for(unsigned int i = 0;i < 4;++i) - delete gwalumps[i]; return result; } else return true; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ece2e301a..8438e4074 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -240,7 +240,7 @@ static int GetMapIndex(const char *mapname, int lastindex, const char *lumpname, MapData *P_OpenMapData(const char * mapname, bool justcheck) { MapData * map = new MapData; - FileReader * wadReader = NULL; + FileRdr * wadReader = nullptr; bool externalfile = !strnicmp(mapname, "file:", 5); if (externalfile) @@ -251,7 +251,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) delete map; return NULL; } - map->resource = FResourceFile::OpenResourceFile(mapname, NULL, true); + map->resource = FResourceFile::OpenResourceFile(mapname, true); wadReader = map->resource->GetReader(); } else @@ -396,7 +396,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) return NULL; } map->lumpnum = lump_wad; - map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), Wads.ReopenLumpNum(lump_wad), true); + map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), Wads.ReopenLumpReader(lump_wad), true); wadReader = map->resource->GetReader(); } } @@ -404,7 +404,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) // Although we're using the resource system, we still want to be sure we're // reading from a wad file. - wadReader->Seek(0, SEEK_SET); + wadReader->Seek(0, FileRdr::SeekSet); wadReader->Read(&id, sizeof(id)); if (id == IWAD_ID || id == PWAD_ID) @@ -412,7 +412,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) char maplabel[9]=""; int index=0; - map->MapLumps[0].Reader = FileRdr(map->resource->GetLump(0)->NewReader()); + map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8); for(uint32_t i = 1; i < map->resource->LumpCount(); i++) @@ -422,7 +422,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) { map->isText = true; - map->MapLumps[ML_TEXTMAP].Reader = FileRdr(map->resource->GetLump(i)->NewReader()); + map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); for(int i = 2;; i++) { @@ -454,7 +454,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) return map; } else continue; - map->MapLumps[index].Reader = FileRdr(map->resource->GetLump(i)->NewReader()); + map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } @@ -486,7 +486,7 @@ MapData *P_OpenMapData(const char * mapname, bool justcheck) maplabel[8]=0; } - map->MapLumps[index].Reader = FileRdr(map->resource->GetLump(i)->NewReader()); + map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } @@ -855,7 +855,7 @@ void P_LoadVertexes (MapData * map) // //=========================================================================== -void P_LoadZSegs (FileReaderBase &data) +void P_LoadZSegs (FileRdr &data) { for (auto &seg : level.segs) { @@ -891,7 +891,7 @@ void P_LoadZSegs (FileReaderBase &data) // //=========================================================================== -void P_LoadGLZSegs (FileReaderBase &data, int type) +void P_LoadGLZSegs (FileRdr &data, int type) { for (unsigned i = 0; i < level.subsectors.Size(); ++i) { @@ -961,7 +961,7 @@ void P_LoadGLZSegs (FileReaderBase &data, int type) // //=========================================================================== -void LoadZNodes(FileReaderBase &data, int glnodes) +void LoadZNodes(FileRdr &data, int glnodes) { // Read extra vertices added during node building uint32_t orgVerts, newVerts; @@ -980,7 +980,7 @@ void LoadZNodes(FileReaderBase &data, int glnodes) } for (i = 0; i < newVerts; ++i) { - fixed_t x, y; + int32_t x, y; data >> x >> y; level.vertexes[i + orgVerts].set(x, y); } @@ -1145,15 +1145,17 @@ void P_LoadZNodes (FileRdr &dalump, uint32_t id) return; } - auto daptr = dalump.Reader(); if (compressed) { - FileReaderZ data (*daptr); - LoadZNodes(data, type); + FileRdr zip; + if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false)) + { + LoadZNodes(zip, type); + } } else { - LoadZNodes(*daptr, type); + LoadZNodes(dalump, type); } } diff --git a/src/resourcefiles/ancientzip.cpp b/src/resourcefiles/ancientzip.cpp index a56d9adeb..8439cc5fb 100644 --- a/src/resourcefiles/ancientzip.cpp +++ b/src/resourcefiles/ancientzip.cpp @@ -70,7 +70,7 @@ if (bs < be) \ c = ReadBuf[bs++]; \ else { \ - be = In->Read(&ReadBuf, sizeof(ReadBuf)); \ + be = (decltype(be))In->Read(&ReadBuf, sizeof(ReadBuf)); \ c = ReadBuf[0]; \ bs = 1; \ } \ @@ -259,7 +259,7 @@ int FZipExploder::DecodeSF(TArray &decoder, int numvals) } int FZipExploder::Explode(unsigned char *out, unsigned int outsize, - FileReader *in, unsigned int insize, + FileRdr &in, unsigned int insize, int flags) { int c, i, minMatchLen = 3, len, dist; @@ -268,7 +268,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, Hold = 0; Bits = 0; - In = in; + In = ∈ InLeft = insize; bs = be = 0; @@ -337,9 +337,9 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize, #define FREE_CODE HSIZE /* 0x2000 (code is unused or was cleared) */ #define HAS_CHILD (HSIZE << 1) /* 0x4000 (code has a child--do not clear) */ -int ShrinkLoop(unsigned char *out, unsigned int outsize, - FileReader *In, unsigned int InLeft) +int ShrinkLoop(unsigned char *out, unsigned int outsize, FileRdr &_In, unsigned int InLeft) { + FileRdr *In = &_In; unsigned char ReadBuf[256]; unsigned short Parent[HSIZE]; unsigned char Value[HSIZE], Stack[HSIZE]; diff --git a/src/resourcefiles/ancientzip.h b/src/resourcefiles/ancientzip.h index d51e89ca5..53725b27c 100644 --- a/src/resourcefiles/ancientzip.h +++ b/src/resourcefiles/ancientzip.h @@ -4,7 +4,7 @@ class FZipExploder { unsigned int Hold, Bits; - FileReader *In; + FileRdr *In; unsigned int InLeft; /**************************************************************** @@ -38,7 +38,7 @@ class FZipExploder int DecodeSFValue(const TArray ¤tTree); int DecodeSF(TArray &decoder, int numvals); public: - int Explode(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize, int flags); + int Explode(unsigned char *out, unsigned int outsize, FileRdr &in, unsigned int insize, int flags); }; class CExplosionError : CRecoverableError @@ -47,4 +47,4 @@ public: CExplosionError(const char *message) : CRecoverableError(message) {} }; -int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader *in, unsigned int insize); \ No newline at end of file +int ShrinkLoop(unsigned char *out, unsigned int outsize, FileRdr &in, unsigned int insize); \ No newline at end of file diff --git a/src/resourcefiles/file_7z.cpp b/src/resourcefiles/file_7z.cpp index aa5018eb3..cb2f310a8 100644 --- a/src/resourcefiles/file_7z.cpp +++ b/src/resourcefiles/file_7z.cpp @@ -58,19 +58,19 @@ extern ISzAlloc g_Alloc; struct CZDFileInStream { ISeekInStream s; - FileReader *File; + FileRdr &File; - CZDFileInStream(FileReader *_file) + CZDFileInStream(FileRdr &_file) + : File(_file) { s.Read = Read; s.Seek = Seek; - File = _file; } static SRes Read(const ISeekInStream *pp, void *buf, size_t *size) { CZDFileInStream *p = (CZDFileInStream *)pp; - long numread = p->File->Read(buf, (long)*size); + auto numread = p->File.Read(buf, (long)*size); if (numread < 0) { *size = 0; @@ -83,26 +83,26 @@ struct CZDFileInStream static SRes Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) { CZDFileInStream *p = (CZDFileInStream *)pp; - int move_method; + FileRdr::ESeek move_method; int res; if (origin == SZ_SEEK_SET) { - move_method = SEEK_SET; + move_method = FileRdr::SeekSet; } else if (origin == SZ_SEEK_CUR) { - move_method = SEEK_CUR; + move_method = FileRdr::SeekCur; } else if (origin == SZ_SEEK_END) { - move_method = SEEK_END; + move_method = FileRdr::SeekEnd; } else { return 1; } - res = p->File->Seek((long)*pos, move_method); - *pos = p->File->Tell(); + res = (int)p->File.Seek((long)*pos, move_method); + *pos = p->File.Tell(); return res; } }; @@ -117,13 +117,13 @@ struct C7zArchive Byte *OutBuffer; size_t OutBufferSize; - C7zArchive(FileReader *file) : ArchiveStream(file) + C7zArchive(FileRdr &file) : ArchiveStream(file) { if (g_CrcTable[1] == 0) { CrcGenerateTable(); } - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); LookToRead2_CreateVTable(&LookStream, false); LookStream.realStream = &ArchiveStream.s; LookToRead2_Init(&LookStream); @@ -192,7 +192,7 @@ class F7ZFile : public FResourceFile C7zArchive *Archive; public: - F7ZFile(const char * filename, FileReader *filer); + F7ZFile(const char * filename, FileRdr &filer); bool Open(bool quiet); virtual ~F7ZFile(); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } @@ -206,7 +206,7 @@ public: // //========================================================================== -F7ZFile::F7ZFile(const char * filename, FileReader *filer) +F7ZFile::F7ZFile(const char * filename, FileRdr &filer) : FResourceFile(filename, filer) { Lumps = NULL; @@ -295,7 +295,7 @@ bool F7ZFile::Open(bool quiet) lump_p->LumpNameSetup(name); lump_p->LumpSize = static_cast(SzArEx_GetFileSize(archPtr, i)); lump_p->Owner = this; - lump_p->Flags = LUMPF_ZIPFILE; + lump_p->Flags = LUMPF_ZIPFILE|LUMPF_COMPRESSED; lump_p->Position = i; lump_p->CheckEmbedded(); lump_p++; @@ -361,21 +361,21 @@ int F7ZLump::FillCache() // //========================================================================== -FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet) +FResourceFile *Check7Z(const char *filename, FileRdr &file, bool quiet) { char head[k7zSignatureSize]; - if (file->GetLength() >= k7zSignatureSize) + if (file.GetLength() >= k7zSignatureSize) { - file->Seek(0, SEEK_SET); - file->Read(&head, k7zSignatureSize); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, k7zSignatureSize); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, k7zSignature, k7zSignatureSize)) { FResourceFile *rf = new F7ZFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_directory.cpp b/src/resourcefiles/file_directory.cpp index 2e5630169..534a6fe38 100644 --- a/src/resourcefiles/file_directory.cpp +++ b/src/resourcefiles/file_directory.cpp @@ -55,7 +55,7 @@ struct FDirectoryLump : public FResourceLump { - virtual FileReader *NewReader(); + virtual FileRdr NewReader(); virtual int FillCache(); FString mFullPath; @@ -90,7 +90,7 @@ public: //========================================================================== FDirectory::FDirectory(const char * directory) -: FResourceFile(NULL, NULL) +: FResourceFile(NULL, FileRdr()) { FString dirname; @@ -287,16 +287,11 @@ void FDirectory::AddEntry(const char *fullpath, int size) // //========================================================================== -FileReader *FDirectoryLump::NewReader() +FileRdr FDirectoryLump::NewReader() { - try - { - return new FileReader(mFullPath); - } - catch (CRecoverableError &) - { - return NULL; - } + FileRdr fr; + fr.OpenFile(mFullPath); + return fr; } //========================================================================== @@ -307,15 +302,14 @@ FileReader *FDirectoryLump::NewReader() int FDirectoryLump::FillCache() { + FileRdr fr; Cache = new char[LumpSize]; - FileReader *reader = NewReader(); - if (reader == NULL) + if (!fr.OpenFile(mFullPath)) { memset(Cache, 0, LumpSize); return 0; } - reader->Read(Cache, LumpSize); - delete reader; + fr.Read(Cache, LumpSize); RefCount = 1; return 1; } @@ -326,7 +320,7 @@ int FDirectoryLump::FillCache() // //========================================================================== -FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckDir(const char *filename, bool quiet) { FResourceFile *rf = new FDirectory(filename); if (rf->Open(quiet)) return rf; diff --git a/src/resourcefiles/file_grp.cpp b/src/resourcefiles/file_grp.cpp index 663aeb16e..72543d356 100644 --- a/src/resourcefiles/file_grp.cpp +++ b/src/resourcefiles/file_grp.cpp @@ -73,7 +73,7 @@ struct GrpLump class FGrpFile : public FUncompressedFile { public: - FGrpFile(const char * filename, FileReader *file); + FGrpFile(const char * filename, FileRdr &file); bool Open(bool quiet); }; @@ -84,7 +84,7 @@ public: // //========================================================================== -FGrpFile::FGrpFile(const char *filename, FileReader *file) +FGrpFile::FGrpFile(const char *filename, FileRdr &file) : FUncompressedFile(filename, file) { Lumps = NULL; @@ -100,11 +100,11 @@ bool FGrpFile::Open(bool quiet) { GrpInfo header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); GrpLump *fileinfo = new GrpLump[NumLumps]; - Reader->Read (fileinfo, NumLumps * sizeof(GrpLump)); + Reader.Read (fileinfo, NumLumps * sizeof(GrpLump)); Lumps = new FUncompressedLump[NumLumps]; @@ -134,21 +134,21 @@ bool FGrpFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckGRP(const char *filename, FileRdr &file, bool quiet) { char head[12]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 12); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, 12); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, "KenSilverman", 12)) { FResourceFile *rf = new FGrpFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_lump.cpp b/src/resourcefiles/file_lump.cpp index ee8751de3..feb8e56d9 100644 --- a/src/resourcefiles/file_lump.cpp +++ b/src/resourcefiles/file_lump.cpp @@ -46,7 +46,7 @@ class FLumpFile : public FUncompressedFile { public: - FLumpFile(const char * filename, FileReader *file); + FLumpFile(const char * filename, FileRdr &file); bool Open(bool quiet); }; @@ -57,7 +57,8 @@ public: // //========================================================================== -FLumpFile::FLumpFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file) +FLumpFile::FLumpFile(const char *filename, FileRdr &file) + : FUncompressedFile(filename, file) { } @@ -76,7 +77,7 @@ bool FLumpFile::Open(bool quiet) Lumps->Name[8] = 0; Lumps->Owner = this; Lumps->Position = 0; - Lumps->LumpSize = Reader->GetLength(); + Lumps->LumpSize = (int)Reader.GetLength(); Lumps->Namespace = ns_global; Lumps->Flags = 0; Lumps->FullName = NULL; @@ -94,11 +95,12 @@ bool FLumpFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckLump(const char *filename, FileRdr &file, bool quiet) { // always succeeds FResourceFile *rf = new FLumpFile(filename, file); if (rf->Open(quiet)) return rf; + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; return NULL; } diff --git a/src/resourcefiles/file_pak.cpp b/src/resourcefiles/file_pak.cpp index b76a937c8..42923092b 100644 --- a/src/resourcefiles/file_pak.cpp +++ b/src/resourcefiles/file_pak.cpp @@ -66,7 +66,7 @@ struct dpackheader_t class FPakFile : public FUncompressedFile { public: - FPakFile(const char * filename, FileReader *file); + FPakFile(const char * filename, FileRdr &file); bool Open(bool quiet); }; @@ -79,7 +79,8 @@ public: // //========================================================================== -FPakFile::FPakFile(const char *filename, FileReader *file) : FUncompressedFile(filename, file) +FPakFile::FPakFile(const char *filename, FileRdr &file) + : FUncompressedFile(filename, file) { Lumps = NULL; } @@ -94,13 +95,13 @@ bool FPakFile::Open(bool quiet) { dpackheader_t header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.dirlen) / sizeof(dpackfile_t); header.dirofs = LittleLong(header.dirofs); dpackfile_t *fileinfo = new dpackfile_t[NumLumps]; - Reader->Seek (header.dirofs, SEEK_SET); - Reader->Read (fileinfo, NumLumps * sizeof(dpackfile_t)); + Reader.Seek (header.dirofs, FileRdr::SeekSet); + Reader.Read (fileinfo, NumLumps * sizeof(dpackfile_t)); Lumps = new FUncompressedLump[NumLumps]; @@ -126,21 +127,21 @@ bool FPakFile::Open(bool quiet) // //========================================================================== -FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckPak(const char *filename, FileRdr &file, bool quiet) { char head[4]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, "PACK", 4)) { FResourceFile *rf = new FPakFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_rff.cpp b/src/resourcefiles/file_rff.cpp index ba73dfc8b..43a4a454f 100644 --- a/src/resourcefiles/file_rff.cpp +++ b/src/resourcefiles/file_rff.cpp @@ -75,7 +75,7 @@ struct RFFLump struct FRFFLump : public FUncompressedLump { - virtual FileReader *GetReader(); + virtual FileRdr *GetReader(); virtual int FillCache(); uint32_t IndexNum; @@ -111,7 +111,7 @@ class FRFFFile : public FResourceFile FRFFLump *Lumps; public: - FRFFFile(const char * filename, FileReader *file); + FRFFFile(const char * filename, FileRdr &file); virtual ~FRFFFile(); virtual bool Open(bool quiet); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } @@ -124,7 +124,7 @@ public: // //========================================================================== -FRFFFile::FRFFFile(const char *filename, FileReader *file) +FRFFFile::FRFFFile(const char *filename, FileRdr &file) : FResourceFile(filename, file) { Lumps = NULL; @@ -141,13 +141,13 @@ bool FRFFFile::Open(bool quiet) RFFLump *lumps; RFFInfo header; - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); header.DirOfs = LittleLong(header.DirOfs); lumps = new RFFLump[header.NumLumps]; - Reader->Seek (header.DirOfs, SEEK_SET); - Reader->Read (lumps, header.NumLumps * sizeof(RFFLump)); + Reader.Seek (header.DirOfs, FileRdr::SeekSet); + Reader.Read (lumps, header.NumLumps * sizeof(RFFLump)); BloodCrypt (lumps, header.DirOfs, header.NumLumps * sizeof(RFFLump)); Lumps = new FRFFLump[NumLumps]; @@ -203,7 +203,7 @@ FRFFFile::~FRFFFile() // //========================================================================== -FileReader *FRFFLump::GetReader() +FileRdr *FRFFLump::GetReader() { // Don't return the reader if this lump is encrypted // In that case always force caching of the lump @@ -247,21 +247,21 @@ int FRFFLump::FillCache() // //========================================================================== -FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckRFF(const char *filename, FileRdr &file, bool quiet) { char head[4]; - if (file->GetLength() >= 16) + if (file.GetLength() >= 16) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, "RFF\x1a", 4)) { FResourceFile *rf = new FRFFFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_wad.cpp b/src/resourcefiles/file_wad.cpp index 477bda8e1..fce8ee1fd 100644 --- a/src/resourcefiles/file_wad.cpp +++ b/src/resourcefiles/file_wad.cpp @@ -40,191 +40,7 @@ #include "w_wad.h" #include "gi.h" #include "i_system.h" - -// Console Doom LZSS wrapper. -class FileReaderLZSS : public FileReaderBase -{ -private: - enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 }; - - FileReader &File; - bool SawEOF; - uint8_t InBuff[BUFF_SIZE]; - - enum StreamState - { - STREAM_EMPTY, - STREAM_BITS, - STREAM_FLUSH, - STREAM_FINAL - }; - struct - { - StreamState State; - - uint8_t *In; - unsigned int AvailIn; - unsigned int InternalOut; - - uint8_t CFlags, Bits; - - uint8_t Window[WINDOW_SIZE+INTERNAL_BUFFER_SIZE]; - const uint8_t *WindowData; - uint8_t *InternalBuffer; - } Stream; - - void FillBuffer() - { - if(Stream.AvailIn) - memmove(InBuff, Stream.In, Stream.AvailIn); - - long numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn); - - if (numread < BUFF_SIZE) - { - SawEOF = true; - } - Stream.In = InBuff; - Stream.AvailIn = numread+Stream.AvailIn; - } - - // Reads a flag byte. - void PrepareBlocks() - { - assert(Stream.InternalBuffer == Stream.WindowData); - Stream.CFlags = *Stream.In++; - --Stream.AvailIn; - Stream.Bits = 0xFF; - Stream.State = STREAM_BITS; - } - - // Reads the next chunk in the block. Returns true if successful and - // returns false if it ran out of input data. - bool UncompressBlock() - { - if(Stream.CFlags & 1) - { - // Check to see if we have enough input - if(Stream.AvailIn < 2) - return false; - Stream.AvailIn -= 2; - - uint16_t pos = BigShort(*(uint16_t*)Stream.In); - uint8_t len = (pos & 0xF)+1; - pos >>= 4; - Stream.In += 2; - if(len == 1) - { - // We've reached the end of the stream. - Stream.State = STREAM_FINAL; - return true; - } - - const uint8_t* copyStart = Stream.InternalBuffer-pos-1; - - // Complete overlap: Single byte repeated - if(pos == 0) - memset(Stream.InternalBuffer, *copyStart, len); - // No overlap: One copy - else if(pos >= len) - memcpy(Stream.InternalBuffer, copyStart, len); - else - { - // Partial overlap: Copy in 2 or 3 chunks. - do - { - unsigned int copy = MIN(len, pos+1); - memcpy(Stream.InternalBuffer, copyStart, copy); - Stream.InternalBuffer += copy; - Stream.InternalOut += copy; - len -= copy; - pos += copy; // Increase our position since we can copy twice as much the next round. - } - while(len); - } - - Stream.InternalOut += len; - Stream.InternalBuffer += len; - } - else - { - // Uncompressed byte. - *Stream.InternalBuffer++ = *Stream.In++; - --Stream.AvailIn; - ++Stream.InternalOut; - } - - Stream.CFlags >>= 1; - Stream.Bits >>= 1; - - // If we're done with this block, flush the output - if(Stream.Bits == 0) - Stream.State = STREAM_FLUSH; - - return true; - } - -public: - FileReaderLZSS(FileReader &file) : File(file), SawEOF(false) - { - Stream.State = STREAM_EMPTY; - Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE; - Stream.InternalOut = 0; - Stream.AvailIn = 0; - - FillBuffer(); - } - - ~FileReaderLZSS() - { - } - - long Read(void *buffer, long len) - { - - uint8_t *Out = (uint8_t*)buffer; - long AvailOut = len; - - do - { - while(Stream.AvailIn) - { - if(Stream.State == STREAM_EMPTY) - PrepareBlocks(); - else if(Stream.State == STREAM_BITS && !UncompressBlock()) - break; - else - break; - } - - unsigned int copy = MIN(Stream.InternalOut, AvailOut); - if(copy > 0) - { - memcpy(Out, Stream.WindowData, copy); - Out += copy; - AvailOut -= copy; - - // Slide our window - memmove(Stream.Window, Stream.Window+copy, WINDOW_SIZE+INTERNAL_BUFFER_SIZE-copy); - Stream.InternalBuffer -= copy; - Stream.InternalOut -= copy; - } - - if(Stream.State == STREAM_FINAL) - break; - - if(Stream.InternalOut == 0 && Stream.State == STREAM_FLUSH) - Stream.State = STREAM_EMPTY; - - if(Stream.AvailIn < 2) - FillBuffer(); - } - while(AvailOut && Stream.State != STREAM_FINAL); - - assert(AvailOut == 0); - return (long)(Out - (uint8_t*)buffer); - } -}; +#include "w_zip.h" //========================================================================== // @@ -239,12 +55,12 @@ public: int Position; int GetFileOffset() { return Position; } - FileReader *GetReader() + FileRdr *GetReader() { if(!Compressed) { - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileRdr::SeekSet); + return &Owner->Reader; } return NULL; } @@ -252,7 +68,7 @@ public: { if(!Compressed) { - const char * buffer = Owner->Reader->GetBuffer(); + const char * buffer = Owner->Reader.GetBuffer(); if (buffer != NULL) { @@ -263,16 +79,19 @@ public: } } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileRdr::SeekSet); Cache = new char[LumpSize]; if(Compressed) { - FileReaderLZSS lzss(*Owner->Reader); - lzss.Read(Cache, LumpSize); + FileRdr lzss; + if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false)) + { + lzss.Read(Cache, LumpSize); + } } else - Owner->Reader->Read(Cache, LumpSize); + Owner->Reader.Read(Cache, LumpSize); RefCount = 1; return 1; @@ -294,7 +113,7 @@ class FWadFile : public FResourceFile void SkinHack (); public: - FWadFile(const char * filename, FileReader *file); + FWadFile(const char * filename, FileRdr &file); ~FWadFile(); void FindStrifeTeaserVoices (); FResourceLump *GetLump(int lump) { return &Lumps[lump]; } @@ -310,7 +129,8 @@ public: // //========================================================================== -FWadFile::FWadFile(const char *filename, FileReader *file) : FResourceFile(filename, file) +FWadFile::FWadFile(const char *filename, FileRdr &file) + : FResourceFile(filename, file) { Lumps = NULL; } @@ -331,9 +151,9 @@ bool FWadFile::Open(bool quiet) wadinfo_t header; uint32_t InfoTableOfs; bool isBigEndian = false; // Little endian is assumed until proven otherwise - const long wadSize = Reader->GetLength(); + auto wadSize = Reader.GetLength(); - Reader->Read(&header, sizeof(header)); + Reader.Read(&header, sizeof(header)); NumLumps = LittleLong(header.NumLumps); InfoTableOfs = LittleLong(header.InfoTableOfs); @@ -353,8 +173,8 @@ bool FWadFile::Open(bool quiet) } wadlump_t *fileinfo = new wadlump_t[NumLumps]; - Reader->Seek (InfoTableOfs, SEEK_SET); - Reader->Read (fileinfo, NumLumps * sizeof(wadlump_t)); + Reader.Seek (InfoTableOfs, FileRdr::SeekSet); + Reader.Read (fileinfo, NumLumps * sizeof(wadlump_t)); Lumps = new FWadFileLump[NumLumps]; @@ -369,7 +189,7 @@ bool FWadFile::Open(bool quiet) Lumps[i].Position = isBigEndian ? BigLong(fileinfo[i].FilePos) : LittleLong(fileinfo[i].FilePos); Lumps[i].LumpSize = isBigEndian ? BigLong(fileinfo[i].Size) : LittleLong(fileinfo[i].Size); Lumps[i].Namespace = ns_global; - Lumps[i].Flags = 0; + Lumps[i].Flags = Lumps[i].Compressed? LUMPF_COMPRESSED : 0; Lumps[i].FullName = NULL; } @@ -655,21 +475,21 @@ void FWadFile::FindStrifeTeaserVoices () // //========================================================================== -FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckWad(const char *filename, FileRdr &file, bool quiet) { char head[4]; - if (file->GetLength() >= 12) + if (file.GetLength() >= 12) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, "IWAD", 4) || !memcmp(head, "PWAD", 4)) { FResourceFile *rf = new FWadFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_zip.cpp b/src/resourcefiles/file_zip.cpp index 3d842131d..a2015ac58 100644 --- a/src/resourcefiles/file_zip.cpp +++ b/src/resourcefiles/file_zip.cpp @@ -51,7 +51,7 @@ // //========================================================================== -static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) +static bool UncompressZipLump(char *Cache, FileRdr &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags) { try { @@ -59,31 +59,23 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L { case METHOD_STORED: { - Reader->Read(Cache, LumpSize); + Reader.Read(Cache, LumpSize); break; } case METHOD_DEFLATE: - { - FileReaderZ frz(*Reader, true); - frz.Read(Cache, LumpSize); - break; - } - case METHOD_BZIP2: - { - FileReaderBZ2 frz(*Reader); - frz.Read(Cache, LumpSize); - break; - } - case METHOD_LZMA: { - FileReaderLZMA frz(*Reader, LumpSize, true); - frz.Read(Cache, LumpSize); + FileRdr frz; + if (frz.OpenDecompressor(Reader, LumpSize, Method, false)) + { + frz.Read(Cache, LumpSize); + } break; } + // Fixme: These should also use a stream case METHOD_IMPLODE: { FZipExploder exploder; @@ -112,8 +104,9 @@ static bool UncompressZipLump(char *Cache, FileReader *Reader, int Method, int L bool FCompressedBuffer::Decompress(char *destbuffer) { - MemoryReader mr(mBuffer, mCompressedSize); - return UncompressZipLump(destbuffer, &mr, mMethod, mSize, mCompressedSize, mZipFlags); + FileRdr mr; + mr.OpenMemory(mBuffer, mCompressedSize); + return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags); } //----------------------------------------------------------------------- @@ -123,7 +116,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer) // //----------------------------------------------------------------------- -static uint32_t Zip_FindCentralDir(FileReader * fin) +static uint32_t Zip_FindCentralDir(FileRdr &fin) { unsigned char buf[BUFREADCOMMENT + 4]; uint32_t FileSize; @@ -131,9 +124,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) uint32_t uMaxBack; // maximum size of global comment uint32_t uPosFound=0; - fin->Seek(0, SEEK_END); + fin.Seek(0, FileRdr::SeekEnd); - FileSize = fin->Tell(); + FileSize = (uint32_t)fin.Tell(); uMaxBack = MIN(0xffff, FileSize); uBackRead = 4; @@ -149,9 +142,9 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) uReadSize = MIN((BUFREADCOMMENT + 4), (FileSize - uReadPos)); - if (fin->Seek(uReadPos, SEEK_SET) != 0) break; + if (fin.Seek(uReadPos, FileRdr::SeekSet) != 0) break; - if (fin->Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; + if (fin.Read(buf, (int32_t)uReadSize) != (int32_t)uReadSize) break; for (i = (int)uReadSize - 3; (i--) > 0;) { @@ -174,7 +167,7 @@ static uint32_t Zip_FindCentralDir(FileReader * fin) // //========================================================================== -FZipFile::FZipFile(const char * filename, FileReader *file) +FZipFile::FZipFile(const char * filename, FileRdr &file) : FResourceFile(filename, file) { Lumps = NULL; @@ -195,8 +188,8 @@ bool FZipFile::Open(bool quiet) } // Read the central directory info. - Reader->Seek(centraldir, SEEK_SET); - Reader->Read(&info, sizeof(FZipEndOfCentralDirectory)); + Reader.Seek(centraldir, FileRdr::SeekSet); + Reader.Read(&info, sizeof(FZipEndOfCentralDirectory)); // No multi-disk zips! if (info.NumEntries != info.NumEntriesOnAllDisks || @@ -212,8 +205,8 @@ bool FZipFile::Open(bool quiet) // Load the entire central directory. Too bad that this contains variable length entries... int dirsize = LittleLong(info.DirectorySize); void *directory = malloc(dirsize); - Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET); - Reader->Read(directory, dirsize); + Reader.Seek(LittleLong(info.DirectoryOffset), FileRdr::SeekSet); + Reader.Read(directory, dirsize); char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; @@ -349,6 +342,7 @@ bool FZipFile::Open(bool quiet) // The start of the Reader will be determined the first time it is accessed. lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Method = uint8_t(zip_fh->Method); + if (lump_p->Method != METHOD_STORED) lump_p->Flags |= LUMPF_COMPRESSED; lump_p->GPFlags = zip_fh->Flags; lump_p->CRC32 = zip_fh->CRC32; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); @@ -394,8 +388,8 @@ FCompressedBuffer FZipLump::GetRawData() { FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)CompressedSize, Method, GPFlags, CRC32, new char[CompressedSize] }; if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); - Owner->Reader->Seek(Position, SEEK_SET); - Owner->Reader->Read(cbuf.mBuffer, CompressedSize); + Owner->Reader.Seek(Position, FileRdr::SeekSet); + Owner->Reader.Read(cbuf.mBuffer, CompressedSize); return cbuf; } @@ -413,10 +407,8 @@ void FZipLump::SetLumpAddress() FZipLocalFileHeader localHeader; int skiplen; - FileReader *file = Owner->Reader; - - file->Seek(Position, SEEK_SET); - file->Read(&localHeader, sizeof(localHeader)); + Owner->Reader.Seek(Position, FileRdr::SeekSet); + Owner->Reader.Read(&localHeader, sizeof(localHeader)); skiplen = LittleShort(localHeader.NameLength) + LittleShort(localHeader.ExtraLength); Position += sizeof(localHeader) + skiplen; Flags &= ~LUMPFZIP_NEEDFILESTART; @@ -428,15 +420,15 @@ void FZipLump::SetLumpAddress() // //========================================================================== -FileReader *FZipLump::GetReader() +FileRdr *FZipLump::GetReader() { // Don't return the reader if this lump is encrypted // In that case always force caching of the lump if (Method == METHOD_STORED) { if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileRdr::SeekSet); + return &Owner->Reader; } else return NULL; } @@ -452,7 +444,7 @@ int FZipLump::FillCache() if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress(); const char *buffer; - if (Method == METHOD_STORED && (buffer = Owner->Reader->GetBuffer()) != NULL) + if (Method == METHOD_STORED && (buffer = Owner->Reader.GetBuffer()) != NULL) { // This is an in-memory file so the cache can point directly to the file's data. Cache = const_cast(buffer) + Position; @@ -460,7 +452,7 @@ int FZipLump::FillCache() return -1; } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileRdr::SeekSet); Cache = new char[LumpSize]; UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags); RefCount = 1; @@ -486,21 +478,21 @@ int FZipLump::GetFileOffset() // //========================================================================== -FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet) +FResourceFile *CheckZip(const char *filename, FileRdr &file, bool quiet) { char head[4]; - if (file->GetLength() >= (long)sizeof(FZipLocalFileHeader)) + if (file.GetLength() >= (long)sizeof(FZipLocalFileHeader)) { - file->Seek(0, SEEK_SET); - file->Read(&head, 4); - file->Seek(0, SEEK_SET); + file.Seek(0, FileRdr::SeekSet); + file.Read(&head, 4); + file.Seek(0, FileRdr::SeekSet); if (!memcmp(head, "PK\x3\x4", 4)) { FResourceFile *rf = new FZipFile(filename, file); if (rf->Open(quiet)) return rf; - rf->Reader = NULL; // to avoid destruction of reader + file = std::move(rf->Reader); // to avoid destruction of reader delete rf; } } diff --git a/src/resourcefiles/file_zip.h b/src/resourcefiles/file_zip.h index 1078a0714..48f9a100e 100644 --- a/src/resourcefiles/file_zip.h +++ b/src/resourcefiles/file_zip.h @@ -22,7 +22,7 @@ struct FZipLump : public FResourceLump int Position; unsigned CRC32; - virtual FileReader *GetReader(); + virtual FileRdr *GetReader(); virtual int FillCache(); private: @@ -43,7 +43,7 @@ class FZipFile : public FResourceFile FZipLump *Lumps; public: - FZipFile(const char * filename, FileReader *file); + FZipFile(const char * filename, FileRdr &file); virtual ~FZipFile(); bool Open(bool quiet); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 18a6b6f15..f5fca6b09 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -45,7 +45,7 @@ //========================================================================== // -// FileReader that reads from a lump's cache +// File reader that reads from a lump's cache // //========================================================================== @@ -212,11 +212,11 @@ FCompressedBuffer FResourceLump::GetRawData() //========================================================================== // -// Returns the owner's FileReader if it can be used to access this lump +// Returns the owner's FileRdr if it can be used to access this lump // //========================================================================== -FileReader *FResourceLump::GetReader() +FileRdr *FResourceLump::GetReader() { return NULL; } @@ -227,9 +227,9 @@ FileReader *FResourceLump::GetReader() // //========================================================================== -FileReader *FResourceLump::NewReader() +FileRdr FResourceLump::NewReader() { - return new FLumpReader(this); + return FileRdr(new FLumpReader(this)); } //========================================================================== @@ -276,46 +276,45 @@ int FResourceLump::ReleaseCache() // //========================================================================== -typedef FResourceFile * (*CheckFunc)(const char *filename, FileReader *file, bool quiet); +typedef FResourceFile * (*CheckFunc)(const char *filename, FileRdr &file, bool quiet); -FResourceFile *CheckWad(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckGRP(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckRFF(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckPak(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckZip(const char *filename, FileReader *file, bool quiet); -FResourceFile *Check7Z(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckLump(const char *filename, FileReader *file, bool quiet); -FResourceFile *CheckDir(const char *filename, FileReader *file, bool quiet); +FResourceFile *CheckWad(const char *filename, FileRdr &file, bool quiet); +FResourceFile *CheckGRP(const char *filename, FileRdr &file, bool quiet); +FResourceFile *CheckRFF(const char *filename, FileRdr &file, bool quiet); +FResourceFile *CheckPak(const char *filename, FileRdr &file, bool quiet); +FResourceFile *CheckZip(const char *filename, FileRdr &file, bool quiet); +FResourceFile *Check7Z(const char *filename, FileRdr &file, bool quiet); +FResourceFile *CheckLump(const char *filename,FileRdr &file, bool quiet); +FResourceFile *CheckDir(const char *filename, bool quiet); static CheckFunc funcs[] = { CheckWad, CheckZip, Check7Z, CheckPak, CheckGRP, CheckRFF, CheckLump }; -FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader *file, bool quiet, bool containeronly) +FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly) { - bool mustclose = false; - if (file == NULL) - { - try - { - file = new FileReader(filename); - mustclose = true; - } - catch (CRecoverableError &) - { - return NULL; - } - } for(size_t i = 0; i < countof(funcs) - containeronly; i++) { FResourceFile *resfile = funcs[i](filename, file, quiet); if (resfile != NULL) return resfile; } - if (mustclose) delete file; return NULL; } +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly) +{ + return DoOpenResourceFile(filename, file, quiet, containeronly); +} + + +FResourceFile *FResourceFile::OpenResourceFile(const char *filename, bool quiet, bool containeronly) +{ + FileRdr file; + if (!file.OpenFile(filename)) return nullptr; + return DoOpenResourceFile(filename, file, quiet, containeronly); +} + FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) { - return CheckDir(filename, NULL, quiet); + return CheckDir(filename, quiet); } //========================================================================== @@ -324,18 +323,17 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) // //========================================================================== -FResourceFile::FResourceFile(const char *filename, FileReader *r) +FResourceFile::FResourceFile(const char *filename, FileRdr &r) { if (filename != NULL) Filename = copystring(filename); else Filename = NULL; - Reader = r; + Reader = std::move(r); } FResourceFile::~FResourceFile() { if (Filename != NULL) delete [] Filename; - delete Reader; } int lumpcmp(const void * a, const void * b) @@ -607,10 +605,10 @@ FResourceLump *FResourceFile::FindLump(const char *name) // //========================================================================== -FileReader *FUncompressedLump::GetReader() +FileRdr *FUncompressedLump::GetReader() { - Owner->Reader->Seek(Position, SEEK_SET); - return Owner->Reader; + Owner->Reader.Seek(Position, FileRdr::SeekSet); + return &Owner->Reader; } //========================================================================== @@ -621,7 +619,7 @@ FileReader *FUncompressedLump::GetReader() int FUncompressedLump::FillCache() { - const char * buffer = Owner->Reader->GetBuffer(); + const char * buffer = Owner->Reader.GetBuffer(); if (buffer != NULL) { @@ -631,9 +629,9 @@ int FUncompressedLump::FillCache() return -1; } - Owner->Reader->Seek(Position, SEEK_SET); + Owner->Reader.Seek(Position, FileRdr::SeekSet); Cache = new char[LumpSize]; - Owner->Reader->Read(Cache, LumpSize); + Owner->Reader.Read(Cache, LumpSize); RefCount = 1; return 1; } @@ -644,7 +642,7 @@ int FUncompressedLump::FillCache() // //========================================================================== -FUncompressedFile::FUncompressedFile(const char *filename, FileReader *r) +FUncompressedFile::FUncompressedFile(const char *filename, FileRdr &r) : FResourceFile(filename, r) { Lumps = NULL; @@ -669,11 +667,11 @@ FExternalLump::FExternalLump(const char *_filename, int filesize) if (filesize == -1) { - FileReader f; + FileRdr f; - if (f.Open(_filename)) + if (f.OpenFile(_filename)) { - LumpSize = f.GetLength(); + LumpSize = (int)f.GetLength(); } else { @@ -702,9 +700,9 @@ FExternalLump::~FExternalLump() int FExternalLump::FillCache() { Cache = new char[LumpSize]; - FileReader f; + FileRdr f; - if (f.Open(filename)) + if (f.OpenFile(filename)) { f.Read(Cache, LumpSize); } @@ -728,7 +726,7 @@ bool FMemoryFile::Open(bool quiet) Lumps->FullName = fname; Lumps->Owner = this; Lumps->Position = 0; - Lumps->LumpSize = Reader->GetLength(); + Lumps->LumpSize = (int)Reader.GetLength(); Lumps->Namespace = ns_global; Lumps->Flags = 0; Lumps->FullName = NULL; diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index f7cc806e2..0d795fae3 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -62,8 +62,8 @@ struct FResourceLump } virtual ~FResourceLump(); - virtual FileReader *GetReader(); - virtual FileReader *NewReader(); + virtual FileRdr *GetReader(); + virtual FileRdr NewReader(); virtual int GetFileOffset() { return -1; } virtual int GetIndexNum() const { return 0; } void LumpNameSetup(FString iname); @@ -81,12 +81,12 @@ protected: class FResourceFile { public: - FileReader *Reader; + FileRdr Reader; const char *Filename; protected: uint32_t NumLumps; - FResourceFile(const char *filename, FileReader *r); + FResourceFile(const char *filename, FileRdr &r); // for archives that can contain directories void PostProcessArchive(void *lumps, size_t lumpsize); @@ -98,12 +98,14 @@ private: int FilterLumpsByGameType(int gametype, void *lumps, size_t lumpsize, uint32_t max); bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max); + static FResourceFile *DoOpenResourceFile(const char *filename, FileRdr &file, bool quiet, bool containeronly); public: - static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false, bool containeronly = false); + static FResourceFile *OpenResourceFile(const char *filename, FileRdr &file, bool quiet = false, bool containeronly = false); + static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false); static FResourceFile *OpenDirectory(const char *filename, bool quiet = false); virtual ~FResourceFile(); - FileReader *GetReader() const { return Reader; } + FileRdr *GetReader() { return &Reader; } uint32_t LumpCount() const { return NumLumps; } uint32_t GetFirstLump() const { return FirstLump; } void SetFirstLump(uint32_t f) { FirstLump = f; } @@ -118,7 +120,7 @@ struct FUncompressedLump : public FResourceLump { int Position; - virtual FileReader *GetReader(); + virtual FileRdr *GetReader(); virtual int FillCache(); virtual int GetFileOffset() { return Position; } @@ -132,7 +134,7 @@ protected: FUncompressedLump * Lumps; - FUncompressedFile(const char *filename, FileReader *r); + FUncompressedFile(const char *filename, FileRdr &r); virtual ~FUncompressedFile(); virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; } @@ -152,12 +154,10 @@ struct FExternalLump : public FResourceLump struct FMemoryFile : public FUncompressedFile { - MemoryArrayReader mr; - FMemoryFile(const char *_filename, const void *sdata, int length) - : FUncompressedFile(_filename, nullptr), mr((const char *)sdata, length) + : FUncompressedFile(_filename, FileRdr()) { - Reader = &mr; + Reader.OpenMemoryArray(sdata, length); } bool Open(bool quiet); diff --git a/src/sound/i_soundfont.cpp b/src/sound/i_soundfont.cpp index 1416e380e..587143fa4 100644 --- a/src/sound/i_soundfont.cpp +++ b/src/sound/i_soundfont.cpp @@ -145,7 +145,7 @@ FileRdr FSF2Reader::OpenFile(const char *name) FZipPatReader::FZipPatReader(const char *filename) { - resf = FResourceFile::OpenResourceFile(filename, nullptr, true); + resf = FResourceFile::OpenResourceFile(filename, true); } FZipPatReader::~FZipPatReader() @@ -166,7 +166,7 @@ FileRdr FZipPatReader::OpenFile(const char *name) auto lump = resf->FindLump(name); if (lump != nullptr) { - return FileRdr(lump->NewReader()); // temporary workaround + return lump->NewReader(); } } return fr; @@ -306,7 +306,7 @@ void FSoundFontManager::ProcessOneFile(const FString &fn) } else if (!memcmp(head, "PK", 2)) { - auto zip = FResourceFile::OpenResourceFile(fn, nullptr, true); + auto zip = FResourceFile::OpenResourceFile(fn, true); if (zip != nullptr) { if (zip->LumpCount() > 1) // Anything with just one lump cannot possibly be a packed GUS patch set so skip it right away and simplify the lookup code diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 165518098..69c1ee5ef 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -47,7 +47,6 @@ #include "textures/textures.h" #include "v_palette.h" -typedef bool (*CheckFunc)(FileReader & file); typedef FTexture * (*CreateFunc)(FileRdr & file, int lumpnum); struct TexCreateInfo diff --git a/src/textures/textures.h b/src/textures/textures.h index c80abf87b..006d24bb7 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -147,8 +147,6 @@ struct patch_t // the [0] is &columnofs[width] }; -class FileReader; - // All FTextures present their data to the world in 8-bit format, but if // the source data is something else, this is it. enum FTextureFormat diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 716b7f322..9b995332b 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -225,12 +225,13 @@ int FWadCollection::AddExternalFile(const char *filename) // [RH] Removed reload hack //========================================================================== -void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) +void FWadCollection::AddFile (const char *filename, FileRdr *wadr) { int startlump; bool isdir = false; + FileRdr wadreader; - if (wadinfo == NULL) + if (wadr == nullptr) { // Does this exist? If so, is it a directory? if (!DirEntryExists(filename, &isdir)) @@ -242,18 +243,15 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) if (!isdir) { - try - { - wadinfo = new FileReader(filename); - } - catch (CRecoverableError &err) + if (!wadreader.OpenFile(filename)) { // Didn't find file - Printf (TEXTCOLOR_RED "%s\n", err.GetMessage()); + Printf (TEXTCOLOR_RED "%s: File not found\n", filename); PrintLastError (); return; } } } + else wadreader = std::move(*wadr); if (!batchrun) Printf (" adding %s", filename); startlump = NumLumps; @@ -261,7 +259,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) FResourceFile *resfile; if (!isdir) - resfile = FResourceFile::OpenResourceFile(filename, wadinfo); + resfile = FResourceFile::OpenResourceFile(filename, wadreader); else resfile = FResourceFile::OpenDirectory(filename); @@ -292,8 +290,8 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) { FString path; path.Format("%s:%s", filename, lump->FullName.GetChars()); - FileReader *embedded = lump->NewReader(); - AddFile(path, embedded); + auto embedded = lump->NewReader(); + AddFile(path, &embedded); } } @@ -303,14 +301,11 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) char cksumout[33]; memset(cksumout, 0, sizeof(cksumout)); - FileReader *reader = wadinfo; - - if (reader != NULL) + if (wadreader.isOpen()) { MD5Context md5; - reader->Seek(0, SEEK_SET); -#pragma message("This does not work!"); - //md5.Update(FileRdr(reader), reader->GetLength()); + wadreader.Seek(0, FileRdr::SeekSet); + md5.Update(wadreader, (unsigned)wadreader.GetLength()); md5.Final(cksum); for (size_t j = 0; j < sizeof(cksum); ++j) @@ -318,7 +313,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) sprintf(cksumout + (j * 2), "%02X", cksum[j]); } - fprintf(hashfile, "file: %s, hash: %s, size: %ld\n", filename, cksumout, reader->GetLength()); + fprintf(hashfile, "file: %s, hash: %s, size: %lld\n", filename, cksumout, (int64_t)wadreader.GetLength()); } else @@ -331,7 +326,7 @@ void FWadCollection::AddFile (const char *filename, FileReader *wadinfo) if (!(lump->Flags & LUMPF_EMBEDDED)) { MD5Context md5; - md5.Update(FileRdr(lump->NewReader()), lump->LumpSize); + md5.Update(lump->NewReader(), lump->LumpSize); md5.Final(cksum); for (size_t j = 0; j < sizeof(cksum); ++j) @@ -926,7 +921,7 @@ void FWadCollection::RenameNerve () int w = GetIwadNum(); while (++w < GetNumWads()) { - FileReader *fr = GetFileReader(w); + auto fr = GetFileReader(w); if (fr == NULL) { continue; @@ -937,10 +932,9 @@ void FWadCollection::RenameNerve () // cheaper way to know this is not the file continue; } - fr->Seek(0, SEEK_SET); + fr->Seek(0, FileRdr::SeekSet); MD5Context md5; -#pragma message("This does not work yet!"); - //md5.Update(fr, fr->GetLength()); + md5.Update(*fr, (unsigned)fr->GetLength()); md5.Final(cksum); if (memcmp(nerve, cksum, 16) == 0) { @@ -988,8 +982,8 @@ void FWadCollection::FixMacHexen() return; } - FileReader* const reader = GetFileReader(GetIwadNum()); - const long iwadSize = reader->GetLength(); + FileRdr *reader = GetFileReader(GetIwadNum()); + auto iwadSize = reader->GetLength(); static const long DEMO_SIZE = 13596228; static const long BETA_SIZE = 13749984; @@ -1002,13 +996,12 @@ void FWadCollection::FixMacHexen() return; } - reader->Seek(0, SEEK_SET); + reader->Seek(0, FileRdr::SeekSet); uint8_t checksum[16]; MD5Context md5; -#pragma message("This does not work yet!"); - //md5.Update(reader, iwadSize); + md5.Update(*reader, (unsigned)iwadSize); md5.Final(checksum); static const uint8_t HEXEN_DEMO_MD5[16] = @@ -1271,9 +1264,9 @@ int FWadCollection::GetLumpFile (int lump) const void FWadCollection::ReadLump (int lump, void *dest) { - FWadLump lumpr = OpenLumpNum (lump); - long size = lumpr.GetLength (); - long numread = lumpr.Read (dest, size); + auto lumpr = OpenLumpReader (lump); + auto size = lumpr.GetLength (); + auto numread = lumpr.Read (dest, size); if (numread != size) { @@ -1303,55 +1296,6 @@ DEFINE_ACTION_FUNCTION(_Wads, ReadLump) ACTION_RETURN_STRING(isLumpValid ? Wads.ReadLump(lump).GetString() : FString()); } -//========================================================================== -// -// OpenLumpNum -// -// Returns a copy of the file object for a lump's wad and positions its -// file pointer at the beginning of the lump. -// -//========================================================================== - -FWadLump FWadCollection::OpenLumpNum (int lump) -{ - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) - { - I_Error ("W_OpenLumpNum: %u >= NumLumps", lump); - } - - return FWadLump(LumpInfo[lump].lump); -} - -//========================================================================== -// -// ReopenLumpNum -// -// Similar to OpenLumpNum, except a new, independant file object is created -// for the lump's wad. Use this when you won't read the lump's data all at -// once (e.g. for streaming an Ogg Vorbis stream from a wad as music). -// -//========================================================================== - -FWadLump *FWadCollection::ReopenLumpNum (int lump) -{ - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) - { - I_Error ("W_ReopenLumpNum: %u >= NumLumps", lump); - } - - return new FWadLump(LumpInfo[lump].lump, true); -} - -FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump) -{ - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) - { - return NULL; - } - - return new FWadLump(lump, LumpInfo[lump].lump); -} - //========================================================================== // // OpenLumpReader @@ -1363,34 +1307,56 @@ FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump) FileRdr FWadCollection::OpenLumpReader(int lump) { - FileRdr rdr; - if ((unsigned)lump >= (unsigned)LumpInfo.Size()) { I_Error("W_OpenLumpNum: %u >= NumLumps", lump); } - rdr.mReader = new FWadLump(LumpInfo[lump].lump); - return rdr; + auto rl = LumpInfo[lump].lump; + auto rd = rl->GetReader(); + + if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !(rl->Flags & (LUMPF_BLOODCRYPT | LUMPF_COMPRESSED))) + { + FileRdr rdr; + rdr.OpenFilePart(*rd, rl->GetFileOffset(), rl->LumpSize); + return rdr; + } + return rl->NewReader(); // This always gets a reader to the cache } FileRdr FWadCollection::ReopenLumpReader(int lump, bool alwayscache) { - FileRdr rdr; - rdr.mReader = alwayscache ? ReopenLumpNumNewFile(lump) : ReopenLumpNum(lump); - return rdr; + if ((unsigned)lump >= (unsigned)LumpInfo.Size()) + { + I_Error("ReopenLumpReader: %u >= NumLumps", lump); + } + + auto rl = LumpInfo[lump].lump; + auto rd = rl->GetReader(); + + if (rl->RefCount == 0 && rd != nullptr && !rd->GetBuffer() && !alwayscache && !(rl->Flags & (LUMPF_BLOODCRYPT|LUMPF_COMPRESSED))) + { + int fileno = Wads.GetLumpFile(lump); + const char *filename = Wads.GetWadFullName(fileno); + FileRdr fr; + if (fr.OpenFile(filename, rl->GetFileOffset(), rl->LumpSize)) + { + return fr; + } + } + return rl->NewReader(); // This always gets a reader to the cache } //========================================================================== // // GetFileReader // -// Retrieves the FileReader object to access the given WAD +// Retrieves the File reader object to access the given WAD // Careful: This is only useful for real WAD files! // //========================================================================== -FileReader *FWadCollection::GetFileReader(int wadnum) +FileRdr *FWadCollection::GetFileReader(int wadnum) { if ((uint32_t)wadnum >= Files.Size()) { @@ -1486,31 +1452,6 @@ const char *FWadCollection::GetWadFullName (int wadnum) const } -//========================================================================== -// -// IsUncompressedFile -// -// Returns true when the lump is available as an uncompressed portion of -// a file. The music player can play such lumps by streaming but anything -// else has to be loaded into memory first. -// -//========================================================================== - -bool FWadCollection::IsUncompressedFile(int lump) const -{ - if ((unsigned)lump >= (unsigned)NumLumps) - { - I_Error ("IsUncompressedFile: %u >= NumLumps",lump); - } - - FResourceLump *l = LumpInfo[lump].lump; - FileReader *f = l->GetReader(); - - // We can access the file only if we get the FILE pointer from the FileReader here. - // Any other case means it won't work. - return (f != NULL && f->GetFile() != NULL); -} - //========================================================================== // // IsEncryptedFile @@ -1529,157 +1470,6 @@ bool FWadCollection::IsEncryptedFile(int lump) const } -// FWadLump ----------------------------------------------------------------- - -FWadLump::FWadLump () -: FileReader(), Lump(NULL) -{ -} - -FWadLump::FWadLump (const FWadLump ©) -: FileReader() -{ - // This must be defined isn't called. - File = copy.File; - Length = copy.Length; - FilePos = copy.FilePos; - StartPos = copy.StartPos; - CloseOnDestruct = false; - if ((Lump = copy.Lump)) Lump->CacheLump(); -} - -#ifdef _DEBUG -FWadLump & FWadLump::operator= (const FWadLump ©) -{ - // Only the debug build actually calls this! - File = copy.File; - Length = copy.Length; - FilePos = copy.FilePos; - StartPos = copy.StartPos; - CloseOnDestruct = false; - if ((Lump = copy.Lump)) Lump->CacheLump(); - return *this; -} -#endif - - -FWadLump::FWadLump(FResourceLump *lump, bool alwayscache) -: FileReader() -{ - FileReader *f = lump->GetReader(); - - if (f != NULL && f->GetFile() != NULL && !alwayscache) - { - // Uncompressed lump in a file - File = f->GetFile(); - Length = lump->LumpSize; - StartPos = FilePos = lump->GetFileOffset(); - Lump = NULL; - } - else - { - File = NULL; - Length = lump->LumpSize; - StartPos = FilePos = 0; - Lump = lump; - Lump->CacheLump(); - } -} - -FWadLump::FWadLump(int lumpnum, FResourceLump *lump) -: FileReader() -{ - FileReader *f = lump->GetReader(); - - if (f != NULL && f->GetFile() != NULL) - { - // Uncompressed lump in a file. For this we will have to open a new FILE, since we need it for streaming - int fileno = Wads.GetLumpFile(lumpnum); - const char *filename = Wads.GetWadFullName(fileno); - File = openfd(filename); - if (File != NULL) - { - Length = lump->LumpSize; - StartPos = FilePos = lump->GetFileOffset(); - Lump = NULL; - CloseOnDestruct = true; - Seek(0, SEEK_SET); - return; - } - } - File = NULL; - Length = lump->LumpSize; - StartPos = FilePos = 0; - Lump = lump; - Lump->CacheLump(); -} - -FWadLump::~FWadLump() -{ - if (Lump != NULL) - { - Lump->ReleaseCache(); - } -} - -long FWadLump::Seek (long offset, int origin) -{ - if (Lump != NULL) - { - switch (origin) - { - case SEEK_CUR: - offset += FilePos; - break; - - case SEEK_END: - offset += Length; - break; - - default: - break; - } - FilePos = clamp (offset, 0, Length); - return 0; - } - return FileReader::Seek(offset, origin); -} - -long FWadLump::Read (void *buffer, long len) -{ - long numread; - long startread = FilePos; - - if (Lump != NULL) - { - if (FilePos + len > Length) - { - len = Length - FilePos; - } - memcpy(buffer, Lump->Cache + FilePos, len); - FilePos += len; - numread = len; - } - else - { - numread = FileReader::Read(buffer, len); - } - return numread; -} - -char *FWadLump::Gets(char *strbuf, int len) -{ - if (Lump != NULL) - { - return GetsFromBuffer(Lump->Cache, strbuf, len); - } - else - { - return FileReader::Gets(strbuf, len); - } - return strbuf; -} - // FMemLump ----------------------------------------------------------------- FMemLump::FMemLump () @@ -1708,10 +1498,10 @@ FMemLump::~FMemLump () FString::FString (ELumpNum lumpnum) { - FWadLump lumpr = Wads.OpenLumpNum ((int)lumpnum); - long size = lumpr.GetLength (); + auto lumpr = Wads.OpenLumpReader ((int)lumpnum); + auto size = lumpr.GetLength (); AllocBuffer (1 + size); - long numread = lumpr.Read (&Chars[0], size); + auto numread = lumpr.Read (&Chars[0], size); Chars[size] = '\0'; if (numread != size) diff --git a/src/w_wad.h b/src/w_wad.h index 73f818564..398c80f66 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -68,44 +68,18 @@ typedef enum { enum ELumpFlags { - LUMPF_MAYBEFLAT=1, - LUMPF_ZIPFILE=2, - LUMPF_EMBEDDED=4, - LUMPF_BLOODCRYPT = 8, + LUMPF_MAYBEFLAT=1, // might be a flat outside F_START/END + LUMPF_ZIPFILE=2, // contains a full path + LUMPF_EMBEDDED=4, // from an embedded WAD + LUMPF_BLOODCRYPT = 8, // encrypted + LUMPF_COMPRESSED = 16, // compressed + LUMPF_SEQUENTIAL = 32, // compressed but a sequential reader can be retrieved. }; // [RH] Copy an 8-char string and uppercase it. void uppercopy (char *to, const char *from); -// A very loose reference to a lump on disk. This is really just a wrapper -// around the main wad's FILE object with a different length recorded. Since -// two lumps from the same wad share the same FILE, you cannot read from -// both of them independantly. -class FWadLump : public FileReader -{ -public: - FWadLump (); - FWadLump (const FWadLump ©); -#ifdef _DEBUG - FWadLump & operator= (const FWadLump ©); -#endif - ~FWadLump(); - - long Seek (long offset, int origin); - long Read (void *buffer, long len); - char *Gets(char *strbuf, int len); - -private: - FWadLump (FResourceLump *Lump, bool alwayscache = false); - FWadLump(int lumpnum, FResourceLump *lump); - - FResourceLump *Lump; - - friend class FWadCollection; -}; - - // A lump in memory. class FMemLump { @@ -138,7 +112,7 @@ public: void SetIwadNum(int x) { IwadIndex = x; } void InitMultipleFiles (TArray &filenames); - void AddFile (const char *filename, FileReader *wadinfo = NULL); + void AddFile (const char *filename, FileRdr *wadinfo = NULL); int CheckIfWadLoaded (const char *name); const char *GetWadName (int wadnum) const; @@ -180,10 +154,6 @@ public: FileRdr OpenLumpReader(int lump); // opens a reader that redirects to the containing file's one. FileRdr ReopenLumpReader(int lump, bool alwayscache = false); // opens an independent reader. - FWadLump OpenLumpNum (int lump); - FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE - FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE - int FindLump (const char *name, int *lastlump, bool anyns=false); // [RH] Find lumps with duplication int FindLumpMulti (const char **names, int *lastlump, bool anyns = false, int *nameindex = NULL); // same with multiple possible names bool CheckLumpName (int lump, const char *name); // [RH] True if lump's name == name @@ -202,7 +172,6 @@ public: int GetLumpIndexNum (int lump) const; // Returns the RFF index number for this lump bool CheckLumpName (int lump, const char *name) const; // [RH] Returns true if the names match - bool IsUncompressedFile(int lump) const; bool IsEncryptedFile(int lump) const; int GetNumLumps () const; @@ -237,7 +206,7 @@ private: void RenameNerve(); void FixMacHexen(); void DeleteAll(); - FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD + FileRdr * GetFileReader(int wadnum); // Gets a FileRdr object to the entire WAD }; extern FWadCollection Wads; diff --git a/src/w_zip.h b/src/w_zip.h index 6120e629b..0a2ce6d4e 100644 --- a/src/w_zip.h +++ b/src/w_zip.h @@ -62,14 +62,6 @@ struct FZipLocalFileHeader #define ZIP_CENTRALFILE MAKE_ID('P','K',1,2) #define ZIP_ENDOFDIR MAKE_ID('P','K',5,6) -#define METHOD_STORED 0 -#define METHOD_SHRINK 1 -#define METHOD_IMPLODE 6 -#define METHOD_DEFLATE 8 -#define METHOD_BZIP2 12 -#define METHOD_LZMA 14 -#define METHOD_PPMD 98 - // File header flags. #define ZF_ENCRYPTED 0x1