Introduce path_key util

It represents a canonical path that can be used as key
for unordered containers
This commit is contained in:
momo5502
2025-01-13 19:00:01 +01:00
parent fa5cc9c049
commit b76dc7cf24
4 changed files with 84 additions and 18 deletions

View File

@@ -0,0 +1,61 @@
#pragma once
#include "string.hpp"
#include <filesystem>
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 path = key.lexically_normal().wstring();
return utils::string::to_lower_consume(path);
}
private:
std::filesystem::path path_{};
};
}
namespace std
{
template <>
struct hash<utils::path_key>
{
size_t operator()(const utils::path_key& p) const noexcept
{
return hash<std::filesystem::path::string_type>()(p.get().native());
}
};
}

View File

@@ -4,6 +4,7 @@
#include <chrono>
#include <filesystem>
#include <utils/path_key.hpp>
namespace utils
{
@@ -44,4 +45,14 @@ namespace utils
{
path = buffer.read_string<char16_t>();
}
inline void serialize(buffer_serializer& buffer, const path_key& path)
{
buffer.write(path.get());
}
inline void deserialize(buffer_deserializer& buffer, path_key& path)
{
path = buffer.read<std::filesystem::path>();
}
}

View File

@@ -7,12 +7,6 @@
namespace
{
std::filesystem::path canonicalize_path(const std::filesystem::path& key)
{
auto path = key.lexically_normal().wstring();
return utils::string::to_lower_consume(path);
}
bool is_subpath(const std::filesystem::path& root, const std::filesystem::path& p)
{
auto root_it = root.begin();
@@ -32,7 +26,7 @@ namespace
void register_hive(registry_manager::hive_map& hives, const std::filesystem::path& key,
const std::filesystem::path& file)
{
hives[canonicalize_path(key).u16string()] = std::make_unique<hive_parser>(file);
hives[key] = std::make_unique<hive_parser>(file);
}
}
@@ -80,22 +74,22 @@ void registry_manager::deserialize(utils::buffer_deserializer& buffer)
std::filesystem::path registry_manager::normalize_path(const std::filesystem::path& path) const
{
auto canonical_path = canonicalize_path(path);
const utils::path_key canonical_path = path;
for (const auto& mapping : this->path_mapping_)
{
if (is_subpath(mapping.first, canonical_path))
if (is_subpath(mapping.first.get(), canonical_path.get()))
{
return mapping.second / canonical_path.lexically_relative(mapping.first);
return mapping.second.get() / canonical_path.get().lexically_relative(mapping.first.get());
}
}
return canonical_path;
return canonical_path.get();
}
void registry_manager::add_path_mapping(const std::filesystem::path& key, const std::filesystem::path& value)
{
this->path_mapping_[canonicalize_path(key).u16string()] = canonicalize_path(value);
this->path_mapping_[key] = value;
}
std::optional<registry_key> registry_manager::get_key(const std::filesystem::path& key)
@@ -116,7 +110,7 @@ std::optional<registry_key> registry_manager::get_key(const std::filesystem::pat
}
registry_key reg_key{};
reg_key.hive = iterator->first;
reg_key.hive = iterator->first.get();
reg_key.path = normal_key.lexically_relative(reg_key.hive);
if (reg_key.path.empty())
@@ -137,7 +131,7 @@ std::optional<registry_value> registry_manager::get_value(const registry_key& ke
{
utils::string::to_lower_inplace(name);
const auto iterator = this->hives_.find(key.hive.u16string());
const auto iterator = this->hives_.find(key.hive);
if (iterator == this->hives_.end())
{
return std::nullopt;
@@ -161,7 +155,7 @@ registry_manager::hive_map::iterator registry_manager::find_hive(const std::file
{
for (auto i = this->hives_.begin(); i != this->hives_.end(); ++i)
{
if (is_subpath(i->first, key))
if (is_subpath(i->first.get(), key))
{
return i;
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "../std_include.hpp"
#include <serialization_helper.hpp>
#include "hive_parser.hpp"
#include "serialization_helper.hpp"
struct registry_key
{
@@ -33,7 +33,7 @@ class registry_manager
{
public:
using hive_ptr = std::unique_ptr<hive_parser>;
using hive_map = std::unordered_map<std::u16string, hive_ptr>;
using hive_map = std::unordered_map<utils::path_key, hive_ptr>;
registry_manager();
registry_manager(const std::filesystem::path& hive_path);
@@ -54,7 +54,7 @@ class registry_manager
private:
std::filesystem::path hive_path_{};
hive_map hives_{};
std::unordered_map<std::u16string, std::filesystem::path> path_mapping_{};
std::unordered_map<utils::path_key, utils::path_key> path_mapping_{};
std::filesystem::path normalize_path(const std::filesystem::path& path) const;
void add_path_mapping(const std::filesystem::path& key, const std::filesystem::path& value);