diff --git a/source/common/filesystem/file_7z.cpp b/source/common/filesystem/file_7z.cpp index 04dfad073..1516f8d32 100644 --- a/source/common/filesystem/file_7z.cpp +++ b/source/common/filesystem/file_7z.cpp @@ -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(Owner)->Archive->Extract(Position, (char*)Cache.Data()); - RefCount = 1; return 1; } diff --git a/source/common/filesystem/file_directory.cpp b/source/common/filesystem/file_directory.cpp index 1cfc68a90..167658a09 100644 --- a/source/common/filesystem/file_directory.cpp +++ b/source/common/filesystem/file_directory.cpp @@ -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; } diff --git a/source/common/filesystem/file_lump.cpp b/source/common/filesystem/file_lump.cpp index e33bb96e0..50344f225 100644 --- a/source/common/filesystem/file_lump.cpp +++ b/source/common/filesystem/file_lump.cpp @@ -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; } diff --git a/source/common/filesystem/file_rff.cpp b/source/common/filesystem/file_rff.cpp index 035ddfda6..8c5cbf1d0 100644 --- a/source/common/filesystem/file_rff.cpp +++ b/source/common/filesystem/file_rff.cpp @@ -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 (LumpSize, 256); uint8_t *data = Cache.Data(); diff --git a/source/common/filesystem/file_zip.cpp b/source/common/filesystem/file_zip.cpp index f4814b435..19b7569ab 100644 --- a/source/common/filesystem/file_zip.cpp +++ b/source/common/filesystem/file_zip.cpp @@ -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; } diff --git a/source/common/filesystem/file_zip.h b/source/common/filesystem/file_zip.h index 466292e40..81da48a7d 100644 --- a/source/common/filesystem/file_zip.h +++ b/source/common/filesystem/file_zip.h @@ -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 \ No newline at end of file +#endif diff --git a/source/common/filesystem/filesystem.cpp b/source/common/filesystem/filesystem.cpp index 30ecfcd5f..ac9d62a48 100644 --- a/source/common/filesystem/filesystem.cpp +++ b/source/common/filesystem/filesystem.cpp @@ -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 &filenames, const TArray 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(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 &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 &r //========================================================================== // -// GetFileRecordReadFile +// ReadFile // // Loads the lump into a TArray and returns it. // @@ -641,6 +605,9 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, TArray &r TArray FileSystem::GetFileData(int lump, int pad) { + if ((size_t)lump >= FileInfo.Size()) + return TArray<(); + auto lumpr = OpenFileReader(lump); auto size = lumpr.GetLength(); TArray data(size + pad, true); @@ -655,6 +622,33 @@ TArray 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 // diff --git a/source/common/filesystem/filesystem.h b/source/common/filesystem/filesystem.h index fc4674b4e..016f05cbc 100644 --- a/source/common/filesystem/filesystem.h +++ b/source/common/filesystem/filesystem.h @@ -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 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 &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 FileInfo; TArray 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; diff --git a/source/common/filesystem/resourcefile.cpp b/source/common/filesystem/resourcefile.cpp index f3ce78c8f..984c16384 100644 --- a/source/common/filesystem/resourcefile.cpp +++ b/source/common/filesystem/resourcefile.cpp @@ -36,6 +36,7 @@ #include #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; } diff --git a/source/common/filesystem/resourcefile.h b/source/common/filesystem/resourcefile.h index d131c9608..4b62ee180 100644 --- a/source/common/filesystem/resourcefile.h +++ b/source/common/filesystem/resourcefile.h @@ -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 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; };