Merge branch 'develop' into claude/fix-issue-3989-db7e45

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-17 08:35:02 +02:00
commit fb729028ba
24 files changed
+873 -655

No files matched your search

+61 -59
View File
@@ -29,6 +29,7 @@
#endif // JSON_NO_IO
#include <iterator> // make_move_iterator, random_access_iterator_tag
#include <limits> // numeric_limits
#include <map> // map
#include <memory> // unique_ptr
#include <set> // swap, operator!=
#include <stdexcept> // length_error
@@ -754,26 +755,20 @@ private:
// one level deep); stops at the first structured child it meets
static bool all_children_leaves(const basic_json& v) noexcept
{
// array_t only needs forward iterators (see custom_array_type)
if (v.m_data.m_type == value_t::array)
{
const auto& a = *v.m_data.m_value.array;
for (auto it = a.rbegin(); it != a.rend(); ++it)
return std::all_of(a.begin(), a.end(), [](const basic_json & el)
{
if (!has_no_children(*it))
{
return false;
}
}
return true;
return has_no_children(el);
});
}
for (const auto& el : *v.m_data.m_value.object)
const auto& o = *v.m_data.m_value.object;
return std::all_of(o.begin(), o.end(), [](const typename object_t::value_type & el)
{
if (!has_no_children(el.second))
{
return false;
}
}
return true;
return has_no_children(el.second);
});
}
// The walk in destroy_container() may take the children of a
@@ -1230,7 +1225,7 @@ public:
}
template < typename O = object_t, detail::enable_if_t < detail::has_stable_elements<O>::value, int > = 0 >
static constexpr std::size_t object_capacity() noexcept
std::size_t object_capacity() const noexcept
{
return 0;
}
@@ -1242,7 +1237,7 @@ public:
}
template < typename O = object_t, detail::enable_if_t < !detail::has_stable_elements<O>::value && !detail::is_nlohmann_ordered_map<O>::value, int > = 0 >
static constexpr std::size_t object_capacity() noexcept
std::size_t object_capacity() const noexcept
{
return detail::unknown_size();
}
@@ -3043,18 +3038,21 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_iterator_range_of_null(const basic_json* obj)
{
static_cast<void>(obj); // unused when JSON_NOEXCEPTION is defined
JSON_THROW(invalid_iterator::create(detail::exception_id::iterator_range_of_null, detail::concat("cannot construct with iterators from ", obj->type_name()), obj));
}
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_incompatible_reference_type(const basic_json& obj)
{
static_cast<void>(obj); // unused when JSON_NOEXCEPTION is defined
JSON_THROW(type_error::create(detail::exception_id::incompatible_reference_type, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
}
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_exceeds_size_type(size_type idx)
{
static_cast<void>(idx); // unused when JSON_NOEXCEPTION is defined
JSON_THROW(std::length_error(detail::concat("array index ", std::to_string(idx), " exceeds size_type")));
}
@@ -3062,6 +3060,8 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_out_of_range(size_type idx, const basic_json& j)
{
static_cast<void>(idx); // unused when JSON_NOEXCEPTION is defined
static_cast<void>(j);
JSON_THROW(out_of_range::create(detail::exception_id::array_index_out_of_range, detail::concat("array index ", std::to_string(idx), " is out of range"), &j));
}
@@ -3070,6 +3070,8 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_key_not_found(const KeyType& key, const basic_json& j)
{
static_cast<void>(key); // unused when JSON_NOEXCEPTION is defined
static_cast<void>(j);
JSON_THROW(out_of_range::create(detail::exception_id::key_not_found, detail::concat("key '", key, "' not found"), &j));
}
@@ -4893,19 +4895,19 @@ public:
iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{
// insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// insert to array and return iterator
return insert_iterator(pos, val);
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
}
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// insert to array and return iterator
return insert_iterator(pos, val);
}
/// @brief inserts element into array
@@ -4913,21 +4915,21 @@ public:
iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{
// insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// moving into a local first keeps this safe even if val aliases
// an element of this array
basic_json tmp(std::move(val));
return insert_iterator(pos, std::move(tmp));
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
}
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// moving into a local first keeps this safe even if val aliases
// an element of this array
basic_json tmp(std::move(val));
return insert_iterator(pos, std::move(tmp));
}
/// @brief inserts copies of element into array
@@ -4935,19 +4937,19 @@ public:
iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{
// insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
if (JSON_HEDLEY_UNLIKELY(!is_array()))
{
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// insert to array and return iterator
return insert_iterator(pos, cnt, val);
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
}
detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
detail::throw_literal<invalid_iterator>(detail::exception_id::iterator_from_other_value, "iterator does not fit current value", this);
}
// insert to array and return iterator
return insert_iterator(pos, cnt, val);
}
/// @brief inserts range of elements into array
@@ -5453,7 +5455,7 @@ public:
// inline fast path for two values of the same non-owning scalar type; anything
// else falls through to the out-of-line general comparison
#define JSON_IMPLEMENT_SCALAR_FAST(op, null_result) \
if (lhs.m_data.m_type == rhs.m_data.m_type) \
if (lhs.m_data.m_type == rhs.m_data.m_type) /* NOLINT(readability/braces) */ \
{ \
switch (lhs.m_data.m_type) \
{ \
@@ -5518,16 +5520,6 @@ public:
#endif
}
JSON_HEDLEY_NEVER_INLINE
static bool less_general(const_reference lhs, const_reference rhs) noexcept
{
// 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.
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type),
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
}
#if JSON_HAS_THREE_WAY_COMPARISON
JSON_HEDLEY_NEVER_INLINE
static std::partial_ordering three_way_general(const_reference lhs, const_reference rhs) noexcept // *NOPAD*
@@ -5540,6 +5532,16 @@ public:
lhs_type <=> rhs_type, // *NOPAD*
to_partial_ordering(compare_iteratively<true>(lhs, rhs, false)), true)
}
#else
JSON_HEDLEY_NEVER_INLINE
static bool less_general(const_reference lhs, const_reference rhs) noexcept
{
// 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.
JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type),
compare_iteratively<true>(lhs, rhs, true) == compare_result::less, false)
}
#endif
/// @brief compare two leaves of the same type inside equal_structured()