From b676d93e03f52645d827da19d87659f6343c6650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mocquillon?= Date: Thu, 23 Sep 2021 18:47:59 +0200 Subject: [PATCH] Use a pair of iterator to represents a range for directory listing --- components/vfs/manager.cpp | 19 ++++++++++-- components/vfs/manager.hpp | 63 ++++++++++++++------------------------ 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 1cb8745497..faebc782aa 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -105,8 +105,23 @@ namespace VFS return {}; } - RecursiveDirectoryIterator Manager::getRecursiveDirectoryIterator(const std::string& path) const + namespace { - return RecursiveDirectoryIterator(mIndex, normalizeFilename(path)); + bool startsWith(std::string_view text, std::string_view start) + { + return text.rfind(start, 0) == 0; + } + } + + Manager::RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(const std::string& path) const + { + if (path.empty()) + return { mIndex.begin(), mIndex.end() }; + auto normalized = normalizeFilename(path); + const auto it = mIndex.lower_bound(normalized); + if (it == mIndex.end() || !startsWith(it->first, normalized)) + return { it, it }; + ++normalized.back(); + return { it, mIndex.lower_bound(normalized) }; } } diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index b98d8021d4..8568e8e784 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -12,51 +12,19 @@ namespace VFS class Archive; class File; - class RecursiveDirectoryIterator; - RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter); - - class RecursiveDirectoryIterator + template + class IteratorPair { public: - RecursiveDirectoryIterator(const std::map& index, const std::string& path) - : mPath(path) - , mIndex(&index) - , mIt(index.lower_bound(path)) - {} - - RecursiveDirectoryIterator(const RecursiveDirectoryIterator&) = default; - - const std::string& operator*() const { return mIt->first; } - const std::string* operator->() const { return &mIt->first; } - - bool operator!=(const RecursiveDirectoryIterator& other) { return mPath != other.mPath || mIt != other.mIt; } - - RecursiveDirectoryIterator& operator++() - { - if (++mIt == mIndex->end() || !starts_with(mIt->first, mPath)) - *this = end(*this); - return *this; - } - - friend RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter); + IteratorPair(Iterator first, Iterator last) : mFirst(first), mLast(last) {} + Iterator begin() const { return mFirst; } + Iterator end() const { return mLast; } private: - static bool starts_with(const std::string& text, const std::string& start) { return text.rfind(start, 0) == 0; } - - std::string mPath; - const std::map* mIndex; - std::map::const_iterator mIt; + Iterator mFirst; + Iterator mLast; }; - inline RecursiveDirectoryIterator begin(RecursiveDirectoryIterator iter) { return iter; } - - inline RecursiveDirectoryIterator end(const RecursiveDirectoryIterator& iter) - { - RecursiveDirectoryIterator result(iter); - result.mIt = result.mIndex->end(); - return result; - } - /// @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) /// can be registered, and will be merged into a single file tree. If the same filename is @@ -64,6 +32,21 @@ 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(std::map::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: + std::map::const_iterator mIt; + }; + + using RecursiveDirectoryRange = IteratorPair; + public: /// @param strict Use strict path handling? If enabled, no case folding will /// be done, but slash/backslash conversions are always done. @@ -105,7 +88,7 @@ namespace VFS /// In practice it return all files of the VFS starting with the given path /// @note the path is normalized /// @note May be called from any thread once the index has been built. - RecursiveDirectoryIterator getRecursiveDirectoryIterator(const std::string& path) const; + RecursiveDirectoryRange getRecursiveDirectoryIterator(const std::string& path) const; private: bool mStrict;