- first stage of uncoupling the file system from the engine.

This replaces several FStrings and TArrays with std::string and std::vector.
This commit is contained in:
Christoph Oelckers 2023-08-18 22:46:31 +02:00
parent 2524ea6b0e
commit 5a32f98bde
9 changed files with 150 additions and 110 deletions

View file

@ -36,9 +36,7 @@
// Note that 7z made the unwise decision to include windows.h :( // Note that 7z made the unwise decision to include windows.h :(
#include "7z.h" #include "7z.h"
#include "7zCrc.h" #include "7zCrc.h"
#include "resourcefile.h" #include "resourcefile.h"
#include "cmdlib.h"
@ -228,7 +226,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
Archive = NULL; Archive = NULL;
if (res == SZ_ERROR_UNSUPPORTED) if (res == SZ_ERROR_UNSUPPORTED)
{ {
Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Decoder does not support this archive\n", FileName.c_str());
} }
else if (res == SZ_ERROR_MEM) else if (res == SZ_ERROR_MEM)
{ {
@ -251,8 +249,8 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
Lumps = new F7ZLump[NumLumps]; Lumps = new F7ZLump[NumLumps];
F7ZLump *lump_p = Lumps; F7ZLump *lump_p = Lumps;
TArray<UInt16> nameUTF16; std::u16string nameUTF16;
TArray<char> nameASCII; std::string nameASCII;
for (uint32_t i = 0; i < NumLumps; ++i) for (uint32_t i = 0; i < NumLumps; ++i)
{ {
@ -271,19 +269,17 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
continue; continue;
} }
nameUTF16.Resize((unsigned)nameLength); nameUTF16.resize((unsigned)nameLength);
nameASCII.Resize((unsigned)nameLength); nameASCII.resize((unsigned)nameLength);
SzArEx_GetFileNameUtf16(archPtr, i, &nameUTF16[0]); // note that the file system is not equipped to handle non-ASCII, so don't bother with proper Unicode conversion here.
SzArEx_GetFileNameUtf16(archPtr, i, (UInt16*)nameUTF16.data());
for (size_t c = 0; c < nameLength; ++c) for (size_t c = 0; c < nameLength; ++c)
{ {
nameASCII[c] = static_cast<char>(nameUTF16[c]); nameASCII[c] = tolower(static_cast<char>(nameUTF16[c]));
if (nameASCII[c] == '\\') nameASCII[c] = '/';
} }
FixPathSeperator(&nameASCII[0]);
FString name = &nameASCII[0]; lump_p->LumpNameSetup(nameASCII.c_str());
name.ToLower();
lump_p->LumpNameSetup(name);
lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i)); lump_p->LumpSize = static_cast<int>(SzArEx_GetFileSize(archPtr, i));
lump_p->Owner = this; lump_p->Owner = this;
lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED; lump_p->Flags = LUMPF_FULLPATH|LUMPF_COMPRESSED;
@ -303,7 +299,7 @@ bool F7ZFile::Open(LumpFilterInfo *filter, FileSystemMessageFunc Printf)
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
{ {
Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: unsupported 7z/LZMA file!\n", FileName.c_str());
return false; return false;
} }
} }

View file

@ -84,7 +84,7 @@ public:
//========================================================================== //==========================================================================
FDirectory::FDirectory(const char * directory, bool nosubdirflag) FDirectory::FDirectory(const char * directory, bool nosubdirflag)
: FResourceFile(NULL), nosubdir(nosubdirflag) : FResourceFile(""), nosubdir(nosubdirflag)
{ {
FString dirname; FString dirname;
@ -194,7 +194,7 @@ int FDirectory::AddDirectory(const char *dirpath, FileSystemMessageFunc Printf)
bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf) bool FDirectory::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
{ {
NumLumps = AddDirectory(FileName, Printf); NumLumps = AddDirectory(FileName.c_str(), Printf);
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter); PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump), filter);
return true; return true;
} }
@ -213,11 +213,11 @@ void FDirectory::AddEntry(const char *fullpath, int size)
lump_p->mFullPath = fullpath; lump_p->mFullPath = fullpath;
// [mxd] Convert name to lowercase // [mxd] Convert name to lowercase
FString name = fullpath + strlen(FileName); std::string name = fullpath + FileName.length();
name.ToLower(); for (auto& c : name) c = tolower(c);
// The lump's name is only the part relative to the main directory // The lump's name is only the part relative to the main directory
lump_p->LumpNameSetup(name); lump_p->LumpNameSetup(name.c_str());
lump_p->LumpSize = size; lump_p->LumpSize = size;
lump_p->Owner = this; lump_p->Owner = this;
lump_p->Flags = 0; lump_p->Flags = 0;

View file

@ -68,10 +68,8 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file)
bool FLumpFile::Open(LumpFilterInfo*) bool FLumpFile::Open(LumpFilterInfo*)
{ {
FString name(ExtractFileBase(FileName, true));
Lumps.Resize(1); Lumps.Resize(1);
Lumps[0].LumpNameSetup(name); Lumps[0].LumpNameSetup(ExtractBaseName(FileName.c_str(), true).c_str());
Lumps[0].Owner = this; Lumps[0].Owner = this;
Lumps[0].Position = 0; Lumps[0].Position = 0;
Lumps[0].LumpSize = (int)Reader.GetLength(); Lumps[0].LumpSize = (int)Reader.GetLength();

View file

@ -181,7 +181,7 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
// Check again to detect broken wads // Check again to detect broken wads
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize) if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
{ {
Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Bad directory offset.\n", FileName.c_str());
return false; return false;
} }
} }
@ -201,10 +201,10 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
// This requires explicit toggling for precisely the files that need it. // This requires explicit toggling for precisely the files that need it.
#if 0 #if 0
Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80; Lumps[i].Compressed = !(gameinfo.flags & GI_SHAREWARE) && (n[0] & 0x80) == 0x80;
n[0] &= ~0x80;
#else #else
Lumps[i].Compressed = false; Lumps[i].Compressed = false;
#endif #endif
n[0] &= ~0x80;
Lumps[i].LumpNameSetup(n); Lumps[i].LumpNameSetup(n);
Lumps[i].Owner = this; Lumps[i].Owner = this;
@ -218,7 +218,7 @@ bool FWadFile::Open(LumpFilterInfo*, FileSystemMessageFunc Printf)
{ {
if (Lumps[i].LumpSize != 0) if (Lumps[i].LumpSize != 0)
{ {
Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].getName()); Printf(FSMessageLevel::Warning, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.c_str(), Lumps[i].getName());
Lumps[i].LumpNameSetup(""); Lumps[i].LumpNameSetup("");
} }
Lumps[i].LumpSize = Lumps[i].Position = 0; Lumps[i].LumpSize = Lumps[i].Position = 0;
@ -303,7 +303,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{ {
if (numendmarkers == 0) return; // no markers found if (numendmarkers == 0) return; // no markers found
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.GetChars(), endmarker, startmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker);
if (flathack) if (flathack)
@ -317,7 +317,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
{ {
// We can't add this to the flats namespace but // We can't add this to the flats namespace but
// it needs to be flagged for the texture manager. // it needs to be flagged for the texture manager.
Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName.GetChars(), Lumps[ii].getName()); Printf(FSMessageLevel::DebugNotify, "%s: Marking %s as potential flat\n", FileName.c_str(), Lumps[ii].getName());
Lumps[ii].Flags |= LUMPF_MAYBEFLAT; Lumps[ii].Flags |= LUMPF_MAYBEFLAT;
} }
} }
@ -331,7 +331,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
int start, end; int start, end;
if (markers[i].markertype != 0) if (markers[i].markertype != 0)
{ {
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.GetChars(), endmarker, startmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), endmarker, startmarker);
i++; i++;
continue; continue;
} }
@ -340,21 +340,21 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// skip over subsequent x_START markers // skip over subsequent x_START markers
while (i < markers.Size() && markers[i].markertype == 0) while (i < markers.Size() && markers[i].markertype == 0)
{ {
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.GetChars(), startmarker); Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), startmarker);
i++; i++;
continue; continue;
} }
// same for x_END markers // same for x_END markers
while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1)) while (i < markers.Size()-1 && (markers[i].markertype == 1 && markers[i+1].markertype == 1))
{ {
Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.GetChars(), endmarker); Printf(FSMessageLevel::Warning, "%s: duplicate %s marker found.\n", FileName.c_str(), endmarker);
i++; i++;
continue; continue;
} }
// We found a starting marker but no end marker. Ignore this block. // We found a starting marker but no end marker. Ignore this block.
if (i >= markers.Size()) if (i >= markers.Size())
{ {
Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.GetChars(), startmarker, endmarker); Printf(FSMessageLevel::Warning, "%s: %s marker without corresponding %s found.\n", FileName.c_str(), startmarker, endmarker);
end = NumLumps; end = NumLumps;
} }
else else
@ -363,14 +363,14 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
} }
// we found a marked block // we found a marked block
Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName.GetChars(), startmarker, markers[start].index, end); Printf(FSMessageLevel::DebugNotify, "%s: Found %s block at (%d-%d)\n", FileName.c_str(), startmarker, markers[start].index, end);
for(int j = markers[start].index + 1; j < end; j++) for(int j = markers[start].index + 1; j < end; j++)
{ {
if (Lumps[j].Namespace != ns_global) if (Lumps[j].Namespace != ns_global)
{ {
if (!warned) if (!warned)
{ {
Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName.GetChars(), j); Printf(FSMessageLevel::Warning, "%s: Overlapping namespaces found (lump %d)\n", FileName.c_str(), j);
} }
warned = true; warned = true;
} }
@ -380,7 +380,7 @@ void FWadFile::SetNamespace(const char *startmarker, const char *endmarker, name
// ignore sprite lumps smaller than 8 bytes (the smallest possible) // ignore sprite lumps smaller than 8 bytes (the smallest possible)
// in size -- this was used by some dmadds wads // in size -- this was used by some dmadds wads
// as an 'empty' graphics resource // as an 'empty' graphics resource
Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName.GetChars(), Lumps[j].getName(), j); Printf(FSMessageLevel::DebugWarn, "%s: Skipped empty sprite %s (lump %d)\n", FileName.c_str(), Lumps[j].getName(), j);
} }
else else
{ {
@ -450,7 +450,7 @@ void FWadFile::SkinHack (FileSystemMessageFunc Printf)
} }
if (skinned && hasmap) if (skinned && hasmap)
{ {
Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName.GetChars()); Printf(FSMessageLevel::Attention, "%s: The maps will not be loaded because it has a skin.\n", FileName.c_str());
Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n"); Printf(FSMessageLevel::Attention, "You should remove the skin from the wad to play these maps.\n");
} }
} }

View file

@ -179,7 +179,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (centraldir == 0) if (centraldir == 0)
{ {
Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: ZIP file corrupt!\n", FileName.c_str());
return false; return false;
} }
@ -195,7 +195,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (info.NumEntries != info.NumEntriesOnAllDisks || if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0) info.FirstDisk != 0 || info.DiskNumber != 0)
{ {
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str());
return false; return false;
} }
@ -214,7 +214,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (info.NumEntries != info.NumEntriesOnAllDisks || if (info.NumEntries != info.NumEntriesOnAllDisks ||
info.FirstDisk != 0 || info.DiskNumber != 0) info.FirstDisk != 0 || info.DiskNumber != 0)
{ {
Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Multipart Zip files are not supported.\n", FileName.c_str());
return false; return false;
} }
@ -253,7 +253,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{ {
free(directory); free(directory);
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str());
return false; return false;
} }
@ -267,7 +267,8 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (!foundprefix) if (!foundprefix)
{ {
// check for special names, if one of these gets found this must be treated as a normal zip. // check for special names, if one of these gets found this must be treated as a normal zip.
bool isspecial = name.IndexOf("/") < 0 || (filter && filter->reservedFolders.Find(name) < filter->reservedFolders.Size()); bool isspecial = name.IndexOf("/") < 0 ||
(filter && std::find(filter->reservedFolders.begin(), filter->reservedFolders.end(), name.GetChars()) != filter->reservedFolders.end());
if (isspecial) break; if (isspecial) break;
name0 = name.Left(name.LastIndexOf("/")+1); name0 = name.Left(name.LastIndexOf("/")+1);
name1 = name.Left(name.IndexOf("/") + 1); name1 = name.Left(name.IndexOf("/") + 1);
@ -292,7 +293,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
// at least one of the more common definition lumps must be present. // at least one of the more common definition lumps must be present.
for (auto &p : filter->requiredPrefixes) for (auto &p : filter->requiredPrefixes)
{ {
if (name.IndexOf(name0 + p) == 0 || name.LastIndexOf(p) == ptrdiff_t(name.Len() - strlen(p))) if (name.IndexOf(name0 + p.c_str()) == 0 || name.LastIndexOf(p.c_str()) == ptrdiff_t(name.Len() - p.length()))
{ {
foundspeciallump = true; foundspeciallump = true;
break; break;
@ -319,7 +320,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
{ {
free(directory); free(directory);
Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.GetChars()); Printf(FSMessageLevel::Error, "%s: Central directory corrupted.", FileName.c_str());
return false; return false;
} }
@ -346,7 +347,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_IMPLODE &&
zip_fh->Method != METHOD_SHRINK) zip_fh->Method != METHOD_SHRINK)
{ {
Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method); Printf(FSMessageLevel::Error, "%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.c_str(), name.GetChars(), zip_fh->Method);
skipped++; skipped++;
continue; continue;
} }
@ -354,7 +355,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
zip_fh->Flags = LittleShort(zip_fh->Flags); zip_fh->Flags = LittleShort(zip_fh->Flags);
if (zip_fh->Flags & ZF_ENCRYPTED) if (zip_fh->Flags & ZF_ENCRYPTED)
{ {
Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars()); Printf(FSMessageLevel::Error, "%s: '%s' is encrypted. Encryption is not supported.\n", FileName.c_str(), name.GetChars());
skipped++; skipped++;
continue; continue;
} }
@ -381,7 +382,7 @@ bool FZipFile::Open(LumpFilterInfo* filter, FileSystemMessageFunc Printf)
if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff) if (zip_64->CompressedSize > 0x7fffffff || zip_64->UncompressedSize > 0x7fffffff)
{ {
// The file system is limited to 32 bit file sizes; // The file system is limited to 32 bit file sizes;
Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName.GetChars(), name.GetChars()); Printf(FSMessageLevel::Warning, "%s: '%s' is too large.\n", FileName.c_str(), name.GetChars());
skipped++; skipped++;
continue; continue;
} }

View file

@ -233,7 +233,7 @@ bool FileSystem::InitMultipleFiles (TArray<FString> &filenames, LumpFilterInfo*
AddFile (filenames[i], nullptr, filter, Printf, hashfile); AddFile (filenames[i], nullptr, filter, Printf, hashfile);
if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/"); if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/");
FStringf path("filter/%s", Files.Last()->GetHash().GetChars()); FStringf path("filter/%s", Files.Last()->GetHash());
MoveLumpsInFolder(path); MoveLumpsInFolder(path);
} }
@ -1449,9 +1449,9 @@ const char *FileSystem::GetResourceFileName (int rfnum) const noexcept
return NULL; return NULL;
} }
name = Files[rfnum]->FileName; name = Files[rfnum]->FileName.c_str();
slash = strrchr (name, '/'); slash = strrchr (name, '/');
return (slash != NULL && slash[1] != 0) ? slash+1 : name; return (slash != nullptr && slash[1] != 0) ? slash+1 : name;
} }
//========================================================================== //==========================================================================
@ -1515,7 +1515,7 @@ const char *FileSystem::GetResourceFileFullName (int rfnum) const noexcept
return nullptr; return nullptr;
} }
return Files[rfnum]->FileName; return Files[rfnum]->FileName.c_str();
} }

View file

@ -40,6 +40,42 @@
#include "md5.h" #include "md5.h"
std::string ExtractBaseName(const char* path, bool include_extension)
{
const char* src, * dot;
src = path + strlen(path) - 1;
if (src >= path)
{
// back up until a / or the start
while (src != path && src[-1] != '/' && src[-1] != '\\') // check both on all systems for consistent behavior with archives.
src--;
if (!include_extension && (dot = strrchr(src, '.')))
{
return std::string(src, dot - src);
}
else
{
return std::string(src);
}
}
return std::string();
}
void strReplace(std::string& str, const char *from, const char* to)
{
if (*from == 0)
return;
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, strlen(from), to);
start_pos += strlen(to);
}
}
//========================================================================== //==========================================================================
// //
// File reader that reads from a lump's cache // File reader that reads from a lump's cache
@ -88,10 +124,10 @@ FResourceLump::~FResourceLump()
// //
//========================================================================== //==========================================================================
void FResourceLump::LumpNameSetup(FString iname) void FResourceLump::LumpNameSetup(const char *iname)
{ {
// this causes interference with real Dehacked lumps. // this causes interference with real Dehacked lumps.
if (!iname.CompareNoCase("dehacked.exe")) if (!stricmp(iname, "dehacked.exe"))
{ {
iname = ""; iname = "";
} }
@ -115,24 +151,24 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
return false; return false;
} }
const FString dirName = ExtractFileBase(archive->FileName); const auto dirName = ExtractBaseName(archive->FileName.c_str());
const FString fileName = ExtractFileBase(resPath, true); const auto fileName = ExtractBaseName(resPath, true);
const FString filePath = dirName + '/' + fileName; const std::string filePath = dirName + '/' + fileName;
return 0 == filePath.CompareNoCase(resPath); return 0 == stricmp(filePath.c_str(), resPath);
} }
void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi) void FResourceLump::CheckEmbedded(LumpFilterInfo* lfi)
{ {
// Checks for embedded archives // Checks for embedded archives
const char *c = strstr(FullName, ".wad"); const char *c = strstr(FullName.c_str(), ".wad");
if (c && strlen(c) == 4 && (!strchr(FullName, '/') || IsWadInFolder(Owner, FullName))) if (c && strlen(c) == 4 && (!strchr(FullName.c_str(), '/') || IsWadInFolder(Owner, FullName.c_str())))
{ {
Flags |= LUMPF_EMBEDDED; Flags |= LUMPF_EMBEDDED;
} }
else if (lfi) for (auto& fstr : lfi->embeddings) else if (lfi) for (auto& fstr : lfi->embeddings)
{ {
if (!stricmp(FullName, fstr)) if (!stricmp(FullName.c_str(), fstr.c_str()))
{ {
Flags |= LUMPF_EMBEDDED; Flags |= LUMPF_EMBEDDED;
} }
@ -200,7 +236,7 @@ void *FResourceLump::Lock()
catch (const FileSystemException& err) catch (const FileSystemException& err)
{ {
// enrich the message with info about this lump. // enrich the message with info about this lump.
throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.GetChars(), err.what()); throw FileSystemException("%s, file '%s': %s", getName(), Owner->FileName.c_str(), err.what());
} }
} }
return Cache; return Cache;
@ -323,7 +359,7 @@ void FResourceFile::GenerateHash()
{ {
// hash the lump directory after sorting // hash the lump directory after sorting
Hash.Format(("%08X-%04X-"), (unsigned)Reader.GetLength(), NumLumps); auto n = snprintf(Hash, 48, "%08X-%04X-", (unsigned)Reader.GetLength(), NumLumps);
MD5Context md5; MD5Context md5;
@ -331,13 +367,13 @@ void FResourceFile::GenerateHash()
for(uint32_t i = 0; i < NumLumps; i++) for(uint32_t i = 0; i < NumLumps; i++)
{ {
auto lump = GetLump(i); auto lump = GetLump(i);
md5.Update((const uint8_t*)lump->FullName.GetChars(), (unsigned)lump->FullName.Len() + 1); md5.Update((const uint8_t*)lump->FullName.c_str(), (unsigned)lump->FullName.length() + 1);
md5.Update((const uint8_t*)&lump->LumpSize, 4); md5.Update((const uint8_t*)&lump->LumpSize, 4);
} }
md5.Final(digest); md5.Final(digest);
for (auto c : digest) for (auto c : digest)
{ {
Hash.AppendFormat("%02X", c); n += snprintf(Hash + n, 3, "%02X", c);
} }
} }
@ -366,11 +402,11 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI
ptrdiff_t len; ptrdiff_t len;
ptrdiff_t lastpos = -1; ptrdiff_t lastpos = -1;
FString file; std::string file;
FString LumpFilter = filter->dotFilter; std::string& LumpFilter = filter->dotFilter;
while ((len = LumpFilter.IndexOf('.', lastpos+1)) > 0) while ((len = LumpFilter.find_first_of('.', lastpos+1)) != LumpFilter.npos)
{ {
max -= FilterLumps(LumpFilter.Left(len), lumps, lumpsize, max); max -= FilterLumps(std::string(LumpFilter, 0, len), lumps, lumpsize, max);
lastpos = len; lastpos = len;
} }
max -= FilterLumps(LumpFilter, lumps, lumpsize, max); max -= FilterLumps(LumpFilter, lumps, lumpsize, max);
@ -388,24 +424,23 @@ void FResourceFile::PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterI
// //
//========================================================================== //==========================================================================
int FResourceFile::FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max) int FResourceFile::FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max)
{ {
FString filter;
uint32_t start, end; uint32_t start, end;
if (filtername.IsEmpty()) if (filtername.empty())
{ {
return 0; return 0;
} }
filter << "filter/" << filtername << '/'; std::string filter = "filter/" + filtername + '/';
bool found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); bool found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
// Workaround for old Doom filter names. // Workaround for old Doom filter names (todo: move out of here.)
if (!found && filtername.IndexOf("doom.id.doom") == 0) if (!found && filtername.find_first_of("doom.id.doom") == 0)
{ {
filter.Substitute("doom.id.doom", "doom.doom"); strReplace(filter, "doom.id.doom", "doom.doom");
found = FindPrefixRange(filter, lumps, lumpsize, max, start, end); found = FindPrefixRange(filter.c_str(), lumps, lumpsize, max, start, end);
} }
if (found) if (found)
@ -417,8 +452,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) for (uint32_t i = start; i < end; ++i, lump_p = (uint8_t *)lump_p + lumpsize)
{ {
FResourceLump *lump = (FResourceLump *)lump_p; FResourceLump *lump = (FResourceLump *)lump_p;
assert(lump->FullName.CompareNoCase(filter, (int)filter.Len()) == 0); assert(strnicmp(lump->FullName.c_str(), filter.c_str(), filter.length()) == 0);
lump->LumpNameSetup(lump->FullName.Mid(filter.Len())); lump->LumpNameSetup(lump->FullName.c_str() + filter.length());
} }
// Move filtered lumps to the end of the lump list. // Move filtered lumps to the end of the lump list.
@ -502,7 +537,7 @@ void FResourceFile::JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t m
// //
//========================================================================== //==========================================================================
bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end) bool FResourceFile::FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t maxlump, uint32_t &start, uint32_t &end)
{ {
uint32_t min, max, mid, inside; uint32_t min, max, mid, inside;
FResourceLump *lump; FResourceLump *lump;
@ -520,7 +555,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
if (cmp == 0) if (cmp == 0)
break; break;
else if (cmp < 0) else if (cmp < 0)
@ -540,7 +575,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
// Go left on matches and right on misses. // Go left on matches and right on misses.
if (cmp == 0) if (cmp == 0)
max = mid - 1; max = mid - 1;
@ -555,7 +590,7 @@ bool FResourceFile::FindPrefixRange(FString filter, void *lumps, size_t lumpsize
{ {
mid = min + (max - min) / 2; mid = min + (max - min) / 2;
lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize); lump = (FResourceLump *)((uint8_t *)lumps + mid * lumpsize);
cmp = lump->FullName.CompareNoCase(filter, (int)filter.Len()); cmp = strnicmp(lump->FullName.c_str(), filter, (int)strlen(filter));
// Go right on matches and left on misses. // Go right on matches and left on misses.
if (cmp == 0) if (cmp == 0)
min = mid + 1; min = mid + 1;
@ -577,7 +612,7 @@ FResourceLump *FResourceFile::FindLump(const char *name)
for (unsigned i = 0; i < NumLumps; i++) for (unsigned i = 0; i < NumLumps; i++)
{ {
FResourceLump *lump = GetLump(i); FResourceLump *lump = GetLump(i);
if (!stricmp(name, lump->FullName)) if (!stricmp(name, lump->FullName.c_str()))
{ {
return lump; return lump;
} }
@ -684,7 +719,7 @@ int FExternalLump::FillCache()
Cache = new char[LumpSize]; Cache = new char[LumpSize];
FileReader f; FileReader f;
if (f.OpenFile(Filename)) if (f.OpenFile(Filename.c_str()))
{ {
auto read = f.Read(Cache, LumpSize); auto read = f.Read(Cache, LumpSize);
if (read != LumpSize) if (read != LumpSize)

View file

@ -4,20 +4,23 @@
#define __RESFILE_H #define __RESFILE_H
#include <limits.h> #include <limits.h>
#include <vector>
#include <string>
#include "files.h" #include "files.h"
#include "zstring.h"
std::string ExtractBaseName(const char* path, bool include_extension = false);
void strReplace(std::string& str, const char* from, const char* to);
// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine. // user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine.
struct LumpFilterInfo struct LumpFilterInfo
{ {
TArray<FString> gameTypeFilter; // this can contain multiple entries std::vector<std::string> gameTypeFilter; // this can contain multiple entries
FString dotFilter; std::string dotFilter;
// The following are for checking if the root directory of a zip can be removed. // The following are for checking if the root directory of a zip can be removed.
TArray<FString> reservedFolders; std::vector<std::string> reservedFolders;
TArray<FString> requiredPrefixes; std::vector<std::string> requiredPrefixes;
TArray<FString> embeddings; std::vector<std::string> embeddings;
std::function<void()> postprocessFunc; std::function<void()> postprocessFunc;
}; };
@ -107,7 +110,7 @@ struct FResourceLump
int LumpSize; int LumpSize;
int RefCount; int RefCount;
protected: protected:
FString FullName; std::string FullName;
public: public:
uint8_t Flags; uint8_t Flags;
char * Cache; char * Cache;
@ -127,7 +130,7 @@ public:
virtual int GetFileOffset() { return -1; } virtual int GetFileOffset() { return -1; }
virtual int GetIndexNum() const { return -1; } virtual int GetIndexNum() const { return -1; }
virtual int GetNamespace() const { return 0; } virtual int GetNamespace() const { return 0; }
void LumpNameSetup(FString iname); void LumpNameSetup(const char* iname);
void CheckEmbedded(LumpFilterInfo* lfi); void CheckEmbedded(LumpFilterInfo* lfi);
virtual FCompressedBuffer GetRawData(); virtual FCompressedBuffer GetRawData();
@ -136,7 +139,7 @@ public:
unsigned Size() const{ return LumpSize; } unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; } int LockCount() const { return RefCount; }
const char* getName() { return FullName.GetChars(); } const char* getName() { return FullName.c_str(); }
protected: protected:
virtual int FillCache() { return -1; } virtual int FillCache() { return -1; }
@ -147,10 +150,10 @@ class FResourceFile
{ {
public: public:
FileReader Reader; FileReader Reader;
FString FileName; std::string FileName;
protected: protected:
uint32_t NumLumps; uint32_t NumLumps;
FString Hash; char Hash[48];
FResourceFile(const char *filename); FResourceFile(const char *filename);
FResourceFile(const char *filename, FileReader &r); FResourceFile(const char *filename, FileReader &r);
@ -159,12 +162,23 @@ protected:
void GenerateHash(); void GenerateHash();
void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter); void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter);
void FixPathSeparator(char* path)
{
while (*path)
{
if (*path == '\\')
*path = '/';
path++;
}
}
private: private:
uint32_t FirstLump; uint32_t FirstLump;
int FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max); int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max);
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max); int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(FString filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end); bool FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end);
void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max); void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf); static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
@ -178,7 +192,7 @@ public:
uint32_t LumpCount() const { return NumLumps; } uint32_t LumpCount() const { return NumLumps; }
uint32_t GetFirstEntry() const { return FirstLump; } uint32_t GetFirstEntry() const { return FirstLump; }
void SetFirstLump(uint32_t f) { FirstLump = f; } void SetFirstLump(uint32_t f) { FirstLump = f; }
const FString &GetHash() const { return Hash; } const char* GetHash() const { return Hash; }
virtual FResourceLump *GetLump(int no) = 0; virtual FResourceLump *GetLump(int no) = 0;
@ -210,7 +224,7 @@ protected:
struct FExternalLump : public FResourceLump struct FExternalLump : public FResourceLump
{ {
FString Filename; std::string Filename;
FExternalLump(const char *_filename, int filesize = -1); FExternalLump(const char *_filename, int filesize = -1);
virtual int FillCache() override; virtual int FillCache() override;

View file

@ -202,11 +202,6 @@ extern bool insave;
extern TDeletingArray<FLightDefaults *> LightDefaults; extern TDeletingArray<FLightDefaults *> LightDefaults;
extern FName MessageBoxClass; extern FName MessageBoxClass;
static const char* iwad_folders[] = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/",
"materials/", "models/", "fonts/", "brightmaps/"};
static const char* iwad_reserved[] = { "mapinfo", "zmapinfo", "umapinfo", "gameinfo", "sndinfo", "sndseq", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "maps/" };
CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL | CVAR_VIRTUAL) CUSTOM_CVAR(Float, i_timescale, 1.0f, CVAR_NOINITCALL | CVAR_VIRTUAL)
{ {
if (netgame) if (netgame)
@ -1920,8 +1915,9 @@ static FString ParseGameInfo(TArray<FString> &pwads, const char *fn, const char
void GetReserved(LumpFilterInfo& lfi) void GetReserved(LumpFilterInfo& lfi)
{ {
for (auto p : iwad_folders) lfi.reservedFolders.Push(p); lfi.reservedFolders = { "flats/", "textures/", "hires/", "sprites/", "voxels/", "colormaps/", "acs/", "maps/", "voices/", "patches/", "graphics/", "sounds/", "music/",
for (auto p : iwad_reserved) lfi.requiredPrefixes.Push(p); "materials/", "models/", "fonts/", "brightmaps/" };
lfi.requiredPrefixes = { "mapinfo", "zmapinfo", "umapinfo", "gameinfo", "sndinfo", "sndseq", "sbarinfo", "menudef", "gldefs", "animdefs", "decorate", "zscript", "iwadinfo", "maps/" };
} }
static FString CheckGameInfo(TArray<FString> & pwads) static FString CheckGameInfo(TArray<FString> & pwads)
@ -3065,7 +3061,7 @@ static int FileSystemPrintf(FSMessageLevel level, const char* fmt, ...)
DPrintf(DMSG_NOTIFY, "%s", text.GetChars()); DPrintf(DMSG_NOTIFY, "%s", text.GetChars());
break; break;
} }
return text.Len(); return (int)text.Len();
} }
//========================================================================== //==========================================================================
// //
@ -3138,9 +3134,9 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
for (auto& inf : blanket) for (auto& inf : blanket)
{ {
if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.Push(inf.name); if (gameinfo.gametype & inf.match) lfi.gameTypeFilter.push_back(inf.name);
} }
lfi.gameTypeFilter.Push(FStringf("game-%s", GameTypeName())); lfi.gameTypeFilter.push_back(FStringf("game-%s", GameTypeName()).GetChars());
GetReserved(lfi); GetReserved(lfi);