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#include <array>
28#include <chrono>
29#include <cstdint>
30#include <cstring>
31#include <functional>
32#include <map>
33#include <memory>
34#include <set>
35#include <string>
36#include <system_error>
37#include <tuple>
38#include <type_traits>
39#include <unordered_map>
40#include <unordered_set>
41#include <utility>
42#include <vector>
43
44namespace beast {
45
46namespace detail {
47
48template <class T>
49/*constexpr*/
50inline void
52{
53 unsigned char* bytes = static_cast<unsigned char*>(
54 std::memmove(std::addressof(t), std::addressof(t), sizeof(T)));
55 for (unsigned i = 0; i < sizeof(T) / 2; ++i)
56 std::swap(bytes[i], bytes[sizeof(T) - 1 - i]);
57}
58
59template <class T>
60/*constexpr*/
61inline void
63{
64}
65
66template <class T>
67/*constexpr*/
68inline void
70{
72}
73
74template <class T, class Hasher>
75/*constexpr*/
76inline void
77maybe_reverse_bytes(T& t, Hasher&)
78{
80 t,
82 bool,
83 Hasher::endian != boost::endian::order::native>{});
84}
85
86} // namespace detail
87
88// is_uniquely_represented<T>
89
90// A type T is contiguously hashable if for all combinations of two values of
91// a type, say x and y, if x == y, then it must also be true that
92// memcmp(addressof(x), addressof(y), sizeof(T)) == 0. I.e. if x == y,
93// then x and y have the same bit pattern representation.
94
95template <class T>
98 bool,
99 std::is_integral<T>::value || std::is_enum<T>::value ||
100 std::is_pointer<T>::value>
101{
102 explicit is_uniquely_represented() = default;
103};
104
105template <class T>
107{
108 explicit is_uniquely_represented() = default;
109};
110
111template <class T>
113{
114 explicit is_uniquely_represented() = default;
115};
116
117template <class T>
118struct is_uniquely_represented<T const volatile>
119 : public is_uniquely_represented<T>
120{
121 explicit is_uniquely_represented() = default;
122};
123
124// is_uniquely_represented<std::pair<T, U>>
125
126template <class T, class U>
127struct is_uniquely_represented<std::pair<T, U>>
128 : public std::integral_constant<
129 bool,
130 is_uniquely_represented<T>::value &&
131 is_uniquely_represented<U>::value &&
132 sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
133{
134 explicit is_uniquely_represented() = default;
135};
136
137// is_uniquely_represented<std::tuple<T...>>
138
139template <class... T>
140struct is_uniquely_represented<std::tuple<T...>>
141 : public std::integral_constant<
142 bool,
143 std::conjunction_v<is_uniquely_represented<T>...> &&
144 sizeof(std::tuple<T...>) == (sizeof(T) + ...)>
145{
146 explicit is_uniquely_represented() = default;
147};
148
149// is_uniquely_represented<T[N]>
150
151template <class T, std::size_t N>
153{
154 explicit is_uniquely_represented() = default;
155};
156
157// is_uniquely_represented<std::array<T, N>>
158
159template <class T, std::size_t N>
160struct is_uniquely_represented<std::array<T, N>>
161 : public std::integral_constant<
162 bool,
163 is_uniquely_represented<T>::value &&
164 sizeof(T) * N == sizeof(std::array<T, N>)>
165{
166 explicit is_uniquely_represented() = default;
167};
168
183template <class T, class HashAlgorithm>
185 : public std::integral_constant<
186 bool,
187 is_uniquely_represented<T>::value &&
188 (sizeof(T) == 1 ||
189 HashAlgorithm::endian == boost::endian::order::native)>
190{
191 explicit is_contiguously_hashable() = default;
192};
193
194template <class T, std::size_t N, class HashAlgorithm>
195struct is_contiguously_hashable<T[N], HashAlgorithm>
196 : public std::integral_constant<
197 bool,
198 is_uniquely_represented<T[N]>::value &&
199 (sizeof(T) == 1 ||
200 HashAlgorithm::endian == boost::endian::order::native)>
201{
202 explicit is_contiguously_hashable() = default;
203};
206//------------------------------------------------------------------------------
207
233// scalars
234
235template <class Hasher, class T>
237hash_append(Hasher& h, T const& t) noexcept
238{
239 h(std::addressof(t), sizeof(t));
240}
241
242template <class Hasher, class T>
243inline std::enable_if_t<
244 !is_contiguously_hashable<T, Hasher>::value &&
247hash_append(Hasher& h, T t) noexcept
248{
250 h(std::addressof(t), sizeof(t));
251}
252
253template <class Hasher, class T>
255hash_append(Hasher& h, T t) noexcept
256{
257 if (t == 0)
258 t = 0;
260 h(&t, sizeof(t));
261}
262
263template <class Hasher>
264inline void
265hash_append(Hasher& h, std::nullptr_t) noexcept
266{
267 void const* p = nullptr;
269 h(&p, sizeof(p));
270}
271
272// Forward declarations for ADL purposes
273
274template <class Hasher, class T, std::size_t N>
276hash_append(Hasher& h, T (&a)[N]) noexcept;
277
278template <class Hasher, class CharT, class Traits, class Alloc>
281 Hasher& h,
283
284template <class Hasher, class CharT, class Traits, class Alloc>
287 Hasher& h,
289
290template <class Hasher, class T, class U>
292hash_append(Hasher& h, std::pair<T, U> const& p) noexcept;
293
294template <class Hasher, class T, class Alloc>
296hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
297
298template <class Hasher, class T, class Alloc>
300hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
301
302template <class Hasher, class T, std::size_t N>
304hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
305
306template <class Hasher, class... T>
307std::enable_if_t<!is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
308hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
309
310template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
311void
313
314template <class Hasher, class Key, class Hash, class Pred, class Alloc>
315void
317
318template <class Hasher, class Key, class Compare, class Alloc>
321 Hasher& h,
322 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
323template <class Hasher, class Key, class Compare, class Alloc>
326 Hasher& h,
327 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
328template <class Hasher, class T0, class T1, class... T>
329void
330hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
331
332// c-array
333
334template <class Hasher, class T, std::size_t N>
336hash_append(Hasher& h, T (&a)[N]) noexcept
337{
338 for (auto const& t : a)
339 hash_append(h, t);
340}
341
342// basic_string
343
344template <class Hasher, class CharT, class Traits, class Alloc>
347 Hasher& h,
349{
350 for (auto c : s)
351 hash_append(h, c);
352 hash_append(h, s.size());
353}
354
355template <class Hasher, class CharT, class Traits, class Alloc>
358 Hasher& h,
360{
361 h(s.data(), s.size() * sizeof(CharT));
362 hash_append(h, s.size());
363}
364
365// pair
366
367template <class Hasher, class T, class U>
368inline std::enable_if_t<
369 !is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
370hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
371{
372 hash_append(h, p.first, p.second);
373}
374
375// vector
376
377template <class Hasher, class T, class Alloc>
379hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
380{
381 for (auto const& t : v)
382 hash_append(h, t);
383 hash_append(h, v.size());
384}
385
386template <class Hasher, class T, class Alloc>
388hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
389{
390 h(v.data(), v.size() * sizeof(T));
391 hash_append(h, v.size());
392}
393
394// array
395
396template <class Hasher, class T, std::size_t N>
398hash_append(Hasher& h, std::array<T, N> const& a) noexcept
399{
400 for (auto const& t : a)
401 hash_append(h, t);
402}
403
404template <class Hasher, class Key, class Compare, class Alloc>
407 Hasher& h,
408 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
409{
410 for (auto const& t : v)
411 hash_append(h, t);
412}
413template <class Hasher, class Key, class Compare, class Alloc>
416 Hasher& h,
417 boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
418{
419 h(&(v.begin()), v.size() * sizeof(Key));
420}
421// tuple
422
423namespace detail {
424
425inline void
426for_each_item(...) noexcept
427{
428}
429
430template <class Hasher, class T>
431inline int
432hash_one(Hasher& h, T const& t) noexcept
433{
434 hash_append(h, t);
435 return 0;
436}
437
438template <class Hasher, class... T, std::size_t... I>
439inline void
441 Hasher& h,
442 std::tuple<T...> const& t,
444{
445 for_each_item(hash_one(h, std::get<I>(t))...);
446}
447
448} // namespace detail
449
450template <class Hasher, class... T>
451inline std::enable_if_t<
452 !is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
453hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
454{
456}
457
458// shared_ptr
459
460template <class Hasher, class T>
461inline void
462hash_append(Hasher& h, std::shared_ptr<T> const& p) noexcept
463{
464 hash_append(h, p.get());
465}
466
467// chrono
468
469template <class Hasher, class Rep, class Period>
470inline void
472{
473 hash_append(h, d.count());
474}
475
476template <class Hasher, class Clock, class Duration>
477inline void
479 Hasher& h,
481{
482 hash_append(h, tp.time_since_epoch());
483}
484
485// variadic
486
487template <class Hasher, class T0, class T1, class... T>
488inline void
489hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept
490{
491 hash_append(h, t0);
492 hash_append(h, t1, t...);
493}
494
495// error_code
496
497template <class HashAlgorithm>
498inline void
499hash_append(HashAlgorithm& h, std::error_code const& ec)
500{
501 hash_append(h, ec.value(), &ec.category());
502}
503
504} // namespace beast
505
506#endif
T addressof(T... args)
T category(T... args)
T memmove(T... args)
void reverse_bytes(T &t)
Definition: hash_append.h:51
int hash_one(Hasher &h, T const &t) noexcept
Definition: hash_append.h:432
void maybe_reverse_bytes(T &t, std::false_type)
Definition: hash_append.h:62
void tuple_hash(Hasher &h, std::tuple< T... > const &t, std::index_sequence< I... >) noexcept
Definition: hash_append.h:440
void for_each_item(...) noexcept
Definition: hash_append.h:426
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:237
STL namespace.
Metafunction returning true if the type can be hashed in one call.
Definition: hash_append.h:190
T swap(T... args)
T value(T... args)