mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 11:26:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "manager.hpp"
 | 
						|
 | 
						|
#include <stdexcept>
 | 
						|
#include <istream>
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
#include <components/misc/strings/lower.hpp>
 | 
						|
 | 
						|
#include "archive.hpp"
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
 | 
						|
    char strict_normalize_char(char ch)
 | 
						|
    {
 | 
						|
        return ch == '\\' ? '/' : ch;
 | 
						|
    }
 | 
						|
 | 
						|
    char nonstrict_normalize_char(char ch)
 | 
						|
    {
 | 
						|
        return ch == '\\' ? '/' : Misc::StringUtils::toLower(ch);
 | 
						|
    }
 | 
						|
 | 
						|
    void normalize_path(std::string& path, bool strict)
 | 
						|
    {
 | 
						|
        char (*normalize_char)(char) = strict ? &strict_normalize_char : &nonstrict_normalize_char;
 | 
						|
        std::transform(path.begin(), path.end(), path.begin(), normalize_char);
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
namespace VFS
 | 
						|
{
 | 
						|
 | 
						|
    Manager::Manager(bool strict)
 | 
						|
        : mStrict(strict)
 | 
						|
    {
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    Manager::~Manager() {}
 | 
						|
 | 
						|
    void Manager::reset()
 | 
						|
    {
 | 
						|
        mIndex.clear();
 | 
						|
        mArchives.clear();
 | 
						|
    }
 | 
						|
 | 
						|
    void Manager::addArchive(std::unique_ptr<Archive>&& archive)
 | 
						|
    {
 | 
						|
        mArchives.push_back(std::move(archive));
 | 
						|
    }
 | 
						|
 | 
						|
    void Manager::buildIndex()
 | 
						|
    {
 | 
						|
        mIndex.clear();
 | 
						|
 | 
						|
        for (const auto& archive : mArchives)
 | 
						|
            archive->listResources(mIndex, mStrict ? &strict_normalize_char : &nonstrict_normalize_char);
 | 
						|
    }
 | 
						|
 | 
						|
    Files::IStreamPtr Manager::get(std::string_view name) const
 | 
						|
    {
 | 
						|
        std::string normalized(name);
 | 
						|
        normalize_path(normalized, mStrict);
 | 
						|
 | 
						|
        return getNormalized(normalized);
 | 
						|
    }
 | 
						|
 | 
						|
    Files::IStreamPtr Manager::getNormalized(const std::string &normalizedName) const
 | 
						|
    {
 | 
						|
        std::map<std::string, File*>::const_iterator found = mIndex.find(normalizedName);
 | 
						|
        if (found == mIndex.end())
 | 
						|
            throw std::runtime_error("Resource '" + normalizedName + "' not found");
 | 
						|
        return found->second->open();
 | 
						|
    }
 | 
						|
 | 
						|
    bool Manager::exists(std::string_view name) const
 | 
						|
    {
 | 
						|
        std::string normalized(name);
 | 
						|
        normalize_path(normalized, mStrict);
 | 
						|
 | 
						|
        return mIndex.find(normalized) != mIndex.end();
 | 
						|
    }
 | 
						|
 | 
						|
    std::string Manager::normalizeFilename(std::string_view name) const
 | 
						|
    {
 | 
						|
        std::string result(name);
 | 
						|
        normalize_path(result, mStrict);
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    std::string Manager::getArchive(std::string_view name) const
 | 
						|
    {
 | 
						|
        std::string normalized(name);
 | 
						|
        normalize_path(normalized, mStrict);
 | 
						|
        for(auto it = mArchives.rbegin(); it != mArchives.rend(); ++it)
 | 
						|
        {
 | 
						|
            if((*it)->contains(normalized, mStrict ? &strict_normalize_char : &nonstrict_normalize_char))
 | 
						|
                return (*it)->getDescription();
 | 
						|
        }
 | 
						|
        return {};
 | 
						|
    }
 | 
						|
 | 
						|
    std::string Manager::getAbsoluteFileName(std::string_view name) const
 | 
						|
    {
 | 
						|
        std::string normalized(name);
 | 
						|
        normalize_path(normalized, mStrict);
 | 
						|
 | 
						|
        std::map<std::string, File*>::const_iterator found = mIndex.find(normalized);
 | 
						|
        if (found == mIndex.end())
 | 
						|
            throw std::runtime_error("Resource '" + normalized + "' not found");
 | 
						|
        return found->second->getPath();
 | 
						|
    }
 | 
						|
 | 
						|
    namespace
 | 
						|
    {
 | 
						|
        bool startsWith(std::string_view text, std::string_view start)
 | 
						|
        {
 | 
						|
            return text.rfind(start, 0) == 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Manager::RecursiveDirectoryRange Manager::getRecursiveDirectoryIterator(std::string_view 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) };
 | 
						|
    }
 | 
						|
}
 |