1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-21 05:39:42 +00:00

Simplify VFS index iteration

This commit is contained in:
Andrei Kortunov 2023-09-02 17:32:22 +04:00
parent c04a0ca3a5
commit 65109b3822
4 changed files with 22 additions and 83 deletions

View file

@ -160,25 +160,6 @@ namespace MWLua
auto vfs = MWBase::Environment::get().getResourceSystem()->getVFS();
sol::usertype<VFS::Manager::StatefulIterator> vfsIterator
= context.mLua->sol().new_usertype<VFS::Manager::StatefulIterator>("VFSIterator");
vfsIterator[sol::meta_function::to_string] = [](const VFS::Manager::StatefulIterator& vfsIterator) {
return "VFSIterator{'" + vfsIterator.getPath() + "'}";
};
vfsIterator["path"] = sol::readonly_property(
[](const VFS::Manager::StatefulIterator& vfsIterator) { return vfsIterator.getPath(); });
auto createIter = [](VFS::Manager::StatefulIterator& vfsIterator) {
return sol::as_function([vfsIterator, i = 1]() mutable {
if (auto v = vfsIterator.next())
return std::tuple<sol::optional<int>, sol::optional<std::string_view>>(i++, *v);
else
return std::tuple<sol::optional<int>, sol::optional<std::string_view>>(sol::nullopt, sol::nullopt);
});
};
vfsIterator["__pairs"] = createIter;
vfsIterator["__ipairs"] = createIter;
sol::usertype<FileHandle> handle = context.mLua->sol().new_usertype<FileHandle>("FileHandle");
handle["fileName"] = sol::readonly_property([](const FileHandle& self) { return self.mFileName; });
handle[sol::meta_function::to_string] = [](const FileHandle& self) {
@ -346,8 +327,19 @@ namespace MWLua
[](const sol::object&) -> sol::object { return sol::nil; });
api["fileExists"] = [vfs](std::string_view fileName) -> bool { return vfs->exists(fileName); };
api["getIterator"]
= [vfs](std::string_view path) -> VFS::Manager::StatefulIterator { return vfs->getStatefulIterator(path); };
api["pathsWithPrefix"] = [vfs](std::string_view prefix) {
auto iterator = vfs->getRecursiveDirectoryIterator(prefix);
return sol::as_function([iterator, current = iterator.begin()]() mutable -> sol::optional<std::string> {
if (current != iterator.end())
{
const std::string& result = *current;
++current;
return result;
}
return sol::nullopt;
});
};
return LuaUtil::makeReadOnly(api);
}

View file

@ -89,17 +89,4 @@ namespace VFS
++normalized.back();
return { it, mIndex.lower_bound(normalized) };
}
Manager::StatefulIterator Manager::getStatefulIterator(std::string_view path) const
{
if (path.empty())
return { mIndex.begin(), mIndex.end(), std::string() };
std::string normalized = Path::normalizeFilename(path);
const auto it = mIndex.lower_bound(normalized);
if (it == mIndex.end() || !startsWith(it->first, normalized))
return { it, it, normalized };
std::string upperBound = normalized;
++upperBound.back();
return { it, mIndex.lower_bound(upperBound), normalized };
}
}

View file

@ -6,7 +6,6 @@
#include <filesystem>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
@ -49,18 +48,11 @@ namespace VFS
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; }
bool operator==(const RecursiveDirectoryIterator& other) const { return mIt == other.mIt; }
RecursiveDirectoryIterator& operator++()
{
++mIt;
return *this;
}
RecursiveDirectoryIterator operator++(int)
{
RecursiveDirectoryIterator old = *this;
mIt++;
return old;
}
private:
std::map<std::string, File*>::const_iterator mIt;
@ -69,31 +61,6 @@ namespace VFS
using RecursiveDirectoryRange = IteratorPair<RecursiveDirectoryIterator>;
public:
class StatefulIterator : RecursiveDirectoryRange
{
public:
StatefulIterator(RecursiveDirectoryIterator first, RecursiveDirectoryIterator last, const std::string& path)
: RecursiveDirectoryRange(first, last)
, mCurrent(first)
, mPath(path)
{
}
const std::string& getPath() const { return mPath; }
std::optional<std::string_view> next()
{
if (mCurrent == end())
return std::nullopt;
return *mCurrent++;
}
private:
RecursiveDirectoryIterator mCurrent;
std::string mPath;
};
// Empty the file index and unregister archives.
void reset();
@ -126,13 +93,6 @@ namespace VFS
/// @note May be called from any thread once the index has been built.
RecursiveDirectoryRange getRecursiveDirectoryIterator(std::string_view path) const;
/// Recursively iterate over the elements of the given path
/// In practice it return all files of the VFS starting with the given path
/// Stores iterator to current element.
/// @note the path is normalized
/// @note May be called from any thread once the index has been built.
StatefulIterator getStatefulIterator(std::string_view path) const;
/// Retrieve the absolute path to the file
/// @note Throws an exception if the file can not be found.
/// @note May be called from any thread once the index has been built.

View file

@ -6,10 +6,6 @@
---
-- @type VFSIterator
-- @field #string path VFS prefix path
---
-- @type FileHandle
-- @field #string fileName VFS path to related file
@ -135,14 +131,18 @@
-- end
---
-- Get iterator to fetch file names with given path prefix from VFS
-- @function [parent=#vfs] getIterator
-- Get iterator function to fetch file names with given path prefix from VFS
-- @function [parent=#vfs] pathsWithPrefix
-- @param #string path Path prefix
-- @return #VFSIterator Opened iterator
-- @usage local dir = vfs.getIterator("Music\\Explore");
-- for _, fileName in pairs(dir) do
-- @return #function Function to get next file name
-- @usage -- get all files with given prefix from VFS index
-- for fileName in vfs.pathsWithPrefix("Music\\Explore") do
-- print(fileName);
-- end
-- @usage -- get some first files
-- local getNextFile = vfs.pathsWithPrefix("Music\\Explore");
-- local firstFile = getNextFile();
-- local secondFile = getNextFile();
---
-- Detect a file handle type