- updated files.cpp with some new features from Raze.

Not really needed for GZDoom but it's convenient to have the files being identical.
This commit is contained in:
Christoph Oelckers 2020-04-11 12:21:23 +02:00
parent c623b04170
commit 6847ea027d
3 changed files with 62 additions and 37 deletions

View file

@ -34,7 +34,8 @@
*/
#include "files.h"
#include "templates.h"
#include "templates.h" // just for 'clamp'
#include "zstring.h"
FILE *myfopen(const char *filename, const char *flags)
@ -187,7 +188,7 @@ public:
return FilePos - StartPos;
}
virtual long Seek(long offset, int origin)
virtual long Seek(long offset, int origin) override
{
switch (origin)
{
@ -212,7 +213,7 @@ public:
return -1;
}
virtual long Read(void *buffer, long len)
virtual long Read(void *buffer, long len) override
{
assert(len >= 0);
if (len <= 0) return 0;
@ -225,7 +226,7 @@ public:
return len;
}
virtual char *Gets(char *strbuf, int len)
virtual char *Gets(char *strbuf, int len) override
{
if (len <= 0 || FilePos >= StartPos + Length) return NULL;
char *p = mReader->Gets(strbuf, len);

View file

@ -304,30 +304,33 @@ public:
// They will just error out when called.
long Tell() const override;
long Seek(long offset, int origin) override;
char *Gets(char *strbuf, int len) override;
char* Gets(char* strbuf, int len) override;
void DecompressionError(const char* error, ...) const;
void SetErrorCallback(const std::function<void(const char*)>& cb)
{
ErrorCallback = cb;
}
void SetOwnsReader();
protected:
FileReader* File = nullptr;
FileReader OwnedFile;
};
class FileWriter
{
protected:
bool OpenDirect(const char *filename);
FileWriter()
{
File = NULL;
}
public:
FileWriter(FILE *f = nullptr) // if passed, this writer will take over the file.
{
File = f;
}
virtual ~FileWriter()
{
if (File != NULL) fclose(File);
Close();
}
static FileWriter *Open(const char *filename);
@ -336,6 +339,11 @@ public:
virtual long Tell();
virtual long Seek(long offset, int mode);
size_t Printf(const char *fmt, ...) GCCPRINTF(2,3);
virtual void Close()
{
if (File != NULL) fclose(File);
File = nullptr;
}
protected:
@ -354,6 +362,7 @@ public:
BufferWriter() {}
virtual size_t Write(const void *buffer, size_t len) override;
TArray<unsigned char> *GetBuffer() { return &mBuffer; }
TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); }
};

View file

@ -33,16 +33,18 @@
**
*/
// This also pulls in windows.h
// Caution: LzmaDec also pulls in windows.h!
#define NOMINMAX
#include "LzmaDec.h"
#include <zlib.h>
#include <bzlib.h>
#include <algorithm>
#include "files.h"
#include "templates.h"
#include "zstring.h"
#include "cmdlib.h"
//==========================================================================
//
// I_Error
@ -82,6 +84,12 @@ char *DecompressorBase::Gets(char *strbuf, int len)
return nullptr;
}
void DecompressorBase::SetOwnsReader()
{
OwnedFile = std::move(*File);
File = &OwnedFile;
}
//==========================================================================
//
// DecompressorZ
@ -95,17 +103,17 @@ class DecompressorZ : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
FileReader &File;
bool SawEOF;
z_stream Stream;
uint8_t InBuff[BUFF_SIZE];
public:
DecompressorZ (FileReader &file, bool zip, const std::function<void(const char*)>& cb)
: File(file), SawEOF(false)
DecompressorZ (FileReader *file, bool zip, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
int err;
File = file;
SetErrorCallback(cb);
FillBuffer ();
@ -157,7 +165,7 @@ public:
void FillBuffer ()
{
auto numread = File.Read (InBuff, BUFF_SIZE);
auto numread = File->Read (InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
@ -186,17 +194,17 @@ class DecompressorBZ2 : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
FileReader &File;
bool SawEOF;
bz_stream Stream;
uint8_t InBuff[BUFF_SIZE];
public:
DecompressorBZ2 (FileReader &file, const std::function<void(const char*)>& cb)
: File(file), SawEOF(false)
DecompressorBZ2 (FileReader *file, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
int err;
File = file;
SetErrorCallback(cb);
stupidGlobal = this;
FillBuffer ();
@ -251,7 +259,7 @@ public:
void FillBuffer ()
{
auto numread = File.Read(InBuff, BUFF_SIZE);
auto numread = File->Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
@ -295,7 +303,6 @@ class DecompressorLZMA : public DecompressorBase
{
enum { BUFF_SIZE = 4096 };
FileReader &File;
bool SawEOF;
CLzmaDec Stream;
size_t Size;
@ -305,18 +312,19 @@ class DecompressorLZMA : public DecompressorBase
public:
DecompressorLZMA (FileReader &file, size_t uncompressed_size, const std::function<void(const char*)>& cb)
: File(file), SawEOF(false)
DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function<void(const char*)>& cb)
: SawEOF(false)
{
uint8_t header[4 + LZMA_PROPS_SIZE];
int err;
File = file;
SetErrorCallback(cb);
Size = uncompressed_size;
OutProcessed = 0;
// Read zip LZMA properties header
if (File.Read(header, sizeof(header)) < (long)sizeof(header))
if (File->Read(header, sizeof(header)) < (long)sizeof(header))
{
DecompressionError("DecompressorLZMA: File too short\n");
}
@ -393,7 +401,7 @@ public:
void FillBuffer ()
{
auto numread = File.Read(InBuff, BUFF_SIZE);
auto numread = File->Read(InBuff, BUFF_SIZE);
if (numread < BUFF_SIZE)
{
@ -415,7 +423,6 @@ class DecompressorLZSS : public DecompressorBase
{
enum { BUFF_SIZE = 4096, WINDOW_SIZE = 4096, INTERNAL_BUFFER_SIZE = 128 };
FileReader &File;
bool SawEOF;
uint8_t InBuff[BUFF_SIZE];
@ -446,7 +453,7 @@ class DecompressorLZSS : public DecompressorBase
if(Stream.AvailIn)
memmove(InBuff, Stream.In, Stream.AvailIn);
auto numread = File.Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn);
auto numread = File->Read(InBuff+Stream.AvailIn, BUFF_SIZE-Stream.AvailIn);
if (numread < BUFF_SIZE)
{
@ -501,7 +508,7 @@ class DecompressorLZSS : public DecompressorBase
// Partial overlap: Copy in 2 or 3 chunks.
do
{
unsigned int copy = MIN<unsigned int>(len, pos+1);
unsigned int copy = std::min<unsigned int>(len, pos+1);
memcpy(Stream.InternalBuffer, copyStart, copy);
Stream.InternalBuffer += copy;
Stream.InternalOut += copy;
@ -533,8 +540,9 @@ class DecompressorLZSS : public DecompressorBase
}
public:
DecompressorLZSS(FileReader &file, const std::function<void(const char*)>& cb) : File(file), SawEOF(false)
DecompressorLZSS(FileReader *file, const std::function<void(const char*)>& cb) : SawEOF(false)
{
File = file;
SetErrorCallback(cb);
Stream.State = STREAM_EMPTY;
Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE;
@ -566,7 +574,7 @@ public:
break;
}
unsigned int copy = MIN<unsigned int>(Stream.InternalOut, AvailOut);
unsigned int copy = std::min<unsigned int>(Stream.InternalOut, AvailOut);
if(copy > 0)
{
memcpy(Out, Stream.WindowData, copy);
@ -599,29 +607,35 @@ public:
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function<void(const char*)>& cb)
{
DecompressorBase *dec = nullptr;
switch (method)
FileReader *p = &parent;
switch (method & ~METHOD_TRANSFEROWNER)
{
case METHOD_DEFLATE:
case METHOD_ZLIB:
dec = new DecompressorZ(parent, method == METHOD_DEFLATE, cb);
dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb);
break;
case METHOD_BZIP2:
dec = new DecompressorBZ2(parent, cb);
dec = new DecompressorBZ2(p, cb);
break;
case METHOD_LZMA:
dec = new DecompressorLZMA(parent, length, cb);
dec = new DecompressorLZMA(p, length, cb);
break;
case METHOD_LZSS:
dec = new DecompressorLZSS(parent, cb);
dec = new DecompressorLZSS(p, cb);
break;
// todo: METHOD_IMPLODE, METHOD_SHRINK
default:
return false;
}
if (method & METHOD_TRANSFEROWNER)
{
dec->SetOwnsReader();
}
dec->Length = (long)length;
if (!seekable)
{
@ -636,3 +650,4 @@ bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, b
return false;
}
}