- rework of the file system code.

Made more efficient by basing the lookup on names, not strings and some additions for acting as a stand-in for Blood's resource manager.
This commit is contained in:
Christoph Oelckers 2019-10-31 01:48:10 +01:00
parent 693095bffb
commit 261af9e401
10 changed files with 260 additions and 242 deletions

View file

@ -171,7 +171,7 @@ struct F7ZLump : public FResourceLump
{
int Position;
virtual int FillCache();
int ValidateCache() override;
};
@ -344,11 +344,10 @@ F7ZFile::~F7ZFile()
//
//==========================================================================
int F7ZLump::FillCache()
int F7ZLump::ValidateCache()
{
Cache.Resize(LumpSize);
static_cast<F7ZFile*>(Owner)->Archive->Extract(Position, (char*)Cache.Data());
RefCount = 1;
return 1;
}

View file

@ -57,7 +57,7 @@
struct FDirectoryLump : public FResourceLump
{
virtual FileReader NewReader();
virtual int FillCache();
int ValidateCache() override;
FString mFullPath;
};
@ -300,7 +300,7 @@ FileReader FDirectoryLump::NewReader()
//
//==========================================================================
int FDirectoryLump::FillCache()
int FDirectoryLump::ValidateCache()
{
FileReader fr;
if (!fr.OpenFile(mFullPath))
@ -311,7 +311,6 @@ int FDirectoryLump::FillCache()
LumpSize = fr.GetLength(); // keep this updated
Cache.Resize(LumpSize);
fr.Read(Cache.Data(), LumpSize);
RefCount = 1;
return 1;
}

View file

@ -73,18 +73,9 @@ bool FLumpFile::Open(bool quiet)
Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength();
Lumps[0].Flags = 0;
Lumps[0].FullName = FileName;
auto p = FileName.LastIndexOf('/');
Lumps[0].PathLen = FileName.LastIndexOf('/') + 1;
Lumps[0].ExtStart = FileName.LastIndexOf('.');
Lumps[0].LumpNameSetup(FileName.GetChars() + p);
NumLumps = 1;
if (Lumps[0].ExtStart < Lumps[0].PathLen) Lumps[0].ExtStart = -1;
/*
if (!quiet)
{
Printf("\n");
}
*/
return true;
}

View file

@ -60,7 +60,6 @@ struct RFFLump
uint8_t Flags;
char Extension[3];
char Name[8];
uint32_t IndexNum; // Used by .sfx, possibly others
};
//==========================================================================
@ -72,11 +71,9 @@ struct RFFLump
struct FRFFLump : public FUncompressedLump
{
virtual FileReader *GetReader();
virtual int FillCache();
int ValidataCache() override;
uint32_t IndexNum;
int GetIndexNum() const { return IndexNum; }
};
//==========================================================================
@ -159,7 +156,7 @@ bool FRFFFile::Open(bool quiet)
{
Lump.Flags |= LUMPF_BLOODCRYPT;
}
Lump.IndexNum = LittleLong(lumps[i].IndexNum);
Lump.ResourceId = LittleLong(lumps[i].ResourceId);
// Rearrange the name and extension to construct the fullname.
char name[13];
strncpy(name, lumps[i].Name, 8);
@ -172,14 +169,6 @@ bool FRFFFile::Open(bool quiet)
name[len+3] = lumps[i].Extension[2];
name[len+4] = 0;
Lump.LumpNameSetup(name);
if (Lump.IndexNum > 0)
{
// Create a second entry for looking up by index.
Lumps.Reserve(1);
auto& l = Lumps.Last();
l = Lumps[Lumps.Size() - 2];
snprintf(name, 13, "{%d}.%c%c%c", l.IndexNum, lumps[i].Extension[0], lumps[i].Extension[1], lumps[i].Extension[2]);
}
}
delete[] lumps;
return true;
@ -212,11 +201,11 @@ FileReader *FRFFLump::GetReader()
//
//==========================================================================
int FRFFLump::FillCache()
int FRFFLump::ValidateCache()
{
int res = FUncompressedLump::FillCache();
int res = FUncompressedLump::ValidateCache();
if (Flags & LUMPF_BLOODCRYPT)
if (res && )(Flags & LUMPF_BLOODCRYPT))
{
int cryptlen = std::min<int> (LumpSize, 256);
uint8_t *data = Cache.Data();

View file

@ -356,14 +356,13 @@ FileReader *FZipLump::GetReader()
//
//==========================================================================
int FZipLump::FillCache()
int FZipLump::ValidataCache()
{
if (Flags & LUMPFZIP_NEEDFILESTART) SetLumpAddress();
Owner->Reader.Seek(Position, FileReader::SeekSet);
Cache.Resize(LumpSize);
UncompressZipLump((char*)Cache.Data(), Owner->Reader, Method, LumpSize, CompressedSize, GPFlags);
RefCount = 1;
return 1;
}

View file

@ -23,7 +23,7 @@ struct FZipLump : public FResourceLump
unsigned CRC32;
virtual FileReader *GetReader();
virtual int FillCache();
virtual int ValidateCache() override;
private:
void SetLumpAddress();
@ -50,4 +50,4 @@ public:
};
#endif
#endif

View file

@ -43,6 +43,7 @@
#include "m_argv.h"
#include "cmdlib.h"
#include "printf.h"
#include "name.h"
//#include "c_dispatch.h"
#include "filesystem.h"
#include "superfasthash.h"
@ -120,15 +121,12 @@ int FileSystem::InitMultipleFiles (TArray<FString> &filenames, const TArray<FStr
}
// [RH] Set up hash table
Hashes.Resize(8 * NumEntries);
FirstFileIndex_BaseName = &Hashes[0];
NextFileIndex_BaseName = &Hashes[NumEntries];
FirstFileIndex_FullName = &Hashes[NumEntries*2];
NextFileIndex_FullName = &Hashes[NumEntries*3];
FirstFileIndex_NoExt = &Hashes[NumEntries*4];
NextFileIndex_NoExt = &Hashes[NumEntries*5];
FirstFileIndex_BaseExt = &Hashes[NumEntries*6];
NextFileIndex_BaseExt = &Hashes[NumEntries*7];
Hashes.Resize(NumLookupModes * 2 * NumEntries);
for (int i = 0; i < NumLookupModes; i++)
{
FirstFileIndex[i] = &Hashes[i * 2 * NumEntries];
NextFileIndex[i] = &Hashes[(i+1) * 2 * NumEntries];
}
InitHashChains ();
FileInfo.ShrinkToFit();
Files.ShrinkToFit();
@ -199,12 +197,12 @@ void FileSystem::AddFile (const char *filename, FileReader *filer)
//==========================================================================
//
// GetFileRecordCheckIfWadLoaded
// CheckIfResourceFileLoaded
//
// Returns true if the specified wad is loaded, false otherwise.
// If a fully-qualified path is specified, then the wad must match exactly.
// Otherwise, any wad with that name will work, whatever its path.
// Returns the wads index if found, or -1 if not.
// Returns true if the specified file is loaded, false otherwise.
// If a fully-qualified path is specified, then the file must match exactly.
// Otherwise, any file with that name will work, whatever its path.
// Returns the file's index if found, or -1 if not.
//
//==========================================================================
@ -237,11 +235,9 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept
//==========================================================================
//
// GetFileRecordFindFile
// FindFile
//
// Same as above but looks for a fully qualified name from a .zip
// These don't care about namespaces though because those are part
// of the path.
// Looks up a file by name, either eith or without path and extension
//
//==========================================================================
@ -253,62 +249,28 @@ int FileSystem::FindFile (const char *name, ELookupMode lookupmode, int filenum)
{
return -1;
}
uint32_t* fli;
uint32_t* nli;
FName lname(name, true);
if (lname == NAME_None) return -1;
switch (lookupmode)
{
case ELookupMode::FullName:
fli = FirstFileIndex_FullName;
nli = NextFileIndex_FullName;
break;
case ELookupMode::NoExtension:
fli = FirstFileIndex_NoExt;
nli = NextFileIndex_NoExt;
break;
case ELookupMode::BaseName:
fli = FirstFileIndex_BaseName;
nli = NextFileIndex_BaseName;
break;
case ELookupMode::BaseWithExtension:
fli = FirstFileIndex_BaseExt;
nli = NextFileIndex_BaseExt;
break;
}
auto len = strlen(name);
for (i = fli[MakeKey(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
if (lookupmode == ELookupMode::IdWithType) return -1;
int lookupindex = (int)lookupmode;
uint32_t* fli = FirstFileIndex[lookupindex];
uint32_t* nli = NextFileIndex[lookupindex];
for (i = fli[int(lname) % NumEntries]; i != NULL_INDEX; i = nli[i])
{
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
auto lump = FileInfo[i].lump;
if (FileInfo[i].rfnum != filenum) continue;
const char* fn = lump->FullName.GetChars();
const char* fnstart, * fnend;
if (lookupmode == ELookupMode::BaseName || lookupmode == ELookupMode::BaseWithExtension) fnstart = fn + lump->PathLen;
else fnstart = fn;
if ((lookupmode == ELookupMode::NoExtension || lookupmode == ELookupMode::BaseName) && lump->ExtStart >= 0) fnend = fn + lump->ExtStart;
else fnend = fn + lump->FullName.Len();
if ((fnend - fnstart) == (ptrdiff_t)len)
{
if (!strnicmp(name, fnstart, len))
{
return i;
}
}
if (lump->LumpName[lookupindex] == lname) return i;
}
return -1;
}
//==========================================================================
//
// GetFileRecordGetFile
// GetFile
//
// Calls GetFileRecordFindFile, but bombs out if not found.
// Calls FindFile, but bombs out if not found.
//
//==========================================================================
@ -328,7 +290,61 @@ int FileSystem::GetFile (const char *name, ELookupMode lookupmode, int filenum)
//==========================================================================
//
// GetFileRecordLumpLength
// FindResource
//
// Looks for content based on Blood resource IDs.
//
//==========================================================================
int FileSystem::FindResource (int resid, const char *type, int filenum) const noexcept
{
uint32_t i;
if (type == NULL)
{
return -1;
}
FName lname(type, true);
if (lname == NAME_None) return -1;
const int lookuptype = (int)ELookupMode::IdWithType
uint32_t* fli = FirstFileIndex[lookuptype];
uint32_t* nli = NextFileIndex[lookuptype];
for (i = fli[int(resid) % NumEntries]; i != NULL_INDEX; i = nli[i])
{
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
auto lump = FileInfo[i].lump;
if (lump->LumpName[lookuptype] == lname) return i;
}
return -1;
}
//==========================================================================
//
// GetResource
//
// Calls GetResource, but bombs out if not found.
//
//==========================================================================
int FileSystem::GetResource (int resid, const char *type, int filenum) const
{
int i;
i = FindResource (resid, type, lookupmode, filenum);
if (i == -1)
{
FStringf error("GetResource: %d of type %s not found!", resid, type);
throw FileSystemError(error.GetChars());
}
return i;
}
//==========================================================================
//
// LumpLength
//
// Returns the buffer size needed to load the given lump.
//
@ -379,7 +395,7 @@ int FileSystem::GetFileFlags (int lump)
//==========================================================================
//
// GetFileRecordInitHashChains
// InitHashChains
//
// Prepares the lumpinfos for hashing.
// (Hey! This looks suspiciously like something from Boom! :-)
@ -388,68 +404,26 @@ int FileSystem::GetFileFlags (int lump)
void FileSystem::InitHashChains (void)
{
char name[8];
unsigned int i, j;
// Mark all buckets as empty
memset(FirstFileIndex_BaseExt, 255, NumEntries * sizeof(FirstFileIndex_BaseExt[0]));
memset(NextFileIndex_BaseExt, 255, NumEntries * sizeof(NextFileIndex_BaseExt[0]));
memset (FirstFileIndex_BaseName, 255, NumEntries*sizeof(FirstFileIndex_BaseName[0]));
memset (NextFileIndex_BaseName, 255, NumEntries*sizeof(NextFileIndex_BaseName[0]));
memset (FirstFileIndex_FullName, 255, NumEntries*sizeof(FirstFileIndex_FullName[0]));
memset (NextFileIndex_FullName, 255, NumEntries*sizeof(NextFileIndex_FullName[0]));
memset(FirstFileIndex_NoExt, 255, NumEntries * sizeof(FirstFileIndex_NoExt[0]));
memset(NextFileIndex_NoExt, 255, NumEntries * sizeof(NextFileIndex_NoExt[0]));
memset(Hashes.Data(), 255, Hashes.Size() * sizeof(Hashes[0]));
// Now set up the chains
for (i = 0; i < (unsigned)NumEntries; i++)
for (int i = 0; i < (unsigned)NumEntries; i++)
{
// Do the same for the full paths
auto lump = FileInfo[i].lump;
auto& Name = lump->FullName;
if (Name.IsNotEmpty())
for (int l = 0; l < NumLookupModes; l++)
{
j = MakeKey(Name) % NumEntries;
NextFileIndex_FullName[i] = FirstFileIndex_FullName[j];
FirstFileIndex_FullName[j] = i;
j = MakeKey(Name + lump->PathLen) % NumEntries;
NextFileIndex_BaseExt[i] = FirstFileIndex_BaseExt[j];
FirstFileIndex_BaseExt[j] = i;
j = MakeKey(Name, lump->ExtStart) % NumEntries;
NextFileIndex_NoExt[i] = FirstFileIndex_NoExt[j];
FirstFileIndex_NoExt[j] = i;
if (lump->ExtStart > lump->PathLen)
int hash;
if (l != (int)ELookupMode::IdWithType && lump->LumpName[l] != NAME_None)
{
j = MakeKey(Name, lump->ExtStart) % NumEntries;
NextFileIndex_NoExt[i] = FirstFileIndex_NoExt[j];
FirstFileIndex_NoExt[j] = i;
j = MakeKey(Name + lump->PathLen, lump->ExtStart - lump->PathLen) % NumEntries;
NextFileIndex_BaseName[i] = FirstFileIndex_BaseName[j];
FirstFileIndex_BaseName[j] = i;
hash = int(lump->LumpName[l]) % NumEntries;
}
else
else if (lump->ResourceId > 0)
{
NextFileIndex_NoExt[i] = NextFileIndex_FullName[i];
FirstFileIndex_NoExt[i] = FirstFileIndex_FullName[i];
NextFileIndex_BaseName[i] = NextFileIndex_BaseExt[i];
FirstFileIndex_BaseName[j] = FirstFileIndex_BaseExt[i];
hash = int(lump->ResourceId) % NumEntries;
}
FString nameNoExt = Name;
auto dot = nameNoExt.LastIndexOf('.');
auto slash = nameNoExt.LastIndexOf('/');
if (dot > slash) nameNoExt.Truncate(dot);
j = MakeKey(nameNoExt) % NumEntries;
NextFileIndex_NoExt[i] = FirstFileIndex_NoExt[j];
FirstFileIndex_NoExt[j] = i;
NextFileIndex[l][hash] = FirstFileIndex[l][hash];
FirstFileIndex[l][hash] = i;
}
}
}
@ -466,36 +440,26 @@ void FileSystem::InitHashChains (void)
int FileSystem::Iterate (const char *name, int *lastlump, ELookupMode lookupmode)
{
union
{
char name8[8];
uint64_t qname;
};
FileRecord *lump_p;
int lookupindex = static_cast<int>(lookupmode);
FName lname(name, true);
assert(lastlump != NULL && *lastlump >= 0);
if (lname == NAME_None)
{
*lastlump = NumEntries;
return -1;
}
lump_p = &FileInfo[*lastlump];
auto len = strlen(name);
while (lump_p < &FileInfo[NumEntries])
{
auto lump = lump_p->lump;
const char* fn = lump->FullName.GetChars();
const char* fnstart, * fnend;
if (lookupmode == ELookupMode::BaseName || lookupmode == ELookupMode::BaseWithExtension) fnstart = fn + lump->PathLen;
else fnstart = fn;
if ((lookupmode == ELookupMode::NoExtension || lookupmode == ELookupMode::BaseName) && lump->ExtStart >= 0) fnend = fn + lump->ExtStart;
else fnend = fn + lump->FullName.Len();
if ((fnend - fnstart) == (ptrdiff_t)len)
if (lump->LumpName[lookupindex] == lname)
{
if (!strnicmp(name, fnstart, len))
{
int lump = int(lump_p - &FileInfo[0]);
*lastlump = lump + 1;
return lump;
}
int lump = int(lump_p - &FileInfo[0]);
*lastlump = lump + 1;
return lump;
}
lump_p++;
}
@ -505,7 +469,7 @@ int FileSystem::Iterate (const char *name, int *lastlump, ELookupMode lookupmode
//==========================================================================
//
// GetFileRecordGetLumpName
// GetLumpName
//
//==========================================================================
@ -514,12 +478,12 @@ const char *FileSystem::GetFileName (int lump) const
if ((size_t)lump >= NumEntries)
return nullptr;
else
return FileInfo[lump].lump->FullName;
return FileInfo[lump].lump->FullName();
}
//==========================================================================
//
// FileSystem :: GetLumpFullPath
// FileSystem :: GetFilrFullPath
//
// Returns the name of the lump's wad prefixed to the lump's full name.
//
@ -542,21 +506,21 @@ FString FileSystem::GetFileFullPath(int lump) const
//
// Returns the index number for this lump. This is *not* the lump's position
// in the lump directory, but rather a special value that RFF can associate
// with files. Other archive types will return 0, since they don't have it.
// with files. Other archive types will return -1, since they don't have it.
//
//==========================================================================
int FileSystem::GetRFFIndexNum(int lump) const
int FileSystem::GetResourceId(int lump) const
{
if ((size_t)lump >= NumEntries)
return 0;
return -1;
else
return FileInfo[lump].lump->GetIndexNum();
return FileInfo[lump].lump->ResourceId;
}
//==========================================================================
//
// GetFileRecordGetLumpFile
// GetLumpFile
//
//==========================================================================
@ -599,12 +563,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray<FolderEntry> &r
result.Clear();
for (unsigned i = 0; i < FileInfo.Size(); i++)
{
if (FileInfo[i].lump->FullName.IndexOf(path) == 0)
if (!strncmp(FileInfo[i].lump->FullName(), path, path.Len()))
{
// Only if it hasn't been replaced.
if ((unsigned)FindFile(FileInfo[i].lump->FullName) == i)
if ((unsigned)FindFile(FileInfo[i].lump->FullName()) == i)
{
result.Push({ FileInfo[i].lump->FullName.GetChars(), i });
result.Push({ FileInfo[i].lump->FullName(), i });
}
}
}
@ -633,7 +597,7 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray<FolderEntry> &r
//==========================================================================
//
// GetFileRecordReadFile
// ReadFile
//
// Loads the lump into a TArray and returns it.
//
@ -641,6 +605,9 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray<FolderEntry> &r
TArray<uint8_t> FileSystem::GetFileData(int lump, int pad)
{
if ((size_t)lump >= FileInfo.Size())
return TArray<<uint8_t>();
auto lumpr = OpenFileReader(lump);
auto size = lumpr.GetLength();
TArray<uint8_t> data(size + pad, true);
@ -655,6 +622,33 @@ TArray<uint8_t> FileSystem::GetFileData(int lump, int pad)
return data;
}
//==========================================================================
//
// Interface to the lump cache
//
//==========================================================================
const void *FileSystem::Lock(int lump)
{
if ((size_t)lump >= FileInfo.Size()) return nullptr;
auto lump = FileInfo[lump].lump;
return lump->Lock();
}
void FileSystem::Unlock(bool mayfree)
{
if ((size_t)lump >= FileInfo.Size()) return;
auto lump = FileInfo[lump].lump;
lump->Unlock(maxfree);
}
const void *FileSystem::Get(int lump)
{
if ((size_t)lump >= FileInfo.Size()) return nullptr;
auto lump = FileInfo[lump].lump;
return lump->Get();
}
//==========================================================================
//
// ReadFile - variant 2
@ -723,7 +717,7 @@ FileReader FileSystem::ReopenFileReader(int lump, bool alwayscache)
//==========================================================================
//
// GetFileRecordGetResourceFileName
// GetResourceFileName
//
// Returns the name of the given wad.
//
@ -791,7 +785,7 @@ int FileSystem::GetEntryCount (int rfnum) const noexcept
//==========================================================================
//
// GetFileRecordGetResourceFileFullName
// GetResourceFileFullName
//
// Returns the name of the given wad, including any path
//

View file

@ -49,14 +49,22 @@ struct FolderEntry
unsigned lumpnum;
};
enum class ELookupMode
enum class ELookupMode // Todo: Merge with FResourceLump::ENameType
{
FullName = 0,
NoExtension = 1,
BaseName = 2,
BaseWithExtension = 3
FullName,
NoExtension,
BaseName,
BaseWithExtension,
IdWithType,
NumLookupModes
};
enum
{
NumLookupModes = (int)ELookupMode::NumLookupModes + 1
};
class FileSystem
{
public:
@ -83,9 +91,17 @@ public:
int FindFile (const std::string &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const noexcept { return FindFile(name.c_str(), lookupmode, filenum); }
int GetFile (const std::string &name, ELookupMode lookupmode = ELookupMode::FullName, int filenum = -1) const { return GetFile(name.c_str(), lookupmode, filenum); }
int FindResource (int resid, const char *type, int filenum = -1) const noexcept;
int GetResource (int resid, const char *type, int filenum = -1) const; // Like FindFile, but throws an exception when it cannot find what it looks for.
TArray<uint8_t> GetFileData(int file, int pad = 0); // reads file into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!)
FileData ReadFile (int file);
FileData ReadFile (const char *name) { return ReadFile (GetFile (name)); }
const void *Lock(int lump);
void Unlock(bool mayfree = false);
void *Get(int lump);
FileReader OpenFileReader(int file); // opens a reader that redirects to the containing file's one.
FileReader ReopenFileReader(int file, bool alwayscache = false); // opens an independent reader.
@ -105,6 +121,7 @@ public:
unsigned GetFilesInFolder(const char *path, TArray<FolderEntry> &result, bool atomic) const;
bool IsEncryptedFile(int file) const noexcept;
int GetResourceId(int file) const;
int GetNumResourceFiles() const { return NumFiles; }
int GetNumEntries () const { return NumEntries; }
@ -117,17 +134,8 @@ protected:
TArray<FileRecord> FileInfo;
TArray<uint32_t> Hashes; // one allocation for all hash lists.
uint32_t *FirstFileIndex_BaseName; // Hash information for the base name (no path and no extension)
uint32_t *NextFileIndex_BaseName;
uint32_t* FirstFileIndex_BaseExt; // Hash information for the base name (no path and no extension)
uint32_t* NextFileIndex_BaseExt;
uint32_t *FirstFileIndex_FullName; // The same information for fully qualified paths
uint32_t *NextFileIndex_FullName;
uint32_t *FirstFileIndex_NoExt; // The same information for fully qualified paths but without the extension
uint32_t *NextFileIndex_NoExt;
uint32_t *FirstFileIndex[NumLookupModes]; // Hash information for the base name (no path and no extension)
uint32_t *NextFileIndex[NumLookupModes];
uint32_t NumFiles = 0; // Not necessarily the same as FileInfo.Size()
uint32_t NumEntries;

View file

@ -36,6 +36,7 @@
#include <zlib.h>
#include "resourcefile.h"
#include "name.h"
extern FString LumpFilter;
@ -78,16 +79,26 @@ FResourceLump::~FResourceLump()
//==========================================================================
//
// Sets up the lump name information for anything not coming from a WAD file.
// Sets up the file name information
// This is stored as FNames for various formats.
//
//==========================================================================
void FResourceLump::LumpNameSetup(FString iname)
{
PathLen = iname.LastIndexOf('/') + 1;
ExtStart = iname.LastIndexOf('.');
if (ExtStart <= PathLen) ExtStart = -1;
FullName = iname;
auto pathLen = iname.LastIndexOf('/') + 1;
LumpName[FullNameType] = iname.GetChars();
LumpName[BaseNameType] = iname.GetChars() + pathLen;
auto extStart = iname.LastIndexOf('.');
if (extStart <= pathLen) extStart = -1;
if (extStart > 0)
{
LumpName[ExtensionType] = iname.GetChars() + extStart + 1;
iname.Truncate(extStart);
}
LumpName[FullNameNoExtType] = iname.GetChars();
LumpName[BaseNameNoExtType] = iname.GetChars() + pathLen;
}
//==========================================================================
@ -100,9 +111,9 @@ void FResourceLump::LumpNameSetup(FString iname)
FCompressedBuffer FResourceLump::GetRawData()
{
FCompressedBuffer cbuf = { (unsigned)LumpSize, (unsigned)LumpSize, METHOD_STORED, 0, 0, new char[LumpSize] };
memcpy(cbuf.mBuffer, CacheLump(), LumpSize);
memcpy(cbuf.mBuffer, Lock(), LumpSize);
cbuf.mCRC32 = crc32(0, (uint8_t*)cbuf.mBuffer, LumpSize);
ReleaseCache();
Unlock(true);
return cbuf;
}
@ -135,7 +146,7 @@ FileReader FResourceLump::NewReader()
//
//==========================================================================
void *FResourceLump::CacheLump()
void *FResourceLump::Lock()
{
if (Cache.Size())
{
@ -143,7 +154,23 @@ void *FResourceLump::CacheLump()
}
else if (LumpSize > 0)
{
FillCache();
ValidateCache()
RefCount++;
}
return Cache.Data();
}
//==========================================================================
//
// Caches a lump's content without increasing the reference counter
//
//==========================================================================
void *FResourceLump::Get()
{
if (Cache.Size() == 0)
{
ValidateCache()
}
return Cache.Data();
}
@ -154,13 +181,13 @@ void *FResourceLump::CacheLump()
//
//==========================================================================
int FResourceLump::ReleaseCache()
int FResourceLump::Unlock(bool mayfree)
{
if (LumpSize > 0 && RefCount > 0)
{
if (--RefCount == 0)
{
Cache.Reset();
if (mayfree) Cache.Reset();
}
}
return RefCount;
@ -246,8 +273,7 @@ int lumpcmp(const void * a, const void * b)
{
FResourceLump * rec1 = (FResourceLump *)a;
FResourceLump * rec2 = (FResourceLump *)b;
return rec1->FullName.CompareNoCase(rec2->FullName);
return stricmp(rec1->LumpName[FResourceLump::FullNameType].GetChars(), rec2->LumpName[FResourceLump::FullNameType].GetChars());
}
//==========================================================================
@ -323,8 +349,8 @@ int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize,
for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize)
{
FResourceLump *lump = (FResourceLump *)lump_p;
assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0);
lump->LumpNameSetup(lump->FullName.Mid(filter.Len()));
assert(filter.CompareNoCase(lump->FullName(), (int)filter.Len()) == 0);
lump->LumpNameSetup(lump->FullName() + filter.Len());
}
// Move filtered lumps to the end of the lump list.
@ -370,7 +396,8 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m
for (void *p = (uint8_t *)lumps + start * lumpsize; p < stop; p = (uint8_t *)p + lumpsize)
{
FResourceLump *lump = (FResourceLump *)p;
lump->FullName = "";
for (auto &ln : lump->LumpName)
ln = NAME_None;
}
}
}
@ -403,10 +430,11 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = filter.CompareNoCase(lump->FullName(), (int)filter.Len());
if (cmp == 0)
break;
else if (cmp < 0)
else if (cmp > 0)
min = mid + 1;
else
max = mid - 1;
@ -423,7 +451,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = filter.CompareNoCase(lump->FullName(), (int)filter.Len());
// Go left on matches and right on misses.
if (cmp == 0)
max = mid - 1;
@ -438,7 +466,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{
mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len());
cmp = filter.CompareNoCase(lump->FullName(), (int)filter.Len());
// Go right on matches and left on misses.
if (cmp == 0)
min = mid + 1;
@ -457,10 +485,12 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
FResourceLump *FResourceFile::FindLump(const char *name)
{
FName lname(name, true);
if (lname == NAME_None) return nullptr;
for (unsigned i = 0; i < NumLumps; i++)
{
FResourceLump *lump = GetLump(i);
if (!stricmp(name, lump->FullName))
if (lump->LumpName[FResourceLump::FullNameType] == lname)
{
return lump;
}
@ -486,12 +516,11 @@ FileReader *FUncompressedLump::GetReader()
//
//==========================================================================
int FUncompressedLump::FillCache()
int FUncompressedLump::ValidateCache()
{
Owner->Reader.Seek(Position, FileReader::SeekSet);
Cache.Resize(LumpSize);
Owner->Reader.Read(Cache.Data(), LumpSize);
RefCount = 1;
return 1;
}
@ -546,7 +575,7 @@ FExternalLump::FExternalLump(const char *_filename, int filesize)
//
//==========================================================================
int FExternalLump::FillCache()
int FExternalLump::ValidateCache()
{
Cache.Resize(LumpSize);
FileReader f;
@ -559,6 +588,5 @@ int FExternalLump::FillCache()
{
memset(Cache.Data(), 0, LumpSize);
}
RefCount = 1;
return 1;
}

View file

@ -42,17 +42,26 @@ struct FCompressedBuffer
}
};
struct FResourceLump
{
enum ENameType
{
FullNameType,
FullNameNoExtType,
BaseNameType,
BaseNameNoExtType,
ExtensionType,
NUMNAMETYPES
};
friend class FResourceFile;
unsigned LumpSize = 0;
int RefCount = 0;
int Flags = 0;
int PathLen = 0;
int ExtStart = -1;
int ResourceId = -1;
FString FullName; // Name with extension and path
FName LumpName[NUMNAMETYPES] = {};
FResourceFile * Owner = nullptr;
TArray<uint8_t> Cache;
@ -62,20 +71,22 @@ struct FResourceLump
virtual FileReader *GetReader();
virtual FileReader NewReader();
virtual int GetFileOffset() { return -1; }
virtual int GetIndexNum() const { return 0; }
void LumpNameSetup(FString iname);
virtual FCompressedBuffer GetRawData();
void *CacheLump();
int ReleaseCache();
void *Lock(); // validates the cache and increases the refcount.
void Unlock(bool freeunrefd = false); // recreases the refcount and optionally frees the buffer
void *Get(); // validates the cache and returns a pointer without locking
// Wrappers for emulating Blood's resource system
unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; }
FString BaseName(); // don't know if these will be needed
FString Type();
const char *ResName() const { return LumpName[BaseNameNoExtType]; } needed
const char *ResType() { return LumpName[ExtensionType]; }
const char *FullName() const { return LumpName[FullNameType]; } needed
protected:
virtual int FillCache() { return -1; }
virtual int ValidateCache() { return -1; }
};
@ -127,7 +138,7 @@ struct FUncompressedLump : public FResourceLump
int Position;
virtual FileReader *GetReader();
virtual int FillCache();
int ValidateCache() override;
virtual int GetFileOffset() { return Position; }
};
@ -150,7 +161,7 @@ struct FExternalLump : public FResourceLump
FString Filename;
FExternalLump(const char *_filename, int filesize = -1);
virtual int FillCache();
virtual int ValidateCache() override;
};