1 | // __ _____ _____ _____ |
2 | // __| | __| | | | JSON for Modern C++ |
3 | // | | |__ | | | | | | version 3.11.3 |
4 | // |_____|_____|_____|_|___| https://github.com/nlohmann/json |
5 | // |
6 | // SPDX-FileCopyrightText: 2013-2023 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 |
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> |
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(seed: type, h: 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 | |