json/include/nlohmann/detail/hash.hpp

130 lines
3.9 KiB
C++
Raw Normal View History

// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.10.5
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
2020-07-14 14:31:19 +02:00
#pragma once
:rotating_light: add new CI and fix warnings (#2561) * :alembic: move CI targets to CMake * :recycle: add target for cpplint * :recycle: add target for self-contained binaries * :recycle: add targets for iwyu and infer * :loud_sound: add version output * :recycle: add target for oclint * :rotating_light: fix warnings * :recycle: rename targets * :recycle: use iwyu properly * :rotating_light: fix warnings * :recycle: use iwyu properly * :recycle: add target for benchmarks * :recycle: add target for CMake flags * :construction_worker: use GitHub Actions * :alembic: try to install Clang 11 * :alembic: try to install GCC 11 * :alembic: try to install Clang 11 * :alembic: try to install GCC 11 * :alembic: add clang analyze target * :fire: remove Google Benchmark * :arrow_up: Google Benchmark 1.5.2 * :fire: use fetchcontent * :penguin: add target to download a Linux version of CMake * :hammer: fix dependency * :rotating_light: fix includes * :rotating_light: fix comment * :wrench: adjust flags for GCC 11.0.0 20210110 (experimental) * :whale: user Docker image to run CI * :wrench: add target for Valgrind * :construction_worker: add target for Valgrind tests * :alembic: add Dart * :rewind: remove Dart * :alembic: do not call ctest in test subdirectory * :alembic: download test data explicitly * :alembic: only execute Valgrind tests * :alembic: fix labels * :fire: remove unneeded jobs * :hammer: cleanup * :bug: fix OCLint call * :white_check_mark: add targets for offline and git-independent tests * :white_check_mark: add targets for C++ language versions and reproducible tests * :hammer: clean up * :construction_worker: add CI steps for cppcheck and cpplint * :rotating_light: fix warnings from Clang-Tidy * :construction_worker: add CI steps for Clang-Tidy * :rotating_light: fix warnings * :wrench: select proper binary * :rotating_light: fix warnings * :rotating_light: suppress some unhelpful warnings * :rotating_light: fix warnings * :art: fix format * :rotating_light: fix warnings * :construction_worker: add CI steps for Sanitizers * :rotating_light: fix warnings * :zap: add optimization to sanitizer build * :rotating_light: fix warnings * :rotating_light: add missing header * :rotating_light: fix warnings * :construction_worker: add CI step for coverage * :construction_worker: add CI steps for disabled exceptions and implicit conversions * :rotating_light: fix warnings * :construction_worker: add CI steps for checking indentation * :bug: fix variable use * :green_heart: fix build * :heavy_minus_sign: remove CircleCI * :construction_worker: add CI step for diagnostics * :rotating_light: fix warning * :fire: clean Travis
2021-03-24 07:15:18 +01:00
#include <cstdint> // uint8_t
#include <cstddef> // size_t
2020-07-14 14:31:19 +02:00
#include <functional> // hash
#include <nlohmann/detail/abi_macros.hpp>
2021-08-18 13:33:35 +02:00
#include <nlohmann/detail/value_t.hpp>
2020-12-26 17:56:16 +01:00
NLOHMANN_JSON_NAMESPACE_BEGIN
2020-07-14 14:31:19 +02:00
namespace detail
{
2020-07-15 13:45:16 +02:00
// boost::hash_combine
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
2020-07-14 14:31:19 +02:00
{
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
return seed;
}
2020-07-15 13:45:16 +02:00
/*!
@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
*/
2020-07-14 14:31:19 +02:00
template<typename BasicJsonType>
std::size_t hash(const BasicJsonType& j)
{
2020-07-15 09:27:01 +02:00
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;
2020-07-15 13:45:16 +02:00
const auto type = static_cast<std::size_t>(j.type());
2020-07-14 14:31:19 +02:00
switch (j.type())
{
case BasicJsonType::value_t::null:
2020-07-14 14:34:55 +02:00
case BasicJsonType::value_t::discarded:
2020-07-15 13:45:16 +02:00
{
return combine(type, 0);
}
2020-07-14 14:31:19 +02:00
case BasicJsonType::value_t::object:
{
2020-07-15 13:45:16 +02:00
auto seed = combine(type, j.size());
2020-07-14 14:31:19 +02:00
for (const auto& element : j.items())
{
2020-07-15 09:27:01 +02:00
const auto h = std::hash<string_t> {}(element.key());
2020-07-14 14:31:19 +02:00
seed = combine(seed, h);
seed = combine(seed, hash(element.value()));
}
return seed;
}
case BasicJsonType::value_t::array:
{
2020-07-15 13:45:16 +02:00
auto seed = combine(type, j.size());
2020-07-14 14:31:19 +02:00
for (const auto& element : j)
{
seed = combine(seed, hash(element));
}
return seed;
}
case BasicJsonType::value_t::string:
{
2020-07-15 09:27:01 +02:00
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
2020-07-15 13:45:16 +02:00
return combine(type, h);
2020-07-14 14:31:19 +02:00
}
case BasicJsonType::value_t::boolean:
{
const auto h = std::hash<bool> {}(j.template get<bool>());
2020-07-15 13:45:16 +02:00
return combine(type, h);
2020-07-14 14:31:19 +02:00
}
case BasicJsonType::value_t::number_integer:
{
2020-07-15 09:27:01 +02:00
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
2020-07-15 13:45:16 +02:00
return combine(type, h);
2020-07-14 14:31:19 +02:00
}
case BasicJsonType::value_t::number_unsigned:
2020-07-14 14:31:19 +02:00
{
2020-07-15 09:27:01 +02:00
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
2020-07-15 13:45:16 +02:00
return combine(type, h);
2020-07-14 14:31:19 +02:00
}
case BasicJsonType::value_t::number_float:
2020-07-14 14:31:19 +02:00
{
2020-07-15 09:27:01 +02:00
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
2020-07-15 13:45:16 +02:00
return combine(type, h);
2020-07-14 14:31:19 +02:00
}
case BasicJsonType::value_t::binary:
2020-07-14 14:31:19 +02:00
{
2020-07-15 13:45:16 +02:00
auto seed = combine(type, j.get_binary().size());
2020-07-15 09:27:01 +02:00
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
seed = combine(seed, h);
2021-08-14 13:40:52 +02:00
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
2020-07-14 14:31:19 +02:00
for (const auto byte : j.get_binary())
{
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
}
return seed;
}
default: // LCOV_EXCL_LINE
:rotating_light: add new CI and fix warnings (#2561) * :alembic: move CI targets to CMake * :recycle: add target for cpplint * :recycle: add target for self-contained binaries * :recycle: add targets for iwyu and infer * :loud_sound: add version output * :recycle: add target for oclint * :rotating_light: fix warnings * :recycle: rename targets * :recycle: use iwyu properly * :rotating_light: fix warnings * :recycle: use iwyu properly * :recycle: add target for benchmarks * :recycle: add target for CMake flags * :construction_worker: use GitHub Actions * :alembic: try to install Clang 11 * :alembic: try to install GCC 11 * :alembic: try to install Clang 11 * :alembic: try to install GCC 11 * :alembic: add clang analyze target * :fire: remove Google Benchmark * :arrow_up: Google Benchmark 1.5.2 * :fire: use fetchcontent * :penguin: add target to download a Linux version of CMake * :hammer: fix dependency * :rotating_light: fix includes * :rotating_light: fix comment * :wrench: adjust flags for GCC 11.0.0 20210110 (experimental) * :whale: user Docker image to run CI * :wrench: add target for Valgrind * :construction_worker: add target for Valgrind tests * :alembic: add Dart * :rewind: remove Dart * :alembic: do not call ctest in test subdirectory * :alembic: download test data explicitly * :alembic: only execute Valgrind tests * :alembic: fix labels * :fire: remove unneeded jobs * :hammer: cleanup * :bug: fix OCLint call * :white_check_mark: add targets for offline and git-independent tests * :white_check_mark: add targets for C++ language versions and reproducible tests * :hammer: clean up * :construction_worker: add CI steps for cppcheck and cpplint * :rotating_light: fix warnings from Clang-Tidy * :construction_worker: add CI steps for Clang-Tidy * :rotating_light: fix warnings * :wrench: select proper binary * :rotating_light: fix warnings * :rotating_light: suppress some unhelpful warnings * :rotating_light: fix warnings * :art: fix format * :rotating_light: fix warnings * :construction_worker: add CI steps for Sanitizers * :rotating_light: fix warnings * :zap: add optimization to sanitizer build * :rotating_light: fix warnings * :rotating_light: add missing header * :rotating_light: fix warnings * :construction_worker: add CI step for coverage * :construction_worker: add CI steps for disabled exceptions and implicit conversions * :rotating_light: fix warnings * :construction_worker: add CI steps for checking indentation * :bug: fix variable use * :green_heart: fix build * :heavy_minus_sign: remove CircleCI * :construction_worker: add CI step for diagnostics * :rotating_light: fix warning * :fire: clean Travis
2021-03-24 07:15:18 +01:00
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return 0; // LCOV_EXCL_LINE
2020-07-15 09:27:01 +02:00
}
2020-07-14 14:31:19 +02:00
}
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END