#include "manager.hpp" #include #include #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(); mArchives.clear(); } void Manager::addArchive(std::unique_ptr&& archive) { mArchives.push_back(std::move(archive)); } void Manager::buildIndex() { mIndex.clear(); for (const auto& archive : mArchives) archive->listResources(mIndex); } Files::IStreamPtr Manager::find(Path::NormalizedView name) const { return findNormalized(name.value()); } Files::IStreamPtr Manager::get(const Path::Normalized& name) const { return getNormalized(name); } Files::IStreamPtr Manager::get(Path::NormalizedView name) const { return getNormalized(name.value()); } Files::IStreamPtr Manager::getNormalized(std::string_view normalizedName) const { assert(Path::isNormalized(normalizedName)); auto ptr = findNormalized(normalizedName); if (ptr == nullptr) throw std::runtime_error("Resource '" + std::string(normalizedName) + "' not found"); return ptr; } bool Manager::exists(const Path::Normalized& name) const { return mIndex.find(name) != mIndex.end(); } bool Manager::exists(Path::NormalizedView name) const { return mIndex.find(name) != mIndex.end(); } std::string Manager::getArchive(const Path::Normalized& name) const { for (auto it = mArchives.rbegin(); it != mArchives.rend(); ++it) { if ((*it)->contains(name)) return (*it)->getDescription(); } return {}; } std::filesystem::path Manager::getAbsoluteFileName(const std::filesystem::path& name) const { std::string normalized = Files::pathToUnicodeString(name); Path::normalizeFilenameInPlace(normalized); const auto found = mIndex.find(normalized); if (found == mIndex.end()) throw std::runtime_error("Resource '" + normalized + "' is not found"); return found->second->getPath(); } RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(std::string_view path) const { if (path.empty()) return { mIndex.begin(), mIndex.end() }; std::string normalized = Path::normalizeFilename(path); const auto it = mIndex.lower_bound(normalized); if (it == mIndex.end() || !it->first.view().starts_with(normalized)) return { it, it }; ++normalized.back(); return { it, mIndex.lower_bound(normalized) }; } RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(VFS::Path::NormalizedView path) const { if (path.value().empty()) return { mIndex.begin(), mIndex.end() }; const auto it = mIndex.lower_bound(path); if (it == mIndex.end() || !it->first.view().starts_with(path.value())) return { it, it }; std::string copy(path.value()); ++copy.back(); return { it, mIndex.lower_bound(copy) }; } RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator() const { return { mIndex.begin(), mIndex.end() }; } Files::IStreamPtr Manager::findNormalized(std::string_view normalizedPath) const { assert(Path::isNormalized(normalizedPath)); const auto it = mIndex.find(normalizedPath); if (it == mIndex.end()) return nullptr; return it->second->open(); } }