packio
hash.h
1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
4 
5 #ifndef PACKIO_JSON_RPC_HASH_H
6 #define PACKIO_JSON_RPC_HASH_H
7 
8 #include <boost/json.hpp>
9 #include <boost/version.hpp>
10 
11 #if BOOST_VERSION < 107700
12 
13 namespace packio {
14 namespace json_rpc {
15 namespace internal {
16 
17 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
18 {
19  seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
20  return seed;
21 }
22 
23 inline std::size_t hash(const boost::json::value& v)
24 {
25  std::size_t seed = 0;
26  switch (v.kind()) {
27  case boost::json::kind::null:
28  // Don't use std::hash<std::nullptr_t>, old gcc/clang do not support it
29  return combine(seed, std::hash<void*>()(nullptr));
30  case boost::json::kind::bool_:
31  return combine(seed, std::hash<bool>{}(v.get_bool()));
32  case boost::json::kind::uint64:
33  return combine(seed, std::hash<uint64_t>{}(v.get_uint64()));
34  case boost::json::kind::int64:
35  return combine(seed, std::hash<int64_t>{}(v.get_int64()));
36  case boost::json::kind::double_:
37  return combine(seed, std::hash<double>{}(v.get_double()));
38  case boost::json::kind::string:
39  return combine(
40  seed,
41  std::hash<std::string_view>{}(std::string_view{
42  v.get_string().data(), v.get_string().size()}));
43  case boost::json::kind::array: {
44  seed = combine(seed, v.get_array().size());
45  for (const auto& element : v.get_array()) {
46  seed = combine(seed, hash(element));
47  }
48  return seed;
49  }
50  case boost::json::kind::object: {
51  seed = combine(seed, v.get_object().size());
52  for (const auto& element : v.get_object()) {
53  std::string_view key{element.key().data(), element.key().size()};
54  seed = combine(seed, std::hash<std::string_view>{}(key));
55  seed = combine(seed, hash(element.value()));
56  }
57  return seed;
58  }
59  }
60 }
61 
62 } // internal
63 } // json_rpc
64 } // packio
65 
66 namespace std {
67 
68 template <>
69 struct hash<boost::json::value> {
70  std::size_t operator()(const boost::json::value& v) const
71  {
72  return packio::json_rpc::internal::hash(v);
73  }
74 };
75 
76 } // std
77 
78 #endif // BOOST_VERSION < 107700
79 
80 #endif // PACKIO_JSON_RPC_HASH_H
The packio namespace.
Definition: arg.h:14