DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
Hash.hpp
Go to the documentation of this file.
1/*
2 MIT License
3
4 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
5
6 Copyright 2022, 2023 Chris M. (RealTimeChris)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in all
16 copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25*/
26/// Hash.hpp - Header file for the hash related stuff.
27/// May 12, 2021
28/// https://discordcoreapi.com
29/// \file Hash.hpp
30#pragma once
31
32#include <memory_resource>
33#include <exception>
34#include <utility>
35#include <vector>
36
37namespace discord_core_api {
38
39 namespace discord_core_internal {
41 }
42
45 struct voice_state_data;
47
48 template<typename value_type>
49 concept voice_state_t = std::same_as<value_type, voice_state_data_light>;
50
51 template<typename value_type>
52 concept guild_member_t = std::same_as<value_type, guild_member_cache_data> || std::same_as<value_type, guild_member_data>;
53
54 template<typename value_type>
55 concept has_id = requires(value_type value) { value.id; };
56
57 template<typename value_type>
58 concept has_two_id = voice_state_t<value_type> || guild_member_t<value_type>;
59
60 template<typename value_type>
61 concept event_delegate_token_t = std::same_as<value_type, discord_core_internal::event_delegate_token>;
62
63 struct object_compare {
64 template<typename value_type01, typename value_type02> DCA_INLINE bool operator()(const value_type01& lhs, const value_type02& rhs) {
65 return lhs == static_cast<value_type01>(rhs);
66 }
67
68 template<typename value_type01> DCA_INLINE bool operator()(const value_type01& lhs, const value_type01& rhs) {
69 return lhs == rhs;
70 }
71 };
72
73 DCA_INLINE uint64_t internalHashFunction(const void* value, uint64_t count) {
74 static constexpr uint64_t fnvOffsetBasis{ 0xcbf29ce484222325 };
75 static constexpr uint64_t fnvPrime{ 0x00000100000001B3 };
76 uint64_t hash{ fnvOffsetBasis };
77 for (uint64_t x = 0; x < count; ++x) {
78 hash ^= static_cast<const uint8_t*>(value)[x];
79 hash *= fnvPrime;
80 }
81 return hash;
82 }
83
84 class two_id_key {
85 public:
86 template<guild_member_t value_type> two_id_key(const value_type& other);
87 template<voice_state_t value_type> two_id_key(const value_type& other);
88
89 snowflake idOne{};
90 snowflake idTwo{};
91 };
92
93 template<typename value_type> struct key_hasher;
94
95 template<has_id value_type> struct key_hasher<value_type> {
96 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
97 return internalHashFunction(&other.id.operator const uint64_t&(), sizeof(uint64_t));
98 }
99 };
100
101 template<> struct key_hasher<const char*> {
102 DCA_INLINE static uint64_t getHashKey(const char* other) {
103 return internalHashFunction(other, std::char_traits<char>::length(other));
104 }
105 };
106
107 template<uint64_t size> struct key_hasher<char[size]> {
108 DCA_INLINE static uint64_t getHashKey(const char (&other)[size]) {
109 return internalHashFunction(other, std::char_traits<char>::length(other));
110 }
111 };
112
113 template<jsonifier::concepts::integer_t value_type> struct key_hasher<value_type> {
114 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
115 return internalHashFunction(&other, sizeof(other));
116 }
117 };
118
119 template<> struct key_hasher<two_id_key> {
120 DCA_INLINE static uint64_t getHashKey(const two_id_key& other) {
121 uint64_t values[2]{};
122 values[0] = other.idOne.operator const uint64_t&();
123 values[1] = other.idTwo.operator const uint64_t&();
124 return internalHashFunction(values, sizeof(uint64_t) * std::size(values));
125 }
126 };
127
128 template<jsonifier::concepts::enum_t value_type> struct key_hasher<value_type> {
129 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
130 return internalHashFunction(&other, sizeof(other));
131 }
132 };
133
134 template<jsonifier::concepts::string_t value_type> struct key_hasher<value_type> {
135 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
136 return internalHashFunction(other.data(), other.size());
137 }
138 };
139
140 template<> struct key_hasher<snowflake> {
141 DCA_INLINE static uint64_t getHashKey(const snowflake& data) {
142 return internalHashFunction(&data.operator const uint64_t&(), sizeof(uint64_t));
143 }
144 };
145
146 template<> struct key_hasher<jsonifier::vector<jsonifier::string>> {
147 DCA_INLINE static uint64_t getHashKey(const jsonifier::vector<jsonifier::string>& data) {
148 jsonifier::string newString{};
149 for (auto& value: data) {
150 newString.append(value);
151 }
152 return internalHashFunction(newString.data(), newString.size());
153 }
154 };
155
156 template<has_two_id value_type> struct key_hasher<value_type> {
157 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
158 return key_hasher<two_id_key>::getHashKey(two_id_key{ other });
159 }
160 };
161
162 template<jsonifier::concepts::unique_ptr_t value_type> struct key_hasher<value_type> {
163 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
164 return key_hasher<typename value_type::element_type>::getHashKey(*other);
165 }
166 };
167
168 template<typename value_Type> struct key_accessor;
169
170 template<voice_state_t value_type> struct key_accessor<value_type> {
171 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
172 return key_hasher<value_type>::getHashKey(other);
173 }
174 };
175
176 template<> struct key_accessor<snowflake> {
177 DCA_INLINE static uint64_t getHashKey(const snowflake& other) {
178 return key_hasher<snowflake>::getHashKey(other);
179 }
180 };
181
182 template<> struct key_accessor<two_id_key> {
183 DCA_INLINE static uint64_t getHashKey(const two_id_key& other) {
184 return key_hasher<two_id_key>::getHashKey(other);
185 }
186 };
187
188 template<> struct key_accessor<const char*> {
189 DCA_INLINE static uint64_t getHashKey(const char* other) {
190 return key_hasher<const char*>::getHashKey(other);
191 }
192 };
193
194 template<uint64_t size> struct key_accessor<char[size]> {
195 DCA_INLINE static uint64_t getHashKey(const char (&other)[size]) {
196 return key_hasher<char[size]>::getHashKey(other);
197 }
198 };
199
200 template<jsonifier::concepts::string_t value_type> struct key_accessor<value_type> {
201 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
202 return key_hasher<value_type>::getHashKey(other);
203 }
204 };
205
206 template<has_id value_type> struct key_accessor<value_type> {
207 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
208 return key_hasher<value_type>::getHashKey(other);
209 }
210 };
211
212 template<jsonifier::concepts::unique_ptr_t value_type> struct key_accessor<value_type> {
213 DCA_INLINE static uint64_t getHashKey(const value_type& other) {
214 return key_hasher<value_type>::getHashKey(other);
215 }
216 };
217
218 template<> struct key_accessor<jsonifier::vector<jsonifier::string>> {
219 DCA_INLINE static uint64_t getHashKey(const jsonifier::vector<jsonifier::string>& other) {
220 return key_hasher<jsonifier::vector<jsonifier::string>>::getHashKey(other);
221 }
222 };
223
224 template<typename value_type> struct hash_policy {
225 template<typename key_type> DCA_INLINE uint64_t indexForHash(key_type&& key) const {
226 return key_hasher<std::remove_cvref_t<key_type>>::getHashKey(key) & (static_cast<const value_type*>(this)->capacityVal - 1);
227 }
228
229 DCA_INLINE static int8_t log2(uint64_t value) {
230 static constexpr int8_t table[64] = { 63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57,
231 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5 };
232 value |= value >> 1;
233 value |= value >> 2;
234 value |= value >> 4;
235 value |= value >> 8;
236 value |= value >> 16;
237 value |= value >> 32;
238 return table[((value - (value >> 1)) * 0x07EDD5E59A4E28C2) >> 58];
239 }
240
241 DCA_INLINE static uint64_t nextPowerOfTwo(uint64_t size) {
242 --size;
243 size |= size >> 1;
244 size |= size >> 2;
245 size |= size >> 4;
246 size |= size >> 8;
247 size |= size >> 16;
248 size |= size >> 32;
249 ++size;
250 return size;
251 }
252
253 static int8_t computeMaxLookAheadDistance(uint64_t num_buckets) {
254 return log2(num_buckets);
255 }
256 };
257
258 template<typename value_type_internal_new> class hash_iterator {
259 public:
260 using iterator_category = std::forward_iterator_tag;
261 using value_type_internal = value_type_internal_new;
262 using value_type = typename value_type_internal::value_type;
263 using reference = value_type&;
264 using pointer = value_type*;
265 using pointer_internal = value_type_internal*;
266 using size_type = uint64_t;
267
268 DCA_INLINE hash_iterator() = default;
269
270 DCA_INLINE hash_iterator(pointer_internal valueNew, size_type currentIndexNew) : value{ valueNew }, currentIndex{ currentIndexNew } {};
271
272 DCA_INLINE hash_iterator& operator++() {
273 skipEmptySlots();
274 return *this;
275 }
276
277 DCA_INLINE hash_iterator& operator--() {
278 skipEmptySlotsRev();
279 return *this;
280 }
281
282 DCA_INLINE hash_iterator& operator-(size_type amountToReverse) {
283 for (size_type x = 0; x < amountToReverse; ++x) {
284 skipEmptySlotsRev();
285 }
286 return *this;
287 }
288
289 DCA_INLINE hash_iterator& operator+(size_type amountToAdd) {
290 for (size_type x = 0; x < amountToAdd; ++x) {
291 skipEmptySlots();
292 }
293 return *this;
294 }
295
296 DCA_INLINE pointer getRawPtr() {
297 return &value->data[currentIndex];
298 }
299
300 DCA_INLINE bool operator==(const hash_iterator&) const {
301 return !value || value->sentinelVector[currentIndex] == -1;
302 }
303
304 DCA_INLINE pointer operator->() {
305 return &value->data[currentIndex];
306 }
307
308 DCA_INLINE reference operator*() {
309 return value->data[currentIndex];
310 }
311
312 protected:
313 pointer_internal value{};
314 size_type currentIndex{};
315
316 void skipEmptySlots() {
317 if (currentIndex < value->sentinelVector.size()) {
318 ++currentIndex;
319 while (value && value->sentinelVector[currentIndex] == 0 && currentIndex < value->sentinelVector.size()) {
320 ++currentIndex;
321 };
322 }
323 }
324
325 void skipEmptySlotsRev() {
326 if (static_cast<int64_t>(currentIndex) > 0) {
327 --currentIndex;
328 while (value && value->sentinelVector[currentIndex] == 0 && static_cast<int64_t>(currentIndex) > 0) {
329 --currentIndex;
330 };
331 }
332 }
333 };
334}
Data structure representing a single guild_member_data.
Data structure representing a single guild_member_data.
A class representing a snowflake identifier with various operations.
Definition Base.hpp:701
The main namespace for the forward-facing interfaces.
Struct representing an event delegate token, associated with an event.