mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-29 13:27:59 +03:00
Merge branch 'fastandloose' into 'master'
Drop support for --fs-strict Closes #7394 See merge request OpenMW/openmw!3093
This commit is contained in:
commit
6601b0cb15
47 changed files with 161 additions and 258 deletions
|
@ -8,14 +8,12 @@ namespace Files
|
|||
{
|
||||
Collections::Collections()
|
||||
: mDirectories()
|
||||
, mFoldCase(false)
|
||||
, mCollections()
|
||||
{
|
||||
}
|
||||
|
||||
Collections::Collections(const Files::PathContainer& directories, bool foldCase)
|
||||
Collections::Collections(const Files::PathContainer& directories)
|
||||
: mDirectories(directories)
|
||||
, mFoldCase(foldCase)
|
||||
, mCollections()
|
||||
{
|
||||
}
|
||||
|
@ -27,7 +25,7 @@ namespace Files
|
|||
if (iter == mCollections.end())
|
||||
{
|
||||
std::pair<MultiDirCollectionContainer::iterator, bool> result
|
||||
= mCollections.emplace(ext, MultiDirCollection(mDirectories, ext, mFoldCase));
|
||||
= mCollections.emplace(ext, MultiDirCollection(mDirectories, ext));
|
||||
|
||||
iter = result.first;
|
||||
}
|
||||
|
@ -44,12 +42,7 @@ namespace Files
|
|||
const auto& path = iter2.path();
|
||||
const auto str = Files::pathToUnicodeString(path.filename());
|
||||
|
||||
if (mFoldCase)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(file, str))
|
||||
return path;
|
||||
}
|
||||
else if (str == file)
|
||||
if (Misc::StringUtils::ciEqual(file, str))
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
@ -66,12 +59,7 @@ namespace Files
|
|||
const auto& path = iter2.path();
|
||||
const auto str = Files::pathToUnicodeString(path.filename());
|
||||
|
||||
if (mFoldCase)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(file, str))
|
||||
return true;
|
||||
}
|
||||
else if (str == file)
|
||||
if (Misc::StringUtils::ciEqual(file, str))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Files
|
|||
Collections();
|
||||
|
||||
///< Directories are listed with increasing priority.
|
||||
Collections(const Files::PathContainer& directories, bool foldCase);
|
||||
Collections(const Files::PathContainer& directories);
|
||||
|
||||
///< Return a file collection for the given extension. Extension must contain the
|
||||
/// leading dot and must be all lower-case.
|
||||
|
@ -35,7 +35,6 @@ namespace Files
|
|||
typedef std::map<std::string, MultiDirCollection> MultiDirCollectionContainer;
|
||||
Files::PathContainer mDirectories;
|
||||
|
||||
bool mFoldCase;
|
||||
mutable MultiDirCollectionContainer mCollections;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,29 +7,9 @@
|
|||
|
||||
namespace Files
|
||||
{
|
||||
struct NameEqual
|
||||
|
||||
MultiDirCollection::MultiDirCollection(const Files::PathContainer& directories, const std::string& extension)
|
||||
{
|
||||
bool mStrict;
|
||||
|
||||
NameEqual(bool strict)
|
||||
: mStrict(strict)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const std::string& left, const std::string& right) const
|
||||
{
|
||||
if (mStrict)
|
||||
return left == right;
|
||||
return Misc::StringUtils::ciEqual(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
MultiDirCollection::MultiDirCollection(
|
||||
const Files::PathContainer& directories, const std::string& extension, bool foldCase)
|
||||
: mFiles(NameLess(!foldCase))
|
||||
{
|
||||
NameEqual equal(!foldCase);
|
||||
|
||||
for (const auto& directory : directories)
|
||||
{
|
||||
if (!std::filesystem::is_directory(directory))
|
||||
|
@ -42,7 +22,7 @@ namespace Files
|
|||
{
|
||||
const auto& path = dirIter.path();
|
||||
|
||||
if (!equal(extension, Files::pathToUnicodeString(path.extension())))
|
||||
if (!Misc::StringUtils::ciEqual(extension, Files::pathToUnicodeString(path.extension())))
|
||||
continue;
|
||||
|
||||
const auto filename = Files::pathToUnicodeString(path.filename());
|
||||
|
|
|
@ -13,23 +13,6 @@ namespace Files
|
|||
{
|
||||
typedef std::vector<std::filesystem::path> PathContainer;
|
||||
|
||||
struct NameLess
|
||||
{
|
||||
bool mStrict;
|
||||
|
||||
NameLess(bool strict)
|
||||
: mStrict(strict)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator()(const std::string& left, const std::string& right) const
|
||||
{
|
||||
if (mStrict)
|
||||
return left < right;
|
||||
return Misc::StringUtils::ciLess(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief File collection across several directories
|
||||
///
|
||||
/// This class lists all files with one specific extensions within one or more
|
||||
|
@ -38,14 +21,14 @@ namespace Files
|
|||
class MultiDirCollection
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, std::filesystem::path, NameLess> TContainer;
|
||||
typedef std::map<std::string, std::filesystem::path, Misc::StringUtils::CiComp> TContainer;
|
||||
typedef TContainer::const_iterator TIter;
|
||||
|
||||
private:
|
||||
TContainer mFiles;
|
||||
|
||||
public:
|
||||
MultiDirCollection(const Files::PathContainer& directories, const std::string& extension, bool foldCase);
|
||||
MultiDirCollection(const Files::PathContainer& directories, const std::string& extension);
|
||||
///< Directories are listed with increasing priority.
|
||||
/// \param extension The extension that should be listed in this collection. Must
|
||||
/// contain the leading dot.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#include "resources.hpp"
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
namespace LuaUi
|
||||
{
|
||||
std::shared_ptr<TextureResource> ResourceManager::registerTexture(TextureData data)
|
||||
{
|
||||
data.mPath = mVfs->normalizeFilename(data.mPath);
|
||||
VFS::Path::normalizeFilenameInPlace(data.mPath);
|
||||
|
||||
TextureResources& list = mTextures[data.mPath];
|
||||
list.push_back(std::make_shared<TextureResource>(data));
|
||||
|
|
|
@ -28,16 +28,10 @@ namespace LuaUi
|
|||
class ResourceManager
|
||||
{
|
||||
public:
|
||||
ResourceManager(const VFS::Manager* vfs)
|
||||
: mVfs(vfs)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<TextureResource> registerTexture(TextureData data);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVfs;
|
||||
using TextureResources = std::vector<std::shared_ptr<TextureResource>>;
|
||||
std::unordered_map<std::string, TextureResources> mTextures;
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -168,9 +169,10 @@ std::string Misc::ResourceHelpers::correctSoundPath(std::string_view resPath, co
|
|||
{
|
||||
std::string sound{ resPath };
|
||||
changeExtension(sound, ".mp3");
|
||||
return vfs->normalizeFilename(sound);
|
||||
VFS::Path::normalizeFilenameInPlace(sound);
|
||||
return sound;
|
||||
}
|
||||
return vfs->normalizeFilename(resPath);
|
||||
return VFS::Path::normalizeFilename(resPath);
|
||||
}
|
||||
|
||||
bool Misc::ResourceHelpers::isHiddenMarker(const ESM::RefId& id)
|
||||
|
@ -184,7 +186,7 @@ namespace
|
|||
{
|
||||
if (auto w = Misc::findExtension(resPath); w != std::string::npos)
|
||||
resPath.insert(w, pattern);
|
||||
return vfs->normalizeFilename(resPath);
|
||||
return VFS::Path::normalizeFilename(resPath);
|
||||
}
|
||||
|
||||
std::string getBestLODMeshName(std::string const& resPath, const VFS::Manager* vfs, std::string_view pattern)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
|
||||
|
@ -109,7 +110,7 @@ namespace Resource
|
|||
|
||||
osg::ref_ptr<const BulletShape> BulletShapeManager::getShape(const std::string& name)
|
||||
{
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<BulletShape> shape;
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
|
@ -169,7 +170,7 @@ namespace Resource
|
|||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::cacheInstance(const std::string& name)
|
||||
{
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<BulletShapeInstance> instance = createInstance(normalized);
|
||||
if (instance)
|
||||
|
@ -179,7 +180,7 @@ namespace Resource
|
|||
|
||||
osg::ref_ptr<BulletShapeInstance> BulletShapeManager::getInstance(const std::string& name)
|
||||
{
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mInstanceCache->takeFromObjectCache(normalized);
|
||||
if (obj.get())
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/misc/pathhelpers.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#include "objectcache.hpp"
|
||||
|
||||
|
@ -85,7 +86,7 @@ namespace Resource
|
|||
|
||||
osg::ref_ptr<osg::Image> ImageManager::getImage(std::string_view filename, bool disableFlip)
|
||||
{
|
||||
const std::string normalized = mVFS->normalizeFilename(filename);
|
||||
const std::string normalized = VFS::Path::normalizeFilename(filename);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/sceneutil/keyframe.hpp>
|
||||
#include <components/sceneutil/osgacontroller.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#include "animation.hpp"
|
||||
#include "objectcache.hpp"
|
||||
|
@ -210,11 +211,9 @@ namespace Resource
|
|||
{
|
||||
}
|
||||
|
||||
KeyframeManager::~KeyframeManager() {}
|
||||
|
||||
osg::ref_ptr<const SceneUtil::KeyframeHolder> KeyframeManager::get(const std::string& name)
|
||||
{
|
||||
const std::string normalized = mVFS->normalizeFilename(name);
|
||||
const std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Resource
|
|||
{
|
||||
public:
|
||||
KeyframeManager(const VFS::Manager* vfs, SceneManager* sceneManager);
|
||||
~KeyframeManager();
|
||||
~KeyframeManager() = default;
|
||||
|
||||
/// Retrieve a read-only keyframe resource by name (case-insensitive).
|
||||
/// @note Throws an exception if the resource is not found.
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Resource
|
|||
class BaseResourceManager
|
||||
{
|
||||
public:
|
||||
virtual ~BaseResourceManager() {}
|
||||
virtual ~BaseResourceManager() = default;
|
||||
virtual void updateCache(double referenceTime) {}
|
||||
virtual void clearCache() {}
|
||||
virtual void setExpiryDelay(double expiryDelay) {}
|
||||
|
@ -46,7 +46,7 @@ namespace Resource
|
|||
{
|
||||
}
|
||||
|
||||
virtual ~GenericResourceManager() {}
|
||||
virtual ~GenericResourceManager() = default;
|
||||
|
||||
/// Clear cache entries that have not been referenced for longer than expiryDelay.
|
||||
void updateCache(double referenceTime) override
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <components/misc/strings/conversion.hpp>
|
||||
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
#include <components/sceneutil/clone.hpp>
|
||||
#include <components/sceneutil/controller.hpp>
|
||||
|
@ -507,7 +508,7 @@ namespace Resource
|
|||
|
||||
bool SceneManager::checkLoaded(const std::string& name, double timeStamp)
|
||||
{
|
||||
return mCache->checkInObjectCache(mVFS->normalizeFilename(name), timeStamp);
|
||||
return mCache->checkInObjectCache(VFS::Path::normalizeFilename(name), timeStamp);
|
||||
}
|
||||
|
||||
/// @brief Callback to read image files from the VFS.
|
||||
|
@ -862,7 +863,7 @@ namespace Resource
|
|||
|
||||
osg::ref_ptr<const osg::Node> SceneManager::getTemplate(const std::string& name, bool compile)
|
||||
{
|
||||
std::string normalized = mVFS->normalizeFilename(name);
|
||||
std::string normalized = VFS::Path::normalizeFilename(name);
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(normalized);
|
||||
if (obj)
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace VFS
|
|||
class File
|
||||
{
|
||||
public:
|
||||
virtual ~File() {}
|
||||
virtual ~File() = default;
|
||||
|
||||
virtual Files::IStreamPtr open() = 0;
|
||||
|
||||
|
@ -22,14 +22,13 @@ namespace VFS
|
|||
class Archive
|
||||
{
|
||||
public:
|
||||
virtual ~Archive() {}
|
||||
virtual ~Archive() = default;
|
||||
|
||||
/// List all resources contained in this archive, and run the resource names through the given normalize
|
||||
/// function.
|
||||
virtual void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) = 0;
|
||||
/// List all resources contained in this archive.
|
||||
virtual void listResources(std::map<std::string, File*>& out) = 0;
|
||||
|
||||
/// True if this archive contains the provided normalized file.
|
||||
virtual bool contains(const std::string& file, char (*normalize_function)(char)) const = 0;
|
||||
virtual bool contains(const std::string& file) const = 0;
|
||||
|
||||
virtual std::string getDescription() const = 0;
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define VFS_BSAARCHIVE_HPP_
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "pathutil.hpp"
|
||||
|
||||
#include <components/bsa/ba2dx10file.hpp>
|
||||
#include <components/bsa/ba2gnrlfile.hpp>
|
||||
|
@ -47,24 +48,22 @@ namespace VFS
|
|||
|
||||
virtual ~BsaArchive() {}
|
||||
|
||||
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override
|
||||
void listResources(std::map<std::string, File*>& out) override
|
||||
{
|
||||
for (auto& resource : mResources)
|
||||
{
|
||||
std::string ent = resource.mInfo->name();
|
||||
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
||||
Path::normalizeFilenameInPlace(ent);
|
||||
|
||||
out[ent] = &resource;
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const std::string& file, char (*normalize_function)(char)) const override
|
||||
bool contains(const std::string& file) const override
|
||||
{
|
||||
for (const auto& it : mResources)
|
||||
{
|
||||
std::string ent = it.mInfo->name();
|
||||
std::transform(ent.begin(), ent.end(), ent.begin(), normalize_function);
|
||||
if (file == ent)
|
||||
if (Path::pathEqual(file, it.mInfo->name()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "filesystemarchive.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "pathutil.hpp"
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/files/constrainedfilestream.hpp>
|
||||
#include <components/files/conversion.hpp>
|
||||
|
@ -17,7 +17,7 @@ namespace VFS
|
|||
{
|
||||
}
|
||||
|
||||
void FileSystemArchive::listResources(std::map<std::string, File*>& out, char (*normalize_function)(char))
|
||||
void FileSystemArchive::listResources(std::map<std::string, File*>& out)
|
||||
{
|
||||
if (!mBuiltIndex)
|
||||
{
|
||||
|
@ -33,16 +33,13 @@ namespace VFS
|
|||
continue;
|
||||
|
||||
const auto& path = i.path();
|
||||
const auto& proper = Files::pathToUnicodeString(path);
|
||||
const std::string proper = Files::pathToUnicodeString(path);
|
||||
|
||||
FileSystemArchiveFile file(path);
|
||||
|
||||
std::string searchable;
|
||||
std::string searchable = Path::normalizeFilename(std::string_view{ proper }.substr(prefix));
|
||||
|
||||
std::transform(std::next(proper.begin(), static_cast<std::string::difference_type>(prefix)),
|
||||
proper.end(), std::back_inserter(searchable), normalize_function);
|
||||
|
||||
const auto inserted = mIndex.insert(std::make_pair(searchable, file));
|
||||
const auto inserted = mIndex.emplace(searchable, file);
|
||||
if (!inserted.second)
|
||||
Log(Debug::Warning)
|
||||
<< "Warning: found duplicate file for '" << proper
|
||||
|
@ -61,7 +58,7 @@ namespace VFS
|
|||
}
|
||||
}
|
||||
|
||||
bool FileSystemArchive::contains(const std::string& file, char (*normalize_function)(char)) const
|
||||
bool FileSystemArchive::contains(const std::string& file) const
|
||||
{
|
||||
return mIndex.find(file) != mIndex.end();
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ namespace VFS
|
|||
public:
|
||||
FileSystemArchive(const std::filesystem::path& path);
|
||||
|
||||
void listResources(std::map<std::string, File*>& out, char (*normalize_function)(char)) override;
|
||||
void listResources(std::map<std::string, File*>& out) override;
|
||||
|
||||
bool contains(const std::string& file, char (*normalize_function)(char)) const override;
|
||||
bool contains(const std::string& file) const override;
|
||||
|
||||
std::string getDescription() const override;
|
||||
|
||||
|
|
|
@ -7,38 +7,10 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
}
|
||||
#include "pathutil.hpp"
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
|
||||
Manager::Manager(bool strict)
|
||||
: mStrict(strict)
|
||||
{
|
||||
}
|
||||
|
||||
Manager::~Manager() {}
|
||||
|
||||
void Manager::reset()
|
||||
{
|
||||
mIndex.clear();
|
||||
|
@ -55,15 +27,12 @@ namespace VFS
|
|||
mIndex.clear();
|
||||
|
||||
for (const auto& archive : mArchives)
|
||||
archive->listResources(mIndex, mStrict ? &strict_normalize_char : &nonstrict_normalize_char);
|
||||
archive->listResources(mIndex);
|
||||
}
|
||||
|
||||
Files::IStreamPtr Manager::get(std::string_view name) const
|
||||
{
|
||||
std::string normalized(name);
|
||||
normalize_path(normalized, mStrict);
|
||||
|
||||
return getNormalized(normalized);
|
||||
return getNormalized(Path::normalizeFilename(name));
|
||||
}
|
||||
|
||||
Files::IStreamPtr Manager::getNormalized(const std::string& normalizedName) const
|
||||
|
@ -76,26 +45,15 @@ namespace VFS
|
|||
|
||||
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;
|
||||
return mIndex.find(Path::normalizeFilename(name)) != mIndex.end();
|
||||
}
|
||||
|
||||
std::string Manager::getArchive(std::string_view name) const
|
||||
{
|
||||
std::string normalized(name);
|
||||
normalize_path(normalized, mStrict);
|
||||
std::string normalized = Path::normalizeFilename(name);
|
||||
for (auto it = mArchives.rbegin(); it != mArchives.rend(); ++it)
|
||||
{
|
||||
if ((*it)->contains(normalized, mStrict ? &strict_normalize_char : &nonstrict_normalize_char))
|
||||
if ((*it)->contains(normalized))
|
||||
return (*it)->getDescription();
|
||||
}
|
||||
return {};
|
||||
|
@ -104,7 +62,7 @@ namespace VFS
|
|||
std::filesystem::path Manager::getAbsoluteFileName(const std::filesystem::path& name) const
|
||||
{
|
||||
std::string normalized = Files::pathToUnicodeString(name);
|
||||
normalize_path(normalized, mStrict);
|
||||
Path::normalizeFilenameInPlace(normalized);
|
||||
|
||||
const auto found = mIndex.find(normalized);
|
||||
if (found == mIndex.end())
|
||||
|
@ -124,7 +82,7 @@ namespace VFS
|
|||
{
|
||||
if (path.empty())
|
||||
return { mIndex.begin(), mIndex.end() };
|
||||
auto normalized = normalizeFilename(path);
|
||||
std::string normalized = Path::normalizeFilename(path);
|
||||
const auto it = mIndex.lower_bound(normalized);
|
||||
if (it == mIndex.end() || !startsWith(it->first, normalized))
|
||||
return { it, it };
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.hpp"
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
|
||||
class Archive;
|
||||
class File;
|
||||
|
||||
template <typename Iterator>
|
||||
class IteratorPair
|
||||
{
|
||||
|
@ -62,12 +61,6 @@ namespace VFS
|
|||
using RecursiveDirectoryRange = IteratorPair<RecursiveDirectoryIterator>;
|
||||
|
||||
public:
|
||||
/// @param strict Use strict path handling? If enabled, no case folding will
|
||||
/// be done, but slash/backslash conversions are always done.
|
||||
Manager(bool strict);
|
||||
|
||||
~Manager();
|
||||
|
||||
// Empty the file index and unregister archives.
|
||||
void reset();
|
||||
|
||||
|
@ -82,10 +75,6 @@ namespace VFS
|
|||
/// @note May be called from any thread once the index has been built.
|
||||
bool exists(std::string_view name) const;
|
||||
|
||||
/// Normalize the given filename, making slashes/backslashes consistent, and lower-casing if mStrict is false.
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
[[nodiscard]] std::string normalizeFilename(std::string_view name) const;
|
||||
|
||||
/// Retrieve a file by name.
|
||||
/// @note Throws an exception if the file can not be found.
|
||||
/// @note May be called from any thread once the index has been built.
|
||||
|
@ -110,8 +99,6 @@ namespace VFS
|
|||
std::filesystem::path getAbsoluteFileName(const std::filesystem::path& name) const;
|
||||
|
||||
private:
|
||||
bool mStrict;
|
||||
|
||||
std::vector<std::unique_ptr<Archive>> mArchives;
|
||||
|
||||
std::map<std::string, File*> mIndex;
|
||||
|
|
56
components/vfs/pathutil.hpp
Normal file
56
components/vfs/pathutil.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef OPENMW_COMPONENTS_VFS_PATHUTIL_H
|
||||
#define OPENMW_COMPONENTS_VFS_PATHUTIL_H
|
||||
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace VFS::Path
|
||||
{
|
||||
inline constexpr char normalize(char c)
|
||||
{
|
||||
return c == '\\' ? '/' : Misc::StringUtils::toLower(c);
|
||||
}
|
||||
|
||||
inline void normalizeFilenameInPlace(std::string& name)
|
||||
{
|
||||
std::transform(name.begin(), name.end(), name.begin(), normalize);
|
||||
}
|
||||
|
||||
/// Normalize the given filename, making slashes/backslashes consistent, and lower-casing.
|
||||
[[nodiscard]] inline std::string normalizeFilename(std::string_view name)
|
||||
{
|
||||
std::string out(name);
|
||||
normalizeFilenameInPlace(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct PathCharLess
|
||||
{
|
||||
bool operator()(char x, char y) const { return normalize(x) < normalize(y); }
|
||||
};
|
||||
|
||||
inline bool pathLess(std::string_view x, std::string_view y)
|
||||
{
|
||||
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end(), PathCharLess());
|
||||
}
|
||||
|
||||
inline bool pathEqual(std::string_view x, std::string_view y)
|
||||
{
|
||||
if (std::size(x) != std::size(y))
|
||||
return false;
|
||||
return std::equal(
|
||||
std::begin(x), std::end(x), std::begin(y), [](char l, char r) { return normalize(l) == normalize(r); });
|
||||
}
|
||||
|
||||
struct PathLess
|
||||
{
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()(std::string_view left, std::string_view right) const { return pathLess(left, right); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue