mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
- added an abstract FileReader wrapper.
The idea here is to decouple the actual reader creation from the code using them so that, for example, the Open function can decide if it wants to open the file regularly or memory mapped and return different readers as deemed useful. For that to work the exposed object needs to be an abstract wrapper so that this can be done without having to use pointers and all the drawbacks coming from that. So far put to use in a few parts of the music code so the general functionality could be tested.
This commit is contained in:
parent
fc981bf5d4
commit
26e948357e
12 changed files with 242 additions and 28 deletions
|
@ -687,3 +687,31 @@ size_t BufferWriter::Write(const void *buffer, size_t len)
|
|||
return len;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
//
|
||||
// The new wrapper
|
||||
//
|
||||
//////////////////////////////////////
|
||||
|
||||
bool FileRdr::OpenFile(const char *filename)
|
||||
{
|
||||
mReader = new FileReader;
|
||||
if (mReader->Open(filename)) return true;
|
||||
delete mReader;
|
||||
mReader = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileRdr::OpenMemory(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
mReader = new MemoryReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileRdr::OpenMemoryArray(const void *mem, FileRdr::Size length)
|
||||
{
|
||||
mReader = new MemoryArrayReader((const char *)mem, (long)length);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
157
src/files.h
157
src/files.h
|
@ -167,6 +167,61 @@ 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
|
||||
{
|
||||
FileReader *mReader;
|
||||
public:
|
||||
FileReaderRedirect(FileReader *parent, long start, long length)
|
||||
{
|
||||
mReader = parent;
|
||||
StartPos = start;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Wraps around a FileReader to decompress a zlib stream
|
||||
class FileReaderZ : public FileReaderBase
|
||||
{
|
||||
|
@ -438,4 +493,106 @@ public:
|
|||
|
||||
|
||||
|
||||
|
||||
class FileRdr // this is just a temporary name, until the old FileReader hierarchy can be made private.
|
||||
{
|
||||
FileReader *mReader = nullptr;
|
||||
|
||||
FileRdr() {}
|
||||
FileRdr(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(FileReader *r)
|
||||
{
|
||||
mReader = r;
|
||||
}
|
||||
|
||||
FileRdr(FileRdr &&r)
|
||||
{
|
||||
mReader = r.mReader;
|
||||
r.mReader = nullptr;
|
||||
}
|
||||
|
||||
~FileRdr()
|
||||
{
|
||||
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.
|
||||
|
||||
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
|
||||
|
|
|
@ -309,7 +309,7 @@ MusInfo *MusInfo::GetWaveDumper(const char *filename, int rate)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static MIDISource *CreateMIDISource(FileReader &reader, EMIDIType miditype)
|
||||
static MIDISource *CreateMIDISource(FileRdr &reader, EMIDIType miditype)
|
||||
{
|
||||
MIDISource *source = nullptr;
|
||||
switch (miditype)
|
||||
|
@ -452,11 +452,14 @@ MusInfo *I_RegisterSong (FileReader *reader, MidiDeviceSetting *device)
|
|||
EMIDIType miditype = IdentifyMIDIType(id, sizeof(id));
|
||||
if (miditype != MIDI_NOTMIDI)
|
||||
{
|
||||
auto source = CreateMIDISource(*reader, miditype);
|
||||
// temporary hack so we can test before converting more.
|
||||
FileRdr rdr(reader);
|
||||
reader = nullptr;
|
||||
|
||||
auto source = CreateMIDISource(rdr, miditype);
|
||||
if (source == nullptr) return 0;
|
||||
if (!source->isValid())
|
||||
{
|
||||
delete reader;
|
||||
delete source;
|
||||
return 0;
|
||||
}
|
||||
|
@ -719,10 +722,10 @@ static MIDISource *GetMIDISource(const char *fn)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
FWadLump wlump = Wads.OpenLumpNum(lump);
|
||||
auto wlump = Wads.OpenLumpReader(lump);
|
||||
uint32_t id[32 / 4];
|
||||
|
||||
if (wlump.Read(id, 32) != 32 || wlump.Seek(-32, SEEK_CUR) != 0)
|
||||
if (wlump.Read(id, 32) != 32 || wlump.Seek(-32, FileRdr::SeekCur) != 0)
|
||||
{
|
||||
Printf("Unable to read lump %s\n", src.GetChars());
|
||||
return nullptr;
|
||||
|
|
|
@ -83,7 +83,9 @@ OPLMIDIDevice::OPLMIDIDevice(const char *args)
|
|||
{
|
||||
OPL_SetCore(args);
|
||||
FullPan = opl_fullpan;
|
||||
FWadLump data = Wads.OpenLumpName("GENMIDI");
|
||||
auto lump = Wads.CheckNumForName("GENMIDI", ns_global);
|
||||
if (lump < 0) I_Error("No GENMIDI lump found");
|
||||
auto data = Wads.OpenLumpReader(lump);
|
||||
|
||||
uint8_t filehdr[8];
|
||||
data.Read(filehdr, 8);
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
class MUSSong2 : public MIDISource
|
||||
{
|
||||
public:
|
||||
MUSSong2(FileReader &reader);
|
||||
MUSSong2(FileRdr &reader);
|
||||
~MUSSong2();
|
||||
|
||||
protected:
|
||||
|
@ -99,7 +99,7 @@ private:
|
|||
class MIDISong2 : public MIDISource
|
||||
{
|
||||
public:
|
||||
MIDISong2(FileReader &reader);
|
||||
MIDISong2(FileRdr &reader);
|
||||
~MIDISong2();
|
||||
|
||||
protected:
|
||||
|
@ -153,7 +153,7 @@ protected:
|
|||
class HMISong : public MIDISource
|
||||
{
|
||||
public:
|
||||
HMISong(FileReader &reader);
|
||||
HMISong(FileRdr &reader);
|
||||
~HMISong();
|
||||
|
||||
protected:
|
||||
|
@ -193,7 +193,7 @@ private:
|
|||
class XMISong : public MIDISource
|
||||
{
|
||||
public:
|
||||
XMISong(FileReader &reader);
|
||||
XMISong(FileRdr &reader);
|
||||
~XMISong();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -126,9 +126,9 @@ struct HMISong::TrackInfo
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
HMISong::HMISong (FileReader &reader)
|
||||
HMISong::HMISong (FileRdr &reader)
|
||||
{
|
||||
int len = reader.GetLength();
|
||||
auto len = reader.GetLength();
|
||||
if (len < 0x100)
|
||||
{ // Way too small to be HMI.
|
||||
return;
|
||||
|
|
|
@ -33,11 +33,6 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#if !defined(__FreeBSD__) && !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "i_musicinterns.h"
|
||||
#include "templates.h"
|
||||
#include "doomdef.h"
|
||||
|
@ -93,7 +88,7 @@ static const uint8_t CtrlTranslate[15] =
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MUSSong2::MUSSong2 (FileReader &reader)
|
||||
MUSSong2::MUSSong2 (FileRdr &reader)
|
||||
: MusHeader(0), MusBuffer(0)
|
||||
{
|
||||
uint8_t front[32];
|
||||
|
|
|
@ -99,13 +99,13 @@ struct MIDISong2::TrackInfo
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
MIDISong2::MIDISong2 (FileReader &reader)
|
||||
MIDISong2::MIDISong2 (FileRdr &reader)
|
||||
: MusHeader(0), Tracks(0)
|
||||
{
|
||||
int p;
|
||||
int i;
|
||||
|
||||
SongLen = reader.GetLength();
|
||||
SongLen = (int)reader.GetLength();
|
||||
MusHeader = new uint8_t[SongLen];
|
||||
if (reader.Read(MusHeader, SongLen) != SongLen)
|
||||
return;
|
||||
|
|
|
@ -105,10 +105,10 @@ struct XMISong::TrackInfo
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
XMISong::XMISong (FileReader &reader)
|
||||
XMISong::XMISong (FileRdr &reader)
|
||||
: MusHeader(0), Songs(0)
|
||||
{
|
||||
SongLen = reader.GetLength();
|
||||
SongLen = (int)reader.GetLength();
|
||||
MusHeader = new uint8_t[SongLen];
|
||||
if (reader.Read(MusHeader, SongLen) != SongLen)
|
||||
return;
|
||||
|
|
|
@ -590,7 +590,7 @@ int LoadDMXGUS()
|
|||
if (lump == -1) lump = Wads.CheckNumForName("DMXGUSC");
|
||||
if (lump == -1) return LoadConfig(midi_config);
|
||||
|
||||
FWadLump data = Wads.OpenLumpNum(lump);
|
||||
auto data = Wads.OpenLumpReader(lump);
|
||||
if (data.GetLength() == 0) return LoadConfig(midi_config);
|
||||
|
||||
// Check if we got some GUS data before using it.
|
||||
|
@ -613,7 +613,7 @@ int LoadDMXGUS()
|
|||
gus_sfreader.reset(psreader);
|
||||
|
||||
char readbuffer[1024];
|
||||
long size = data.GetLength();
|
||||
auto size = data.GetLength();
|
||||
long read = 0;
|
||||
uint8_t remap[256];
|
||||
|
||||
|
@ -624,7 +624,7 @@ int LoadDMXGUS()
|
|||
int status = -1;
|
||||
int gusbank = (gus_memsize >= 1 && gus_memsize <= 4) ? gus_memsize : -1;
|
||||
|
||||
data.Seek(0, SEEK_SET);
|
||||
data.Seek(0, FileRdr::SeekSet);
|
||||
|
||||
while (data.Gets(readbuffer, 1024) && read < size)
|
||||
{
|
||||
|
|
|
@ -1352,6 +1352,34 @@ FWadLump *FWadCollection::ReopenLumpNumNewFile (int lump)
|
|||
return new FWadLump(lump, LumpInfo[lump].lump);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenLumpReader
|
||||
//
|
||||
// uses a more abstract interface to allow for easier low level optimization later
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FileRdr FWadCollection::ReopenLumpReader(int lump, bool alwayscache)
|
||||
{
|
||||
FileRdr rdr;
|
||||
rdr.mReader = alwayscache ? ReopenLumpNumNewFile(lump) : ReopenLumpNum(lump);
|
||||
return rdr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -177,13 +177,13 @@ public:
|
|||
FMemLump ReadLump (int lump);
|
||||
FMemLump ReadLump (const char *name) { return ReadLump (GetNumForName (name)); }
|
||||
|
||||
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 OpenLumpName (const char *name) { return OpenLumpNum (GetNumForName (name)); }
|
||||
FWadLump *ReopenLumpNum (int lump); // Opens a new, independent FILE
|
||||
FWadLump *ReopenLumpNumNewFile (int lump); // Opens a new, independent FILE
|
||||
|
||||
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
|
||||
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
|
||||
|
@ -237,6 +237,7 @@ private:
|
|||
void RenameNerve();
|
||||
void FixMacHexen();
|
||||
void DeleteAll();
|
||||
FileReader * GetFileReader(int wadnum); // Gets a FileReader object to the entire WAD
|
||||
};
|
||||
|
||||
extern FWadCollection Wads;
|
||||
|
|
Loading…
Reference in a new issue