TrinityCore
Loading...
Searching...
No Matches
Hash.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITYCORE_HASH_H
19#define TRINITYCORE_HASH_H
20
21#include <functional>
22#include <span>
23#include <utility>
24
25namespace Trinity
26{
27 template <typename T>
28 inline void hash_combine(std::size_t& seed, T const& val)
29 {
30 // Taken from boost::hash_combine
31
32 seed = seed + 0x9E3779B9 + std::hash<T>()(val);
33
34 if constexpr (sizeof(std::size_t) == 8)
35 {
36 constexpr std::size_t m = 0xE9846AF9B1A615D;
37
38 seed ^= seed >> 32;
39 seed *= m;
40 seed ^= seed >> 32;
41 seed *= m;
42 seed ^= seed >> 28;
43 }
44 else
45 {
46 constexpr std::size_t m1 = 0x21F0AAAD;
47 constexpr std::size_t m2 = 0x735A2D97;
48
49 seed ^= seed >> 16;
50 seed *= m1;
51 seed ^= seed >> 15;
52 seed *= m2;
53 seed ^= seed >> 15;
54 }
55 }
56
57 template <std::size_t>
59
60 template <>
62 {
63 static constexpr std::uint32_t Basis = 0x811C9DC5u;
64 static constexpr std::uint32_t Prime = 0x01000193u;
65 };
66
67 template <>
69 {
70 static constexpr std::uint64_t Basis = 0xCBF29CE484222325ull;
71 static constexpr std::uint64_t Prime = 0x00000100000001B3ull;
72 };
73
74 template <typename T>
75 concept HashablePrimitive = std::is_arithmetic_v<T> || std::is_enum_v<T> || std::is_pointer_v<T>;
76
77 template <typename T = std::size_t>
78 struct HashFnv1a
79 {
80 using Constants = HashFnv1aConstants<sizeof(T)>;
81
82 T Value = Constants::Basis;
83
84 template <HashablePrimitive V, std::size_t Extent>
85 inline constexpr void UpdateData(std::span<V, Extent> data) noexcept
86 {
87 T hash = Value;
88
89 if (std::is_constant_evaluated())
90 {
91 static_assert(std::is_integral_v<V> || std::is_enum_v<V>, "Only integral types can be hashed at compile time");
92
93 using I = typename std::conditional_t<std::is_enum_v<V>, std::underlying_type<V>, std::type_identity<V>>::type;
94
95 for (V c : data)
96 {
97 for (std::size_t i = 0; i < sizeof(V); ++i)
98 {
99 hash ^= static_cast<T>((static_cast<I>(c) >> (i * 8)) & 0xFF);
100 hash *= Constants::Prime;
101 }
102 }
103 }
104 else
105 {
106 std::byte const* c = reinterpret_cast<std::byte const*>(data.data());
107 std::byte const* end = c + data.size_bytes();
108 while (c != end)
109 {
110 hash ^= static_cast<T>(*c);
111 hash *= Constants::Prime;
112 ++c;
113 }
114 }
115
116 Value = hash;
117 }
118
119 template <HashablePrimitive V>
120 inline constexpr void UpdateData(V data) noexcept
121 {
122 this->UpdateData(std::span<V, 1>(&data, 1));
123 }
124
125 template <typename V>
126 inline constexpr void UpdateData(V const& data) noexcept requires requires { std::span(data); }
127 {
128 this->UpdateData(std::span(data));
129 }
130
131 template <HashablePrimitive V, std::size_t Extent>
132 inline static constexpr T GetHash(std::span<V, Extent> data) noexcept
133 {
134 HashFnv1a hash;
135 hash.UpdateData(data);
136 return hash.Value;
137 }
138
139 template <HashablePrimitive V>
140 inline static constexpr T GetHash(V data) noexcept
141 {
142 return HashFnv1a::GetHash(std::span<V, 1>(&data, 1));
143 }
144
145 template <typename V>
146 inline static constexpr T GetHash(V const& data) noexcept requires requires { std::span(data); }
147 {
148 return HashFnv1a::GetHash(std::span(data));
149 }
150 };
151
152 template <typename T, typename Hash = std::hash<T>>
153 struct TransparentHash : Hash
154 {
155 using is_transparent = int;
156 };
157}
158
161template <typename K, typename V>
162struct std::hash<std::pair<K, V>>
163{
164 std::size_t operator()(std::pair<K, V> const& p) const
165 {
166 std::size_t hashVal = std::hash<K>()(p.first);
167 Trinity::hash_combine(hashVal, p.second);
168 return hashVal;
169 }
170};
171
172#endif // TRINITYCORE_HASH_H
void hash_combine(std::size_t &seed, T const &val)
Definition Hash.h:28
STL namespace.
static constexpr T GetHash(std::span< V, Extent > data) noexcept
Definition Hash.h:132
constexpr void UpdateData(std::span< V, Extent > data) noexcept
Definition Hash.h:85
static constexpr T GetHash(V data) noexcept
Definition Hash.h:140
static constexpr T GetHash(V const &data) noexcept
Definition Hash.h:146
constexpr void UpdateData(V data) noexcept
Definition Hash.h:120
constexpr void UpdateData(V const &data) noexcept
Definition Hash.h:126
std::size_t operator()(std::pair< K, V > const &p) const
Definition Hash.h:164