#pragma once #include "string.hpp" #include namespace utils { class path_key { public: path_key() = default; path_key(const std::filesystem::path& p) : path_(canonicalize_path(p)) { } path_key(const path_key&) = default; path_key(path_key&&) noexcept = default; path_key& operator=(const path_key&) = default; path_key& operator=(path_key&&) noexcept = default; ~path_key() = default; const std::filesystem::path& get() const { return this->path_; } bool operator==(const path_key& other) const { return this->get() == other.get(); } bool operator!=(const path_key& other) const { return !this->operator==(other); } static std::filesystem::path canonicalize_path(const std::filesystem::path& key) { auto key_string = key.u16string(); std::ranges::replace(key_string, u'\\', '/'); auto path = std::filesystem::path(key_string).lexically_normal().wstring(); return utils::string::to_lower_consume(path); } private: std::filesystem::path path_{}; }; } namespace std { template <> struct hash { size_t operator()(const utils::path_key& p) const noexcept { return hash()(p.get().native()); } }; }