Reduces string allocations in paths.

This commit is contained in:
Vladislav Belov 2025-10-05 01:11:03 +02:00
parent d22d8776e6
commit e63c80c613
No known key found for this signature in database
GPG key ID: 353545E45DB9CCB3
8 changed files with 54 additions and 32 deletions

View file

@ -311,7 +311,7 @@ cassert(sizeof(ECDR) == 22);
// ArchiveFile_Zip
//-----------------------------------------------------------------------------
class ArchiveFile_Zip : public IArchiveFile
class ArchiveFile_Zip final : public IArchiveFile
{
public:
ArchiveFile_Zip(const PFile& file, off_t ofs, off_t csize, u32 checksum, ZipMethod method)
@ -321,22 +321,22 @@ public:
{
}
virtual size_t Precedence() const
size_t Precedence() const override
{
return 2u;
}
virtual wchar_t LocationCode() const
wchar_t LocationCode() const override
{
return 'A';
}
virtual OsPath Path() const
const OsPath& Path() const override
{
return m_file->Pathname();
}
virtual Status Load(const OsPath& /*name*/, const std::shared_ptr<u8>& buf, size_t size) const
Status Load(const OsPath& /*name*/, const std::shared_ptr<u8>& buf, size_t size) const override
{
AdjustOffset();

View file

@ -36,7 +36,7 @@ struct IFileLoader
virtual size_t Precedence() const = 0;
virtual wchar_t LocationCode() const = 0;
virtual OsPath Path() const = 0;
virtual const OsPath& Path() const = 0;
virtual Status Load(const OsPath& name, const std::shared_ptr<u8>& buf, size_t size) const = 0;
};

View file

@ -33,7 +33,7 @@
#include <cstddef>
#include <memory>
class RealDirectory : public IFileLoader
class RealDirectory final : public IFileLoader
{
NONCOPYABLE(RealDirectory);
public:
@ -50,13 +50,13 @@ public:
}
// IFileLoader
virtual size_t Precedence() const;
virtual wchar_t LocationCode() const;
virtual OsPath Path() const
size_t Precedence() const override;
wchar_t LocationCode() const override;
const OsPath& Path() const override
{
return m_path;
}
virtual Status Load(const OsPath& name, const std::shared_ptr<u8>& buf, size_t size) const;
Status Load(const OsPath& name, const std::shared_ptr<u8>& buf, size_t size) const override;
Status Store(const OsPath& name, const std::shared_ptr<u8>& fileContents, size_t size);

View file

@ -114,7 +114,8 @@ Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames
for(size_t i = 0; osEnt->d_name[i] != '\0'; i++)
RETURN_STATUS_IF_ERR(Path::Validate(osEnt->d_name[i]));
const OsPath name(osEnt->d_name);
const std::wstring_view name{osEnt->d_name};
// get file information (mode, size, mtime)
struct stat s;
@ -124,7 +125,7 @@ Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames
#else
// .. call regular stat().
errno = 0;
const OsPath pathname = path / name;
const OsPath pathname = path / OsPath(osEnt->d_name);
if(wstat(pathname, &s) != 0)
{
if(errno == ENOENT)
@ -140,9 +141,9 @@ Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames
#endif
if(files && S_ISREG(s.st_mode))
files->push_back(CFileInfo(name, s.st_size, s.st_mtime));
files->emplace_back(osEnt->d_name, s.st_size, s.st_mtime);
else if(subdirectoryNames && S_ISDIR(s.st_mode) && name != L"." && name != L"..")
subdirectoryNames->push_back(name);
subdirectoryNames->emplace_back(osEnt->d_name);
}
}

View file

@ -36,21 +36,23 @@
class MockLoader : public IFileLoader
{
private:
size_t m_Precedence;
public:
MockLoader(size_t precedence) :
m_Precedence(precedence)
{
}
size_t Precedence() const { return m_Precedence; }
wchar_t LocationCode() const { return L'\0'; }
OsPath Path() const { return L"";}
Status Load(const OsPath& /*name*/, const std::shared_ptr<u8>& /*buf*/, size_t /*size*/) const
size_t Precedence() const override { return m_Precedence; }
wchar_t LocationCode() const override { return L'\0'; }
const OsPath& Path() const override { return m_Path; }
Status Load(const OsPath& /*name*/, const std::shared_ptr<u8>& /*buf*/, size_t /*size*/) const override
{
return INFO::OK;
}
private:
size_t m_Precedence;
OsPath m_Path;
};
class TestVfsTree : public CxxTest::TestSuite

View file

@ -49,6 +49,7 @@
#include <istream>
#include <string>
#include <string_view>
#include <utility>
namespace ERR
{
@ -95,6 +96,12 @@ public:
DetectSeparator();
}
Path(Path&& p)
: path(std::move(p.path))
{
DetectSeparator();
}
Path(const char* p)
: path((const unsigned char*)p, (const unsigned char*)p+strlen(p))
// interpret bytes as unsigned; makes no difference for ASCII,
@ -115,7 +122,13 @@ public:
DetectSeparator();
}
Path(const std::wstring& s)
Path(std::wstring s)
: path(std::move(s))
{
DetectSeparator();
}
Path(const std::wstring_view& s)
: path(s)
{
DetectSeparator();
@ -128,6 +141,13 @@ public:
return *this;
}
Path& operator=(Path&& rhs)
{
path = std::move(rhs.path);
DetectSeparator();
return *this;
}
bool empty() const
{
return path.empty();
@ -217,14 +237,13 @@ public:
return filename.string().substr(0, idxDot);
}
// (Path return type allows callers to use our operator==)
Path Extension() const
std::wstring_view Extension() const
{
const Path filename = Filename();
const size_t idxDot = filename.string().find_last_of('.');
const std::wstring_view filename{path};
const size_t idxDot = filename.find_last_of('.');
if(idxDot == String::npos)
return Path();
return filename.string().substr(idxDot);
return {};
return filename.substr(idxDot);
}
Path ChangeExtension(Path extension) const
@ -232,7 +251,7 @@ public:
return Parent() / Path(Basename().string() + extension.string());
}
Path operator/(Path rhs) const
Path operator/(const Path& rhs) const
{
Path ret = *this;
if(ret.path.empty()) // (empty paths assume '/')

View file

@ -116,7 +116,7 @@ bool CCacheLoader::CanUseArchiveCache(const VfsPath& sourcePath, const VfsPath&
VfsPath CCacheLoader::ArchiveCachePath(const VfsPath& sourcePath) const
{
return sourcePath.ChangeExtension(sourcePath.Extension().string() + L".cached" + m_FileExtension);
return sourcePath.ChangeExtension(std::wstring{sourcePath.Extension()} + L".cached" + m_FileExtension);
}
VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initialHash, u32 version)
@ -148,7 +148,7 @@ VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initi
return VfsPath("cache") /
path_name_only(path.BeforeCommon(sourcePath).Parent().string().c_str()) /
sourcePath.ChangeExtension(sourcePath.Extension().string() +
sourcePath.ChangeExtension(std::wstring{sourcePath.Extension()} +
L"." +
// Use a short prefix of the full hash (we don't need high collision-resistance)
wstring_from_utf8(Hexify(digest, 8)) +

View file

@ -126,7 +126,7 @@ VfsPath GetBaseFilename(const VfsPath& filename)
if (!VfsFileExists(filePath))
throw std::runtime_error{fmt::format("The file \"{}\" does not exist.", filePath.string8())};
if (filePath.Extension().string8() != ".js")
if (filePath.Extension() != L".js")
{
throw std::runtime_error{fmt::format("The file \"{}\" is not a JavaScript module.",
filePath.string8())};