- transition to new FileReader interface complete, but untested.
This commit is contained in:
parent
247785bca2
commit
b14ee50d0d
31 changed files with 1253 additions and 1708 deletions
628
src/files.h
628
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<bool(TArray<uint8_t>&)> 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<uint8_t> &GetArray() { return buf; }
|
||||
|
||||
void UpdateLength() { Length = buf.Size(); }
|
||||
|
||||
protected:
|
||||
TArray<uint8_t> buf;
|
||||
};
|
||||
|
||||
|
||||
class FileWriter
|
||||
|
|
@ -491,138 +277,4 @@ public:
|
|||
TArray<unsigned char> *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<bool(TArray<uint8_t>&)> 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue