💡 add documentation
This commit is contained in:
parent
496ddd127c
commit
b821ed074f
3 changed files with 52 additions and 22 deletions
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t, uint8_t
|
||||||
#include <functional> // hash
|
#include <functional> // hash
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
|
@ -8,12 +8,24 @@ namespace nlohmann
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// boost::hash_combine
|
||||||
std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
||||||
{
|
{
|
||||||
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
||||||
return seed;
|
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>
|
template<typename BasicJsonType>
|
||||||
std::size_t hash(const BasicJsonType& j)
|
std::size_t hash(const BasicJsonType& j)
|
||||||
{
|
{
|
||||||
|
@ -22,15 +34,18 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
using number_float_t = typename BasicJsonType::number_float_t;
|
using number_float_t = typename BasicJsonType::number_float_t;
|
||||||
|
|
||||||
|
const auto type = static_cast<std::size_t>(j.type());
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
case BasicJsonType::value_t::null:
|
case BasicJsonType::value_t::null:
|
||||||
case BasicJsonType::value_t::discarded:
|
case BasicJsonType::value_t::discarded:
|
||||||
return combine(static_cast<std::size_t>(j.type()), 0);
|
{
|
||||||
|
return combine(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::object:
|
case BasicJsonType::value_t::object:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.size());
|
auto seed = combine(type, j.size());
|
||||||
for (const auto& element : j.items())
|
for (const auto& element : j.items())
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(element.key());
|
const auto h = std::hash<string_t> {}(element.key());
|
||||||
|
@ -42,7 +57,7 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
|
|
||||||
case BasicJsonType::value_t::array:
|
case BasicJsonType::value_t::array:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.size());
|
auto seed = combine(type, j.size());
|
||||||
for (const auto& element : j)
|
for (const auto& element : j)
|
||||||
{
|
{
|
||||||
seed = combine(seed, hash(element));
|
seed = combine(seed, hash(element));
|
||||||
|
@ -53,36 +68,36 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
case BasicJsonType::value_t::string:
|
case BasicJsonType::value_t::string:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::boolean:
|
case BasicJsonType::value_t::boolean:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<bool> {}(j.template get<bool>());
|
const auto h = std::hash<bool> {}(j.template get<bool>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::number_integer:
|
case BasicJsonType::value_t::number_integer:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::number_unsigned:
|
case nlohmann::detail::value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::number_float:
|
case nlohmann::detail::value_t::number_float:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::binary:
|
case nlohmann::detail::value_t::binary:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.get_binary().size());
|
auto seed = combine(type, j.get_binary().size());
|
||||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, j.get_binary().subtype());
|
seed = combine(seed, j.get_binary().subtype());
|
||||||
|
|
|
@ -4445,7 +4445,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
// #include <nlohmann/detail/hash.hpp>
|
// #include <nlohmann/detail/hash.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t, uint8_t
|
||||||
#include <functional> // hash
|
#include <functional> // hash
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
|
@ -4453,12 +4453,24 @@ namespace nlohmann
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// boost::hash_combine
|
||||||
std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
||||||
{
|
{
|
||||||
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
||||||
return seed;
|
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>
|
template<typename BasicJsonType>
|
||||||
std::size_t hash(const BasicJsonType& j)
|
std::size_t hash(const BasicJsonType& j)
|
||||||
{
|
{
|
||||||
|
@ -4467,15 +4479,18 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
using number_float_t = typename BasicJsonType::number_float_t;
|
using number_float_t = typename BasicJsonType::number_float_t;
|
||||||
|
|
||||||
|
const auto type = static_cast<std::size_t>(j.type());
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
case BasicJsonType::value_t::null:
|
case BasicJsonType::value_t::null:
|
||||||
case BasicJsonType::value_t::discarded:
|
case BasicJsonType::value_t::discarded:
|
||||||
return combine(static_cast<std::size_t>(j.type()), 0);
|
{
|
||||||
|
return combine(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::object:
|
case BasicJsonType::value_t::object:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.size());
|
auto seed = combine(type, j.size());
|
||||||
for (const auto& element : j.items())
|
for (const auto& element : j.items())
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(element.key());
|
const auto h = std::hash<string_t> {}(element.key());
|
||||||
|
@ -4487,7 +4502,7 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
|
|
||||||
case BasicJsonType::value_t::array:
|
case BasicJsonType::value_t::array:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.size());
|
auto seed = combine(type, j.size());
|
||||||
for (const auto& element : j)
|
for (const auto& element : j)
|
||||||
{
|
{
|
||||||
seed = combine(seed, hash(element));
|
seed = combine(seed, hash(element));
|
||||||
|
@ -4498,36 +4513,36 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
case BasicJsonType::value_t::string:
|
case BasicJsonType::value_t::string:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::boolean:
|
case BasicJsonType::value_t::boolean:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<bool> {}(j.template get<bool>());
|
const auto h = std::hash<bool> {}(j.template get<bool>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::number_integer:
|
case BasicJsonType::value_t::number_integer:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::number_unsigned:
|
case nlohmann::detail::value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::number_float:
|
case nlohmann::detail::value_t::number_float:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
||||||
return combine(static_cast<std::size_t>(j.type()), h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case nlohmann::detail::value_t::binary:
|
case nlohmann::detail::value_t::binary:
|
||||||
{
|
{
|
||||||
auto seed = combine(static_cast<std::size_t>(j.type()), j.get_binary().size());
|
auto seed = combine(type, j.get_binary().size());
|
||||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, j.get_binary().subtype());
|
seed = combine(seed, j.get_binary().subtype());
|
||||||
|
|
|
@ -54,7 +54,7 @@ TEST_CASE("hash")
|
||||||
hashes.insert(std::hash<json> {}(json("foo")));
|
hashes.insert(std::hash<json> {}(json("foo")));
|
||||||
|
|
||||||
// number
|
// number
|
||||||
hashes.insert(std::hash<json> {}(json(int(0))));
|
hashes.insert(std::hash<json> {}(json(0)));
|
||||||
hashes.insert(std::hash<json> {}(json(unsigned(0))));
|
hashes.insert(std::hash<json> {}(json(unsigned(0))));
|
||||||
|
|
||||||
hashes.insert(std::hash<json> {}(json(-1)));
|
hashes.insert(std::hash<json> {}(json(-1)));
|
||||||
|
@ -81,4 +81,4 @@ TEST_CASE("hash")
|
||||||
hashes.insert(std::hash<json> {}(json(json::value_t::discarded)));
|
hashes.insert(std::hash<json> {}(json(json::value_t::discarded)));
|
||||||
|
|
||||||
CHECK(hashes.size() == 21);
|
CHECK(hashes.size() == 21);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue