rippled
Loading...
Searching...
No Matches
hash_append.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of Beast: https://github.com/vinniefalco/Beast
4 Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
5 Vinnie Falco <vinnie.falco@gmail.com
6
7 Permission to use, copy, modify, and/or distribute this software for any
8 purpose with or without fee is hereby granted, provided that the above
9 copyright notice and this permission notice appear in all copies.
10
11 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*/
19//==============================================================================
20
21#ifndef BEAST_HASH_HASH_APPEND_H_INCLUDED
22#define BEAST_HASH_HASH_APPEND_H_INCLUDED
23
24#include <boost/container/flat_set.hpp>
25#include <boost/endian/conversion.hpp>
26
27/*
28
29Workaround for overzealous clang warning, which trips on libstdc++ headers
30
31 In file included from
32 /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_algo.h:61:
33 /usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/stl_tempbuf.h:263:8:
34 error: 'get_temporary_buffer<std::pair<ripple::Quality, const
35 std::vector<std::unique_ptr<ripple::Step>> *>>' is deprecated
36 [-Werror,-Wdeprecated-declarations] 263 |
37 std::get_temporary_buffer<value_type>(_M_original_len));
38 ^
39*/
40
41#if defined(__clang__)
42#pragma clang diagnostic push
43#pragma clang diagnostic ignored "-Wdeprecated"
44#pragma clang diagnostic ignored "-Wdeprecated-declarations"
45#endif
46
47#include <functional>
48#include <memory>
49
50#if defined(__clang__)
51#pragma clang diagnostic pop
52#endif
53
54#include <array>
55#include <chrono>
56#include <cstdint>
57#include <cstring>
58#include <map>
59#include <set>
60#include <string>
61#include <system_error>
62#include <tuple>
63#include <type_traits>
64#include <unordered_map>
65#include <unordered_set>
66#include <utility>
67#include <vector>
68
69namespace beast {
70
71namespace detail {
72
73template <class T>
74/*constexpr*/
75inline void
77{
78 unsigned char* bytes = static_cast<unsigned char*>(
79 std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
80 for (unsigned i = 0; i < sizeof(T) / 2; ++i)
81 std::swap(bytes[i], bytes[sizeof(T) - 1 - i]);
82}
83
84template <class T>
85/*constexpr*/
86inline void
88{
89}
90
91template <class T>
92/*constexpr*/
93inline void
95{
97}
98
99template <class T, class Hasher>
100/*constexpr*/
101inline void
103{
105 t,
107 bool,
108 Hasher::endian != boost::endian::order::native>{});
109}
110
111} // namespace detail
112
113// is_uniquely_represented<T>
114
115// A type T is contiguously hashable if for all combinations of two values of
116// a type, say x and y, if x == y, then it must also be true that
117// memcmp(addressof(x), addressof(y), sizeof(T)) == 0. I.e. if x == y,
118// then x and y have the same bit pattern representation.
119
120template <class T>
122 : public std::integral_constant<
123 bool,
124 std::is_integral<T>::value || std::is_enum<T>::value ||
125 std::is_pointer<T>::value>
126{
127 explicit is_uniquely_represented() = default;
128};
129
130template <class T>
132{
133 explicit is_uniquely_represented() = default;
134};
135
136template <class T>
138{
139 explicit is_uniquely_represented() = default;
140};
141
142template <class T>
143struct is_uniquely_represented<T const volatile>
144 : public is_uniquely_represented<T>
145{
146 explicit is_uniquely_represented() = default;
147};
148
149// is_uniquely_represented<std::pair<T, U>>
150
151template <class T, class U>
152struct is_uniquely_represented<std::pair<T, U>>
153 : public std::integral_constant<
154 bool,
155 is_uniquely_represented<T>::value &&
156 is_uniquely_represented<U>::value &&
157 sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
158{
159 explicit is_uniquely_represented() = default;
160};
161
162// is_uniquely_represented<std::tuple<T...>>
163
164template <class... T>
165struct is_uniquely_represented<std::tuple<T...>>
166 : public std::integral_constant<
167 bool,
168 std::conjunction_v<is_uniquely_represented<T>...> &&
169 sizeof(std::tuple<T...>) == (sizeof(T) + ...)>
170{
171 explicit is_uniquely_represented() = default;
172};
173
174// is_uniquely_represented<T[N]>
175
176template <class T, std::size_t N>
178{
179 explicit is_uniquely_represented() = default;
180};
181
182// is_uniquely_represented<std::array<T, N>>
183
184template <class T, std::size_t N>
185struct is_uniquely_represented<std::array<T, N>>
186 : public std::integral_constant<
187 bool,
188 is_uniquely_represented<T>::value &&
189 sizeof(T) * N == sizeof(std::array<T, N>)>
190{
191 explicit is_uniquely_represented() = default;
192};
193
208template <class T, class HashAlgorithm>
210 : public std::integral_constant<
211 bool,
212 is_uniquely_represented<T>::value &&
213 (sizeof(T) == 1 ||
214 HashAlgorithm::endian == boost::endian::order::native)>
215{
216 explicit is_contiguously_hashable() = default;
217};
218
219template <class T, std::size_t N, class HashAlgorithm>
220struct is_contiguously_hashable<T[N], HashAlgorithm>
221 : public std::integral_constant<
222 bool,
223 is_uniquely_represented<T[N]>::value &&
224 (sizeof(T) == 1 ||
225 HashAlgorithm::endian == boost::endian::order::native)>
226{
227 explicit is_contiguously_hashable() = default;
228};
231//------------------------------------------------------------------------------
232
258// scalars
259
260template <class Hasher, class T>
262hash_append(Hasher& h, T const& t) noexcept
263{
264 h(std::addressof(t), sizeof(t));
265}
266
267template <class Hasher, class T>
268inline std::enable_if_t<
269 !is_contiguously_hashable<T, Hasher>::value &&
272hash_append(Hasher& h, T t) noexcept
273{
275 h(std::addressof(t), sizeof(t));
276}
277
278template <class Hasher, class T>
280hash_append(Hasher& h, T t) noexcept
281{
282 if (t == 0)
283 t = 0;
285 h(&t, sizeof(t));
286}
287
288template <class Hasher>
289inline void
290hash_append(Hasher& h, std::nullptr_t) noexcept
291{
292 void const* p = nullptr;
294 h(&p, sizeof(p));
295}
296
297// Forward declarations for ADL purposes
298
299template <class Hasher, class T, std::size_t N>
301hash_append(Hasher& h, T (&a)[N]) noexcept;
302
303template <class Hasher, class CharT, class Traits, class Alloc>
306 Hasher& h,
308
309template <class Hasher, class CharT, class Traits, class Alloc>
312 Hasher& h,
314
315template <class Hasher, class T, class U>
317hash_append(Hasher& h, std::pair<T, U> const& p) noexcept;
318
319template <class Hasher, class T, class Alloc>
321hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
322
323template <class Hasher, class T, class Alloc>
325hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
326
327template <class Hasher, class T, std::size_t N>
329hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
330
331template <class Hasher, class... T>
332std::enable_if_t<!is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
333hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
334
335template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
336void
338
339template <class Hasher, class Key, class Hash, class Pred, class Alloc>
340void
342
343template <class Hasher, class Key, class Compare, class Alloc>
346 Hasher& h,
347 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
348template <class Hasher, class Key, class Compare, class Alloc>
351 Hasher& h,
352 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
353template <class Hasher, class T0, class T1, class... T>
354void
355hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
356
357// c-array
358
359template <class Hasher, class T, std::size_t N>
361hash_append(Hasher& h, T (&a)[N]) noexcept
362{
363 for (auto const& t : a)
364 hash_append(h, t);
365}
366
367// basic_string
368
369template <class Hasher, class CharT, class Traits, class Alloc>
372 Hasher& h,
374{
375 for (auto c : s)
376 hash_append(h, c);
377 hash_append(h, s.size());
378}
379
380template <class Hasher, class CharT, class Traits, class Alloc>
383 Hasher& h,
385{
386 h(s.data(), s.size() * sizeof(CharT));
387 hash_append(h, s.size());
388}
389
390// pair
391
392template <class Hasher, class T, class U>
393inline std::enable_if_t<
394 !is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
395hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
396{
397 hash_append(h, p.first, p.second);
398}
399
400// vector
401
402template <class Hasher, class T, class Alloc>
404hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
405{
406 for (auto const& t : v)
407 hash_append(h, t);
408 hash_append(h, v.size());
409}
410
411template <class Hasher, class T, class Alloc>
413hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
414{
415 h(v.data(), v.size() * sizeof(T));
416 hash_append(h, v.size());
417}
418
419// array
420
421template <class Hasher, class T, std::size_t N>
423hash_append(Hasher& h, std::array<T, N> const& a) noexcept
424{
425 for (auto const& t : a)
426 hash_append(h, t);
427}
428
429template <class Hasher, class Key, class Compare, class Alloc>
432 Hasher& h,
433 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
434{
435 for (auto const& t : v)
436 hash_append(h, t);
437}
438template <class Hasher, class Key, class Compare, class Alloc>
441 Hasher& h,
442 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
443{
444 h(&(v.begin()), v.size() * sizeof(Key));
445}
446// tuple
447
448namespace detail {
449
450inline void
451for_each_item(...) noexcept
452{
453}
454
455template <class Hasher, class T>
456inline int
457hash_one(Hasher& h, T const& t) noexcept
458{
459 hash_append(h, t);
460 return 0;
461}
462
463template <class Hasher, class... T, std::size_t... I>
464inline void
466 Hasher& h,
467 std::tuple<T...> const& t,
469{
470 for_each_item(hash_one(h, std::get<I>(t))...);
471}
472
473} // namespace detail
474
475template <class Hasher, class... T>
476inline std::enable_if_t<
477 !is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
478hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
479{
481}
482
483// shared_ptr
484
485template <class Hasher, class T>
486inline void
487hash_append(Hasher& h, std::shared_ptr<T> const& p) noexcept
488{
489 hash_append(h, p.get());
490}
491
492// chrono
493
494template <class Hasher, class Rep, class Period>
495inline void
497{
498 hash_append(h, d.count());
499}
500
501template <class Hasher, class Clock, class Duration>
502inline void
504 Hasher& h,
506{
507 hash_append(h, tp.time_since_epoch());
508}
509
510// variadic
511
512template <class Hasher, class T0, class T1, class... T>
513inline void
514hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept
515{
516 hash_append(h, t0);
517 hash_append(h, t1, t...);
518}
519
520// error_code
521
522template <class HashAlgorithm>
523inline void
524hash_append(HashAlgorithm& h, std::error_code const& ec)
525{
526 hash_append(h, ec.value(), &ec.category());
527}
528
529} // namespace beast
530
531#endif
T addressof(T... args)
T category(T... args)
T memmove(T... args)
void reverse_bytes(T &t)
Definition: hash_append.h:76
int hash_one(Hasher &h, T const &t) noexcept
Definition: hash_append.h:457
void maybe_reverse_bytes(T &t, std::false_type)
Definition: hash_append.h:87
void tuple_hash(Hasher &h, std::tuple< T... > const &t, std::index_sequence< I... >) noexcept
Definition: hash_append.h:465
void for_each_item(...) noexcept
Definition: hash_append.h:451
std::enable_if_t< is_contiguously_hashable< T, Hasher >::value > hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
Definition: hash_append.h:262
STL namespace.
Metafunction returning true if the type can be hashed in one call.
Definition: hash_append.h:215
T swap(T... args)
T value(T... args)