add io::path.normalized()

This commit is contained in:
MihailRis 2025-02-04 14:58:41 +03:00
parent 1ec8f89599
commit 59f46ad530
5 changed files with 39 additions and 35 deletions

View File

@ -23,7 +23,7 @@ StdfsDevice::StdfsDevice(fs::path root, bool createDirectory)
}
fs::path StdfsDevice::resolve(std::string_view path) {
return root / fs::u8path(path);
return root / fs::u8path(io::path(std::string(path)).normalized().string());
}
void StdfsDevice::write(std::string_view path, const void* data, size_t size) {
@ -123,5 +123,5 @@ private:
};
std::unique_ptr<PathsGenerator> StdfsDevice::list(std::string_view path) {
return std::make_unique<StdfsPathsGenerator>(root / fs::u8path(path));
return std::make_unique<StdfsPathsGenerator>(resolve(path));
}

View File

@ -25,32 +25,6 @@ static inline io::path EXPORT_FOLDER = "export";
static inline io::path CONTROLS_FILE = "controls.toml";
static inline io::path SETTINGS_FILE = "settings.toml";
static io::path toCanonic(io::path path) {
std::stack<std::string> parts;
path = std::filesystem::u8path(path.string()).lexically_normal().string();
do {
parts.push(path.name());
path = path.parent();
} while (!path.empty());
path = "";
while (!parts.empty()) {
const std::string part = parts.top();
parts.pop();
if (part == ".") {
continue;
}
if (part == "..") {
throw files_access_error("entry point reached");
}
path = path / part;
}
return path;
}
void EnginePaths::prepare() {
io::set_device("res", std::make_shared<io::StdfsDevice>(resourcesFolder, false));
io::set_device("user", std::make_shared<io::StdfsDevice>(userFilesFolder));

View File

@ -10,12 +10,6 @@
#include "data/dv.hpp"
#include "content/ContentPack.hpp"
class files_access_error : public std::runtime_error {
public:
files_access_error(const std::string& msg) : std::runtime_error(msg) {
}
};
class EnginePaths {
public:
void prepare();

View File

@ -1,6 +1,6 @@
#include "path.hpp"
#include <stdexcept>
#include <stack>
using namespace io;
@ -9,3 +9,30 @@ void path::checkValid() const {
throw std::runtime_error("path entry point is not specified: " + str);
}
}
path path::normalized() const {
io::path path = pathPart();
std::stack<std::string> parts;
do {
parts.push(path.name());
path.str = path.parent().string();
} while (!path.empty());
while (!parts.empty()) {
const std::string part = parts.top();
parts.pop();
if (part == ".") {
continue;
}
if (part == "..") {
throw access_error("entry point reached");
}
path = path / part;
}
if (path.colonPos != std::string::npos) {
path = path.entryPoint() + ":" + path.string();
}
return path;
}

View File

@ -1,9 +1,16 @@
#pragma once
#include <string>
#include <stdexcept>
#include <filesystem>
namespace io {
class access_error : public std::runtime_error {
public:
access_error(const std::string& msg) : std::runtime_error(msg) {
}
};
/// @brief std::filesystem::path project-specific alternative having
/// `entry_point:path` scheme and solving std::filesystem::path problems:
/// - implicit std::string conversions depending on compiler
@ -115,6 +122,8 @@ namespace io {
return str.substr(0, slashpos);
}
path normalized() const;
std::string string() const {
return str;
}