Horizon
hash.hpp
1 #pragma once
2 
3 #include <cstdint> // uint8_t
4 #include <cstddef> // size_t
5 #include <functional> // hash
6 
7 #include <nlohmann/detail/macro_scope.hpp>
8 #include <nlohmann/detail/value_t.hpp>
9 
10 namespace nlohmann
11 {
12 namespace detail
13 {
14 
15 // boost::hash_combine
16 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
17 {
18  seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
19  return seed;
20 }
21 
33 template<typename BasicJsonType>
34 std::size_t hash(const BasicJsonType& j)
35 {
36  using string_t = typename BasicJsonType::string_t;
37  using number_integer_t = typename BasicJsonType::number_integer_t;
38  using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
39  using number_float_t = typename BasicJsonType::number_float_t;
40 
41  const auto type = static_cast<std::size_t>(j.type());
42  switch (j.type())
43  {
44  case BasicJsonType::value_t::null:
45  case BasicJsonType::value_t::discarded:
46  {
47  return combine(type, 0);
48  }
49 
50  case BasicJsonType::value_t::object:
51  {
52  auto seed = combine(type, j.size());
53  for (const auto& element : j.items())
54  {
55  const auto h = std::hash<string_t> {}(element.key());
56  seed = combine(seed, h);
57  seed = combine(seed, hash(element.value()));
58  }
59  return seed;
60  }
61 
62  case BasicJsonType::value_t::array:
63  {
64  auto seed = combine(type, j.size());
65  for (const auto& element : j)
66  {
67  seed = combine(seed, hash(element));
68  }
69  return seed;
70  }
71 
72  case BasicJsonType::value_t::string:
73  {
74  const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
75  return combine(type, h);
76  }
77 
78  case BasicJsonType::value_t::boolean:
79  {
80  const auto h = std::hash<bool> {}(j.template get<bool>());
81  return combine(type, h);
82  }
83 
84  case BasicJsonType::value_t::number_integer:
85  {
86  const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
87  return combine(type, h);
88  }
89 
90  case BasicJsonType::value_t::number_unsigned:
91  {
92  const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
93  return combine(type, h);
94  }
95 
96  case BasicJsonType::value_t::number_float:
97  {
98  const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
99  return combine(type, h);
100  }
101 
102  case BasicJsonType::value_t::binary:
103  {
104  auto seed = combine(type, j.get_binary().size());
105  const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
106  seed = combine(seed, h);
107  seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
108  for (const auto byte : j.get_binary())
109  {
110  seed = combine(seed, std::hash<std::uint8_t> {}(byte));
111  }
112  return seed;
113  }
114 
115  default: // LCOV_EXCL_LINE
116  JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
117  return 0; // LCOV_EXCL_LINE
118  }
119 }
120 
121 } // namespace detail
122 } // namespace nlohmann
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: hash.hpp:34
namespace for Niels Lohmann
Definition: adl_serializer.hpp:12