rippled
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 <ripple/beast/hash/endian.h>
25 #include <ripple/beast/hash/meta.h>
26 #include <boost/container/flat_set.hpp>
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 
44 namespace beast {
45 
46 namespace detail {
47 
48 template <class T>
49 /*constexpr*/
50 inline 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 
59 template <class T>
60 /*constexpr*/
61 inline void
63 {
64 }
65 
66 template <class T>
67 /*constexpr*/
68 inline void
70 {
71  reverse_bytes(t);
72 }
73 
74 template <class T, class Hasher>
75 /*constexpr*/
76 inline void
77 maybe_reverse_bytes(T& t, Hasher&)
78 {
81 }
82 
83 } // namespace detail
84 
85 // is_uniquely_represented<T>
86 
87 // A type T is contiguously hashable if for all combinations of two values of
88 // a type, say x and y, if x == y, then it must also be true that
89 // memcmp(addressof(x), addressof(y), sizeof(T)) == 0. I.e. if x == y,
90 // then x and y have the same bit pattern representation.
91 
92 template <class T>
94  : public std::integral_constant<
95  bool,
96  std::is_integral<T>::value || std::is_enum<T>::value ||
97  std::is_pointer<T>::value>
98 {
99  explicit is_uniquely_represented() = default;
100 };
101 
102 template <class T>
104 {
105  explicit is_uniquely_represented() = default;
106 };
107 
108 template <class T>
109 struct is_uniquely_represented<T volatile> : public is_uniquely_represented<T>
110 {
111  explicit is_uniquely_represented() = default;
112 };
113 
114 template <class T>
115 struct is_uniquely_represented<T const volatile>
116  : public is_uniquely_represented<T>
117 {
118  explicit is_uniquely_represented() = default;
119 };
120 
121 // is_uniquely_represented<std::pair<T, U>>
122 
123 template <class T, class U>
124 struct is_uniquely_represented<std::pair<T, U>>
125  : public std::integral_constant<
126  bool,
127  is_uniquely_represented<T>::value &&
128  is_uniquely_represented<U>::value &&
129  sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
130 {
131  explicit is_uniquely_represented() = default;
132 };
133 
134 // is_uniquely_represented<std::tuple<T...>>
135 
136 template <class... T>
137 struct is_uniquely_represented<std::tuple<T...>>
138  : public std::integral_constant<
139  bool,
140  static_and<is_uniquely_represented<T>::value...>::value &&
141  static_sum<sizeof(T)...>::value == sizeof(std::tuple<T...>)>
142 {
143  explicit is_uniquely_represented() = default;
144 };
145 
146 // is_uniquely_represented<T[N]>
147 
148 template <class T, std::size_t N>
150 {
151  explicit is_uniquely_represented() = default;
152 };
153 
154 // is_uniquely_represented<std::array<T, N>>
155 
156 template <class T, std::size_t N>
157 struct is_uniquely_represented<std::array<T, N>>
158  : public std::integral_constant<
159  bool,
160  is_uniquely_represented<T>::value &&
161  sizeof(T) * N == sizeof(std::array<T, N>)>
162 {
163  explicit is_uniquely_represented() = default;
164 };
165 
180 template <class T, class HashAlgorithm>
182  : public std::integral_constant<
183  bool,
184  is_uniquely_represented<T>::value &&
185  (sizeof(T) == 1 || HashAlgorithm::endian == endian::native)>
186 {
187  explicit is_contiguously_hashable() = default;
188 };
189 
190 template <class T, std::size_t N, class HashAlgorithm>
191 struct is_contiguously_hashable<T[N], HashAlgorithm>
192  : public std::integral_constant<
193  bool,
194  is_uniquely_represented<T[N]>::value &&
195  (sizeof(T) == 1 || HashAlgorithm::endian == endian::native)>
196 {
197  explicit is_contiguously_hashable() = default;
198 };
201 //------------------------------------------------------------------------------
202 
228 // scalars
229 
230 template <class Hasher, class T>
232 hash_append(Hasher& h, T const& t) noexcept
233 {
234  h(std::addressof(t), sizeof(t));
235 }
236 
237 template <class Hasher, class T>
238 inline std::enable_if_t<
239  !is_contiguously_hashable<T, Hasher>::value &&
242 hash_append(Hasher& h, T t) noexcept
243 {
245  h(std::addressof(t), sizeof(t));
246 }
247 
248 template <class Hasher, class T>
250 hash_append(Hasher& h, T t) noexcept
251 {
252  if (t == 0)
253  t = 0;
255  h(&t, sizeof(t));
256 }
257 
258 template <class Hasher>
259 inline void
260 hash_append(Hasher& h, std::nullptr_t) noexcept
261 {
262  void const* p = nullptr;
264  h(&p, sizeof(p));
265 }
266 
267 // Forward declarations for ADL purposes
268 
269 template <class Hasher, class T, std::size_t N>
271 hash_append(Hasher& h, T (&a)[N]) noexcept;
272 
273 template <class Hasher, class CharT, class Traits, class Alloc>
276  Hasher& h,
277  std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
278 
279 template <class Hasher, class CharT, class Traits, class Alloc>
282  Hasher& h,
283  std::basic_string<CharT, Traits, Alloc> const& s) noexcept;
284 
285 template <class Hasher, class T, class U>
287 hash_append(Hasher& h, std::pair<T, U> const& p) noexcept;
288 
289 template <class Hasher, class T, class Alloc>
291 hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
292 
293 template <class Hasher, class T, class Alloc>
295 hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept;
296 
297 template <class Hasher, class T, std::size_t N>
299 hash_append(Hasher& h, std::array<T, N> const& a) noexcept;
300 
301 template <class Hasher, class... T>
302 std::enable_if_t<!is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
303 hash_append(Hasher& h, std::tuple<T...> const& t) noexcept;
304 
305 template <class Hasher, class Key, class T, class Hash, class Pred, class Alloc>
306 void
308 
309 template <class Hasher, class Key, class Hash, class Pred, class Alloc>
310 void
312 
313 template <class Hasher, class Key, class Compare, class Alloc>
316  Hasher& h,
317  boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
318 template <class Hasher, class Key, class Compare, class Alloc>
321  Hasher& h,
322  boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept;
323 template <class Hasher, class T0, class T1, class... T>
324 void
325 hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept;
326 
327 // c-array
328 
329 template <class Hasher, class T, std::size_t N>
331 hash_append(Hasher& h, T (&a)[N]) noexcept
332 {
333  for (auto const& t : a)
334  hash_append(h, t);
335 }
336 
337 // basic_string
338 
339 template <class Hasher, class CharT, class Traits, class Alloc>
342  Hasher& h,
343  std::basic_string<CharT, Traits, Alloc> const& s) noexcept
344 {
345  for (auto c : s)
346  hash_append(h, c);
347  hash_append(h, s.size());
348 }
349 
350 template <class Hasher, class CharT, class Traits, class Alloc>
353  Hasher& h,
354  std::basic_string<CharT, Traits, Alloc> const& s) noexcept
355 {
356  h(s.data(), s.size() * sizeof(CharT));
357  hash_append(h, s.size());
358 }
359 
360 // pair
361 
362 template <class Hasher, class T, class U>
363 inline std::enable_if_t<
364  !is_contiguously_hashable<std::pair<T, U>, Hasher>::value>
365 hash_append(Hasher& h, std::pair<T, U> const& p) noexcept
366 {
367  hash_append(h, p.first, p.second);
368 }
369 
370 // vector
371 
372 template <class Hasher, class T, class Alloc>
374 hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
375 {
376  for (auto const& t : v)
377  hash_append(h, t);
378  hash_append(h, v.size());
379 }
380 
381 template <class Hasher, class T, class Alloc>
383 hash_append(Hasher& h, std::vector<T, Alloc> const& v) noexcept
384 {
385  h(v.data(), v.size() * sizeof(T));
386  hash_append(h, v.size());
387 }
388 
389 // array
390 
391 template <class Hasher, class T, std::size_t N>
393 hash_append(Hasher& h, std::array<T, N> const& a) noexcept
394 {
395  for (auto const& t : a)
396  hash_append(h, t);
397 }
398 
399 template <class Hasher, class Key, class Compare, class Alloc>
402  Hasher& h,
403  boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
404 {
405  for (auto const& t : v)
406  hash_append(h, t);
407 }
408 template <class Hasher, class Key, class Compare, class Alloc>
411  Hasher& h,
412  boost::container::flat_set<Key, Compare, Alloc> const& v) noexcept
413 {
414  h(&(v.begin()), v.size() * sizeof(Key));
415 }
416 // tuple
417 
418 namespace detail {
419 
420 inline void
421 for_each_item(...) noexcept
422 {
423 }
424 
425 template <class Hasher, class T>
426 inline int
427 hash_one(Hasher& h, T const& t) noexcept
428 {
429  hash_append(h, t);
430  return 0;
431 }
432 
433 template <class Hasher, class... T, std::size_t... I>
434 inline void
436  Hasher& h,
437  std::tuple<T...> const& t,
438  std::index_sequence<I...>) noexcept
439 {
440  for_each_item(hash_one(h, std::get<I>(t))...);
441 }
442 
443 } // namespace detail
444 
445 template <class Hasher, class... T>
446 inline std::enable_if_t<
447  !is_contiguously_hashable<std::tuple<T...>, Hasher>::value>
448 hash_append(Hasher& h, std::tuple<T...> const& t) noexcept
449 {
451 }
452 
453 // shared_ptr
454 
455 template <class Hasher, class T>
456 inline void
457 hash_append(Hasher& h, std::shared_ptr<T> const& p) noexcept
458 {
459  hash_append(h, p.get());
460 }
461 
462 // chrono
463 
464 template <class Hasher, class Rep, class Period>
465 inline void
466 hash_append(Hasher& h, std::chrono::duration<Rep, Period> const& d) noexcept
467 {
468  hash_append(h, d.count());
469 }
470 
471 template <class Hasher, class Clock, class Duration>
472 inline void
474  Hasher& h,
475  std::chrono::time_point<Clock, Duration> const& tp) noexcept
476 {
477  hash_append(h, tp.time_since_epoch());
478 }
479 
480 // variadic
481 
482 template <class Hasher, class T0, class T1, class... T>
483 inline void
484 hash_append(Hasher& h, T0 const& t0, T1 const& t1, T const&... t) noexcept
485 {
486  hash_append(h, t0);
487  hash_append(h, t1, t...);
488 }
489 
490 // error_code
491 
492 template <class HashAlgorithm>
493 inline void
494 hash_append(HashAlgorithm& h, std::error_code const& ec)
495 {
496  hash_append(h, ec.value(), &ec.category());
497 }
498 
499 } // namespace beast
500 
501 #endif
std::false_type
std::basic_string
STL class.
std::shared_ptr
STL class.
utility
cstring
system_error
beast::detail::hash_one
int hash_one(Hasher &h, T const &t) noexcept
Definition: hash_append.h:427
beast::detail::maybe_reverse_bytes
void maybe_reverse_bytes(T &t, std::false_type)
Definition: hash_append.h:62
functional
unordered_set
std::pair
std::index_sequence
vector
std::chrono::duration
tuple
beast::is_contiguously_hashable::is_contiguously_hashable
is_contiguously_hashable()=default
std::error_code
STL class.
beast::is_uniquely_represented
Definition: hash_append.h:93
beast::is_uniquely_represented::is_uniquely_represented
is_uniquely_represented()=default
std::nullptr_t
std::is_enum
std::addressof
T addressof(T... args)
beast::detail::reverse_bytes
void reverse_bytes(T &t)
Definition: hash_append.h:51
std::enable_if_t
chrono
array
beast::is_contiguously_hashable
Metafunction returning true if the type can be hashed in one call.
Definition: hash_append.h:181
beast::detail::tuple_hash
void tuple_hash(Hasher &h, std::tuple< T... > const &t, std::index_sequence< I... >) noexcept
Definition: hash_append.h:435
std::chrono::time_point
std::error_code::category
T category(T... args)
cstdint
map
std::is_integral
memory
std::swap
T swap(T... args)
std::error_code::value
T value(T... args)
std
STL namespace.
beast::hash_append
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:232
std::size_t
std::is_pointer
std::memmove
T memmove(T... args)
unordered_map
type_traits
set
beast::detail::for_each_item
void for_each_item(...) noexcept
Definition: hash_append.h:421
beast
Definition: base_uint.h:646
string