• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++
3 // |  |  |__   |  |  | | | |  version 3.11.2
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 #pragma once
10 
11 #include <cstdint> // uint8_t
12 #include <cstddef> // size_t
13 #include <functional> // hash
14 
15 #include <nlohmann/detail/abi_macros.hpp>
16 #include <nlohmann/detail/value_t.hpp>
17 
18 NLOHMANN_JSON_NAMESPACE_BEGIN
19 namespace detail
20 {
21 
22 // boost::hash_combine
combine(std::size_t seed,std::size_t h)23 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
24 {
25     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
26     return seed;
27 }
28 
29 /*!
30 @brief hash a JSON value
31 
32 The hash function tries to rely on std::hash where possible. Furthermore, the
33 type of the JSON value is taken into account to have different hash values for
34 null, 0, 0U, and false, etc.
35 
36 @tparam BasicJsonType basic_json specialization
37 @param j JSON value to hash
38 @return hash value of j
39 */
40 template<typename BasicJsonType>
hash(const BasicJsonType & j)41 std::size_t hash(const BasicJsonType& j)
42 {
43     using string_t = typename BasicJsonType::string_t;
44     using number_integer_t = typename BasicJsonType::number_integer_t;
45     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
46     using number_float_t = typename BasicJsonType::number_float_t;
47 
48     const auto type = static_cast<std::size_t>(j.type());
49     switch (j.type())
50     {
51         case BasicJsonType::value_t::null:
52         case BasicJsonType::value_t::discarded:
53         {
54             return combine(type, 0);
55         }
56 
57         case BasicJsonType::value_t::object:
58         {
59             auto seed = combine(type, j.size());
60             for (const auto& element : j.items())
61             {
62                 const auto h = std::hash<string_t> {}(element.key());
63                 seed = combine(seed, h);
64                 seed = combine(seed, hash(element.value()));
65             }
66             return seed;
67         }
68 
69         case BasicJsonType::value_t::array:
70         {
71             auto seed = combine(type, j.size());
72             for (const auto& element : j)
73             {
74                 seed = combine(seed, hash(element));
75             }
76             return seed;
77         }
78 
79         case BasicJsonType::value_t::string:
80         {
81             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
82             return combine(type, h);
83         }
84 
85         case BasicJsonType::value_t::boolean:
86         {
87             const auto h = std::hash<bool> {}(j.template get<bool>());
88             return combine(type, h);
89         }
90 
91         case BasicJsonType::value_t::number_integer:
92         {
93             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
94             return combine(type, h);
95         }
96 
97         case BasicJsonType::value_t::number_unsigned:
98         {
99             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
100             return combine(type, h);
101         }
102 
103         case BasicJsonType::value_t::number_float:
104         {
105             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
106             return combine(type, h);
107         }
108 
109         case BasicJsonType::value_t::binary:
110         {
111             auto seed = combine(type, j.get_binary().size());
112             const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
113             seed = combine(seed, h);
114             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
115             for (const auto byte : j.get_binary())
116             {
117                 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
118             }
119             return seed;
120         }
121 
122         default:                   // LCOV_EXCL_LINE
123             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
124             return 0;              // LCOV_EXCL_LINE
125     }
126 }
127 
128 }  // namespace detail
129 NLOHMANN_JSON_NAMESPACE_END
130