Compare commits

..
Author SHA1 Message Date
dependabot[bot] 989affd378 Bump cppcheck from 1.5.2 to 1.5.3 in /cmake/requirements
Bumps [cppcheck](https://github.com/msclock/cppcheck-wheel) from 1.5.2 to 1.5.3.
- [Release notes](https://github.com/msclock/cppcheck-wheel/releases)
- [Commits](https://github.com/msclock/cppcheck-wheel/compare/v1.5.2...v1.5.3)

---
updated-dependencies:
- dependency-name: cppcheck
  dependency-version: 1.5.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-16 00:05:03 +00:00
17 changed files with 169 additions and 256 deletions

No files matched your search

+8 -10
View File
@@ -166,21 +166,19 @@ jobs:
# link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash # link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash
# before doctest prints its first line - 39 of 102 tests on clang 18. # before doctest prints its first line - 39 of 102 tests on clang 18.
# Keep the objects small by splitting the test files instead. # Keep the objects small by splitting the test files instead.
# The tests link with LLD: GNU ld fails on objects with more than 32767 # Objects with more than 65535 sections fail to link with "relocation
# sections with "relocation truncated to fit: IMAGE_REL_AMD64_REL32 # truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata'": the MinGW
# against `.rdata'", as it stores the section an associative COMDAT # linker stores the section an associative COMDAT section belongs to in
# section belongs to in 16 bits (x_associated in binutils' # 16 bits (x_associated in binutils' include/coff/internal.h), so it
# include/coff/internal.h) and so discards the jump tables of inline # discards the jump tables of inline functions together with the wrong
# functions together with the wrong function. Each basic_json # function. Each basic_json specialization a test file instantiates adds
# specialization and input type a test file instantiates adds many # many sections, so test a second one in a file of its own.
# sections, so unit-msgpack.cpp and unit-regression2.cpp kept crossing
# that limit as the library grew.
- name: Run CMake - name: Run CMake
run: cmake -S . -B build ^ run: cmake -S . -B build ^
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^ -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
-DCMAKE_CXX_FLAGS="--target=x86_64-w64-mingw32 -stdlib=libstdc++ -pthread" ^ -DCMAKE_CXX_FLAGS="--target=x86_64-w64-mingw32 -stdlib=libstdc++ -pthread" ^
-DCMAKE_CXX_FLAGS_DEBUG="-g0" ^ -DCMAKE_CXX_FLAGS_DEBUG="-g0" ^
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld -lwinpthread" ^ -DCMAKE_EXE_LINKER_FLAGS="-lwinpthread" ^
-G"MinGW Makefiles" ^ -G"MinGW Makefiles" ^
-DCMAKE_BUILD_TYPE=Debug ^ -DCMAKE_BUILD_TYPE=Debug ^
-DJSON_BuildTests=On -DJSON_BuildTests=On
+1 -1
View File
@@ -1 +1 @@
cppcheck==1.5.2 cppcheck==1.5.3
@@ -13,7 +13,7 @@
#include <optional> // optional #include <optional> // optional
#endif #endif
#include <iterator> // begin, end, make_move_iterator, move_iterator #include <iterator> // begin, end
#include <memory> // allocator_traits #include <memory> // allocator_traits
#include <string> // basic_string, char_traits #include <string> // basic_string, char_traits
#include <tuple> // tuple, get #include <tuple> // tuple, get
@@ -48,32 +48,6 @@ namespace detail
* leave j with the type of the new value, but the pointer to the destroyed old one. * leave j with the type of the new value, but the pointer to the destroyed old one.
*/ */
// a move iterator over the elements of an rvalue container, unless they are
// const (e.g., std::set): libstdc++ before GCC 5 defines the reference of a
// std::move_iterator as value_type&&, which cannot bind to a const element
template<typename Iterator>
std::move_iterator<Iterator> make_move_iterator_if_mutable_impl(const Iterator& it, std::true_type /*mutable*/)
{
return std::make_move_iterator(it);
}
template<typename Iterator>
Iterator make_move_iterator_if_mutable_impl(const Iterator& it, std::false_type /*mutable*/)
{
return it;
}
template<typename Iterator>
using is_mutable_iterator = std::integral_constant < bool,
!std::is_const<typename std::remove_reference<decltype(*std::declval<Iterator&>())>::type>::value >;
template<typename Iterator>
auto make_move_iterator_if_mutable(const Iterator& it)
-> decltype(make_move_iterator_if_mutable_impl(it, is_mutable_iterator<Iterator> {}))
{
return make_move_iterator_if_mutable_impl(it, is_mutable_iterator<Iterator> {});
}
template<value_t> struct external_constructor; template<value_t> struct external_constructor;
template<> template<>
@@ -200,7 +174,7 @@ struct external_constructor<value_t::array>
using std::begin; using std::begin;
using std::end; using std::end;
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(make_move_iterator_if_mutable(begin(arr)), make_move_iterator_if_mutable(end(arr)))); const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(std::make_move_iterator(begin(arr)), std::make_move_iterator(end(arr))));
j.replace_value(value_t::array, value); j.replace_value(value_t::array, value);
} }
@@ -261,7 +235,7 @@ struct external_constructor<value_t::object>
using std::begin; using std::begin;
using std::end; using std::end;
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::object_t>(make_move_iterator_if_mutable(begin(obj)), make_move_iterator_if_mutable(end(obj)))); const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::object_t>(std::make_move_iterator(begin(obj)), std::make_move_iterator(end(obj))));
j.replace_value(value_t::object, value); j.replace_value(value_t::object, value);
} }
@@ -439,27 +413,25 @@ using is_movable_container_rvalue = negation<disjunction<
std::is_const<T>, std::is_const<T>,
has_dedicated_to_json<T>, has_dedicated_to_json<T>,
is_basic_json<T>, is_basic_json<T>,
is_range_view_type<T>,
is_enum_keyed_map_type<T>, is_enum_keyed_map_type<T>,
std::is_same<T, std::vector<bool>>>>; std::is_same<T, std::vector<bool>>>>;
// rvalue array-like containers; object types are ruled out before views are // rvalue array-like containers
// checked, as std::ranges::view<T> for the object_t of an ordered_json would
// need that ordered_json to be complete (GCC 11, see #3312)
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
using is_rvalue_array_to_json = conjunction<is_movable_container_rvalue<T>, using is_rvalue_array_to_json = conjunction<is_movable_container_rvalue<T>,
negation<is_compatible_object_type<BasicJsonType, T>>,
negation<is_range_view_type<T>>,
is_compatible_array_type<BasicJsonType, T>, is_compatible_array_type<BasicJsonType, T>,
negation<disjunction< negation<disjunction<
std::is_same<T, typename BasicJsonType::array_t>, std::is_same<T, typename BasicJsonType::array_t>,
std::is_same<T, typename BasicJsonType::binary_t>, std::is_same<T, typename BasicJsonType::binary_t>,
is_compatible_object_type<BasicJsonType, T>,
is_compatible_string_type<BasicJsonType, T>, is_compatible_string_type<BasicJsonType, T>,
is_compatible_binary_type<BasicJsonType, T>>>>; is_compatible_binary_type<BasicJsonType, T>>>>;
// rvalue containers: their elements are moved instead of copied // rvalue containers: their elements are moved instead of copied
template<typename BasicJsonType, typename CompatibleArrayType, template<typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_rvalue_array_to_json<BasicJsonType, CompatibleArrayType>::value, int> = 0> enable_if_t<is_rvalue_array_to_json<BasicJsonType, CompatibleArrayType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleArrayType && arr) // NOLINT(cppcoreguidelines-missing-std-forward) inline void to_json(BasicJsonType& j, CompatibleArrayType && arr)
{ {
external_constructor<value_t::array>::construct_moving(j, arr); external_constructor<value_t::array>::construct_moving(j, arr);
} }
@@ -537,8 +509,7 @@ inline void to_json(BasicJsonType& j, const EnumKeyedMap& map)
} }
#endif #endif
// rvalue object-like containers (views have no key_type and mapped_type, so // rvalue object-like containers
// they are no compatible object type)
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>, using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>,
negation<std::is_same<T, typename BasicJsonType::object_t>>, negation<std::is_same<T, typename BasicJsonType::object_t>>,
@@ -546,7 +517,7 @@ using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>,
template<typename BasicJsonType, typename CompatibleObjectType, template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<is_rvalue_object_to_json<BasicJsonType, CompatibleObjectType>::value, int> = 0> enable_if_t<is_rvalue_object_to_json<BasicJsonType, CompatibleObjectType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleObjectType && obj) // NOLINT(cppcoreguidelines-missing-std-forward) inline void to_json(BasicJsonType& j, CompatibleObjectType && obj)
{ {
external_constructor<value_t::object>::construct_moving(j, obj); external_constructor<value_t::object>::construct_moving(j, obj);
} }
+1 -1
View File
@@ -185,7 +185,7 @@ JSON_HEDLEY_ALWAYS_INLINE shortest_decimal to_shortest(std::uint64_t bits) noexc
const uint128_parts p = umul192_hi128(p10.high, p10.low, bin_sig << static_cast<unsigned>(shift)); const uint128_parts p = umul192_hi128(p10.high, p10.low, bin_sig << static_cast<unsigned>(shift));
std::uint64_t integral = p.high >> static_cast<unsigned>(extra_shift); std::uint64_t integral = p.high >> static_cast<unsigned>(extra_shift);
// (no casts in the shifts: MSVC 2015 warns C4554 on them despite the parentheses) // (no casts in the shifts: MSVC 2015 warns C4554 on them despite the parentheses)
constexpr auto fractional_low_shift = static_cast<unsigned>(extra_shift); constexpr unsigned fractional_low_shift = static_cast<unsigned>(extra_shift);
constexpr unsigned fractional_high_shift = 64u - fractional_low_shift; constexpr unsigned fractional_high_shift = 64u - fractional_low_shift;
const std::uint64_t fractional = (p.high << fractional_high_shift) | (p.low >> fractional_low_shift); const std::uint64_t fractional = (p.high << fractional_high_shift) | (p.low >> fractional_low_shift);
std::uint64_t digit = 0; std::uint64_t digit = 0;
+2 -1
View File
@@ -494,7 +494,8 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_missing_member(c
static_cast<void>(string_type); static_cast<void>(string_type);
static_cast<void>(val); static_cast<void>(val);
// context-sensitive error message // context-sensitive error message
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat((op == "op") ? std::string("operation") : concat("operation '", op, '\''), string_type ? " must have string member '" : " must have member '", member, "'"), &val)); const std::string error_msg = (op == "op") ? std::string("operation") : concat("operation '", op, '\'');
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat(error_msg, string_type ? " must have string member '" : " must have member '", member, "'"), &val));
} }
template<typename StringType, typename BasicJsonType> template<typename StringType, typename BasicJsonType>
@@ -680,12 +680,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{ {
JSON_ASSERT(m_object != nullptr); JSON_ASSERT(m_object != nullptr);
if (JSON_HEDLEY_UNLIKELY(!m_object->is_object())) if (JSON_HEDLEY_LIKELY(m_object->is_object()))
{ {
throw_literal<invalid_iterator>(exception_id::iterator_key_not_object, "cannot use key() for non-object iterators", m_object); return m_it.object_iterator->first;
} }
return m_it.object_iterator->first; throw_literal<invalid_iterator>(exception_id::iterator_key_not_object, "cannot use key() for non-object iterators", m_object);
} }
/*! /*!
+3 -4
View File
@@ -11,7 +11,6 @@
#include <algorithm> // all_of #include <algorithm> // all_of
#include <cctype> // isdigit #include <cctype> // isdigit
#include <cerrno> // errno, ERANGE #include <cerrno> // errno, ERANGE
#include <cstddef> // size_t
#include <cstdlib> // strtoull #include <cstdlib> // strtoull
#ifndef JSON_NO_IO #ifndef JSON_NO_IO
#include <iosfwd> // ostream #include <iosfwd> // ostream
@@ -335,7 +334,7 @@ class json_pointer
{ {
break; // not a plain number: let strtoull decide break; // not a plain number: let strtoull decide
} }
acc = static_cast<size_type>((acc * 10) + static_cast<size_type>(c - '0')); acc = static_cast<size_type>(acc * 10 + static_cast<size_type>(c - '0'));
if (JSON_HEDLEY_UNLIKELY(i == s.size() - 1)) if (JSON_HEDLEY_UNLIKELY(i == s.size() - 1))
{ {
idx = acc; idx = acc;
@@ -530,10 +529,10 @@ class json_pointer
static std::size_t hash_of(std::size_t parent, const string_t& token) noexcept static std::size_t hash_of(std::size_t parent, const string_t& token) noexcept
{ {
std::size_t h = parent * static_cast<std::size_t>(0x9E3779B97F4A7C15ULL & (std::numeric_limits<std::size_t>::max)()); std::size_t h = parent * static_cast<std::size_t>(0x9E3779B97F4A7C15ULL);
for (std::size_t i = 0; i < token.size(); ++i) for (std::size_t i = 0; i < token.size(); ++i)
{ {
h = (h ^ static_cast<unsigned char>(token[i])) * static_cast<std::size_t>(0x100000001B3ULL & (std::numeric_limits<std::size_t>::max)()); h = (h ^ static_cast<unsigned char>(token[i])) * static_cast<std::size_t>(0x100000001B3ULL);
} }
return h ^ (h >> 29u); return h ^ (h >> 29u);
} }
+49 -51
View File
@@ -29,7 +29,6 @@
#endif // JSON_NO_IO #endif // JSON_NO_IO
#include <iterator> // make_move_iterator, random_access_iterator_tag #include <iterator> // make_move_iterator, random_access_iterator_tag
#include <limits> // numeric_limits #include <limits> // numeric_limits
#include <map> // map
#include <memory> // unique_ptr #include <memory> // unique_ptr
#include <set> // swap, operator!= #include <set> // swap, operator!=
#include <stdexcept> // length_error #include <stdexcept> // length_error
@@ -755,20 +754,26 @@ private:
// one level deep); stops at the first structured child it meets // one level deep); stops at the first structured child it meets
static bool all_children_leaves(const basic_json& v) noexcept 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) if (v.m_data.m_type == value_t::array)
{ {
const auto& a = *v.m_data.m_value.array; const auto& a = *v.m_data.m_value.array;
return std::all_of(a.begin(), a.end(), [](const basic_json & el) for (auto it = a.rbegin(); it != a.rend(); ++it)
{ {
return has_no_children(el); if (!has_no_children(*it))
}); {
return false;
}
}
return true;
} }
const auto& o = *v.m_data.m_value.object; for (const auto& el : *v.m_data.m_value.object)
return std::all_of(o.begin(), o.end(), [](const typename object_t::value_type & el)
{ {
return has_no_children(el.second); if (!has_no_children(el.second))
}); {
return false;
}
}
return true;
} }
// The walk in destroy_container() may take the children of a // The walk in destroy_container() may take the children of a
@@ -1225,7 +1230,7 @@ public:
} }
template < typename O = object_t, detail::enable_if_t < detail::has_stable_elements<O>::value, int > = 0 > template < typename O = object_t, detail::enable_if_t < detail::has_stable_elements<O>::value, int > = 0 >
std::size_t object_capacity() const noexcept static constexpr std::size_t object_capacity() noexcept
{ {
return 0; return 0;
} }
@@ -1237,7 +1242,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 > template < typename O = object_t, detail::enable_if_t < !detail::has_stable_elements<O>::value && !detail::is_nlohmann_ordered_map<O>::value, int > = 0 >
std::size_t object_capacity() const noexcept static constexpr std::size_t object_capacity() noexcept
{ {
return detail::unknown_size(); return detail::unknown_size();
} }
@@ -3038,21 +3043,18 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_iterator_range_of_null(const basic_json* obj) 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_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 JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_incompatible_reference_type(const basic_json& obj) 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_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 JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_exceeds_size_type(size_type idx) 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"))); JSON_THROW(std::length_error(detail::concat("array index ", std::to_string(idx), " exceeds size_type")));
} }
@@ -3060,8 +3062,6 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_out_of_range(size_type idx, const basic_json& j) 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)); 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,8 +3070,6 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_key_not_found(const KeyType& key, const basic_json& j) 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)); JSON_THROW(out_of_range::create(detail::exception_id::key_not_found, detail::concat("key '", key, "' not found"), &j));
} }
@@ -4895,19 +4893,19 @@ public:
iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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);
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts element into array
@@ -4915,21 +4913,21 @@ public:
iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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));
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts copies of element into array
@@ -4937,19 +4935,19 @@ public:
iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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);
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts range of elements into array
@@ -5455,7 +5453,7 @@ public:
// inline fast path for two values of the same non-owning scalar type; anything // inline fast path for two values of the same non-owning scalar type; anything
// else falls through to the out-of-line general comparison // else falls through to the out-of-line general comparison
#define JSON_IMPLEMENT_SCALAR_FAST(op, null_result) \ #define JSON_IMPLEMENT_SCALAR_FAST(op, null_result) \
if (lhs.m_data.m_type == rhs.m_data.m_type) /* NOLINT(readability/braces) */ \ if (lhs.m_data.m_type == rhs.m_data.m_type) \
{ \ { \
switch (lhs.m_data.m_type) \ switch (lhs.m_data.m_type) \
{ \ { \
-1
View File
@@ -23,7 +23,6 @@
#include <nlohmann/detail/abi_macros.hpp> #include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/macro_scope.hpp> #include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/type_traits.hpp> #include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/thirdparty/hedley/hedley.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
+67 -100
View File
@@ -29,7 +29,6 @@
#endif // JSON_NO_IO #endif // JSON_NO_IO
#include <iterator> // make_move_iterator, random_access_iterator_tag #include <iterator> // make_move_iterator, random_access_iterator_tag
#include <limits> // numeric_limits #include <limits> // numeric_limits
#include <map> // map
#include <memory> // unique_ptr #include <memory> // unique_ptr
#include <set> // swap, operator!= #include <set> // swap, operator!=
#include <stdexcept> // length_error #include <stdexcept> // length_error
@@ -5795,7 +5794,8 @@ JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE void throw_patch_missing_member(c
static_cast<void>(string_type); static_cast<void>(string_type);
static_cast<void>(val); static_cast<void>(val);
// context-sensitive error message // context-sensitive error message
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat((op == "op") ? std::string("operation") : concat("operation '", op, '\''), string_type ? " must have string member '" : " must have member '", member, "'"), &val)); const std::string error_msg = (op == "op") ? std::string("operation") : concat("operation '", op, '\'');
JSON_THROW(parse_error::create(exception_id::patch_invalid_operation, 0, concat(error_msg, string_type ? " must have string member '" : " must have member '", member, "'"), &val));
} }
template<typename StringType, typename BasicJsonType> template<typename StringType, typename BasicJsonType>
@@ -6555,7 +6555,7 @@ NLOHMANN_JSON_NAMESPACE_END
#include <optional> // optional #include <optional> // optional
#endif #endif
#include <iterator> // begin, end, make_move_iterator, move_iterator #include <iterator> // begin, end
#include <memory> // allocator_traits #include <memory> // allocator_traits
#include <string> // basic_string, char_traits #include <string> // basic_string, char_traits
#include <tuple> // tuple, get #include <tuple> // tuple, get
@@ -7204,32 +7204,6 @@ namespace detail
* leave j with the type of the new value, but the pointer to the destroyed old one. * leave j with the type of the new value, but the pointer to the destroyed old one.
*/ */
// a move iterator over the elements of an rvalue container, unless they are
// const (e.g., std::set): libstdc++ before GCC 5 defines the reference of a
// std::move_iterator as value_type&&, which cannot bind to a const element
template<typename Iterator>
std::move_iterator<Iterator> make_move_iterator_if_mutable_impl(const Iterator& it, std::true_type /*mutable*/)
{
return std::make_move_iterator(it);
}
template<typename Iterator>
Iterator make_move_iterator_if_mutable_impl(const Iterator& it, std::false_type /*mutable*/)
{
return it;
}
template<typename Iterator>
using is_mutable_iterator = std::integral_constant < bool,
!std::is_const<typename std::remove_reference<decltype(*std::declval<Iterator&>())>::type>::value >;
template<typename Iterator>
auto make_move_iterator_if_mutable(const Iterator& it)
-> decltype(make_move_iterator_if_mutable_impl(it, is_mutable_iterator<Iterator> {}))
{
return make_move_iterator_if_mutable_impl(it, is_mutable_iterator<Iterator> {});
}
template<value_t> struct external_constructor; template<value_t> struct external_constructor;
template<> template<>
@@ -7356,7 +7330,7 @@ struct external_constructor<value_t::array>
using std::begin; using std::begin;
using std::end; using std::end;
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(make_move_iterator_if_mutable(begin(arr)), make_move_iterator_if_mutable(end(arr)))); const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(std::make_move_iterator(begin(arr)), std::make_move_iterator(end(arr))));
j.replace_value(value_t::array, value); j.replace_value(value_t::array, value);
} }
@@ -7417,7 +7391,7 @@ struct external_constructor<value_t::object>
using std::begin; using std::begin;
using std::end; using std::end;
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::object_t>(make_move_iterator_if_mutable(begin(obj)), make_move_iterator_if_mutable(end(obj)))); const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::object_t>(std::make_move_iterator(begin(obj)), std::make_move_iterator(end(obj))));
j.replace_value(value_t::object, value); j.replace_value(value_t::object, value);
} }
@@ -7595,27 +7569,25 @@ using is_movable_container_rvalue = negation<disjunction<
std::is_const<T>, std::is_const<T>,
has_dedicated_to_json<T>, has_dedicated_to_json<T>,
is_basic_json<T>, is_basic_json<T>,
is_range_view_type<T>,
is_enum_keyed_map_type<T>, is_enum_keyed_map_type<T>,
std::is_same<T, std::vector<bool>>>>; std::is_same<T, std::vector<bool>>>>;
// rvalue array-like containers; object types are ruled out before views are // rvalue array-like containers
// checked, as std::ranges::view<T> for the object_t of an ordered_json would
// need that ordered_json to be complete (GCC 11, see #3312)
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
using is_rvalue_array_to_json = conjunction<is_movable_container_rvalue<T>, using is_rvalue_array_to_json = conjunction<is_movable_container_rvalue<T>,
negation<is_compatible_object_type<BasicJsonType, T>>,
negation<is_range_view_type<T>>,
is_compatible_array_type<BasicJsonType, T>, is_compatible_array_type<BasicJsonType, T>,
negation<disjunction< negation<disjunction<
std::is_same<T, typename BasicJsonType::array_t>, std::is_same<T, typename BasicJsonType::array_t>,
std::is_same<T, typename BasicJsonType::binary_t>, std::is_same<T, typename BasicJsonType::binary_t>,
is_compatible_object_type<BasicJsonType, T>,
is_compatible_string_type<BasicJsonType, T>, is_compatible_string_type<BasicJsonType, T>,
is_compatible_binary_type<BasicJsonType, T>>>>; is_compatible_binary_type<BasicJsonType, T>>>>;
// rvalue containers: their elements are moved instead of copied // rvalue containers: their elements are moved instead of copied
template<typename BasicJsonType, typename CompatibleArrayType, template<typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_rvalue_array_to_json<BasicJsonType, CompatibleArrayType>::value, int> = 0> enable_if_t<is_rvalue_array_to_json<BasicJsonType, CompatibleArrayType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleArrayType && arr) // NOLINT(cppcoreguidelines-missing-std-forward) inline void to_json(BasicJsonType& j, CompatibleArrayType && arr)
{ {
external_constructor<value_t::array>::construct_moving(j, arr); external_constructor<value_t::array>::construct_moving(j, arr);
} }
@@ -7693,8 +7665,7 @@ inline void to_json(BasicJsonType& j, const EnumKeyedMap& map)
} }
#endif #endif
// rvalue object-like containers (views have no key_type and mapped_type, so // rvalue object-like containers
// they are no compatible object type)
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>, using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>,
negation<std::is_same<T, typename BasicJsonType::object_t>>, negation<std::is_same<T, typename BasicJsonType::object_t>>,
@@ -7702,7 +7673,7 @@ using is_rvalue_object_to_json = conjunction<is_movable_container_rvalue<T>,
template<typename BasicJsonType, typename CompatibleObjectType, template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<is_rvalue_object_to_json<BasicJsonType, CompatibleObjectType>::value, int> = 0> enable_if_t<is_rvalue_object_to_json<BasicJsonType, CompatibleObjectType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleObjectType && obj) // NOLINT(cppcoreguidelines-missing-std-forward) inline void to_json(BasicJsonType& j, CompatibleObjectType && obj)
{ {
external_constructor<value_t::object>::construct_moving(j, obj); external_constructor<value_t::object>::construct_moving(j, obj);
} }
@@ -20744,12 +20715,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{ {
JSON_ASSERT(m_object != nullptr); JSON_ASSERT(m_object != nullptr);
if (JSON_HEDLEY_UNLIKELY(!m_object->is_object())) if (JSON_HEDLEY_LIKELY(m_object->is_object()))
{ {
throw_literal<invalid_iterator>(exception_id::iterator_key_not_object, "cannot use key() for non-object iterators", m_object); return m_it.object_iterator->first;
} }
return m_it.object_iterator->first; throw_literal<invalid_iterator>(exception_id::iterator_key_not_object, "cannot use key() for non-object iterators", m_object);
} }
/*! /*!
@@ -20976,7 +20947,6 @@ NLOHMANN_JSON_NAMESPACE_END
#include <algorithm> // all_of #include <algorithm> // all_of
#include <cctype> // isdigit #include <cctype> // isdigit
#include <cerrno> // errno, ERANGE #include <cerrno> // errno, ERANGE
#include <cstddef> // size_t
#include <cstdlib> // strtoull #include <cstdlib> // strtoull
#ifndef JSON_NO_IO #ifndef JSON_NO_IO
#include <iosfwd> // ostream #include <iosfwd> // ostream
@@ -21307,7 +21277,7 @@ class json_pointer
{ {
break; // not a plain number: let strtoull decide break; // not a plain number: let strtoull decide
} }
acc = static_cast<size_type>((acc * 10) + static_cast<size_type>(c - '0')); acc = static_cast<size_type>(acc * 10 + static_cast<size_type>(c - '0'));
if (JSON_HEDLEY_UNLIKELY(i == s.size() - 1)) if (JSON_HEDLEY_UNLIKELY(i == s.size() - 1))
{ {
idx = acc; idx = acc;
@@ -21502,10 +21472,10 @@ class json_pointer
static std::size_t hash_of(std::size_t parent, const string_t& token) noexcept static std::size_t hash_of(std::size_t parent, const string_t& token) noexcept
{ {
std::size_t h = parent * static_cast<std::size_t>(0x9E3779B97F4A7C15ULL & (std::numeric_limits<std::size_t>::max)()); std::size_t h = parent * static_cast<std::size_t>(0x9E3779B97F4A7C15ULL);
for (std::size_t i = 0; i < token.size(); ++i) for (std::size_t i = 0; i < token.size(); ++i)
{ {
h = (h ^ static_cast<unsigned char>(token[i])) * static_cast<std::size_t>(0x100000001B3ULL & (std::numeric_limits<std::size_t>::max)()); h = (h ^ static_cast<unsigned char>(token[i])) * static_cast<std::size_t>(0x100000001B3ULL);
} }
return h ^ (h >> 29u); return h ^ (h >> 29u);
} }
@@ -26484,7 +26454,7 @@ JSON_HEDLEY_ALWAYS_INLINE shortest_decimal to_shortest(std::uint64_t bits) noexc
const uint128_parts p = umul192_hi128(p10.high, p10.low, bin_sig << static_cast<unsigned>(shift)); const uint128_parts p = umul192_hi128(p10.high, p10.low, bin_sig << static_cast<unsigned>(shift));
std::uint64_t integral = p.high >> static_cast<unsigned>(extra_shift); std::uint64_t integral = p.high >> static_cast<unsigned>(extra_shift);
// (no casts in the shifts: MSVC 2015 warns C4554 on them despite the parentheses) // (no casts in the shifts: MSVC 2015 warns C4554 on them despite the parentheses)
constexpr auto fractional_low_shift = static_cast<unsigned>(extra_shift); constexpr unsigned fractional_low_shift = static_cast<unsigned>(extra_shift);
constexpr unsigned fractional_high_shift = 64u - fractional_low_shift; constexpr unsigned fractional_high_shift = 64u - fractional_low_shift;
const std::uint64_t fractional = (p.high << fractional_high_shift) | (p.low >> fractional_low_shift); const std::uint64_t fractional = (p.high << fractional_high_shift) | (p.low >> fractional_low_shift);
std::uint64_t digit = 0; std::uint64_t digit = 0;
@@ -29734,8 +29704,6 @@ NLOHMANN_JSON_NAMESPACE_END
// #include <nlohmann/detail/meta/type_traits.hpp> // #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN NLOHMANN_JSON_NAMESPACE_BEGIN
@@ -30820,20 +30788,26 @@ private:
// one level deep); stops at the first structured child it meets // one level deep); stops at the first structured child it meets
static bool all_children_leaves(const basic_json& v) noexcept 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) if (v.m_data.m_type == value_t::array)
{ {
const auto& a = *v.m_data.m_value.array; const auto& a = *v.m_data.m_value.array;
return std::all_of(a.begin(), a.end(), [](const basic_json & el) for (auto it = a.rbegin(); it != a.rend(); ++it)
{ {
return has_no_children(el); if (!has_no_children(*it))
}); {
return false;
}
}
return true;
} }
const auto& o = *v.m_data.m_value.object; for (const auto& el : *v.m_data.m_value.object)
return std::all_of(o.begin(), o.end(), [](const typename object_t::value_type & el)
{ {
return has_no_children(el.second); if (!has_no_children(el.second))
}); {
return false;
}
}
return true;
} }
// The walk in destroy_container() may take the children of a // The walk in destroy_container() may take the children of a
@@ -31290,7 +31264,7 @@ public:
} }
template < typename O = object_t, detail::enable_if_t < detail::has_stable_elements<O>::value, int > = 0 > template < typename O = object_t, detail::enable_if_t < detail::has_stable_elements<O>::value, int > = 0 >
std::size_t object_capacity() const noexcept static constexpr std::size_t object_capacity() noexcept
{ {
return 0; return 0;
} }
@@ -31302,7 +31276,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 > template < typename O = object_t, detail::enable_if_t < !detail::has_stable_elements<O>::value && !detail::is_nlohmann_ordered_map<O>::value, int > = 0 >
std::size_t object_capacity() const noexcept static constexpr std::size_t object_capacity() noexcept
{ {
return detail::unknown_size(); return detail::unknown_size();
} }
@@ -33103,21 +33077,18 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_iterator_range_of_null(const basic_json* obj) 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_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 JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_incompatible_reference_type(const basic_json& obj) 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_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 JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_exceeds_size_type(size_type idx) 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"))); JSON_THROW(std::length_error(detail::concat("array index ", std::to_string(idx), " exceeds size_type")));
} }
@@ -33125,8 +33096,6 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_array_index_out_of_range(size_type idx, const basic_json& j) 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)); 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));
} }
@@ -33135,8 +33104,6 @@ public:
JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE JSON_HEDLEY_NO_RETURN JSON_HEDLEY_NEVER_INLINE
static void throw_key_not_found(const KeyType& key, const basic_json& j) 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)); JSON_THROW(out_of_range::create(detail::exception_id::key_not_found, detail::concat("key '", key, "' not found"), &j));
} }
@@ -34960,19 +34927,19 @@ public:
iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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);
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts element into array
@@ -34980,21 +34947,21 @@ public:
iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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));
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts copies of element into array
@@ -35002,19 +34969,19 @@ public:
iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param) iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
{ {
// insert only works for arrays // insert only works for arrays
if (JSON_HEDLEY_UNLIKELY(!is_array())) if (JSON_HEDLEY_LIKELY(is_array()))
{ {
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);
} }
// check if iterator pos fits to this JSON value detail::throw_cannot_use_with(detail::exception_id::insert_wrong_type, "insert()", *this);
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 /// @brief inserts range of elements into array
@@ -35520,7 +35487,7 @@ public:
// inline fast path for two values of the same non-owning scalar type; anything // inline fast path for two values of the same non-owning scalar type; anything
// else falls through to the out-of-line general comparison // else falls through to the out-of-line general comparison
#define JSON_IMPLEMENT_SCALAR_FAST(op, null_result) \ #define JSON_IMPLEMENT_SCALAR_FAST(op, null_result) \
if (lhs.m_data.m_type == rhs.m_data.m_type) /* NOLINT(readability/braces) */ \ if (lhs.m_data.m_type == rhs.m_data.m_type) \
{ \ { \
switch (lhs.m_data.m_type) \ switch (lhs.m_data.m_type) \
{ \ { \
+7 -7
View File
@@ -198,11 +198,11 @@ TEST_CASE("copy constructor and destructor across value types")
const json src_uint = 7u; const json src_uint = 7u;
const json src_float = 2.5; const json src_float = 2.5;
json c_null(src_null); // NOLINT(performance-unnecessary-copy-initialization): tests the copy constructor json c_null(src_null);
json c_bool(src_bool); // NOLINT(performance-unnecessary-copy-initialization): tests the copy constructor json c_bool(src_bool);
json c_int(src_int); // NOLINT(performance-unnecessary-copy-initialization): tests the copy constructor json c_int(src_int);
json c_uint(src_uint); // NOLINT(performance-unnecessary-copy-initialization): tests the copy constructor json c_uint(src_uint);
json c_float(src_float); // NOLINT(performance-unnecessary-copy-initialization): tests the copy constructor json c_float(src_float);
CHECK(c_null.is_null()); CHECK(c_null.is_null());
CHECK(c_bool == true); CHECK(c_bool == true);
@@ -300,12 +300,12 @@ TEST_CASE("copy constructor and destructor across value types")
REQUIRE(v.size() == 70); REQUIRE(v.size() == 70);
std::vector<json> copy(v); std::vector<json> copy(v);
CHECK((copy == v)); CHECK(copy == v);
// mutating the copy leaves the original alone // mutating the copy leaves the original alone
copy[5] = "changed"; copy[5] = "changed";
copy[6].push_back(1); copy[6].push_back(1);
CHECK((copy != v)); CHECK(copy != v);
CHECK(v[5] == std::string(5, 'x')); CHECK(v[5] == std::string(5, 'x'));
CHECK(v[6].size() == 3); CHECK(v[6].size() == 3);
+2 -2
View File
@@ -817,8 +817,8 @@ template<class Key, class T, class IgnoredLess = std::less<Key>,
struct relocating_map : nlohmann::ordered_map<Key, T, IgnoredLess, Allocator> struct relocating_map : nlohmann::ordered_map<Key, T, IgnoredLess, Allocator>
{ {
using base_type = nlohmann::ordered_map<Key, T, IgnoredLess, Allocator>; using base_type = nlohmann::ordered_map<Key, T, IgnoredLess, Allocator>;
using iterator = typename base_type::iterator; using typename base_type::iterator;
using Container = typename base_type::Container; using typename base_type::Container;
using base_type::base_type; using base_type::base_type;
template<typename... Args> template<typename... Args>
+4 -5
View File
@@ -1637,7 +1637,6 @@ TEST_CASE_TEMPLATE("reverse iteration and member access", Json, nlohmann::json,
{ {
Json j = {1, 2, 3, 4}; Json j = {1, 2, 3, 4};
const std::vector<int> reversed = {4, 3, 2, 1};
auto it = j.end(); auto it = j.end();
std::vector<int> seen; std::vector<int> seen;
while (it != j.begin()) while (it != j.begin())
@@ -1645,7 +1644,7 @@ TEST_CASE_TEMPLATE("reverse iteration and member access", Json, nlohmann::json,
--it; --it;
seen.push_back(it->template get<int>()); seen.push_back(it->template get<int>());
} }
CHECK(seen == reversed); CHECK(seen == std::vector<int> {4, 3, 2, 1});
auto it2 = j.end(); auto it2 = j.end();
auto old = it2--; auto old = it2--;
@@ -1657,14 +1656,14 @@ TEST_CASE_TEMPLATE("reverse iteration and member access", Json, nlohmann::json,
{ {
seen.push_back(r->template get<int>()); seen.push_back(r->template get<int>());
} }
CHECK(seen == reversed); CHECK(seen == std::vector<int> {4, 3, 2, 1});
seen.clear(); seen.clear();
for (auto r = j.crbegin(); r != j.crend(); ++r) for (auto r = j.crbegin(); r != j.crend(); ++r)
{ {
seen.push_back(r->template get<int>()); seen.push_back(*r);
} }
CHECK(seen == reversed); CHECK(seen == std::vector<int> {4, 3, 2, 1});
} }
SECTION("object: -- and rbegin/rend") SECTION("object: -- and rbegin/rend")
+2 -2
View File
@@ -1230,11 +1230,11 @@ TEST_CASE("JSON pointer array index tokens match strtoull semantics")
SECTION("random tokens") SECTION("random tokens")
{ {
std::mt19937 gen(42); // NOLINT(cert-msc32-c,cert-msc51-cpp,bugprone-random-generator-seed): reproducible std::mt19937 gen(42);
const std::string alphabet = "0123456789012345678901234567890123456789-+ ex"; const std::string alphabet = "0123456789012345678901234567890123456789-+ ex";
for (int i = 0; i < 5000; ++i) for (int i = 0; i < 5000; ++i)
{ {
std::string token(gen() % 23, '0'); std::string token(static_cast<std::size_t>(gen() % 23), '0');
for (auto& c : token) for (auto& c : token)
{ {
c = alphabet[gen() % alphabet.size()]; c = alphabet[gen() % alphabet.size()];
+2 -8
View File
@@ -1374,13 +1374,7 @@ void check_dump_against_reference(const std::string& s, const bool with_strict =
}; };
for (const auto error_handler : error_handlers) for (const auto error_handler : error_handlers)
{ {
#if defined(JSON_NOEXCEPTION)
// a strict dump of invalid UTF-8 calls std::abort() instead of throwing
static_cast<void>(with_strict);
if (error_handler == json::error_handler_t::strict)
#else
if (!with_strict && error_handler == json::error_handler_t::strict) if (!with_strict && error_handler == json::error_handler_t::strict)
#endif
{ {
continue; continue;
} }
@@ -1435,7 +1429,7 @@ TEST_CASE("invalid UTF-8 at every position is handled like the reference")
"\xF4\x90\x80\x80", "\xF4\x90\x80\x80",
// sequences cut short by ASCII, a control character, a quote, a // sequences cut short by ASCII, a control character, a quote, a
// backslash, DEL, or the lead byte of a well-formed character // backslash, DEL, or the lead byte of a well-formed character
"\xC3" "a", "\xE2\x82" "\n", "\xE2\x82\"", "\xF0\x9F\x98\\", "\xC3\x7F", "\xC3\xC3\xA4", "\xE2\xF0\x9F\x98\x80", // NOLINT(bugprone-suspicious-missing-comma): "\xC3" "a" ends the hex escape "\xC3" "a", "\xE2\x82" "\n", "\xE2\x82\"", "\xF0\x9F\x98\\", "\xC3\x7F", "\xC3\xC3\xA4", "\xE2\xF0\x9F\x98\x80",
// truncated sequences // truncated sequences
"\xC3", "\xE2\x82", "\xF0\x9F\x98" "\xC3", "\xE2\x82", "\xF0\x9F\x98"
}; };
@@ -1495,7 +1489,7 @@ TEST_CASE("invalid UTF-8 at every position is handled like the reference")
{ {
for (const auto& pattern : patterns) for (const auto& pattern : patterns)
{ {
check_dump_against_reference(make_string(filler, pos, pattern, length - pos), bytes <= (filler.size() == 1 ? 17u : 8u)); check_dump_against_reference(make_string(filler, pos, pattern, length - pos), bytes <= (filler.size() == 1 ? 17 : 8));
} }
} }
} }
-4
View File
@@ -218,11 +218,7 @@ TEST_CASE("compliance tests from nativejson-benchmark")
n1e308[0] = '['; n1e308[0] = '[';
n1e308[1] = '1'; n1e308[1] = '1';
n1e308[310] = ']'; n1e308[310] = ']';
#if JSON_STRICT_NUL_HANDLING
n1e308.pop_back(); // a NUL byte after the value is a syntax error in strict mode
#else
n1e308[311] = '\0'; n1e308[311] = '\0';
#endif
TEST_DOUBLE(n1e308, 1E308); TEST_DOUBLE(n1e308, 1E308);
} }
+9 -18
View File
@@ -54,8 +54,8 @@ TEST_CASE("exception messages of out-of-line throw sites")
SECTION("at") SECTION("at")
{ {
const json& carr = arr; const json carr = arr;
const json& cobj = obj; const json cobj = obj;
CHECK_MSG((void)arr.at(static_cast<json::size_type>(10)), "[json.exception.out_of_range.401] array index 10 is out of range"); CHECK_MSG((void)arr.at(static_cast<json::size_type>(10)), "[json.exception.out_of_range.401] array index 10 is out of range");
CHECK_MSG((void)carr.at(static_cast<json::size_type>(3)), "[json.exception.out_of_range.401] array index 3 is out of range"); CHECK_MSG((void)carr.at(static_cast<json::size_type>(3)), "[json.exception.out_of_range.401] array index 3 is out of range");
CHECK_MSG((void)num.at(static_cast<json::size_type>(0)), "[json.exception.type_error.304] cannot use at() with number"); CHECK_MSG((void)num.at(static_cast<json::size_type>(0)), "[json.exception.type_error.304] cannot use at() with number");
@@ -65,7 +65,7 @@ TEST_CASE("exception messages of out-of-line throw sites")
CHECK_MSG((void)num.at("a"), "[json.exception.type_error.304] cannot use at() with number"); CHECK_MSG((void)num.at("a"), "[json.exception.type_error.304] cannot use at() with number");
nlohmann::ordered_json oobj = {{"a", 1}}; nlohmann::ordered_json oobj = {{"a", 1}};
const nlohmann::ordered_json& coobj = oobj; const nlohmann::ordered_json coobj = oobj;
CHECK_MSG((void)oobj.at("z"), "[json.exception.out_of_range.403] key 'z' not found"); CHECK_MSG((void)oobj.at("z"), "[json.exception.out_of_range.403] key 'z' not found");
CHECK_MSG((void)coobj.at("z"), "[json.exception.out_of_range.403] key 'z' not found"); CHECK_MSG((void)coobj.at("z"), "[json.exception.out_of_range.403] key 'z' not found");
CHECK_MSG((void)coobj.at(std::string("zz")), "[json.exception.out_of_range.403] key 'zz' not found"); CHECK_MSG((void)coobj.at(std::string("zz")), "[json.exception.out_of_range.403] key 'zz' not found");
@@ -94,10 +94,9 @@ TEST_CASE("exception messages of out-of-line throw sites")
CHECK_MSG(obj.update(arr.begin(), arr2.end()), "[json.exception.invalid_iterator.210] iterators do not fit"); CHECK_MSG(obj.update(arr.begin(), arr2.end()), "[json.exception.invalid_iterator.210] iterators do not fit");
} }
#if !defined(JSON_NOEXCEPTION) // patch_msg() catches the exceptions, which JSON_NOEXCEPTION turns into std::abort()
SECTION("patch") SECTION("patch")
{ {
const auto patch_msg = [](const char* doc, const char* patch) -> std::string const auto patch_msg = [](const char* doc, const char* patch)
{ {
try try
{ {
@@ -106,23 +105,16 @@ TEST_CASE("exception messages of out-of-line throw sites")
} }
catch (const json::exception& e) catch (const json::exception& e)
{ {
// with JSON_DIAGNOSTICS, what() names the offending value like "(/0) ", // with JSON_DIAGNOSTICS, what() names the offending value like "(/0) "; drop it
// and with JSON_DIAGNOSTIC_POSITIONS its position like "(bytes 0-2) "; drop both
std::string msg = e.what(); std::string msg = e.what();
for (const char* marker : const auto pos = msg.find(" (/");
{ if (pos != std::string::npos)
" (/", " (bytes "
})
{ {
const auto pos = msg.find(marker); msg.erase(pos + 1, msg.find(") ", pos) - pos + 1);
if (pos != std::string::npos)
{
msg.erase(pos + 1, msg.find(") ", pos) - pos + 1);
}
} }
return msg; return msg;
} }
return {}; return std::string();
}; };
CHECK(patch_msg("{}", "{}") == "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects"); CHECK(patch_msg("{}", "{}") == "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects");
@@ -140,5 +132,4 @@ TEST_CASE("exception messages of out-of-line throw sites")
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"test\",\"path\":\"/a\",\"value\":2}]") == "[json.exception.other_error.501] unsuccessful: {\"op\":\"test\",\"path\":\"/a\",\"value\":2}"); CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"test\",\"path\":\"/a\",\"value\":2}]") == "[json.exception.other_error.501] unsuccessful: {\"op\":\"test\",\"path\":\"/a\",\"value\":2}");
CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"move\",\"path\":\"/a\"}]") == "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'"); CHECK(patch_msg("{\"a\":1}", "[{\"op\":\"move\",\"path\":\"/a\"}]") == "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'");
} }
#endif
} }