mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-13 22:42:07 +00:00
- file system error management refactoring.
This commit is contained in:
parent
145450a044
commit
1dc47f91c2
19 changed files with 288 additions and 152 deletions
|
@ -1066,8 +1066,6 @@ set (PCH_SOURCES
|
|||
common/utility/m_alloc.cpp
|
||||
common/utility/utf8.cpp
|
||||
common/utility/palette.cpp
|
||||
common/utility/files.cpp
|
||||
common/utility/files_decompress.cpp
|
||||
common/utility/memarena.cpp
|
||||
common/utility/cmdlib.cpp
|
||||
common/utility/configfile.cpp
|
||||
|
@ -1084,19 +1082,6 @@ set (PCH_SOURCES
|
|||
common/thirdparty/libsmackerdec/src/HuffmanVLC.cpp
|
||||
common/thirdparty/libsmackerdec/src/LogError.cpp
|
||||
common/thirdparty/libsmackerdec/src/SmackerDecoder.cpp
|
||||
common/filesystem/filesystem.cpp
|
||||
common/filesystem/ancientzip.cpp
|
||||
common/filesystem/file_7z.cpp
|
||||
common/filesystem/file_grp.cpp
|
||||
common/filesystem/file_lump.cpp
|
||||
common/filesystem/file_rff.cpp
|
||||
common/filesystem/file_wad.cpp
|
||||
common/filesystem/file_zip.cpp
|
||||
common/filesystem/file_pak.cpp
|
||||
common/filesystem/file_whres.cpp
|
||||
common/filesystem/file_ssi.cpp
|
||||
common/filesystem/file_directory.cpp
|
||||
common/filesystem/resourcefile.cpp
|
||||
common/engine/cycler.cpp
|
||||
common/engine/d_event.cpp
|
||||
common/engine/date.cpp
|
||||
|
@ -1220,6 +1205,23 @@ set( ZDOOM_SOURCES
|
|||
common/thirdparty/math/tan.c
|
||||
common/thirdparty/math/tanh.c
|
||||
common/thirdparty/math/fastsin.cpp
|
||||
|
||||
common/filesystem/filesystem.cpp
|
||||
common/filesystem/ancientzip.cpp
|
||||
common/filesystem/file_7z.cpp
|
||||
common/filesystem/file_grp.cpp
|
||||
common/filesystem/file_lump.cpp
|
||||
common/filesystem/file_rff.cpp
|
||||
common/filesystem/file_wad.cpp
|
||||
common/filesystem/file_zip.cpp
|
||||
common/filesystem/file_pak.cpp
|
||||
common/filesystem/file_whres.cpp
|
||||
common/filesystem/file_ssi.cpp
|
||||
common/filesystem/file_directory.cpp
|
||||
common/filesystem/resourcefile.cpp
|
||||
common/filesystem/files.cpp
|
||||
common/filesystem/files_decompress.cpp
|
||||
|
||||
)
|
||||
|
||||
set( ZDOOM_NONPCH_SOURCES ${ZDOOM_SOURCES} )
|
||||
|
|
|
@ -310,7 +310,7 @@ int FZipExploder::Explode(unsigned char *out, unsigned int outsize,
|
|||
len += minMatchLen;
|
||||
dist++;
|
||||
if (bIdx + len > outsize) {
|
||||
throw CExplosionError("Not enough output space");
|
||||
return -1;
|
||||
}
|
||||
if ((unsigned int)dist > bIdx) {
|
||||
/* Anything before the first input byte is zero. */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include "files.h"
|
||||
#include "engineerrors.h"
|
||||
|
||||
class FZipExploder
|
||||
{
|
||||
|
@ -42,10 +41,4 @@ public:
|
|||
int Explode(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize, int flags);
|
||||
};
|
||||
|
||||
class CExplosionError : public CRecoverableError
|
||||
{
|
||||
public:
|
||||
CExplosionError(const char *message) : CRecoverableError(message) {}
|
||||
};
|
||||
|
||||
int ShrinkLoop(unsigned char *out, unsigned int outsize, FileReader &in, unsigned int insize);
|
|
@ -168,7 +168,7 @@ struct F7ZLump : public FResourceLump
|
|||
{
|
||||
int Position;
|
||||
|
||||
virtual int FillCache();
|
||||
virtual int FillCache() override;
|
||||
|
||||
};
|
||||
|
||||
|
@ -340,7 +340,11 @@ F7ZFile::~F7ZFile()
|
|||
int F7ZLump::FillCache()
|
||||
{
|
||||
Cache = new char[LumpSize];
|
||||
static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
|
||||
SRes code = static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, Cache);
|
||||
if (code != SZ_OK)
|
||||
{
|
||||
throw FileSystemException("Error %d reading from 7z archive", code);
|
||||
}
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -250,10 +250,13 @@ int FDirectoryLump::FillCache()
|
|||
Cache = new char[LumpSize];
|
||||
if (!fr.OpenFile(mFullPath))
|
||||
{
|
||||
memset(Cache, 0, LumpSize);
|
||||
return 0;
|
||||
throw FileSystemException("unable to open file");
|
||||
}
|
||||
auto read = fr.Read(Cache, LumpSize);
|
||||
if (read != LumpSize)
|
||||
{
|
||||
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
|
||||
}
|
||||
fr.Read(Cache, LumpSize);
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ struct RFFLump
|
|||
struct FRFFLump : public FUncompressedLump
|
||||
{
|
||||
virtual FileReader *GetReader();
|
||||
virtual int FillCache();
|
||||
virtual int FillCache() override;
|
||||
|
||||
uint32_t IndexNum;
|
||||
|
||||
|
|
|
@ -100,13 +100,19 @@ public:
|
|||
if(Compressed)
|
||||
{
|
||||
FileReader lzss;
|
||||
if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, [](const char* err) { I_Error("%s", err); }))
|
||||
if (lzss.OpenDecompressor(Owner->Reader, LumpSize, METHOD_LZSS, false, true))
|
||||
{
|
||||
lzss.Read(Cache, LumpSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
Owner->Reader.Read(Cache, LumpSize);
|
||||
{
|
||||
auto read = Owner->Reader.Read(Cache, LumpSize);
|
||||
if (read != LumpSize)
|
||||
{
|
||||
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
|
||||
}
|
||||
}
|
||||
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdexcept>
|
||||
#include "file_zip.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
|
@ -49,7 +50,7 @@
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags)
|
||||
static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int LumpSize, int CompressedSize, int GPFlags, bool exceptions)
|
||||
{
|
||||
switch (Method)
|
||||
{
|
||||
|
@ -64,7 +65,7 @@ static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int L
|
|||
case METHOD_LZMA:
|
||||
{
|
||||
FileReader frz;
|
||||
if (frz.OpenDecompressor(Reader, LumpSize, Method, false, [](const char* err) { I_Error("%s", err); }))
|
||||
if (frz.OpenDecompressor(Reader, LumpSize, Method, false, exceptions))
|
||||
{
|
||||
frz.Read(Cache, LumpSize);
|
||||
}
|
||||
|
@ -75,7 +76,11 @@ static bool UncompressZipLump(char *Cache, FileReader &Reader, int Method, int L
|
|||
case METHOD_IMPLODE:
|
||||
{
|
||||
FZipExploder exploder;
|
||||
exploder.Explode((unsigned char *)Cache, LumpSize, Reader, CompressedSize, GPFlags);
|
||||
if (exploder.Explode((unsigned char*)Cache, LumpSize, Reader, CompressedSize, GPFlags) == -1)
|
||||
{
|
||||
// decompression failed so zero the cache.
|
||||
memset(Cache, 0, LumpSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -96,7 +101,7 @@ bool FCompressedBuffer::Decompress(char *destbuffer)
|
|||
{
|
||||
FileReader mr;
|
||||
mr.OpenMemory(mBuffer, mCompressedSize);
|
||||
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags);
|
||||
return UncompressZipLump(destbuffer, mr, mMethod, mSize, mCompressedSize, mZipFlags, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -499,16 +504,7 @@ int FZipLump::FillCache()
|
|||
|
||||
Owner->Reader.Seek(Position, FileReader::SeekSet);
|
||||
Cache = new char[LumpSize];
|
||||
try
|
||||
{
|
||||
UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags);
|
||||
}
|
||||
catch (const CRecoverableError& )
|
||||
{
|
||||
// this cannot propagate the exception but also has no means to handle the error message. Damn...
|
||||
// At least don't return uninitialized memory here.
|
||||
memset(Cache, 0, LumpSize);
|
||||
}
|
||||
UncompressZipLump(Cache, Owner->Reader, Method, LumpSize, CompressedSize, GPFlags, true);
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ struct FZipLump : public FResourceLump
|
|||
unsigned CRC32;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
virtual int FillCache();
|
||||
virtual int FillCache() override;
|
||||
|
||||
private:
|
||||
void SetLumpAddress();
|
||||
|
|
|
@ -39,11 +39,36 @@
|
|||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <functional>
|
||||
#include "basics.h"
|
||||
#include "m_swap.h"
|
||||
#include "tarray.h"
|
||||
|
||||
class FileSystemException : public std::exception
|
||||
{
|
||||
protected:
|
||||
static const int MAX_FSERRORTEXT = 1024;
|
||||
char m_Message[MAX_FSERRORTEXT];
|
||||
|
||||
public:
|
||||
FileSystemException(const char* error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, error);
|
||||
vsnprintf(m_Message, MAX_FSERRORTEXT, error, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
FileSystemException(const char* error, va_list argptr)
|
||||
{
|
||||
vsnprintf(m_Message, MAX_FSERRORTEXT, error, argptr);
|
||||
}
|
||||
char const* what() const noexcept override
|
||||
{
|
||||
return m_Message;
|
||||
}
|
||||
};
|
||||
|
||||
// Zip compression methods, extended by some internal types to be passed to OpenDecompressor
|
||||
enum
|
||||
{
|
||||
|
@ -172,7 +197,7 @@ public:
|
|||
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<bool(TArray<uint8_t>&)> getter); // read contents to a buffer and return a reader to it
|
||||
bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function<void(const char*)>& cb); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
|
||||
bool OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, bool exceptions = false); // creates a decompressor stream. 'seekable' uses a buffered version so that the Seek and Tell methods can be used.
|
||||
|
||||
Size Tell() const
|
||||
{
|
||||
|
@ -306,7 +331,7 @@ public:
|
|||
|
||||
class DecompressorBase : public FileReaderInterface
|
||||
{
|
||||
std::function<void(const char*)> ErrorCallback = nullptr;
|
||||
bool exceptions = false;
|
||||
public:
|
||||
// These do not work but need to be defined to satisfy the FileReaderInterface.
|
||||
// They will just error out when called.
|
||||
|
@ -314,11 +339,8 @@ public:
|
|||
long Seek(long offset, int origin) 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();
|
||||
void EnableExceptions(bool on) { exceptions = on; }
|
||||
|
||||
protected:
|
||||
FileReader* File = nullptr;
|
|
@ -47,25 +47,22 @@
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// I_Error
|
||||
// DecompressionError
|
||||
//
|
||||
// Throw an error that will send us to the console if we are far enough
|
||||
// along in the startup process.
|
||||
// Allows catching errors from the decompressor. The default is just to
|
||||
// return failure from the calling function.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void DecompressorBase::DecompressionError(const char *error, ...) const
|
||||
{
|
||||
const int MAX_ERRORTEXT = 300;
|
||||
va_list argptr;
|
||||
char errortext[MAX_ERRORTEXT];
|
||||
|
||||
va_start(argptr, error);
|
||||
vsnprintf(errortext, MAX_ERRORTEXT, error, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (ErrorCallback != nullptr) ErrorCallback(errortext);
|
||||
else throw std::runtime_error(errortext);
|
||||
if (exceptions)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, error);
|
||||
throw FileSystemException(error, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
}
|
||||
|
||||
long DecompressorBase::Tell () const
|
||||
|
@ -103,18 +100,22 @@ class DecompressorZ : public DecompressorBase
|
|||
{
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
bool SawEOF;
|
||||
bool SawEOF = false;
|
||||
z_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
public:
|
||||
DecompressorZ (FileReader *file, bool zip, const std::function<void(const char*)>& cb)
|
||||
: SawEOF(false)
|
||||
bool Open (FileReader *file, bool zip)
|
||||
{
|
||||
if (File != nullptr)
|
||||
{
|
||||
DecompressionError("File already open");
|
||||
return false;
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
File = file;
|
||||
SetErrorCallback(cb);
|
||||
FillBuffer ();
|
||||
|
||||
Stream.zalloc = Z_NULL;
|
||||
|
@ -126,7 +127,9 @@ public:
|
|||
if (err != Z_OK)
|
||||
{
|
||||
DecompressionError ("DecompressorZ: inflateInit failed: %s\n", M_ZLibError(err).GetChars());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
~DecompressorZ ()
|
||||
|
@ -138,6 +141,12 @@ public:
|
|||
{
|
||||
int err;
|
||||
|
||||
if (File == nullptr)
|
||||
{
|
||||
DecompressionError("File not open");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream.next_out = (Bytef *)buffer;
|
||||
Stream.avail_out = len;
|
||||
|
||||
|
@ -153,11 +162,13 @@ public:
|
|||
if (err != Z_OK && err != Z_STREAM_END)
|
||||
{
|
||||
DecompressionError ("Corrupt zlib stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
DecompressionError ("Ran out of data in zlib stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return len - Stream.avail_out;
|
||||
|
@ -194,18 +205,22 @@ class DecompressorBZ2 : public DecompressorBase
|
|||
{
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
bool SawEOF;
|
||||
bool SawEOF = false;
|
||||
bz_stream Stream;
|
||||
uint8_t InBuff[BUFF_SIZE];
|
||||
|
||||
public:
|
||||
DecompressorBZ2 (FileReader *file, const std::function<void(const char*)>& cb)
|
||||
: SawEOF(false)
|
||||
bool Open(FileReader *file)
|
||||
{
|
||||
if (File != nullptr)
|
||||
{
|
||||
DecompressionError("File already open");
|
||||
return false;
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
File = file;
|
||||
SetErrorCallback(cb);
|
||||
stupidGlobal = this;
|
||||
FillBuffer ();
|
||||
|
||||
|
@ -218,7 +233,9 @@ public:
|
|||
if (err != BZ_OK)
|
||||
{
|
||||
DecompressionError ("DecompressorBZ2: bzDecompressInit failed: %d\n", err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
~DecompressorBZ2 ()
|
||||
|
@ -229,6 +246,12 @@ public:
|
|||
|
||||
long Read (void *buffer, long len) override
|
||||
{
|
||||
if (File == nullptr)
|
||||
{
|
||||
DecompressionError("File not open");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
stupidGlobal = this;
|
||||
|
@ -247,11 +270,13 @@ public:
|
|||
if (err != BZ_OK && err != BZ_STREAM_END)
|
||||
{
|
||||
DecompressionError ("Corrupt bzip2 stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Stream.avail_out != 0)
|
||||
{
|
||||
DecompressionError ("Ran out of data in bzip2 stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return len - Stream.avail_out;
|
||||
|
@ -303,7 +328,7 @@ class DecompressorLZMA : public DecompressorBase
|
|||
{
|
||||
enum { BUFF_SIZE = 4096 };
|
||||
|
||||
bool SawEOF;
|
||||
bool SawEOF = false;
|
||||
CLzmaDec Stream;
|
||||
size_t Size;
|
||||
size_t InPos, InSize;
|
||||
|
@ -312,13 +337,17 @@ class DecompressorLZMA : public DecompressorBase
|
|||
|
||||
public:
|
||||
|
||||
DecompressorLZMA (FileReader *file, size_t uncompressed_size, const std::function<void(const char*)>& cb)
|
||||
: SawEOF(false)
|
||||
bool Open(FileReader *file, size_t uncompressed_size)
|
||||
{
|
||||
if (File != nullptr)
|
||||
{
|
||||
DecompressionError("File already open");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t header[4 + LZMA_PROPS_SIZE];
|
||||
int err;
|
||||
File = file;
|
||||
SetErrorCallback(cb);
|
||||
|
||||
Size = uncompressed_size;
|
||||
OutProcessed = 0;
|
||||
|
@ -327,11 +356,13 @@ public:
|
|||
if (File->Read(header, sizeof(header)) < (long)sizeof(header))
|
||||
{
|
||||
DecompressionError("DecompressorLZMA: File too short\n");
|
||||
return false;
|
||||
}
|
||||
if (header[2] + header[3] * 256 != LZMA_PROPS_SIZE)
|
||||
{
|
||||
DecompressionError("DecompressorLZMA: LZMA props size is %d (expected %d)\n",
|
||||
header[2] + header[3] * 256, LZMA_PROPS_SIZE);
|
||||
return false;
|
||||
}
|
||||
|
||||
FillBuffer();
|
||||
|
@ -342,9 +373,11 @@ public:
|
|||
if (err != SZ_OK)
|
||||
{
|
||||
DecompressionError("DecompressorLZMA: LzmaDec_Allocate failed: %d\n", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
LzmaDec_Init(&Stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
~DecompressorLZMA ()
|
||||
|
@ -354,6 +387,12 @@ public:
|
|||
|
||||
long Read (void *buffer, long len) override
|
||||
{
|
||||
if (File == nullptr)
|
||||
{
|
||||
DecompressionError("File not open");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int err;
|
||||
Byte *next_out = (Byte *)buffer;
|
||||
|
||||
|
@ -372,12 +411,14 @@ public:
|
|||
if (err != SZ_OK)
|
||||
{
|
||||
DecompressionError ("Corrupt LZMA stream");
|
||||
return 0;
|
||||
}
|
||||
if (in_processed == 0 && out_processed == 0)
|
||||
{
|
||||
if (status != LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
DecompressionError ("Corrupt LZMA stream");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (InSize == 0 && !SawEOF)
|
||||
|
@ -389,11 +430,13 @@ public:
|
|||
if (err != Z_OK && err != Z_STREAM_END)
|
||||
{
|
||||
DecompressionError ("Corrupt LZMA stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
DecompressionError ("Ran out of data in LZMA stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (long)(next_out - (Byte *)buffer);
|
||||
|
@ -540,16 +583,22 @@ class DecompressorLZSS : public DecompressorBase
|
|||
}
|
||||
|
||||
public:
|
||||
DecompressorLZSS(FileReader *file, const std::function<void(const char*)>& cb) : SawEOF(false)
|
||||
bool Open(FileReader *file)
|
||||
{
|
||||
if (File != nullptr)
|
||||
{
|
||||
DecompressionError("File already open");
|
||||
return false;
|
||||
}
|
||||
|
||||
File = file;
|
||||
SetErrorCallback(cb);
|
||||
Stream.State = STREAM_EMPTY;
|
||||
Stream.WindowData = Stream.InternalBuffer = Stream.Window+WINDOW_SIZE;
|
||||
Stream.InternalOut = 0;
|
||||
Stream.AvailIn = 0;
|
||||
|
||||
FillBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
~DecompressorLZSS()
|
||||
|
@ -604,50 +653,91 @@ public:
|
|||
};
|
||||
|
||||
|
||||
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, const std::function<void(const char*)>& cb)
|
||||
bool FileReader::OpenDecompressor(FileReader &parent, Size length, int method, bool seekable, bool exceptions)
|
||||
{
|
||||
DecompressorBase *dec = nullptr;
|
||||
FileReader *p = &parent;
|
||||
switch (method & ~METHOD_TRANSFEROWNER)
|
||||
DecompressorBase* dec = nullptr;
|
||||
try
|
||||
{
|
||||
FileReader* p = &parent;
|
||||
switch (method & ~METHOD_TRANSFEROWNER)
|
||||
{
|
||||
case METHOD_DEFLATE:
|
||||
case METHOD_ZLIB:
|
||||
dec = new DecompressorZ(p, method == METHOD_DEFLATE, cb);
|
||||
{
|
||||
auto idec = new DecompressorZ;
|
||||
dec = idec;
|
||||
idec->EnableExceptions(exceptions);
|
||||
if (!idec->Open(p, method == METHOD_DEFLATE))
|
||||
{
|
||||
delete idec;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case METHOD_BZIP2:
|
||||
dec = new DecompressorBZ2(p, cb);
|
||||
{
|
||||
auto idec = new DecompressorBZ2;
|
||||
dec = idec;
|
||||
idec->EnableExceptions(exceptions);
|
||||
if (!idec->Open(p))
|
||||
{
|
||||
delete idec;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case METHOD_LZMA:
|
||||
dec = new DecompressorLZMA(p, length, cb);
|
||||
{
|
||||
auto idec = new DecompressorLZMA;
|
||||
dec = idec;
|
||||
idec->EnableExceptions(exceptions);
|
||||
if (!idec->Open(p, length))
|
||||
{
|
||||
delete idec;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case METHOD_LZSS:
|
||||
dec = new DecompressorLZSS(p, cb);
|
||||
{
|
||||
auto idec = new DecompressorLZSS;
|
||||
dec = idec;
|
||||
idec->EnableExceptions(exceptions);
|
||||
if (!idec->Open(p))
|
||||
{
|
||||
delete idec;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// todo: METHOD_IMPLODE, METHOD_SHRINK
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (method & METHOD_TRANSFEROWNER)
|
||||
{
|
||||
dec->SetOwnsReader();
|
||||
}
|
||||
}
|
||||
if (method & METHOD_TRANSFEROWNER)
|
||||
{
|
||||
dec->SetOwnsReader();
|
||||
}
|
||||
|
||||
dec->Length = (long)length;
|
||||
if (!seekable)
|
||||
{
|
||||
Close();
|
||||
mReader = dec;
|
||||
return true;
|
||||
dec->Length = (long)length;
|
||||
if (!seekable)
|
||||
{
|
||||
Close();
|
||||
mReader = dec;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: create a wrapper. for now this fails
|
||||
delete dec;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (...)
|
||||
{
|
||||
// todo: create a wrapper. for now this fails
|
||||
delete dec;
|
||||
return false;
|
||||
if (dec) delete dec;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
@ -569,7 +569,7 @@ int FileSystem::GetNumForName (const char *name, int space)
|
|||
i = CheckNumForName (name, space);
|
||||
|
||||
if (i == -1)
|
||||
I_Error ("GetNumForName: %s not found!", name);
|
||||
throw FileSystemException("GetNumForName: %s not found!", name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ int FileSystem::GetNumForFullName (const char *name)
|
|||
i = CheckNumForFullName (name);
|
||||
|
||||
if (i == -1)
|
||||
I_Error ("GetNumForFullName: %s not found!", name);
|
||||
throw FileSystemException("GetNumForFullName: %s not found!", name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ int FileSystem::GetResource (int resid, const char *type, int filenum) const
|
|||
|
||||
if (i == -1)
|
||||
{
|
||||
I_Error("GetResource: %d of type %s not found!", resid, type);
|
||||
throw FileSystemException("GetResource: %d of type %s not found!", resid, type);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -922,19 +922,19 @@ void FileSystem::InitHashChains (void)
|
|||
|
||||
LumpShortName& FileSystem::GetShortName(int i)
|
||||
{
|
||||
if ((unsigned)i >= NumEntries) I_Error("GetShortName: Invalid index");
|
||||
if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index");
|
||||
return FileInfo[i].shortName;
|
||||
}
|
||||
|
||||
FString& FileSystem::GetLongName(int i)
|
||||
{
|
||||
if ((unsigned)i >= NumEntries) I_Error("GetLongName: Invalid index");
|
||||
if ((unsigned)i >= NumEntries) throw FileSystemException("GetLongName: Invalid index");
|
||||
return FileInfo[i].longName;
|
||||
}
|
||||
|
||||
void FileSystem::RenameFile(int num, const char* newfn)
|
||||
{
|
||||
if ((unsigned)num >= NumEntries) I_Error("RenameFile: Invalid index");
|
||||
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
|
||||
FileInfo[num].longName = newfn;
|
||||
// This does not alter the short name - call GetShortname to do that!
|
||||
}
|
||||
|
@ -1345,7 +1345,7 @@ TArray<uint8_t> FileSystem::GetFileData(int lump, int pad)
|
|||
|
||||
if (numread != size)
|
||||
{
|
||||
I_Error("GetFileData: only read %ld of %ld on lump %i\n",
|
||||
throw FileSystemException("GetFileData: only read %ld of %ld on lump %i\n",
|
||||
numread, size, lump);
|
||||
}
|
||||
if (pad > 0) memset(&data[size], 0, pad);
|
||||
|
@ -1367,8 +1367,8 @@ void FileSystem::ReadFile (int lump, void *dest)
|
|||
|
||||
if (numread != size)
|
||||
{
|
||||
I_Error ("W_ReadFile: only read %ld of %ld on lump %i\n",
|
||||
numread, size, lump);
|
||||
throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n",
|
||||
numread, size, GetLongName(lump).GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1399,7 +1399,7 @@ FileReader FileSystem::OpenFileReader(int lump)
|
|||
{
|
||||
if ((unsigned)lump >= (unsigned)FileInfo.Size())
|
||||
{
|
||||
I_Error("OpenFileReader: %u >= NumEntries", lump);
|
||||
throw FileSystemException("OpenFileReader: %u >= NumEntries", lump);
|
||||
}
|
||||
|
||||
auto rl = FileInfo[lump].lump;
|
||||
|
@ -1418,7 +1418,7 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache)
|
|||
{
|
||||
if ((unsigned)lump >= (unsigned)FileInfo.Size())
|
||||
{
|
||||
I_Error("ReopenFileReader: %u >= NumEntries", lump);
|
||||
throw FileSystemException("ReopenFileReader: %u >= NumEntries", lump);
|
||||
}
|
||||
|
||||
auto rl = FileInfo[lump].lump;
|
||||
|
@ -1619,7 +1619,7 @@ FString::FString (ELumpNum lumpnum)
|
|||
|
||||
if (numread != size)
|
||||
{
|
||||
I_Error ("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
|
||||
throw FileSystemException("ConstructStringFromLump: Only read %ld of %ld bytes on lump %i (%s)\n",
|
||||
numread, size, lumpnum, fileSystem.GetFileFullName((int)lumpnum));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,15 @@ void *FResourceLump::Lock()
|
|||
}
|
||||
else if (LumpSize > 0)
|
||||
{
|
||||
FillCache();
|
||||
try
|
||||
{
|
||||
FillCache();
|
||||
}
|
||||
catch (const FileSystemException& err)
|
||||
{
|
||||
// enrich the message with info about this lump.
|
||||
throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.GetChars(), err.what());
|
||||
}
|
||||
}
|
||||
return Cache;
|
||||
}
|
||||
|
@ -609,7 +617,13 @@ int FUncompressedLump::FillCache()
|
|||
|
||||
Owner->Reader.Seek(Position, FileReader::SeekSet);
|
||||
Cache = new char[LumpSize];
|
||||
Owner->Reader.Read(Cache, LumpSize);
|
||||
|
||||
auto read = Owner->Reader.Read(Cache, LumpSize);
|
||||
if (read != LumpSize)
|
||||
{
|
||||
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
|
||||
}
|
||||
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
}
|
||||
|
@ -672,11 +686,15 @@ int FExternalLump::FillCache()
|
|||
|
||||
if (f.OpenFile(Filename))
|
||||
{
|
||||
f.Read(Cache, LumpSize);
|
||||
auto read = f.Read(Cache, LumpSize);
|
||||
if (read != LumpSize)
|
||||
{
|
||||
throw FileSystemException("only read %d of %d bytes", (int)read, (int)LumpSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(Cache, 0, LumpSize);
|
||||
throw FileSystemException("unable to open file");
|
||||
}
|
||||
RefCount = 1;
|
||||
return 1;
|
||||
|
|
|
@ -190,7 +190,7 @@ struct FUncompressedLump : public FResourceLump
|
|||
int Position;
|
||||
|
||||
virtual FileReader *GetReader();
|
||||
virtual int FillCache();
|
||||
virtual int FillCache() override;
|
||||
virtual int GetFileOffset() { return Position; }
|
||||
|
||||
};
|
||||
|
@ -213,7 +213,7 @@ struct FExternalLump : public FResourceLump
|
|||
FString Filename;
|
||||
|
||||
FExternalLump(const char *_filename, int filesize = -1);
|
||||
virtual int FillCache();
|
||||
virtual int FillCache() override;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -59,13 +59,13 @@ public:
|
|||
strncpy (m_Message, message, MAX_ERRORTEXT-1);
|
||||
m_Message[MAX_ERRORTEXT-1] = '\0';
|
||||
}
|
||||
void AppendMessage(const char *message)
|
||||
void AppendMessage(const char *message) noexcept
|
||||
{
|
||||
size_t len = strlen(m_Message);
|
||||
strncpy(m_Message + len, message, MAX_ERRORTEXT - 1 - len);
|
||||
m_Message[MAX_ERRORTEXT - 1] = '\0';
|
||||
}
|
||||
const char *GetMessage (void) const
|
||||
const char *GetMessage (void) const noexcept
|
||||
{
|
||||
if (m_Message[0] != '\0')
|
||||
return (const char *)m_Message;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
int utf8_encode(int32_t codepoint, uint8_t *buffer, int *size);
|
||||
int utf8_decode(const uint8_t *src, int *size);
|
||||
int GetCharFromString(const uint8_t *&string);
|
||||
|
|
|
@ -1233,7 +1233,7 @@ void D_DoomLoop ()
|
|||
return;
|
||||
}
|
||||
}
|
||||
catch (CRecoverableError &error)
|
||||
catch (const CRecoverableError &error)
|
||||
{
|
||||
if (error.GetMessage ())
|
||||
{
|
||||
|
@ -1241,6 +1241,14 @@ void D_DoomLoop ()
|
|||
}
|
||||
D_ErrorCleanup ();
|
||||
}
|
||||
catch (const FileSystemException& error) // in case this propagates up to here it should be treated as a recoverable error.
|
||||
{
|
||||
if (error.what())
|
||||
{
|
||||
Printf(PRINT_NONOTIFY | PRINT_BOLD, "\n%s\n", error.what());
|
||||
}
|
||||
D_ErrorCleanup();
|
||||
}
|
||||
catch (CVMAbortException &error)
|
||||
{
|
||||
error.MaybePrintMessage();
|
||||
|
|
|
@ -733,45 +733,36 @@ bool MapLoader::LoadExtendedNodes (FileReader &dalump, uint32_t id)
|
|||
if (compressed)
|
||||
{
|
||||
FileReader zip;
|
||||
try
|
||||
if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false, true))
|
||||
{
|
||||
if (zip.OpenDecompressor(dalump, -1, METHOD_ZLIB, false, [](const char* err) { I_Error("%s", err); }))
|
||||
{
|
||||
LoadZNodes(zip, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("Error loading nodes: Corrupt data.\n");
|
||||
return false;
|
||||
}
|
||||
LoadZNodes(zip, type);
|
||||
return true;
|
||||
}
|
||||
catch (const CRecoverableError& err)
|
||||
else
|
||||
{
|
||||
Printf("Error loading nodes: %s.\n", err.what());
|
||||
|
||||
ForceNodeBuild = true;
|
||||
Level->subsectors.Clear();
|
||||
Level->segs.Clear();
|
||||
Level->nodes.Clear();
|
||||
return false;
|
||||
Printf("Error loading nodes: Corrupt data.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadZNodes(dalump, type);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (CRecoverableError &error)
|
||||
{
|
||||
Printf("Error loading nodes: %s\n", error.GetMessage());
|
||||
|
||||
ForceNodeBuild = true;
|
||||
Level->subsectors.Clear();
|
||||
Level->segs.Clear();
|
||||
Level->nodes.Clear();
|
||||
return false;
|
||||
}
|
||||
catch (FileSystemException& error)
|
||||
{
|
||||
Printf("Error loading nodes: %s\n", error.what());
|
||||
}
|
||||
// clean up.
|
||||
ForceNodeBuild = true;
|
||||
Level->subsectors.Clear();
|
||||
Level->segs.Clear();
|
||||
Level->nodes.Clear();
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
@ -3349,9 +3340,10 @@ void MapLoader::LoadLightmap(MapData *map)
|
|||
return;
|
||||
|
||||
FileReader fr;
|
||||
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, METHOD_ZLIB, false, [](const char* err) { I_Error("%s", err); }))
|
||||
if (!fr.OpenDecompressor(map->Reader(ML_LIGHTMAP), -1, METHOD_ZLIB, false, false))
|
||||
return;
|
||||
|
||||
|
||||
int version = fr.ReadInt32();
|
||||
if (version != 0)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue