plugify 1.2.8
Loading...
Searching...
No Matches
hash.hpp
1#pragma once
2
3#include <filesystem>
4#include <string>
5#include <vector>
6#include <algorithm>
7#include <locale>
8
9#include "plg/string.hpp"
10
11namespace plg {
12 // std::hash<std::filesystem::path> not in the C++20 standard by default
13 struct path_hash {
14 auto operator()(const std::filesystem::path& path) const noexcept {
15 return hash_value(path);
16 }
17 };
18
19 struct string_hash {
20 using is_transparent = void; // Enables heterogeneous lookup
21
22 auto operator()(const char* txt) const {
23 return std::hash<std::string_view>{}(txt);
24 }
25
26 auto operator()(std::string_view txt) const {
27 return std::hash<std::string_view>{}(txt);
28 }
29
30 auto operator()(const std::string& txt) const {
31 return std::hash<std::string>{}(txt);
32 }
33
34 auto operator()(const plg::string& txt) const {
35 return std::hash<plg::string>{}(txt);
36 }
37 };
38
39 // --- Hash traits depending on pointer size ---
40 template <std::size_t Size>
42
43 template <>
44 struct hash_traits<4> { // 32-bit
45 static constexpr std::size_t fnv_basis = 0x811C9DC5u;
46 static constexpr std::size_t fnv_prime = 0x01000193u;
47 static constexpr std::size_t golden_ratio = 0x9e3779b9u;
48 };
49
50 template <>
51 struct hash_traits<8> { // 64-bit
52 static constexpr std::size_t fnv_basis = 0xcbf29ce484222325ULL;
53 static constexpr std::size_t fnv_prime = 0x100000001b3ULL;
54 static constexpr std::size_t golden_ratio = 0x9e3779b97f4a7c15ULL;
55 };
56
57 using active_hash_traits = hash_traits<sizeof(std::size_t)>;
58
60 using is_transparent = void; // Enables heterogeneous lookup
61
62 template <typename T>
63 std::size_t operator()(const T& str) const noexcept {
64 std::size_t hash = active_hash_traits::fnv_basis; // FNV-1a
65 for (const auto& c : str) {
66 hash ^= static_cast<std::size_t>(std::tolower(c));
67 hash *= active_hash_traits::fnv_prime;
68 }
69 return hash;
70 }
71 };
72
74 using is_transparent = void; // Enables heterogeneous lookup
75
76 template <typename T1, typename T2>
77 bool operator()(const T1& lhs, const T2& rhs) const noexcept {
78 return std::lexicographical_compare(
79 lhs.begin(), lhs.end(),
80 rhs.begin(), rhs.end(),
81 [](const auto& ac, const auto& bc) {
82 return std::tolower(ac) < std::tolower(bc);
83 }
84 );
85 }
86 };
87
88 inline void hash_combine(size_t&) {
89 }
90
91 template <class T>
92 inline void hash_combine(std::size_t& seed, const T& v) {
93 std::hash<T> hasher;
94 seed ^= hasher(v) + active_hash_traits::golden_ratio + (seed << 6) + (seed >> 2);
95 }
96
97 template <class... Ts>
98 inline std::size_t hash_combine_all(const Ts&... args) {
99 std::size_t seed = 0;
100 (hash_combine(seed, args), ...); // fold expression
101 return seed;
102 }
103
104 template <typename T1, typename T2>
105 struct pair_hash {
106 size_t operator()(const std::pair<T1, T2>& p) const {
107 return hash_combine_all(p.first, p.second);
108 }
109 };
110}