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 for (V c : data)
94 {
95 for (std::size_t i = 0; i < sizeof(V); ++i)
96 {
97 hash ^= (static_cast<T>(c) >> (i * 8)) & 0xFF;
98 hash *= Constants::Prime;
99 }
100 }
101 }
102 else
103 {
104 std::byte const* c = reinterpret_cast<std::byte const*>(data.data());
105 std::byte const* end = c + data.size_bytes();
106 while (c != end)
107 {
108 hash ^= static_cast<T>(*c);
109 hash *= Constants::Prime;
110 ++c;
111 }
112 }
113
114 Value = hash;
115 }
116
117 template <HashablePrimitive V>
118 inline constexpr void UpdateData(V data) noexcept
119 {
120 this->UpdateData(std::span<V, 1>(&data, 1));
121 }
122
123 template <typename V>
124 inline constexpr void UpdateData(V const& data) noexcept requires requires { std::span(data); }
125 {
126 this->UpdateData(std::span(data));
127 }
128
129 template <HashablePrimitive V, std::size_t Extent>
130 inline static constexpr std::size_t GetHash(std::span<V, Extent> data) noexcept
131 {
132 HashFnv1a hash;
133 hash.UpdateData(data);
134 return hash.Value;
135 }
136
137 template <HashablePrimitive V>
138 inline static constexpr std::size_t GetHash(V data) noexcept
139 {
140 return HashFnv1a::GetHash(std::span<V, 1>(&data, 1));
141 }
142
143 template <typename V>
144 inline static constexpr std::size_t GetHash(V const& data) noexcept requires requires { std::span(data); }
145 {
146 return HashFnv1a::GetHash(std::span(data));
147 }
148 };
149
150 template <typename T, typename Hash = std::hash<T>>
151 struct TransparentHash : Hash
152 {
153 using is_transparent = int;
154 };
155}
156
159template <typename K, typename V>
160struct std::hash<std::pair<K, V>>
161{
162 std::size_t operator()(std::pair<K, V> const& p) const
163 {
164 std::size_t hashVal = std::hash<K>()(p.first);
165 Trinity::hash_combine(hashVal, p.second);
166 return hashVal;
167 }
168};
169
170#endif // TRINITYCORE_HASH_H
void hash_combine(std::size_t &seed, T const &val)
Definition Hash.h:28
STL namespace.
constexpr void UpdateData(std::span< V, Extent > data) noexcept
Definition Hash.h:85
static constexpr std::size_t GetHash(V const &data) noexcept
Definition Hash.h:144
static constexpr std::size_t GetHash(std::span< V, Extent > data) noexcept
Definition Hash.h:130
static constexpr std::size_t GetHash(V data) noexcept
Definition Hash.h:138
constexpr void UpdateData(V data) noexcept
Definition Hash.h:118
constexpr void UpdateData(V const &data) noexcept
Definition Hash.h:124
std::size_t operator()(std::pair< K, V > const &p) const
Definition Hash.h:162