#include "path.hpp" #include #include #include #include #include #include namespace anm2ed::util::path { namespace { template CharT to_lower_char(CharT character) { if constexpr (std::is_same_v) return static_cast(std::towlower(static_cast(character))); else return static_cast(std::tolower(static_cast(character))); } } std::filesystem::path to_lower(const std::filesystem::path& path) { auto native = path.native(); for (auto& character : native) character = to_lower_char(character); return std::filesystem::path(native); } std::filesystem::path backslash_replace(const std::filesystem::path& path) { auto native = path.native(); constexpr auto backslash = static_cast('\\'); constexpr auto slash = static_cast('/'); for (auto& character : native) if (character == backslash) character = slash; return std::filesystem::path(native); } std::string to_utf8(const std::filesystem::path& path) { auto u8 = path.u8string(); return std::string(u8.begin(), u8.end()); } std::filesystem::path from_utf8(const std::string& utf8) { return std::filesystem::path(std::u8string(utf8.begin(), utf8.end())); } bool is_exist(const std::filesystem::path& path) { if (path.empty()) return false; std::error_code errorCode; return std::filesystem::exists(path, errorCode) && ((void)std::filesystem::status(path, errorCode), !errorCode); } bool is_extension(const std::filesystem::path& path, const std::string& extension) { if (path.empty()) return false; auto extensionUtf8 = to_utf8(std::filesystem::path(path).extension()); std::transform(extensionUtf8.begin(), extensionUtf8.end(), extensionUtf8.begin(), ::tolower); return extensionUtf8 == ("." + extension); } bool is_executable(const std::filesystem::path& path) { if (path.empty()) return false; std::error_code ec; auto status = std::filesystem::status(path, ec); if (ec) return false; if (!std::filesystem::exists(status)) return false; if (!std::filesystem::is_regular_file(status)) return false; #ifdef WIN32 auto extension = to_lower(path.extension()); if (extension != ".exe" && extension != ".bat" && extension != ".cmd") return false; #else auto permissions = status.permissions(); auto executableMask = std::filesystem::perms::owner_exec | std::filesystem::perms::group_exec | std::filesystem::perms::others_exec; if ((permissions & executableMask) == std::filesystem::perms::none) return false; #endif return true; } bool ensure_directory(const std::filesystem::path& path) { if (path.empty()) return false; std::error_code ec; if (std::filesystem::create_directories(path, ec)) return true; return is_exist(path.parent_path()); } std::filesystem::path make_relative(const std::filesystem::path& path) { if (path.empty()) return path; if (!path.is_absolute()) return path; std::error_code ec{}; auto relative = std::filesystem::relative(path, ec); if (!ec) return relative; return path; } std::filesystem::path make_relative(const std::filesystem::path& path, const std::filesystem::path& base) { if (path.empty()) return path; if (base.empty() || !path.is_absolute()) return path; std::error_code ec{}; auto relative = std::filesystem::relative(path, base, ec); if (!ec) return relative; return path; } std::filesystem::path lower_case_backslash_handle(const std::filesystem::path& path) { auto newPath = path; if (is_exist(newPath)) return newPath; newPath = backslash_replace(newPath); if (is_exist(newPath)) return newPath; newPath = to_lower(newPath); return newPath; } }