mirror of
https://github.com/nlohmann/json.git
synced 2026-04-30 19:59:26 +00:00
Merge branch 'develop' of https://github.com/nlohmann/json into bon8
Conflicts: docs/mkdocs/docs/api/basic_json/index.md docs/mkdocs/docs/features/binary_formats/index.md docs/mkdocs/mkdocs.yml tests/src/unit-binary_formats.cpp
This commit is contained in:
@@ -33,7 +33,7 @@ SOFTWARE.
|
||||
* contains the most recent documentation and should also be applicable to *
|
||||
* previous versions; documentation for deprecated functions is not *
|
||||
* removed, but marked deprecated. See "Generate documentation" section in *
|
||||
* file docs/README.md. *
|
||||
* file docs/README.md. *
|
||||
\****************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
|
||||
@@ -916,6 +916,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||
}
|
||||
JSON_ASSERT(m_type == val.type());
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
}
|
||||
@@ -1905,7 +1906,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
|
||||
detail::negation<detail::is_basic_json<ValueType>>,
|
||||
detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
|
||||
|
||||
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
|
||||
detail::negation<std::is_same<ValueType, std::string_view>>,
|
||||
#endif
|
||||
@@ -3538,7 +3538,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////
|
||||
// lexicographical comparison operators //
|
||||
//////////////////////////////////////////
|
||||
@@ -3546,6 +3545,212 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @name lexicographical comparison operators
|
||||
/// @{
|
||||
|
||||
// note parentheses around operands are necessary; see
|
||||
// https://github.com/nlohmann/json/issues/1530
|
||||
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
|
||||
const auto lhs_type = lhs.type(); \
|
||||
const auto rhs_type = rhs.type(); \
|
||||
\
|
||||
if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
|
||||
{ \
|
||||
switch (lhs_type) \
|
||||
{ \
|
||||
case value_t::array: \
|
||||
return (*lhs.m_value.array) op (*rhs.m_value.array); \
|
||||
\
|
||||
case value_t::object: \
|
||||
return (*lhs.m_value.object) op (*rhs.m_value.object); \
|
||||
\
|
||||
case value_t::null: \
|
||||
return (null_result); \
|
||||
\
|
||||
case value_t::string: \
|
||||
return (*lhs.m_value.string) op (*rhs.m_value.string); \
|
||||
\
|
||||
case value_t::boolean: \
|
||||
return (lhs.m_value.boolean) op (rhs.m_value.boolean); \
|
||||
\
|
||||
case value_t::number_integer: \
|
||||
return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \
|
||||
\
|
||||
case value_t::number_unsigned: \
|
||||
return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \
|
||||
\
|
||||
case value_t::number_float: \
|
||||
return (lhs.m_value.number_float) op (rhs.m_value.number_float); \
|
||||
\
|
||||
case value_t::binary: \
|
||||
return (*lhs.m_value.binary) op (*rhs.m_value.binary); \
|
||||
\
|
||||
case value_t::discarded: \
|
||||
default: \
|
||||
return (unordered_result); \
|
||||
} \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
|
||||
{ \
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float; \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
|
||||
{ \
|
||||
return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer); \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
|
||||
{ \
|
||||
return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
|
||||
{ \
|
||||
return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned); \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
|
||||
{ \
|
||||
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
|
||||
} \
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
|
||||
{ \
|
||||
return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
|
||||
} \
|
||||
else if(compares_unordered(lhs, rhs))\
|
||||
{\
|
||||
return (unordered_result);\
|
||||
}\
|
||||
\
|
||||
return (default_result);
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
// returns true if:
|
||||
// - any operand is NaN and the other operand is of number type
|
||||
// - any operand is discarded
|
||||
// in legacy mode, discarded values are considered ordered if
|
||||
// an operation is computed as an odd number of inverses of others
|
||||
static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
|
||||
{
|
||||
if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
|
||||
|| (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
|
||||
#else
|
||||
static_cast<void>(inverse);
|
||||
return lhs.is_discarded() || rhs.is_discarded();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
|
||||
{
|
||||
return compares_unordered(*this, rhs, inverse);
|
||||
}
|
||||
|
||||
public:
|
||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||
/// @brief comparison: equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
|
||||
bool operator==(const_reference rhs) const noexcept
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
const_reference lhs = *this;
|
||||
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief comparison: equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
|
||||
template<typename ScalarType>
|
||||
requires std::is_scalar_v<ScalarType>
|
||||
bool operator==(ScalarType rhs) const noexcept
|
||||
{
|
||||
return *this == basic_json(rhs);
|
||||
}
|
||||
|
||||
/// @brief comparison: not equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||
bool operator!=(const_reference rhs) const noexcept
|
||||
{
|
||||
if (compares_unordered(rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// @brief comparison: 3-way
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
||||
{
|
||||
const_reference lhs = *this;
|
||||
// default_result is used if we cannot compare values. In that case,
|
||||
// we compare types.
|
||||
JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
|
||||
std::partial_ordering::equivalent,
|
||||
std::partial_ordering::unordered,
|
||||
lhs_type <=> rhs_type) // *NOPAD*
|
||||
}
|
||||
|
||||
/// @brief comparison: 3-way
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||
template<typename ScalarType>
|
||||
requires std::is_scalar_v<ScalarType>
|
||||
std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
|
||||
{
|
||||
return *this <=> basic_json(rhs); // *NOPAD*
|
||||
}
|
||||
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
// all operators that are computed as an odd number of inverses of others
|
||||
// need to be overloaded to emulate the legacy comparison behavior
|
||||
|
||||
/// @brief comparison: less than or equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
bool operator<=(const_reference rhs) const noexcept
|
||||
{
|
||||
if (compares_unordered(rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(rhs < *this);
|
||||
}
|
||||
|
||||
/// @brief comparison: less than or equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
|
||||
template<typename ScalarType>
|
||||
requires std::is_scalar_v<ScalarType>
|
||||
bool operator<=(ScalarType rhs) const noexcept
|
||||
{
|
||||
return *this <= basic_json(rhs);
|
||||
}
|
||||
|
||||
/// @brief comparison: greater than or equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
bool operator>=(const_reference rhs) const noexcept
|
||||
{
|
||||
if (compares_unordered(rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(*this < rhs);
|
||||
}
|
||||
|
||||
/// @brief comparison: greater than or equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
|
||||
template<typename ScalarType>
|
||||
requires std::is_scalar_v<ScalarType>
|
||||
bool operator>=(ScalarType rhs) const noexcept
|
||||
{
|
||||
return *this >= basic_json(rhs);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/// @brief comparison: equal
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
|
||||
friend bool operator==(const_reference lhs, const_reference rhs) noexcept
|
||||
@@ -3554,71 +3759,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
const auto lhs_type = lhs.type();
|
||||
const auto rhs_type = rhs.type();
|
||||
|
||||
if (lhs_type == rhs_type)
|
||||
{
|
||||
switch (lhs_type)
|
||||
{
|
||||
case value_t::array:
|
||||
return *lhs.m_value.array == *rhs.m_value.array;
|
||||
|
||||
case value_t::object:
|
||||
return *lhs.m_value.object == *rhs.m_value.object;
|
||||
|
||||
case value_t::null:
|
||||
return true;
|
||||
|
||||
case value_t::string:
|
||||
return *lhs.m_value.string == *rhs.m_value.string;
|
||||
|
||||
case value_t::boolean:
|
||||
return lhs.m_value.boolean == rhs.m_value.boolean;
|
||||
|
||||
case value_t::number_integer:
|
||||
return lhs.m_value.number_integer == rhs.m_value.number_integer;
|
||||
|
||||
case value_t::number_unsigned:
|
||||
return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
|
||||
|
||||
case value_t::number_float:
|
||||
return lhs.m_value.number_float == rhs.m_value.number_float;
|
||||
|
||||
case value_t::binary:
|
||||
return *lhs.m_value.binary == *rhs.m_value.binary;
|
||||
|
||||
case value_t::discarded:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
|
||||
{
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
|
||||
{
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
|
||||
{
|
||||
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
|
||||
{
|
||||
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
|
||||
}
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
|
||||
return false;
|
||||
JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
@@ -3646,6 +3787,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
||||
{
|
||||
if (compares_unordered(lhs, rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
@@ -3671,76 +3816,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
|
||||
friend bool operator<(const_reference lhs, const_reference rhs) noexcept
|
||||
{
|
||||
const auto lhs_type = lhs.type();
|
||||
const auto rhs_type = rhs.type();
|
||||
|
||||
if (lhs_type == rhs_type)
|
||||
{
|
||||
switch (lhs_type)
|
||||
{
|
||||
case value_t::array:
|
||||
// note parentheses are necessary, see
|
||||
// https://github.com/nlohmann/json/issues/1530
|
||||
return (*lhs.m_value.array) < (*rhs.m_value.array);
|
||||
|
||||
case value_t::object:
|
||||
return (*lhs.m_value.object) < (*rhs.m_value.object);
|
||||
|
||||
case value_t::null:
|
||||
return false;
|
||||
|
||||
case value_t::string:
|
||||
return (*lhs.m_value.string) < (*rhs.m_value.string);
|
||||
|
||||
case value_t::boolean:
|
||||
return (lhs.m_value.boolean) < (rhs.m_value.boolean);
|
||||
|
||||
case value_t::number_integer:
|
||||
return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
|
||||
|
||||
case value_t::number_unsigned:
|
||||
return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
|
||||
|
||||
case value_t::number_float:
|
||||
return (lhs.m_value.number_float) < (rhs.m_value.number_float);
|
||||
|
||||
case value_t::binary:
|
||||
return (*lhs.m_value.binary) < (*rhs.m_value.binary);
|
||||
|
||||
case value_t::discarded:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
|
||||
{
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
|
||||
{
|
||||
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
|
||||
{
|
||||
return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
|
||||
{
|
||||
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
|
||||
}
|
||||
|
||||
// We only reach this line if we cannot compare values. In that case,
|
||||
// default_result is used if we cannot compare values. In that case,
|
||||
// we compare types. Note we have to call the operator explicitly,
|
||||
// because MSVC has problems otherwise.
|
||||
return operator<(lhs_type, rhs_type);
|
||||
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
|
||||
}
|
||||
|
||||
/// @brief comparison: less than
|
||||
@@ -3765,6 +3844,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
|
||||
friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
|
||||
{
|
||||
if (compares_unordered(lhs, rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
@@ -3790,6 +3873,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
|
||||
friend bool operator>(const_reference lhs, const_reference rhs) noexcept
|
||||
{
|
||||
// double inverse
|
||||
if (compares_unordered(lhs, rhs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(lhs <= rhs);
|
||||
}
|
||||
|
||||
@@ -3815,6 +3903,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
|
||||
friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
|
||||
{
|
||||
if (compares_unordered(lhs, rhs, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
@@ -3835,6 +3927,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
return basic_json(lhs) >= rhs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef JSON_IMPLEMENT_OPERATOR
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -4426,29 +4521,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json from_bjdata(const T* ptr, std::size_t len,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
return from_bjdata(ptr, ptr + len, strict, allow_exceptions);
|
||||
}
|
||||
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json from_bjdata(detail::span_input_adapter&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
{
|
||||
basic_json result;
|
||||
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
|
||||
auto ia = i.get();
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/from_bson/
|
||||
template<typename InputType>
|
||||
@@ -5107,10 +5179,14 @@ struct less< ::nlohmann::detail::value_t> // do not remove the space after '<',
|
||||
@brief compare two value_t enum values
|
||||
@since version 3.0.0
|
||||
*/
|
||||
bool operator()(nlohmann::detail::value_t lhs,
|
||||
nlohmann::detail::value_t rhs) const noexcept
|
||||
bool operator()(::nlohmann::detail::value_t lhs,
|
||||
::nlohmann::detail::value_t rhs) const noexcept
|
||||
{
|
||||
return nlohmann::detail::operator<(lhs, rhs);
|
||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||
return std::is_lt(lhs <=> rhs); // *NOPAD*
|
||||
#else
|
||||
return ::nlohmann::detail::operator<(lhs, rhs);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user