1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 15:29:55 +00:00

Add type for normalized VFS path and use for VFS::Manager file map key

This will reduce the number of path normalizations while more places will use
this type. In some cases it also will reduce number of temporary allocations for
new strings.

For now make conversion from and to std::string_view implicit to allow gradual
migration to this type.
This commit is contained in:
elsid 2024-01-15 22:26:56 +01:00
parent a2147d70cc
commit 35d9b18b4c
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
5 changed files with 79 additions and 5 deletions

View file

@ -61,7 +61,7 @@ namespace TestingOpenMW
void listResources(VFS::FileMap& out) override void listResources(VFS::FileMap& out) override
{ {
for (const auto& [key, value] : mFiles) for (const auto& [key, value] : mFiles)
out.emplace(VFS::Path::normalizeFilename(key), value); out.emplace(key, value);
} }
bool contains(std::string_view file) const override { return mFiles.contains(file); } bool contains(std::string_view file) const override { return mFiles.contains(file); }

View file

@ -8,7 +8,12 @@ namespace VFS
{ {
class File; class File;
using FileMap = std::map<std::string, File*, std::less<>>; namespace Path
{
class Normalized;
}
using FileMap = std::map<Path::Normalized, File*, std::less<>>;
} }
#endif #endif

View file

@ -83,7 +83,7 @@ namespace VFS
return { mIndex.begin(), mIndex.end() }; return { mIndex.begin(), mIndex.end() };
std::string normalized = Path::normalizeFilename(path); std::string normalized = Path::normalizeFilename(path);
const auto it = mIndex.lower_bound(normalized); const auto it = mIndex.lower_bound(normalized);
if (it == mIndex.end() || !it->first.starts_with(normalized)) if (it == mIndex.end() || !it->first.view().starts_with(normalized))
return { it, it }; return { it, it };
++normalized.back(); ++normalized.back();
return { it, mIndex.lower_bound(normalized) }; return { it, mIndex.lower_bound(normalized) };

View file

@ -4,6 +4,7 @@
#include <components/misc/strings/lower.hpp> #include <components/misc/strings/lower.hpp>
#include <algorithm> #include <algorithm>
#include <ostream>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -51,6 +52,73 @@ namespace VFS::Path
bool operator()(std::string_view left, std::string_view right) const { return pathLess(left, right); } bool operator()(std::string_view left, std::string_view right) const { return pathLess(left, right); }
}; };
class Normalized
{
public:
Normalized() = default;
Normalized(std::string_view value)
: mValue(normalizeFilename(value))
{
}
Normalized(const char* value)
: Normalized(std::string_view(value))
{
}
Normalized(const std::string& value)
: Normalized(std::string_view(value))
{
}
explicit Normalized(std::string&& value)
: mValue(std::move(value))
{
normalizeFilenameInPlace(mValue);
}
const std::string& value() const& { return mValue; }
std::string value() && { return std::move(mValue); }
std::string_view view() const { return mValue; }
operator std::string_view() const { return mValue; }
operator const std::string&() const { return mValue; }
friend bool operator==(const Normalized& lhs, const Normalized& rhs) = default;
template <class T>
friend bool operator==(const Normalized& lhs, const T& rhs)
{
return lhs.mValue == rhs;
}
friend bool operator<(const Normalized& lhs, const Normalized& rhs) { return lhs.mValue < rhs.mValue; }
template <class T>
friend bool operator<(const Normalized& lhs, const T& rhs)
{
return lhs.mValue < rhs;
}
template <class T>
friend bool operator<(const T& lhs, const Normalized& rhs)
{
return lhs < rhs.mValue;
}
friend std::ostream& operator<<(std::ostream& stream, const Normalized& value)
{
return stream << value.mValue;
}
private:
std::string mValue;
};
} }
#endif #endif

View file

@ -4,6 +4,7 @@
#include <string> #include <string>
#include "filemap.hpp" #include "filemap.hpp"
#include "pathutil.hpp"
namespace VFS namespace VFS
{ {
@ -15,9 +16,9 @@ namespace VFS
{ {
} }
const std::string& operator*() const { return mIt->first; } const std::string& operator*() const { return mIt->first.value(); }
const std::string* operator->() const { return &mIt->first; } const std::string* operator->() const { return &mIt->first.value(); }
RecursiveDirectoryIterator& operator++() RecursiveDirectoryIterator& operator++()
{ {