mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.9 KiB
C++
85 lines
2.9 KiB
C++
#include "filesystemarchive.hpp"
|
|
|
|
#include <filesystem>
|
|
|
|
#include "pathutil.hpp"
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
#include <components/files/constrainedfilestream.hpp>
|
|
#include <components/files/conversion.hpp>
|
|
|
|
namespace VFS
|
|
{
|
|
|
|
FileSystemArchive::FileSystemArchive(const std::filesystem::path& path)
|
|
: mPath(path)
|
|
{
|
|
const auto str = mPath.u8string();
|
|
std::size_t prefix = str.size();
|
|
|
|
if (prefix > 0 && str[prefix - 1] != '\\' && str[prefix - 1] != '/')
|
|
++prefix;
|
|
|
|
std::filesystem::recursive_directory_iterator iterator(mPath);
|
|
|
|
for (auto it = std::filesystem::begin(iterator), end = std::filesystem::end(iterator); it != end;)
|
|
{
|
|
const std::filesystem::directory_entry& entry = *it;
|
|
|
|
if (!entry.is_directory())
|
|
{
|
|
const std::filesystem::path& filePath = entry.path();
|
|
const std::string proper = Files::pathToUnicodeString(filePath);
|
|
VFS::Path::Normalized searchable(std::string_view{ proper }.substr(prefix));
|
|
FileSystemArchiveFile file(filePath);
|
|
|
|
const auto inserted = mIndex.emplace(std::move(searchable), std::move(file));
|
|
if (!inserted.second)
|
|
Log(Debug::Warning)
|
|
<< "Found duplicate file for '" << proper
|
|
<< "', please check your file system for two files with the same name in different cases.";
|
|
}
|
|
|
|
// Exception thrown by the operator++ may not contain the context of the error like what exact path caused
|
|
// the problem which makes it hard to understand what's going on when iteration happens over a directory
|
|
// with thousands of files and subdirectories.
|
|
const std::filesystem::path prevPath = entry.path();
|
|
std::error_code ec;
|
|
it.increment(ec);
|
|
if (ec != std::error_code())
|
|
throw std::runtime_error("Failed to recursively iterate over \"" + Files::pathToUnicodeString(mPath)
|
|
+ "\" when incrementing to the next item from \"" + Files::pathToUnicodeString(prevPath)
|
|
+ "\": " + ec.message());
|
|
}
|
|
}
|
|
|
|
void FileSystemArchive::listResources(FileMap& out)
|
|
{
|
|
for (auto& [k, v] : mIndex)
|
|
out[k] = &v;
|
|
}
|
|
|
|
bool FileSystemArchive::contains(Path::NormalizedView file) const
|
|
{
|
|
return mIndex.find(file) != mIndex.end();
|
|
}
|
|
|
|
std::string FileSystemArchive::getDescription() const
|
|
{
|
|
return "DIR: " + Files::pathToUnicodeString(mPath);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
|
|
FileSystemArchiveFile::FileSystemArchiveFile(const std::filesystem::path& path)
|
|
: mPath(path)
|
|
{
|
|
}
|
|
|
|
Files::IStreamPtr FileSystemArchiveFile::open()
|
|
{
|
|
return Files::openConstrainedFileStream(mPath);
|
|
}
|
|
|
|
}
|