hash.hpp 3.9 KB

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