From 62c98b84200c36b638cf6ba9c453eacfdea7746d Mon Sep 17 00:00:00 2001 From: alexei-zebra Date: Tue, 6 Aug 2024 15:32:56 +0300 Subject: [PATCH] refactor engine_paths --- src/files/engine_paths.cpp | 178 +++++++++++++++++++++---------------- src/files/engine_paths.hpp | 57 ++++++------ 2 files changed, 130 insertions(+), 105 deletions(-) diff --git a/src/files/engine_paths.cpp b/src/files/engine_paths.cpp index 18713331..66fdcbcf 100644 --- a/src/files/engine_paths.cpp +++ b/src/files/engine_paths.cpp @@ -5,33 +5,80 @@ #include #include #include +#include #include "../typedefs.hpp" #include "../util/stringutil.hpp" #include "WorldFiles.hpp" -const fs::path SCREENSHOTS_FOLDER {"screenshots"}; -const fs::path CONTENT_FOLDER {"content"}; -const fs::path CONTROLS_FILE {"controls.toml"}; -const fs::path SETTINGS_FILE {"settings.toml"}; +/** + * @brief ENUM for accessing folder and file names + */ +enum F_F_NAME{ + SCREENSHOTS_FOLDER, + CONTENT_FOLDER, + CONTROLS_FILE, + SETTINGS_FILE, + + COUNT +}; + +/** + * @brief array for get file or folder name by enum `F_F_NAME` + * + * @example example: + * `std::filesystem::path settings = f_f_names[SETTINGS_FILE];` + */ +static std::array f_f_names{ + "screenshots", + "content", + "controls.toml", + "settings.toml" +}; + +static std::filesystem::path toCanonic(std::filesystem::path path) { + std::stack parts; + path = path.lexically_normal(); + do { + parts.push(path.filename().u8string()); + path = path.parent_path(); + } while (!path.empty()); + + path = fs::u8path(""); + + 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 / std::filesystem::path(part); + } + return path; +} + void EnginePaths::prepare() { - fs::path contentFolder = userfiles / fs::path(CONTENT_FOLDER); + std::filesystem::path contentFolder = userFilesFolder / std::filesystem::path(f_f_names[CONTENT_FOLDER]); if (!fs::is_directory(contentFolder)) { fs::create_directories(contentFolder); } } -fs::path EnginePaths::getUserfiles() const { - return userfiles; +std::filesystem::path EnginePaths::getUserFilesFolder() const { + return userFilesFolder; } -fs::path EnginePaths::getResources() const { - return resources; +std::filesystem::path EnginePaths::getResourcesFolder() const { + return resourcesFolder; } -fs::path EnginePaths::getScreenshotFile(const std::string& ext) { - fs::path folder = userfiles / fs::path(SCREENSHOTS_FOLDER); +std::filesystem::path EnginePaths::getNewScreenshotFile(const std::string& ext) { + std::filesystem::path folder = userFilesFolder / std::filesystem::path(f_f_names[SCREENSHOTS_FOLDER]); if (!fs::is_directory(folder)) { fs::create_directory(folder); } @@ -44,7 +91,7 @@ fs::path EnginePaths::getScreenshotFile(const std::string& ext) { ss << std::put_time(&tm, format); std::string datetimestr = ss.str(); - fs::path filename = + std::filesystem::path filename = folder / fs::u8path("screenshot-" + datetimestr + "." + ext); uint index = 0; while (fs::exists(filename)) { @@ -57,44 +104,44 @@ fs::path EnginePaths::getScreenshotFile(const std::string& ext) { return filename; } -fs::path EnginePaths::getWorldsFolder() { - return userfiles / fs::path("worlds"); +std::filesystem::path EnginePaths::getWorldsFolder() { + return userFilesFolder / std::filesystem::path("worlds"); } -fs::path EnginePaths::getWorldFolder() { - return worldFolder; +std::filesystem::path EnginePaths::getCurrentWorldFolder() { + return currentWorldFolder; } -fs::path EnginePaths::getWorldFolder(const std::string& name) { - return getWorldsFolder() / fs::path(name); +std::filesystem::path EnginePaths::getWorldFolderByName(const std::string& name) { + return getWorldsFolder() / std::filesystem::path(name); } -fs::path EnginePaths::getControlsFile() { - return userfiles / fs::path(CONTROLS_FILE); +std::filesystem::path EnginePaths::getControlsFile() { + return userFilesFolder / std::filesystem::path(f_f_names[CONTROLS_FILE]); } -fs::path EnginePaths::getSettingsFile() { - return userfiles / fs::path(SETTINGS_FILE); +std::filesystem::path EnginePaths::getSettingsFile() { + return userFilesFolder / std::filesystem::path(f_f_names[SETTINGS_FILE]); } -std::vector EnginePaths::scanForWorlds() { - std::vector folders; +std::vector EnginePaths::scanForWorlds() { + std::vector folders; - fs::path folder = getWorldsFolder(); + std::filesystem::path folder = getWorldsFolder(); if (!fs::is_directory(folder)) return folders; for (const auto& entry : fs::directory_iterator(folder)) { if (!entry.is_directory()) { continue; } - const fs::path& worldFolder = entry.path(); - fs::path worldFile = worldFolder / fs::u8path(WorldFiles::WORLD_FILE); + const std::filesystem::path& worldFolder = entry.path(); + std::filesystem::path worldFile = worldFolder / fs::u8path(WorldFiles::WORLD_FILE); if (!fs::is_regular_file(worldFile)) { continue; } folders.push_back(worldFolder); } - std::sort(folders.begin(), folders.end(), [](fs::path a, fs::path b) { + std::sort(folders.begin(), folders.end(), [](std::filesystem::path a, std::filesystem::path b) { a = a / fs::u8path(WorldFiles::WORLD_FILE); b = b / fs::u8path(WorldFiles::WORLD_FILE); return fs::last_write_time(a) > fs::last_write_time(b); @@ -102,51 +149,23 @@ std::vector EnginePaths::scanForWorlds() { return folders; } -bool EnginePaths::isWorldNameUsed(const std::string& name) { - return fs::exists(EnginePaths::getWorldsFolder() / fs::u8path(name)); +void EnginePaths::setUserFilesFolder(std::filesystem::path folder) { + this->userFilesFolder = std::move(folder); } -void EnginePaths::setUserfiles(fs::path folder) { - this->userfiles = std::move(folder); +void EnginePaths::setResourcesFolder(std::filesystem::path folder) { + this->resourcesFolder = std::move(folder); } -void EnginePaths::setResources(fs::path folder) { - this->resources = std::move(folder); -} - -void EnginePaths::setWorldFolder(fs::path folder) { - this->worldFolder = std::move(folder); +void EnginePaths::setCurrentWorldFolder(std::filesystem::path folder) { + this->currentWorldFolder = std::move(folder); } void EnginePaths::setContentPacks(std::vector* contentPacks) { this->contentPacks = contentPacks; } -static fs::path toCanonic(fs::path path) { - std::stack parts; - path = path.lexically_normal(); - while (true) { - parts.push(path.filename().u8string()); - path = path.parent_path(); - if (path.empty()) break; - } - path = fs::u8path(""); - 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 / fs::path(part); - } - return path; -} - -fs::path EnginePaths::resolve(const std::string& path, bool throwErr) { +std::filesystem::path EnginePaths::resolve(const std::string& path, bool throwErr) { size_t separator = path.find(':'); if (separator == std::string::npos) { throw files_access_error("no entry point specified"); @@ -156,13 +175,13 @@ fs::path EnginePaths::resolve(const std::string& path, bool throwErr) { filename = toCanonic(fs::u8path(filename)).u8string(); if (prefix == "res" || prefix == "core") { - return resources / fs::u8path(filename); + return resourcesFolder / fs::u8path(filename); } if (prefix == "user") { - return userfiles / fs::u8path(filename); + return userFilesFolder / fs::u8path(filename); } if (prefix == "world") { - return worldFolder / fs::u8path(filename); + return currentWorldFolder / fs::u8path(filename); } if (contentPacks) { @@ -175,17 +194,18 @@ fs::path EnginePaths::resolve(const std::string& path, bool throwErr) { if (throwErr) { throw files_access_error("unknown entry point '" + prefix + "'"); } - return fs::path(filename); + return std::filesystem::path(filename); } -ResPaths::ResPaths(fs::path mainRoot, std::vector roots) + +ResPaths::ResPaths(std::filesystem::path mainRoot, std::vector roots) : mainRoot(std::move(mainRoot)), roots(std::move(roots)) { } -fs::path ResPaths::find(const std::string& filename) const { +std::filesystem::path ResPaths::find(const std::string& filename) const { for (int i = roots.size() - 1; i >= 0; i--) { auto& root = roots[i]; - fs::path file = root.path / fs::u8path(filename); + std::filesystem::path file = root.path / fs::u8path(filename); if (fs::exists(file)) { return file; } @@ -196,12 +216,12 @@ fs::path ResPaths::find(const std::string& filename) const { std::string ResPaths::findRaw(const std::string& filename) const { for (int i = roots.size() - 1; i >= 0; i--) { auto& root = roots[i]; - if (fs::exists(root.path / fs::path(filename))) { + if (fs::exists(root.path / std::filesystem::path(filename))) { return root.name + ":" + filename; } } auto resDir = mainRoot; - if (fs::exists(resDir / fs::path(filename))) { + if (fs::exists(resDir / std::filesystem::path(filename))) { return "core:" + filename; } throw std::runtime_error("could not to find file " + util::quote(filename)); @@ -212,7 +232,7 @@ std::vector ResPaths::listdirRaw(const std::string& folderName std::vector entries; for (int i = roots.size() - 1; i >= 0; i--) { auto& root = roots[i]; - fs::path folder = root.path / fs::u8path(folderName); + std::filesystem::path folder = root.path / fs::u8path(folderName); if (!fs::is_directory(folder)) continue; for (const auto& entry : fs::directory_iterator(folder)) { auto name = entry.path().filename().u8string(); @@ -220,7 +240,7 @@ std::vector ResPaths::listdirRaw(const std::string& folderName } } { - fs::path folder = mainRoot / fs::u8path(folderName); + std::filesystem::path folder = mainRoot / fs::u8path(folderName); if (!fs::is_directory(folder)) return entries; for (const auto& entry : fs::directory_iterator(folder)) { auto name = entry.path().filename().u8string(); @@ -230,18 +250,18 @@ std::vector ResPaths::listdirRaw(const std::string& folderName return entries; } -std::vector ResPaths::listdir(const std::string& folderName) const { - std::vector entries; +std::vector ResPaths::listdir(const std::string& folderName) const { + std::vector entries; for (int i = roots.size() - 1; i >= 0; i--) { auto& root = roots[i]; - fs::path folder = root.path / fs::u8path(folderName); + std::filesystem::path folder = root.path / fs::u8path(folderName); if (!fs::is_directory(folder)) continue; for (const auto& entry : fs::directory_iterator(folder)) { entries.push_back(entry.path()); } } { - fs::path folder = mainRoot / fs::u8path(folderName); + std::filesystem::path folder = mainRoot / fs::u8path(folderName); if (!fs::is_directory(folder)) return entries; for (const auto& entry : fs::directory_iterator(folder)) { entries.push_back(entry.path()); @@ -250,6 +270,6 @@ std::vector ResPaths::listdir(const std::string& folderName) const { return entries; } -const fs::path& ResPaths::getMainRoot() const { +const std::filesystem::path& ResPaths::getMainRoot() const { return mainRoot; } diff --git a/src/files/engine_paths.hpp b/src/files/engine_paths.hpp index 6465905f..b93746b2 100644 --- a/src/files/engine_paths.hpp +++ b/src/files/engine_paths.hpp @@ -8,7 +8,6 @@ #include "../content/ContentPack.hpp" -namespace fs = std::filesystem; class files_access_error : public std::runtime_error { public: @@ -17,51 +16,57 @@ public: }; class EnginePaths { - fs::path userfiles {"."}; - fs::path resources {"res"}; - fs::path worldFolder; - std::vector* contentPacks = nullptr; public: void prepare(); - fs::path getUserfiles() const; - fs::path getResources() const; + void setUserFilesFolder(std::filesystem::path folder); + std::filesystem::path getUserFilesFolder() const; - fs::path getScreenshotFile(const std::string& ext); - fs::path getWorldsFolder(); - fs::path getWorldFolder(); - fs::path getWorldFolder(const std::string& name); - fs::path getControlsFile(); - fs::path getSettingsFile(); - bool isWorldNameUsed(const std::string& name); + void setResourcesFolder(std::filesystem::path folder); + std::filesystem::path getResourcesFolder() const; + + std::filesystem::path getWorldsFolder(); + std::filesystem::path getWorldFolderByName(const std::string& name); + + void setCurrentWorldFolder(std::filesystem::path folder); + std::filesystem::path getCurrentWorldFolder(); + + std::filesystem::path getNewScreenshotFile(const std::string& ext); + std::filesystem::path getControlsFile(); + std::filesystem::path getSettingsFile(); - void setUserfiles(fs::path folder); - void setResources(fs::path folder); void setContentPacks(std::vector* contentPacks); - void setWorldFolder(fs::path folder); - std::vector scanForWorlds(); + std::vector scanForWorlds(); - fs::path resolve(const std::string& path, bool throwErr = true); + std::filesystem::path resolve(const std::string& path, bool throwErr = true); + +private: + std::filesystem::path userFilesFolder {"."}; + std::filesystem::path resourcesFolder {"res"}; + std::filesystem::path currentWorldFolder; + std::vector* contentPacks = nullptr; }; struct PathsRoot { std::string name; - fs::path path; + std::filesystem::path path; }; class ResPaths { - fs::path mainRoot; - std::vector roots; public: - ResPaths(fs::path mainRoot, std::vector roots); + ResPaths(std::filesystem::path mainRoot, std::vector roots); - fs::path find(const std::string& filename) const; + std::filesystem::path find(const std::string& filename) const; std::string findRaw(const std::string& filename) const; - std::vector listdir(const std::string& folder) const; + std::vector listdir(const std::string& folder) const; std::vector listdirRaw(const std::string& folder) const; - const fs::path& getMainRoot() const; + const std::filesystem::path& getMainRoot() const; + +private: + std::filesystem::path mainRoot; + std::vector roots; }; #endif // FILES_ENGINE_PATHS_HPP_