- also use the stringpool for the lump names in the filesystem.

This commit is contained in:
Christoph Oelckers 2023-08-22 01:08:14 +02:00
parent 3d673e3f20
commit 6d2047eef6

View file

@ -89,13 +89,13 @@ struct FileSystem::LumpRecord
{ {
FResourceLump *lump; FResourceLump *lump;
LumpShortName shortName; LumpShortName shortName;
std::string longName; const char* LongName;
int rfnum; int rfnum;
int Namespace; int Namespace;
int resourceId; int resourceId;
int flags; int flags;
void SetFromLump(int filenum, FResourceLump* lmp) void SetFromLump(int filenum, FResourceLump* lmp, StringPool* sp)
{ {
lump = lmp; lump = lmp;
rfnum = filenum; rfnum = filenum;
@ -105,47 +105,48 @@ struct FileSystem::LumpRecord
{ {
UpperCopy(shortName.String, lump->getName()); UpperCopy(shortName.String, lump->getName());
shortName.String[8] = 0; shortName.String[8] = 0;
longName = ""; LongName = "";
Namespace = lump->GetNamespace(); Namespace = lump->GetNamespace();
resourceId = -1; resourceId = -1;
} }
else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName()) else if ((lump->Flags & LUMPF_EMBEDDED) || !lump->getName() || !*lump->getName())
{ {
shortName.qword = 0; shortName.qword = 0;
longName = ""; LongName = "";
Namespace = ns_hidden; Namespace = ns_hidden;
resourceId = -1; resourceId = -1;
} }
else else
{ {
longName = lump->getName(); LongName = lump->getName();
resourceId = lump->GetIndexNum(); resourceId = lump->GetIndexNum();
// Map some directories to WAD namespaces. // Map some directories to WAD namespaces.
// Note that some of these namespaces don't exist in WADS. // Note that some of these namespaces don't exist in WADS.
// CheckNumForName will handle any request for these namespaces accordingly. // CheckNumForName will handle any request for these namespaces accordingly.
Namespace = !strncmp(longName.c_str(), "flats/", 6) ? ns_flats : Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats :
!strncmp(longName.c_str(), "textures/", 9) ? ns_newtextures : !strncmp(LongName, "textures/", 9) ? ns_newtextures :
!strncmp(longName.c_str(), "hires/", 6) ? ns_hires : !strncmp(LongName, "hires/", 6) ? ns_hires :
!strncmp(longName.c_str(), "sprites/", 8) ? ns_sprites : !strncmp(LongName, "sprites/", 8) ? ns_sprites :
!strncmp(longName.c_str(), "voxels/", 7) ? ns_voxels : !strncmp(LongName, "voxels/", 7) ? ns_voxels :
!strncmp(longName.c_str(), "colormaps/", 10) ? ns_colormaps : !strncmp(LongName, "colormaps/", 10) ? ns_colormaps :
!strncmp(longName.c_str(), "acs/", 4) ? ns_acslibrary : !strncmp(LongName, "acs/", 4) ? ns_acslibrary :
!strncmp(longName.c_str(), "voices/", 7) ? ns_strifevoices : !strncmp(LongName, "voices/", 7) ? ns_strifevoices :
!strncmp(longName.c_str(), "patches/", 8) ? ns_patches : !strncmp(LongName, "patches/", 8) ? ns_patches :
!strncmp(longName.c_str(), "graphics/", 9) ? ns_graphics : !strncmp(LongName, "graphics/", 9) ? ns_graphics :
!strncmp(longName.c_str(), "sounds/", 7) ? ns_sounds : !strncmp(LongName, "sounds/", 7) ? ns_sounds :
!strncmp(longName.c_str(), "music/", 6) ? ns_music : !strncmp(LongName, "music/", 6) ? ns_music :
!strchr(longName.c_str(), '/') ? ns_global : !strchr(LongName, '/') ? ns_global :
ns_hidden; ns_hidden;
if (Namespace == ns_hidden) shortName.qword = 0; if (Namespace == ns_hidden) shortName.qword = 0;
else else if (strstr(LongName, ".{"))
{ {
std::string longName = LongName;
ptrdiff_t encodedResID = longName.find_last_of(".{"); ptrdiff_t encodedResID = longName.find_last_of(".{");
if (resourceId == -1 && encodedResID != std::string::npos) if (resourceId == -1 && encodedResID != std::string::npos)
{ {
const char* p = longName.c_str() + encodedResID; const char* p = LongName + encodedResID;
char* q; char* q;
int id = (int)strtoull(p+2, &q, 10); // only decimal numbers allowed here. int id = (int)strtoull(p+2, &q, 10); // only decimal numbers allowed here.
if (q[0] == '}' && (q[1] == '.' || q[1] == 0)) if (q[0] == '}' && (q[1] == '.' || q[1] == 0))
@ -153,9 +154,10 @@ struct FileSystem::LumpRecord
longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1); longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1);
resourceId = id; resourceId = id;
} }
LongName = sp->Strdup(longName.c_str());
} }
ptrdiff_t slash = longName.find_last_of('/'); ptrdiff_t slash = longName.find_last_of('/');
std::string base = (slash != std::string::npos) ? longName.c_str() + (slash + 1) : longName.c_str(); std::string base = (slash != std::string::npos) ? LongName + (slash + 1) : LongName;
auto dot = base.find_last_of('.'); auto dot = base.find_last_of('.');
if (dot != std::string::npos) base.resize(dot); if (dot != std::string::npos) base.resize(dot);
UpperCopy(shortName.String, base.c_str()); UpperCopy(shortName.String, base.c_str());
@ -293,7 +295,7 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
void FileSystem::AddLump(FResourceLump *lump) void FileSystem::AddLump(FResourceLump *lump)
{ {
FileInfo.resize(FileInfo.size() + 1); FileInfo.resize(FileInfo.size() + 1);
FileInfo.back().SetFromLump(-1, lump); FileInfo.back().SetFromLump(-1, lump, stringpool);
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
@ -398,7 +400,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
FResourceLump *lump = resfile->GetLump(i); FResourceLump *lump = resfile->GetLump(i);
FileInfo.resize(FileInfo.size() + 1); FileInfo.resize(FileInfo.size() + 1);
FileSystem::LumpRecord* lump_p = &FileInfo.back(); FileSystem::LumpRecord* lump_p = &FileInfo.back();
lump_p->SetFromLump((int)Files.size(), lump); lump_p->SetFromLump((int)Files.size(), lump, stringpool);
} }
Files.push_back(resfile); Files.push_back(resfile);
@ -631,12 +633,12 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
{ {
if (strnicmp(name, FileInfo[i].longName.c_str(), len)) continue; if (strnicmp(name, FileInfo[i].LongName, len)) continue;
if (FileInfo[i].longName[len] == 0) break; // this is a full match if (FileInfo[i].LongName[len] == 0) break; // this is a full match
if (ignoreext && FileInfo[i].longName[len] == '.') if (ignoreext && FileInfo[i].LongName[len] == '.')
{ {
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
if (strpbrk(FileInfo[i].longName.c_str() + len + 1, "./") == nullptr) break; if (strpbrk(FileInfo[i].LongName + len + 1, "./") == nullptr) break;
} }
} }
@ -661,7 +663,7 @@ int FileSystem::CheckNumForFullName (const char *name, int rfnum)
i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries]; i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries];
while (i != NULL_INDEX && while (i != NULL_INDEX &&
(stricmp(name, FileInfo[i].longName.c_str()) || FileInfo[i].rfnum != rfnum)) (stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum))
{ {
i = NextLumpIndex_FullName[i]; i = NextLumpIndex_FullName[i];
} }
@ -712,10 +714,10 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i]) for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
{ {
if (strnicmp(name, FileInfo[i].longName.c_str(), len)) continue; if (strnicmp(name, FileInfo[i].LongName, len)) continue;
if (FileInfo[i].longName[len] != '.') continue; // we are looking for extensions but this file doesn't have one. if (FileInfo[i].LongName[len] != '.') continue; // we are looking for extensions but this file doesn't have one.
auto cp = FileInfo[i].longName.c_str() + len + 1; auto cp = FileInfo[i].LongName + len + 1;
// is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension? // is this the last '.' in the last path element, indicating that the remaining part of the name is only an extension?
if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry. if (strpbrk(cp, "./") != nullptr) continue; // No, so it cannot be a valid entry.
@ -751,7 +753,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no
{ {
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue; if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
if (FileInfo[i].resourceId != resid) continue; if (FileInfo[i].resourceId != resid) continue;
auto extp = strrchr(FileInfo[i].longName.c_str(), '.'); auto extp = strrchr(FileInfo[i].LongName, '.');
if (!extp) continue; if (!extp) continue;
if (!stricmp(extp + 1, type)) return i; if (!stricmp(extp + 1, type)) return i;
} }
@ -865,13 +867,13 @@ void FileSystem::InitHashChains (void)
FirstLumpIndex[j] = i; FirstLumpIndex[j] = i;
// Do the same for the full paths // Do the same for the full paths
if (!FileInfo[i].longName.empty()) if (FileInfo[i].LongName[0] != 0)
{ {
j = MakeHash(FileInfo[i].longName.c_str()) % NumEntries; j = MakeHash(FileInfo[i].LongName) % NumEntries;
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j]; NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
FirstLumpIndex_FullName[j] = i; FirstLumpIndex_FullName[j] = i;
auto nameNoExt = FileInfo[i].longName; std::string nameNoExt = FileInfo[i].LongName;
auto dot = nameNoExt.find_last_of('.'); auto dot = nameNoExt.find_last_of('.');
auto slash = nameNoExt.find_last_of('/'); auto slash = nameNoExt.find_last_of('/');
if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot); if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot);
@ -906,7 +908,7 @@ LumpShortName& FileSystem::GetShortName(int i)
void FileSystem::RenameFile(int num, const char* newfn) void FileSystem::RenameFile(int num, const char* newfn)
{ {
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index"); if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
FileInfo[num].longName = newfn; FileInfo[num].LongName = stringpool->Strdup(newfn);
// This does not alter the short name - call GetShortname to do that! // This does not alter the short name - call GetShortname to do that!
} }
@ -940,13 +942,13 @@ void FileSystem::MoveLumpsInFolder(const char *path)
{ {
auto& li = FileInfo[i]; auto& li = FileInfo[i];
if (li.rfnum >= GetIwadNum()) break; if (li.rfnum >= GetIwadNum()) break;
if (strnicmp(li.longName.c_str(), path, len) == 0) if (strnicmp(li.LongName, path, len) == 0)
{ {
FileInfo.push_back(li); FileInfo.push_back(li);
li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list. li.lump = &placeholderLump; // Make the old entry point to something empty. We cannot delete the lump record here because it'd require adjustment of all indices in the list.
auto &ln = FileInfo.back(); auto &ln = FileInfo.back();
ln.lump->LumpNameSetup(ln.longName.c_str() + len, stringpool); // may be able to avoid the string allocation! ln.lump->LumpNameSetup(ln.LongName + len, stringpool); // may be able to avoid the string allocation!
ln.SetFromLump(rfnum, ln.lump); ln.SetFromLump(rfnum, ln.lump, stringpool);
} }
} }
} }
@ -1045,7 +1047,7 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
{ {
while (lump_p <= &FileInfo.back()) while (lump_p <= &FileInfo.back())
{ {
if (!stricmp(name, lump_p->longName.c_str())) if (!stricmp(name, lump_p->LongName))
{ {
int lump = int(lump_p - FileInfo.data()); int lump = int(lump_p - FileInfo.data());
*lastlump = lump + 1; *lastlump = lump + 1;
@ -1059,10 +1061,10 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
auto len = strlen(name); auto len = strlen(name);
while (lump_p <= &FileInfo.back()) while (lump_p <= &FileInfo.back())
{ {
auto res = strnicmp(name, lump_p->longName.c_str(), len); auto res = strnicmp(name, lump_p->LongName, len);
if (res == 0) if (res == 0)
{ {
auto p = lump_p->longName.c_str() + len; auto p = lump_p->LongName + len;
if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0)) if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0))
{ {
int lump = int(lump_p - FileInfo.data()); int lump = int(lump_p - FileInfo.data());
@ -1119,8 +1121,8 @@ const char *FileSystem::GetFileFullName (int lump, bool returnshort) const
{ {
if ((size_t)lump >= NumEntries) if ((size_t)lump >= NumEntries)
return NULL; return NULL;
else if (!FileInfo[lump].longName.empty()) else if (FileInfo[lump].LongName[0] != 0)
return FileInfo[lump].longName.c_str(); return FileInfo[lump].LongName;
else if (returnshort) else if (returnshort)
return FileInfo[lump].shortName.String; return FileInfo[lump].shortName.String;
else return nullptr; else return nullptr;
@ -1198,7 +1200,7 @@ const char *FileSystem::GetResourceType(int lump) const
return nullptr; return nullptr;
else else
{ {
auto p = strrchr(FileInfo[lump].longName.c_str(), '.'); auto p = strrchr(FileInfo[lump].LongName, '.');
if (!p) return ""; // has no extension if (!p) return ""; // has no extension
if (strchr(p, '/')) return ""; // the '.' is part of a directory. if (strchr(p, '/')) return ""; // the '.' is part of a directory.
return p + 1; return p + 1;
@ -1250,12 +1252,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector<FolderEntr
result.clear(); result.clear();
for (size_t i = 0; i < FileInfo.size(); i++) for (size_t i = 0; i < FileInfo.size(); i++)
{ {
if (FileInfo[i].longName.find(path) == 0) if (strncmp(FileInfo[i].LongName, path.c_str(), path.length()) == 0)
{ {
// Only if it hasn't been replaced. // Only if it hasn't been replaced.
if ((unsigned)fileSystem.CheckNumForFullName(FileInfo[i].longName.c_str()) == i) if ((unsigned)fileSystem.CheckNumForFullName(FileInfo[i].LongName) == i)
{ {
FolderEntry fe{ FileInfo[i].longName.c_str(), (uint32_t)i }; FolderEntry fe{ FileInfo[i].LongName, (uint32_t)i };
result.push_back(fe); result.push_back(fe);
} }
} }
@ -1299,7 +1301,7 @@ void FileSystem::ReadFile (int lump, void *dest)
if (numread != size) if (numread != size)
{ {
throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n", throw FileSystemException("W_ReadFile: only read %ld of %ld on '%s'\n",
numread, size, FileInfo[lump].longName.c_str()); numread, size, FileInfo[lump].LongName);
} }
} }
@ -1503,9 +1505,9 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
if (lump < 0) return false; // Does not exist. if (lump < 0) return false; // Does not exist.
auto oldlump = FileInfo[lump]; auto oldlump = FileInfo[lump];
ptrdiff_t slash = oldlump.longName.find_last_of('/'); auto slash = strrchr(oldlump.LongName, '/');
if (slash == std::string::npos) if (slash == nullptr)
{ {
FileInfo[lump].flags = LUMPF_FULLPATH; FileInfo[lump].flags = LUMPF_FULLPATH;
return true; // already is pathless. return true; // already is pathless.
@ -1513,7 +1515,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
// just create a new reference to the original data with a different name. // just create a new reference to the original data with a different name.
oldlump.longName.erase(oldlump.longName.begin(), oldlump.longName.begin() + (slash + 1)); oldlump.LongName = slash + 1;
oldlump.resourceId = id; oldlump.resourceId = id;
oldlump.flags = LUMPF_FULLPATH; oldlump.flags = LUMPF_FULLPATH;
FileInfo.push_back(oldlump); FileInfo.push_back(oldlump);