130 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			130 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //     __ _____ _____ _____
 | ||
|  | //  __|  |   __|     |   | |  JSON for Modern C++
 | ||
|  | // |  |  |__   |  |  | | | |  version 3.11.3
 | ||
|  | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 | ||
|  | //
 | ||
|  | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
 | ||
|  | // SPDX-License-Identifier: MIT
 | ||
|  | 
 | ||
|  | #pragma once
 | ||
|  | 
 | ||
|  | #include <cstdint> // uint8_t
 | ||
|  | #include <cstddef> // size_t
 | ||
|  | #include <functional> // hash
 | ||
|  | 
 | ||
|  | #include <nlohmann/detail/abi_macros.hpp>
 | ||
|  | #include <nlohmann/detail/value_t.hpp>
 | ||
|  | 
 | ||
|  | NLOHMANN_JSON_NAMESPACE_BEGIN | ||
|  | namespace detail | ||
|  | { | ||
|  | 
 | ||
|  | // boost::hash_combine
 | ||
|  | inline std::size_t combine(std::size_t seed, std::size_t h) noexcept | ||
|  | { | ||
|  |     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); | ||
|  |     return seed; | ||
|  | } | ||
|  | 
 | ||
|  | /*!
 | ||
|  | @brief hash a JSON value | ||
|  | 
 | ||
|  | The hash function tries to rely on std::hash where possible. Furthermore, the | ||
|  | type of the JSON value is taken into account to have different hash values for | ||
|  | null, 0, 0U, and false, etc. | ||
|  | 
 | ||
|  | @tparam BasicJsonType basic_json specialization | ||
|  | @param j JSON value to hash | ||
|  | @return hash value of j | ||
|  | */ | ||
|  | template<typename BasicJsonType> | ||
|  | std::size_t hash(const BasicJsonType& j) | ||
|  | { | ||
|  |     using string_t = typename BasicJsonType::string_t; | ||
|  |     using number_integer_t = typename BasicJsonType::number_integer_t; | ||
|  |     using number_unsigned_t = typename BasicJsonType::number_unsigned_t; | ||
|  |     using number_float_t = typename BasicJsonType::number_float_t; | ||
|  | 
 | ||
|  |     const auto type = static_cast<std::size_t>(j.type()); | ||
|  |     switch (j.type()) | ||
|  |     { | ||
|  |         case BasicJsonType::value_t::null: | ||
|  |         case BasicJsonType::value_t::discarded: | ||
|  |         { | ||
|  |             return combine(type, 0); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::object: | ||
|  |         { | ||
|  |             auto seed = combine(type, j.size()); | ||
|  |             for (const auto& element : j.items()) | ||
|  |             { | ||
|  |                 const auto h = std::hash<string_t> {}(element.key()); | ||
|  |                 seed = combine(seed, h); | ||
|  |                 seed = combine(seed, hash(element.value())); | ||
|  |             } | ||
|  |             return seed; | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::array: | ||
|  |         { | ||
|  |             auto seed = combine(type, j.size()); | ||
|  |             for (const auto& element : j) | ||
|  |             { | ||
|  |                 seed = combine(seed, hash(element)); | ||
|  |             } | ||
|  |             return seed; | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::string: | ||
|  |         { | ||
|  |             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>()); | ||
|  |             return combine(type, h); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::boolean: | ||
|  |         { | ||
|  |             const auto h = std::hash<bool> {}(j.template get<bool>()); | ||
|  |             return combine(type, h); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::number_integer: | ||
|  |         { | ||
|  |             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>()); | ||
|  |             return combine(type, h); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::number_unsigned: | ||
|  |         { | ||
|  |             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>()); | ||
|  |             return combine(type, h); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::number_float: | ||
|  |         { | ||
|  |             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>()); | ||
|  |             return combine(type, h); | ||
|  |         } | ||
|  | 
 | ||
|  |         case BasicJsonType::value_t::binary: | ||
|  |         { | ||
|  |             auto seed = combine(type, j.get_binary().size()); | ||
|  |             const auto h = std::hash<bool> {}(j.get_binary().has_subtype()); | ||
|  |             seed = combine(seed, h); | ||
|  |             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype())); | ||
|  |             for (const auto byte : j.get_binary()) | ||
|  |             { | ||
|  |                 seed = combine(seed, std::hash<std::uint8_t> {}(byte)); | ||
|  |             } | ||
|  |             return seed; | ||
|  |         } | ||
|  | 
 | ||
|  |         default:                   // LCOV_EXCL_LINE
 | ||
|  |             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 | ||
|  |             return 0;              // LCOV_EXCL_LINE
 | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | }  // namespace detail
 | ||
|  | NLOHMANN_JSON_NAMESPACE_END |