FileSystem cleanup.
* split off the Doom specific lookup with short 8 character names into its own class and cleaned up the interface a bit. * get rid of all short name aliasing 'optimization' - modern compilers are capable of optimizing memcmp and memcpy to use equally efficient code so none of these hacks are needed anymore. * added reader for Descent 3's HOG2 format - yet another of these endless uncompressed formats with just a different directory structure...
This commit is contained in:
parent
634a646c2d
commit
a3475d3973
23 changed files with 1186 additions and 944 deletions
|
|
@ -52,28 +52,6 @@ namespace FileSys {
|
|||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define NULL_INDEX (0xffffffff)
|
||||
|
||||
static void UpperCopy(char* to, const char* from)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8 && from[i]; i++)
|
||||
to[i] = toupper(from[i]);
|
||||
for (; i < 8; i++)
|
||||
to[i] = 0;
|
||||
}
|
||||
|
||||
|
||||
//djb2
|
||||
static uint32_t MakeHash(const char* str, size_t length = SIZE_MAX)
|
||||
{
|
||||
uint32_t hash = 5381;
|
||||
uint32_t c;
|
||||
while (length-- > 0 && (c = *str++)) hash = hash * 33 + (c | 32);
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void md5Hash(FileReader& reader, uint8_t* digest)
|
||||
{
|
||||
using namespace md5;
|
||||
|
|
@ -92,11 +70,9 @@ static void md5Hash(FileReader& reader, uint8_t* digest)
|
|||
struct FileSystem::LumpRecord
|
||||
{
|
||||
FResourceFile *resfile;
|
||||
LumpShortName shortName;
|
||||
const char* LongName;
|
||||
const char* Name;
|
||||
int resindex;
|
||||
int16_t rfnum; // this is not necessarily the same as resfile's index!
|
||||
int16_t Namespace;
|
||||
int resourceId;
|
||||
int flags;
|
||||
|
||||
|
|
@ -109,52 +85,24 @@ struct FileSystem::LumpRecord
|
|||
|
||||
auto lflags = file->GetEntryFlags(fileindex);
|
||||
if (!name) name = file->getName(fileindex);
|
||||
if (lflags & RESFF_SHORTNAME)
|
||||
if ((lflags & RESFF_EMBEDDED) || !name || !*name)
|
||||
{
|
||||
UpperCopy(shortName.String, name);
|
||||
shortName.String[8] = 0;
|
||||
LongName = "";
|
||||
Namespace = file->GetEntryNamespace(fileindex);
|
||||
resourceId = -1;
|
||||
}
|
||||
else if ((lflags & RESFF_EMBEDDED) || !name || !*name)
|
||||
{
|
||||
shortName.qword = 0;
|
||||
LongName = "";
|
||||
Namespace = ns_hidden;
|
||||
Name = "";
|
||||
resourceId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LongName = name;
|
||||
Name = name;
|
||||
resourceId = file->GetEntryResourceID(fileindex);
|
||||
|
||||
// Map some directories to WAD namespaces.
|
||||
// Note that some of these namespaces don't exist in WADS.
|
||||
// CheckNumForName will handle any request for these namespaces accordingly.
|
||||
Namespace = !strncmp(LongName, "flats/", 6) ? ns_flats :
|
||||
!strncmp(LongName, "textures/", 9) ? ns_newtextures :
|
||||
!strncmp(LongName, "hires/", 6) ? ns_hires :
|
||||
!strncmp(LongName, "sprites/", 8) ? ns_sprites :
|
||||
!strncmp(LongName, "voxels/", 7) ? ns_voxels :
|
||||
!strncmp(LongName, "colormaps/", 10) ? ns_colormaps :
|
||||
!strncmp(LongName, "acs/", 4) ? ns_acslibrary :
|
||||
!strncmp(LongName, "voices/", 7) ? ns_strifevoices :
|
||||
!strncmp(LongName, "patches/", 8) ? ns_patches :
|
||||
!strncmp(LongName, "graphics/", 9) ? ns_graphics :
|
||||
!strncmp(LongName, "sounds/", 7) ? ns_sounds :
|
||||
!strncmp(LongName, "music/", 6) ? ns_music :
|
||||
!strchr(LongName, '/') ? ns_global :
|
||||
ns_hidden;
|
||||
|
||||
if (Namespace == ns_hidden) shortName.qword = 0;
|
||||
else if (strstr(LongName, ".{"))
|
||||
// allow embedding a resource ID in the name - we need to strip that out here.
|
||||
if (strstr(Name, ".{"))
|
||||
{
|
||||
std::string longName = LongName;
|
||||
std::string longName = Name;
|
||||
ptrdiff_t encodedResID = longName.find_last_of(".{");
|
||||
if (resourceId == -1 && (size_t)encodedResID != std::string::npos)
|
||||
{
|
||||
const char* p = LongName + encodedResID;
|
||||
const char* p = Name + encodedResID;
|
||||
char* q;
|
||||
int id = (int)strtoull(p + 2, &q, 10); // only decimal numbers allowed here.
|
||||
if (q[0] == '}' && (q[1] == '.' || q[1] == 0))
|
||||
|
|
@ -162,27 +110,13 @@ struct FileSystem::LumpRecord
|
|||
longName.erase(longName.begin() + encodedResID, longName.begin() + (q - p) + 1);
|
||||
resourceId = id;
|
||||
}
|
||||
LongName = sp->Strdup(longName.c_str());
|
||||
Name = sp->Strdup(longName.c_str());
|
||||
}
|
||||
}
|
||||
auto slash = strrchr(LongName, '/');
|
||||
std::string base = slash ? (slash + 1) : LongName;
|
||||
auto slash = strrchr(Name, '/');
|
||||
std::string base = slash ? (slash + 1) : Name;
|
||||
auto dot = base.find_last_of('.');
|
||||
if (dot != std::string::npos) base.resize(dot);
|
||||
UpperCopy(shortName.String, base.c_str());
|
||||
|
||||
// Since '\' can't be used as a file name's part inside a ZIP
|
||||
// we have to work around this for sprites because it is a valid
|
||||
// frame character.
|
||||
if (Namespace == ns_sprites || Namespace == ns_voxels || Namespace == ns_hires)
|
||||
{
|
||||
char* c;
|
||||
|
||||
while ((c = (char*)memchr(shortName.String, '^', 8)))
|
||||
{
|
||||
*c = '\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -223,22 +157,16 @@ void FileSystem::DeleteAll ()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// InitMultipleFiles
|
||||
// Initialize
|
||||
//
|
||||
// Pass a null terminated list of files to use. All files are optional,
|
||||
// Pass a vector of files to use. All files are optional,
|
||||
// but at least one file must be found. File names can appear multiple
|
||||
// times. The name searcher looks backwards, so a later file can
|
||||
// override an earlier one.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Printf)
|
||||
{
|
||||
std::vector<std::string> filenames = { filename };
|
||||
return InitMultipleFiles(filenames, nullptr, Printf);
|
||||
}
|
||||
|
||||
bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
bool FileSystem::InitFiles(std::vector<std::string>& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
int numfiles;
|
||||
|
||||
|
|
@ -254,9 +182,9 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
// first, check for duplicates
|
||||
if (!allowduplicates)
|
||||
{
|
||||
for (size_t i=0;i<filenames.size(); i++)
|
||||
for (size_t i = 0; i < filenames.size(); i++)
|
||||
{
|
||||
for (size_t j=i+1;j<filenames.size(); j++)
|
||||
for (size_t j = i + 1; j < filenames.size(); j++)
|
||||
{
|
||||
if (filenames[i] == filenames[j])
|
||||
{
|
||||
|
|
@ -267,7 +195,7 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
}
|
||||
}
|
||||
|
||||
for(size_t i=0;i<filenames.size(); i++)
|
||||
for (size_t i = 0; i < filenames.size(); i++)
|
||||
{
|
||||
AddFile(filenames[i].c_str(), nullptr, filter, Printf);
|
||||
|
||||
|
|
@ -282,6 +210,12 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileSystem::Initialize(std::vector<std::string>& filenames, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
if (!InitFiles(filenames, filter, Printf, allowduplicates)) return false;
|
||||
if (filter && filter->postprocessFunc) filter->postprocessFunc();
|
||||
|
||||
// [RH] Set up hash table
|
||||
|
|
@ -304,7 +238,7 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in
|
|||
fr.OpenMemoryArray(blob);
|
||||
|
||||
// wrap this into a single lump resource file (should be done a little better later.)
|
||||
auto rf = new FResourceFile(name, fr, stringpool);
|
||||
auto rf = new FResourceFile(name, fr, stringpool, 0);
|
||||
auto Entries = rf->AllocateEntries(1);
|
||||
Entries[0].FileName = rf->NormalizeFileName(ExtractBaseName(name, true).c_str());
|
||||
Entries[0].ResourceID = -1;
|
||||
|
|
@ -327,7 +261,7 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in
|
|||
// [RH] Removed reload hack
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, FileSystemFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
int startlump;
|
||||
bool isdir = false;
|
||||
|
|
@ -443,114 +377,6 @@ int FileSystem::CheckIfResourceFileLoaded (const char *name) noexcept
|
|||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckNumForName
|
||||
//
|
||||
// Returns -1 if name not found. The version with a third parameter will
|
||||
// look exclusively in the specified wad for the lump.
|
||||
//
|
||||
// [RH] Changed to use hash lookup ala BOOM instead of a linear search
|
||||
// and namespace parameter
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::CheckNumForName (const char *name, int space) const
|
||||
{
|
||||
union
|
||||
{
|
||||
char uname[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
uint32_t i;
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Let's not search for names that are longer than 8 characters and contain path separators
|
||||
// They are almost certainly full path names passed to this function.
|
||||
if (strlen(name) > 8 && strpbrk(name, "/."))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
UpperCopy (uname, name);
|
||||
i = FirstLumpIndex[MakeHash(uname, 8) % NumEntries];
|
||||
|
||||
while (i != NULL_INDEX)
|
||||
{
|
||||
|
||||
if (FileInfo[i].shortName.qword == qname)
|
||||
{
|
||||
auto &lump = FileInfo[i];
|
||||
if (lump.Namespace == space) break;
|
||||
// If the lump is from one of the special namespaces exclusive to Zips
|
||||
// the check has to be done differently:
|
||||
// If we find a lump with this name in the global namespace that does not come
|
||||
// from a Zip return that. WADs don't know these namespaces and single lumps must
|
||||
// work as well.
|
||||
auto lflags = lump.resfile->GetEntryFlags(lump.resindex);
|
||||
if (space > ns_specialzipdirectory && lump.Namespace == ns_global &&
|
||||
!((lflags ^lump.flags) & RESFF_FULLPATH)) break;
|
||||
}
|
||||
i = NextLumpIndex[i];
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
int FileSystem::CheckNumForName (const char *name, int space, int rfnum, bool exact) const
|
||||
{
|
||||
union
|
||||
{
|
||||
char uname[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
uint32_t i;
|
||||
|
||||
if (rfnum < 0)
|
||||
{
|
||||
return CheckNumForName (name, space);
|
||||
}
|
||||
|
||||
UpperCopy (uname, name);
|
||||
i = FirstLumpIndex[MakeHash (uname, 8) % NumEntries];
|
||||
|
||||
// If exact is true if will only find lumps in the same WAD, otherwise
|
||||
// also those in earlier WADs.
|
||||
|
||||
while (i != NULL_INDEX &&
|
||||
(FileInfo[i].shortName.qword != qname || FileInfo[i].Namespace != space ||
|
||||
(exact? (FileInfo[i].rfnum != rfnum) : (FileInfo[i].rfnum > rfnum)) ))
|
||||
{
|
||||
i = NextLumpIndex[i];
|
||||
}
|
||||
|
||||
return i != NULL_INDEX ? i : -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetNumForName
|
||||
//
|
||||
// Calls CheckNumForName, but bombs out if not found.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetNumForName (const char *name, int space) const
|
||||
{
|
||||
int i;
|
||||
|
||||
i = CheckNumForName (name, space);
|
||||
|
||||
if (i == -1)
|
||||
throw FileSystemException("GetNumForName: %s not found!", name);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckNumForFullName
|
||||
|
|
@ -561,7 +387,7 @@ int FileSystem::GetNumForName (const char *name, int space) const
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int namespc, bool ignoreext) const
|
||||
int FileSystem::CheckNumForFullName (const char *name, bool ignoreext) const
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
|
|
@ -576,21 +402,16 @@ int FileSystem::CheckNumForFullName (const char *name, bool trynormal, int names
|
|||
|
||||
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
|
||||
{
|
||||
if (strnicmp(name, FileInfo[i].LongName, len)) continue;
|
||||
if (FileInfo[i].LongName[len] == 0) break; // this is a full match
|
||||
if (ignoreext && FileInfo[i].LongName[len] == '.')
|
||||
if (strnicmp(name, FileInfo[i].Name, len)) continue;
|
||||
if (FileInfo[i].Name[len] == 0) break; // this is a full match
|
||||
if (ignoreext && FileInfo[i].Name[len] == '.')
|
||||
{
|
||||
// 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 + len + 1, "./") == nullptr) break;
|
||||
if (strpbrk(FileInfo[i].Name + len + 1, "./") == nullptr) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != NULL_INDEX) return i;
|
||||
|
||||
if (trynormal && strlen(name) <= 8 && !strpbrk(name, "./"))
|
||||
{
|
||||
return CheckNumForName(name, namespc);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -606,7 +427,7 @@ int FileSystem::CheckNumForFullNameInFile (const char *name, int rfnum) const
|
|||
i = FirstLumpIndex_FullName[MakeHash (name) % NumEntries];
|
||||
|
||||
while (i != NULL_INDEX &&
|
||||
(stricmp(name, FileInfo[i].LongName) || FileInfo[i].rfnum != rfnum))
|
||||
(stricmp(name, FileInfo[i].Name) || FileInfo[i].rfnum != rfnum))
|
||||
{
|
||||
i = NextLumpIndex_FullName[i];
|
||||
}
|
||||
|
|
@ -657,10 +478,10 @@ int FileSystem::FindFileWithExtensions(const char* name, const char *const *exts
|
|||
|
||||
for (i = fli[MakeHash(name) % NumEntries]; i != NULL_INDEX; i = nli[i])
|
||||
{
|
||||
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 (strnicmp(name, FileInfo[i].Name, len)) continue;
|
||||
if (FileInfo[i].Name[len] != '.') continue; // we are looking for extensions but this file doesn't have one.
|
||||
|
||||
auto cp = FileInfo[i].LongName + len + 1;
|
||||
auto cp = FileInfo[i].Name + len + 1;
|
||||
// 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.
|
||||
|
||||
|
|
@ -696,7 +517,7 @@ int FileSystem::FindResource (int resid, const char *type, int filenum) const no
|
|||
{
|
||||
if (filenum > 0 && FileInfo[i].rfnum != filenum) continue;
|
||||
if (FileInfo[i].resourceId != resid) continue;
|
||||
auto extp = strrchr(FileInfo[i].LongName, '.');
|
||||
auto extp = strrchr(FileInfo[i].Name, '.');
|
||||
if (!extp) continue;
|
||||
if (!stricmp(extp + 1, type)) return i;
|
||||
}
|
||||
|
|
@ -773,34 +594,28 @@ void FileSystem::InitHashChains (void)
|
|||
unsigned int i, j;
|
||||
|
||||
NumEntries = (uint32_t)FileInfo.size();
|
||||
Hashes.resize(8 * NumEntries);
|
||||
Hashes.resize(6 * NumEntries);
|
||||
// Mark all buckets as empty
|
||||
memset(Hashes.data(), -1, Hashes.size() * sizeof(Hashes[0]));
|
||||
FirstLumpIndex = &Hashes[0];
|
||||
NextLumpIndex = &Hashes[NumEntries];
|
||||
FirstLumpIndex_FullName = &Hashes[NumEntries * 2];
|
||||
NextLumpIndex_FullName = &Hashes[NumEntries * 3];
|
||||
FirstLumpIndex_NoExt = &Hashes[NumEntries * 4];
|
||||
NextLumpIndex_NoExt = &Hashes[NumEntries * 5];
|
||||
FirstLumpIndex_ResId = &Hashes[NumEntries * 6];
|
||||
NextLumpIndex_ResId = &Hashes[NumEntries * 7];
|
||||
FirstLumpIndex_FullName = &Hashes[NumEntries * 0];
|
||||
NextLumpIndex_FullName = &Hashes[NumEntries * 1];
|
||||
FirstLumpIndex_NoExt = &Hashes[NumEntries * 2];
|
||||
NextLumpIndex_NoExt = &Hashes[NumEntries * 3];
|
||||
FirstLumpIndex_ResId = &Hashes[NumEntries * 4];
|
||||
NextLumpIndex_ResId = &Hashes[NumEntries * 5];
|
||||
|
||||
|
||||
// Now set up the chains
|
||||
for (i = 0; i < (unsigned)NumEntries; i++)
|
||||
{
|
||||
j = MakeHash (FileInfo[i].shortName.String, 8) % NumEntries;
|
||||
NextLumpIndex[i] = FirstLumpIndex[j];
|
||||
FirstLumpIndex[j] = i;
|
||||
|
||||
// Do the same for the full paths
|
||||
if (FileInfo[i].LongName[0] != 0)
|
||||
if (FileInfo[i].Name[0] != 0)
|
||||
{
|
||||
j = MakeHash(FileInfo[i].LongName) % NumEntries;
|
||||
j = MakeHash(FileInfo[i].Name) % NumEntries;
|
||||
NextLumpIndex_FullName[i] = FirstLumpIndex_FullName[j];
|
||||
FirstLumpIndex_FullName[j] = i;
|
||||
|
||||
std::string nameNoExt = FileInfo[i].LongName;
|
||||
std::string nameNoExt = FileInfo[i].Name;
|
||||
auto dot = nameNoExt.find_last_of('.');
|
||||
auto slash = nameNoExt.find_last_of('/');
|
||||
if ((dot > slash || slash == std::string::npos) && dot != std::string::npos) nameNoExt.resize(dot);
|
||||
|
|
@ -819,24 +634,10 @@ void FileSystem::InitHashChains (void)
|
|||
Files.shrink_to_fit();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// should only be called before the hash chains are set up.
|
||||
// If done later this needs rehashing.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
LumpShortName& FileSystem::GetShortName(int i)
|
||||
{
|
||||
if ((unsigned)i >= NumEntries) throw FileSystemException("GetShortName: Invalid index");
|
||||
return FileInfo[i].shortName;
|
||||
}
|
||||
|
||||
void FileSystem::RenameFile(int num, const char* newfn)
|
||||
{
|
||||
if ((unsigned)num >= NumEntries) throw FileSystemException("RenameFile: Invalid index");
|
||||
FileInfo[num].LongName = stringpool->Strdup(newfn);
|
||||
// This does not alter the short name - call GetShortname to do that!
|
||||
FileInfo[num].Name = stringpool->Strdup(newfn);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -867,14 +668,13 @@ void FileSystem::MoveLumpsInFolder(const char *path)
|
|||
{
|
||||
auto& li = FileInfo[i];
|
||||
if (li.rfnum >= GetIwadNum()) break;
|
||||
if (strnicmp(li.LongName, path, len) == 0)
|
||||
if (strnicmp(li.Name, path, len) == 0)
|
||||
{
|
||||
auto lic = li; // make a copy before pushing.
|
||||
FileInfo.push_back(lic);
|
||||
li.LongName = ""; //nuke the name of the old record.
|
||||
li.shortName.qword = 0;
|
||||
li.Name = ""; //nuke the name of the old record.
|
||||
auto &ln = FileInfo.back();
|
||||
ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.LongName + len);
|
||||
ln.SetFromLump(li.resfile, li.resindex, rfnum, stringpool, ln.Name + len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -888,87 +688,6 @@ void FileSystem::MoveLumpsInFolder(const char *path)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLump (const char *name, int *lastlump, bool anyns)
|
||||
{
|
||||
if ((size_t)*lastlump >= FileInfo.size()) return -1;
|
||||
union
|
||||
{
|
||||
char name8[8];
|
||||
uint64_t qname;
|
||||
};
|
||||
|
||||
UpperCopy (name8, name);
|
||||
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
||||
const LumpRecord * last = FileInfo.data() + FileInfo.size();
|
||||
|
||||
LumpRecord * lump_p = FileInfo.data() + *lastlump;
|
||||
|
||||
while (lump_p < last)
|
||||
{
|
||||
if ((anyns || lump_p->Namespace == ns_global) && lump_p->shortName.qword == qname)
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
return lump;
|
||||
}
|
||||
lump_p++;
|
||||
}
|
||||
|
||||
*lastlump = NumEntries;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_FindLumpMulti
|
||||
//
|
||||
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
||||
// SNDINFO lumps. Returns everything having one of the passed names.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLumpMulti (const char **names, int *lastlump, bool anyns, int *nameindex)
|
||||
{
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
||||
const LumpRecord * last = FileInfo.data() + FileInfo.size();
|
||||
|
||||
LumpRecord * lump_p = FileInfo.data() + *lastlump;
|
||||
|
||||
while (lump_p < last)
|
||||
{
|
||||
if (anyns || lump_p->Namespace == ns_global)
|
||||
{
|
||||
|
||||
for(const char **name = names; *name != NULL; name++)
|
||||
{
|
||||
if (!strnicmp(*name, lump_p->shortName.String, 8))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
if (nameindex != NULL) *nameindex = int(name - names);
|
||||
return lump;
|
||||
}
|
||||
}
|
||||
}
|
||||
lump_p++;
|
||||
}
|
||||
|
||||
*lastlump = NumEntries;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_FindLump
|
||||
//
|
||||
// Find a named lump. Specifically allows duplicates for merging of e.g.
|
||||
// SNDINFO lumps.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
||||
{
|
||||
assert(lastlump != NULL && *lastlump >= 0);
|
||||
|
|
@ -981,7 +700,7 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
{
|
||||
while (lump_p < last)
|
||||
{
|
||||
if (!stricmp(name, lump_p->LongName))
|
||||
if (!stricmp(name, lump_p->Name))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
*lastlump = lump + 1;
|
||||
|
|
@ -995,10 +714,10 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
auto len = strlen(name);
|
||||
while (lump_p <= &FileInfo.back())
|
||||
{
|
||||
auto res = strnicmp(name, lump_p->LongName, len);
|
||||
auto res = strnicmp(name, lump_p->Name, len);
|
||||
if (res == 0)
|
||||
{
|
||||
auto p = lump_p->LongName + len;
|
||||
auto p = lump_p->Name + len;
|
||||
if (*p == 0 || (*p == '.' && strpbrk(p + 1, "./") == 0))
|
||||
{
|
||||
int lump = int(lump_p - FileInfo.data());
|
||||
|
|
@ -1017,49 +736,17 @@ int FileSystem::FindLumpFullName(const char* name, int* lastlump, bool noext)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_CheckLumpName
|
||||
// FileSystem :: GetFileName
|
||||
//
|
||||
// Returns the lump's internal name
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool FileSystem::CheckFileName (int lump, const char *name)
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return false;
|
||||
|
||||
return !strnicmp (FileInfo[lump].shortName.String, name, 8);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetLumpName
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const char* FileSystem::GetFileShortName(int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return nullptr;
|
||||
else
|
||||
return FileInfo[lump].shortName.String;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileSystem :: GetFileFullName
|
||||
//
|
||||
// Returns the lump's full name if it has one or its short name if not.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
const char *FileSystem::GetFileName (int lump, bool returnshort) const
|
||||
const char* FileSystem::GetFileName(int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return NULL;
|
||||
else if (FileInfo[lump].LongName[0] != 0)
|
||||
return FileInfo[lump].LongName;
|
||||
else if (returnshort)
|
||||
return FileInfo[lump].shortName.String;
|
||||
else return nullptr;
|
||||
else return FileInfo[lump].Name;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -1083,25 +770,6 @@ std::string FileSystem::GetFileFullPath(int lump) const
|
|||
return foo;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// GetFileNamespace
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetFileNamespace (int lump) const
|
||||
{
|
||||
if ((size_t)lump >= NumEntries)
|
||||
return ns_global;
|
||||
else
|
||||
return FileInfo[lump].Namespace;
|
||||
}
|
||||
|
||||
void FileSystem::SetFileNamespace(int lump, int ns)
|
||||
{
|
||||
if ((size_t)lump < NumEntries) FileInfo[lump].Namespace = ns;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FileSystem :: GetResourceId
|
||||
|
|
@ -1134,7 +802,7 @@ const char *FileSystem::GetResourceType(int lump) const
|
|||
return nullptr;
|
||||
else
|
||||
{
|
||||
auto p = strrchr(FileInfo[lump].LongName, '.');
|
||||
auto p = strrchr(FileInfo[lump].Name, '.');
|
||||
if (!p) return ""; // has no extension
|
||||
if (strchr(p, '/')) return ""; // the '.' is part of a directory.
|
||||
return p + 1;
|
||||
|
|
@ -1186,12 +854,12 @@ unsigned FileSystem::GetFilesInFolder(const char *inpath, std::vector<FolderEntr
|
|||
result.clear();
|
||||
for (size_t i = 0; i < FileInfo.size(); i++)
|
||||
{
|
||||
if (strncmp(FileInfo[i].LongName, path.c_str(), path.length()) == 0)
|
||||
if (strncmp(FileInfo[i].Name, path.c_str(), path.length()) == 0)
|
||||
{
|
||||
// Only if it hasn't been replaced.
|
||||
if ((unsigned)CheckNumForFullName(FileInfo[i].LongName) == i)
|
||||
if ((unsigned)CheckNumForFullName(FileInfo[i].Name) == i)
|
||||
{
|
||||
FolderEntry fe{ FileInfo[i].LongName, (uint32_t)i };
|
||||
FolderEntry fe{ FileInfo[i].Name, (uint32_t)i };
|
||||
result.push_back(fe);
|
||||
}
|
||||
}
|
||||
|
|
@ -1235,7 +903,7 @@ void FileSystem::ReadFile (int lump, void *dest)
|
|||
if (numread != size)
|
||||
{
|
||||
throw FileSystemException("W_ReadFile: only read %td of %td on '%s'\n",
|
||||
numread, size, FileInfo[lump].LongName);
|
||||
numread, size, FileInfo[lump].Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1354,6 +1022,21 @@ int FileSystem::GetFirstEntry (int rfnum) const noexcept
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetResourceFileFlags(int rfnum) const noexcept
|
||||
{
|
||||
if ((uint32_t)rfnum >= Files.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Files[rfnum]->GetFlags();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FileSystem::GetLastEntry (int rfnum) const noexcept
|
||||
{
|
||||
if ((uint32_t)rfnum >= Files.size())
|
||||
|
|
@ -1415,7 +1098,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
|
|||
if (lump < 0) return false; // Does not exist.
|
||||
|
||||
auto oldlump = FileInfo[lump];
|
||||
auto slash = strrchr(oldlump.LongName, '/');
|
||||
auto slash = strrchr(oldlump.Name, '/');
|
||||
|
||||
if (slash == nullptr)
|
||||
{
|
||||
|
|
@ -1425,7 +1108,7 @@ bool FileSystem::CreatePathlessCopy(const char *name, int id, int /*flags*/)
|
|||
|
||||
|
||||
// just create a new reference to the original data with a different name.
|
||||
oldlump.LongName = slash + 1;
|
||||
oldlump.Name = slash + 1;
|
||||
oldlump.resourceId = id;
|
||||
oldlump.flags = RESFF_FULLPATH;
|
||||
FileInfo.push_back(oldlump);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue