From a2147d70cc45d60a4f2d048980a5bcd5496d4b55 Mon Sep 17 00:00:00 2001 From: elsid Date: Tue, 16 Jan 2024 00:30:41 +0100 Subject: [PATCH 1/2] Use forward declaration for some VFS types This will allow to save on preprocessed code size in the future changes. --- apps/niftest/niftest.cpp | 1 + apps/opencs/model/world/resources.cpp | 1 + apps/openmw/mwgui/loadingscreen.cpp | 1 + apps/openmw/mwgui/settingswindow.cpp | 1 + apps/openmw/mwlua/vfsbindings.cpp | 1 + apps/openmw/mwrender/animation.cpp | 1 + apps/openmw/mwrender/postprocessor.cpp | 1 + apps/openmw/mwsound/soundmanagerimp.cpp | 1 + apps/openmw_test_suite/testing_util.hpp | 1 + components/vfs/archive.hpp | 22 ++------ components/vfs/bsaarchive.hpp | 1 + components/vfs/file.hpp | 21 ++++++++ components/vfs/filemap.hpp | 14 +++++ components/vfs/filesystemarchive.hpp | 3 +- components/vfs/manager.cpp | 9 +++- components/vfs/manager.hpp | 49 +++-------------- components/vfs/recursivedirectoryiterator.hpp | 53 +++++++++++++++++++ 17 files changed, 120 insertions(+), 61 deletions(-) create mode 100644 components/vfs/file.hpp create mode 100644 components/vfs/filemap.hpp create mode 100644 components/vfs/recursivedirectoryiterator.hpp diff --git a/apps/niftest/niftest.cpp b/apps/niftest/niftest.cpp index 29488fb677..32fd65c348 100644 --- a/apps/niftest/niftest.cpp +++ b/apps/niftest/niftest.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index bfab0193b0..345f6008ec 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -11,6 +11,7 @@ #include #include +#include CSMWorld::Resources::Resources( const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type, const char* const* extensions) diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 1723841b32..8ba2bb8312 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/inputmanager.hpp" diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index fbd54586df..0ffadc43a3 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "../mwbase/environment.hpp" diff --git a/apps/openmw/mwlua/vfsbindings.cpp b/apps/openmw/mwlua/vfsbindings.cpp index 0eccb336c2..c9b1a45fe2 100644 --- a/apps/openmw/mwlua/vfsbindings.cpp +++ b/apps/openmw/mwlua/vfsbindings.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 7fa8e43c37..feed9719b6 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include diff --git a/apps/openmw/mwrender/postprocessor.cpp b/apps/openmw/mwrender/postprocessor.cpp index 1aaeb460b7..c31f49f35a 100644 --- a/apps/openmw/mwrender/postprocessor.cpp +++ b/apps/openmw/mwrender/postprocessor.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 64f8959218..383d316c91 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" diff --git a/apps/openmw_test_suite/testing_util.hpp b/apps/openmw_test_suite/testing_util.hpp index 0c941053a7..aa76f7f944 100644 --- a/apps/openmw_test_suite/testing_util.hpp +++ b/apps/openmw_test_suite/testing_util.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/components/vfs/archive.hpp b/components/vfs/archive.hpp index 79c876b391..42b88219d7 100644 --- a/components/vfs/archive.hpp +++ b/components/vfs/archive.hpp @@ -1,27 +1,13 @@ -#ifndef OPENMW_COMPONENTS_RESOURCE_ARCHIVE_H -#define OPENMW_COMPONENTS_RESOURCE_ARCHIVE_H +#ifndef OPENMW_COMPONENTS_VFS_ARCHIVE_H +#define OPENMW_COMPONENTS_VFS_ARCHIVE_H -#include -#include +#include #include -#include +#include "filemap.hpp" namespace VFS { - - class File - { - public: - virtual ~File() = default; - - virtual Files::IStreamPtr open() = 0; - - virtual std::filesystem::path getPath() = 0; - }; - - using FileMap = std::map>; - class Archive { public: diff --git a/components/vfs/bsaarchive.hpp b/components/vfs/bsaarchive.hpp index 29098db45d..304fc438ad 100644 --- a/components/vfs/bsaarchive.hpp +++ b/components/vfs/bsaarchive.hpp @@ -2,6 +2,7 @@ #define VFS_BSAARCHIVE_HPP_ #include "archive.hpp" +#include "file.hpp" #include "pathutil.hpp" #include diff --git a/components/vfs/file.hpp b/components/vfs/file.hpp new file mode 100644 index 0000000000..f2dadb1162 --- /dev/null +++ b/components/vfs/file.hpp @@ -0,0 +1,21 @@ +#ifndef OPENMW_COMPONENTS_VFS_FILE_H +#define OPENMW_COMPONENTS_VFS_FILE_H + +#include + +#include + +namespace VFS +{ + class File + { + public: + virtual ~File() = default; + + virtual Files::IStreamPtr open() = 0; + + virtual std::filesystem::path getPath() = 0; + }; +} + +#endif diff --git a/components/vfs/filemap.hpp b/components/vfs/filemap.hpp new file mode 100644 index 0000000000..808153fc05 --- /dev/null +++ b/components/vfs/filemap.hpp @@ -0,0 +1,14 @@ +#ifndef OPENMW_COMPONENTS_VFS_FILEMAP_H +#define OPENMW_COMPONENTS_VFS_FILEMAP_H + +#include +#include + +namespace VFS +{ + class File; + + using FileMap = std::map>; +} + +#endif diff --git a/components/vfs/filesystemarchive.hpp b/components/vfs/filesystemarchive.hpp index e31ef9bd30..00fe5ba971 100644 --- a/components/vfs/filesystemarchive.hpp +++ b/components/vfs/filesystemarchive.hpp @@ -2,8 +2,9 @@ #define OPENMW_COMPONENTS_RESOURCE_FILESYSTEMARCHIVE_H #include "archive.hpp" -#include +#include "file.hpp" +#include #include namespace VFS diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index cc231847f5..5315f17252 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -5,12 +5,19 @@ #include #include +#include #include "archive.hpp" +#include "file.hpp" #include "pathutil.hpp" +#include "recursivedirectoryiterator.hpp" namespace VFS { + Manager::Manager() = default; + + Manager::~Manager() = default; + void Manager::reset() { mIndex.clear(); @@ -70,7 +77,7 @@ namespace VFS return found->second->getPath(); } - Manager::RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(std::string_view path) const + RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(std::string_view path) const { if (path.empty()) return { mIndex.begin(), mIndex.end() }; diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index 76405aae2c..05990a8607 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -4,32 +4,17 @@ #include #include -#include #include #include +#include #include -#include "archive.hpp" +#include "filemap.hpp" namespace VFS { - - template - class IteratorPair - { - public: - IteratorPair(Iterator first, Iterator last) - : mFirst(first) - , mLast(last) - { - } - Iterator begin() const { return mFirst; } - Iterator end() const { return mLast; } - - private: - Iterator mFirst; - Iterator mLast; - }; + class Archive; + class RecursiveDirectoryRange; /// @brief The main class responsible for loading files from a virtual file system. /// @par Various archive types (e.g. directories on the filesystem, or compressed archives) @@ -38,29 +23,11 @@ namespace VFS /// @par Most of the methods in this class are considered thread-safe, see each method documentation for details. class Manager { - class RecursiveDirectoryIterator - { - public: - RecursiveDirectoryIterator(FileMap::const_iterator it) - : mIt(it) - { - } - const std::string& operator*() const { return mIt->first; } - const std::string* operator->() const { return &mIt->first; } - bool operator!=(const RecursiveDirectoryIterator& other) { return mIt != other.mIt; } - RecursiveDirectoryIterator& operator++() - { - ++mIt; - return *this; - } - - private: - FileMap::const_iterator mIt; - }; - - using RecursiveDirectoryRange = IteratorPair; - public: + Manager(); + + ~Manager(); + // Empty the file index and unregister archives. void reset(); diff --git a/components/vfs/recursivedirectoryiterator.hpp b/components/vfs/recursivedirectoryiterator.hpp new file mode 100644 index 0000000000..82f8e594fd --- /dev/null +++ b/components/vfs/recursivedirectoryiterator.hpp @@ -0,0 +1,53 @@ +#ifndef OPENMW_COMPONENTS_VFS_RECURSIVEDIRECTORYITERATOR_H +#define OPENMW_COMPONENTS_VFS_RECURSIVEDIRECTORYITERATOR_H + +#include + +#include "filemap.hpp" + +namespace VFS +{ + class RecursiveDirectoryIterator + { + public: + RecursiveDirectoryIterator(FileMap::const_iterator it) + : mIt(it) + { + } + + const std::string& operator*() const { return mIt->first; } + + const std::string* operator->() const { return &mIt->first; } + + RecursiveDirectoryIterator& operator++() + { + ++mIt; + return *this; + } + + friend bool operator==(const RecursiveDirectoryIterator& lhs, const RecursiveDirectoryIterator& rhs) = default; + + private: + FileMap::const_iterator mIt; + }; + + class RecursiveDirectoryRange + { + public: + RecursiveDirectoryRange(RecursiveDirectoryIterator first, RecursiveDirectoryIterator last) + : mBegin(first) + , mEnd(last) + { + } + + RecursiveDirectoryIterator begin() const { return mBegin; } + + RecursiveDirectoryIterator end() const { return mEnd; } + + private: + RecursiveDirectoryIterator mBegin; + RecursiveDirectoryIterator mEnd; + }; +} + +#endif From 35d9b18b4c009f6adf56421ee59dd7d8f34e69f9 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 15 Jan 2024 22:26:56 +0100 Subject: [PATCH 2/2] 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. --- apps/openmw_test_suite/testing_util.hpp | 2 +- components/vfs/filemap.hpp | 7 +- components/vfs/manager.cpp | 2 +- components/vfs/pathutil.hpp | 68 +++++++++++++++++++ components/vfs/recursivedirectoryiterator.hpp | 5 +- 5 files changed, 79 insertions(+), 5 deletions(-) diff --git a/apps/openmw_test_suite/testing_util.hpp b/apps/openmw_test_suite/testing_util.hpp index aa76f7f944..b819848a8f 100644 --- a/apps/openmw_test_suite/testing_util.hpp +++ b/apps/openmw_test_suite/testing_util.hpp @@ -61,7 +61,7 @@ namespace TestingOpenMW void listResources(VFS::FileMap& out) override { 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); } diff --git a/components/vfs/filemap.hpp b/components/vfs/filemap.hpp index 808153fc05..1b7d390d88 100644 --- a/components/vfs/filemap.hpp +++ b/components/vfs/filemap.hpp @@ -8,7 +8,12 @@ namespace VFS { class File; - using FileMap = std::map>; + namespace Path + { + class Normalized; + } + + using FileMap = std::map>; } #endif diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 5315f17252..d312ce9d84 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -83,7 +83,7 @@ namespace VFS return { mIndex.begin(), mIndex.end() }; std::string normalized = Path::normalizeFilename(path); 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 }; ++normalized.back(); return { it, mIndex.lower_bound(normalized) }; diff --git a/components/vfs/pathutil.hpp b/components/vfs/pathutil.hpp index 724b406f1d..9bcc263842 100644 --- a/components/vfs/pathutil.hpp +++ b/components/vfs/pathutil.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -51,6 +52,73 @@ namespace VFS::Path 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 + 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 + friend bool operator<(const Normalized& lhs, const T& rhs) + { + return lhs.mValue < rhs; + } + + template + 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 diff --git a/components/vfs/recursivedirectoryiterator.hpp b/components/vfs/recursivedirectoryiterator.hpp index 82f8e594fd..39fb26e873 100644 --- a/components/vfs/recursivedirectoryiterator.hpp +++ b/components/vfs/recursivedirectoryiterator.hpp @@ -4,6 +4,7 @@ #include #include "filemap.hpp" +#include "pathutil.hpp" 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++() {