Compare commits

...
Author SHA1 Message Date
Niels Lohmann 0c0d5edda3 Make insert(pos, basic_json&&) move its argument instead of copying it
insert(const_iterator pos, basic_json&& val) delegated to
insert(pos, val), but val is a named rvalue reference, so inside the
function it is an lvalue: the call always resolved to
insert(const_iterator, const basic_json&) and deep-copied the value.
This has been the case since the overload was introduced, in every
release. push_back(basic_json&&), by contrast, already moves.

Give the rvalue overload its own body with the same two checks
(type_error.309, invalid_iterator.202), then move the argument into a
local before inserting it. Moving into a local first, rather than
inserting std::move(val) directly, keeps this safe even when val
aliases an element of the same array (e.g.
arr.insert(arr.begin(), std::move(arr[1]))), since
std::vector::insert(pos, T&&) is not guaranteed to handle an argument
that aliases one of its own elements.

This is a deliberate, small behavior change: the moved-from argument
now ends up null afterwards, the same as after push_back(&&), instead
of keeping its old value unchanged. No signature changes, so the
public API and ABI are unaffected. Add unit-modifiers coverage for
the moved-from state and for self-aliasing insertion, both with and
without reallocation of the underlying array.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 11:11:16 +02:00
Niels Lohmann ff2ec8116d Deduplicate the 16 copied from_cbor/msgpack/ubjson/bjdata/bon8/bson bodies
Each of the 16 binary deserialization overloads (from_cbor,
from_msgpack, from_ubjson, from_bjdata, from_bon8, from_bson, each in
an InputType&& and an iterator/sentinel version, plus the deprecated
span overloads of from_cbor/from_msgpack/from_ubjson/from_bson) had
the same body, differing only in the input_format_t value. Every copy
built a temporary binary_reader from std::move(ia) and called
sax_parse on it in the same expression, which also produced a
false-positive cppcheck accessMoved on all 16 lines and needed a
NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) on
the four span overloads.

Add a private from_binary_impl() helper that builds the reader as a
named local instead, and make each of the 16 overloads a one-line
forward to it. All public signatures, default arguments,
JSON_HEDLEY_WARN_UNUSED_RESULT and JSON_HEDLEY_DEPRECATED_FOR
attributes are unchanged, tag_handler keeps defaulting to
cbor_tag_handler_t::error for the non-CBOR formats (matching
binary_reader::sax_parse's own default), and the helper is placed in
the existing private section before the binary section banner rather
than between the from_* overloads, so from_binary_impl() itself does
not collide with #5688's insertion point. Collapsing the
from_bjdata/from_bon8 bodies into one-line forwards does rewrite the
"return result; }" context lines that #5688 inserts its two
deprecated overloads after, so that PR will need a small manual
rebase (reinserting its overloads after the new one-line bodies)
rather than applying cleanly.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 11:11:15 +02:00
Niels Lohmann b591304d04 Fix stale and copy-pasted comments in basic_json
Several comments no longer match the code: the class invariant and
assert_invariant()'s doc still named the members m_value/m_type
(now m_data.m_value/m_data.m_type) and did not mention the binary
invariant that assert_invariant() already checks; the json_value note
and the get<PointerType>() @tparam list omitted binary_t even though
binary is a variable-length, pointer-stored type like the others; the
key-based value() overload's brief said "via JSON Pointer", which is
the other overload; and swap(binary_t&)/swap(binary_t::container_type&)
both carried "swap only works for strings", copied from swap(string_t&).

Comment-only change; behavior, the public API and the ABI are
unchanged. The private get_impl() doxygen and the emplace() comments
that border #5585's hunk are intentionally left alone.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:42:29 +02:00
Niels Lohmann c2553bac5a Deduplicate the string/binary cleanup in the two erase() overloads
erase(pos) and erase(first, last) each carried a byte-identical
14-line block that destroys and deallocates a string or binary
value before resetting the type to null. That reimplements the
string/binary cases of json_value::destroy(), so any future change to
how those values are freed would have to be made in three places
instead of one. Both overloads now just call destroy() and reset the
union; for the other primitive types (boolean, numbers) destroy() is
a no-op, so behavior is unchanged.

Also fix erase(first, last)'s error-path branch hint, which used
JSON_HEDLEY_LIKELY where erase(pos), the iterator-range constructor,
and every other error path in the class use JSON_HEDLEY_UNLIKELY.
This only affects code layout, not semantics.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:40:04 +02:00
Niels Lohmann 1274e0f250 Remove stale cppcheck suppressions and name the local parser in parse()
Running the pinned cppcheck (ci_cppcheck's invocation) without
--inline-suppr across all configurations reports no syntaxError, no
ignoredReturnValue and no assertWithSideEffect, so the corresponding
suppressions in json_fwd.hpp, string_concat.hpp and
assert_invariant() no longer match anything (json_fwd.hpp's is kept,
since downstream users who run an older cppcheck against it could
still hit the warning it once silenced).

The three basic_json::parse() overloads still trigger a false-positive
accessMoved/accessForwarded because they build a temporary parser and
call .parse() on it in the same expression; giving that parser a name
makes the warning go away without changing behavior, and removes the
last of the inline suppressions on these functions.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:37:48 +02:00
Niels Lohmann ffd3a3722b Remove four cppcheck accessForwarded suppressions in the move constructor
basic_json(basic_json&&) built its base subobject with
std::forward<json_base_class_t>(other), so cppcheck saw the whole of
other as forwarded and flagged every subsequent access to it as
accessForwarded, three of them still marked "TODO check". Only the
base subobject is actually moved from; cast explicitly to the base
type instead, the way ordered_map already does, so cppcheck can tell
the two are unrelated. Behavior is unchanged: for a non-reference T,
std::forward<T>(x) is defined as static_cast<T&&>(x).

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:36:41 +02:00
Niels Lohmann f5e4b9b8cf Stop the noexcept null constructor delegating to a throwing one
basic_json(std::nullptr_t) delegated to basic_json(value_t), whose
underlying json_value(value_t) constructor allocates for other types
and can therefore throw, which is why the noexcept had a
NOLINT(bugprone-exception-escape). The delegated-to constructor also
called assert_invariant() a second time. The default member
initializers of data already produce the same null state (a
value-initialized, i.e. zeroed, union with object == nullptr), so the
delegation and its NOLINT can simply be dropped.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:34:05 +02:00
Niels Lohmann e5c3e81279 Fix meta()'s dead, syntactically invalid HP aCC branch
The HP aCC branch of basic_json::meta() was missing a semicolon and
has therefore never compiled; adding only a semicolon would also make
it throw type_error.305, since it assigned a plain string to
result["compiler"] and then indexed into it like the other branches
do into an object. Make the branch consistent with the others by
assigning an object with "family" and "version" keys, narrow the
condition to __HP_aCC (a C compiler cannot build this header-only
library), and fix meta.md, which documented the old (impossible)
plain-string behavior.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 10:32:07 +02:00
Niels Lohmann 1d98396a19 Remove unused private aliases from basic_json
The private aliases primitive_iterator_t, internal_iterator and
output_adapter_t are not used anywhere: iter_impl, binary_writer and
the tests refer to the detail:: names directly. As the aliases are
private, no user or derived class can depend on them. The
internal_iterator.hpp include stays because iter_impl needs it.

Part of #5724

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-30 09:47:00 +02:00
5 changed files with 226 additions and 397 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ JSON object holding version information
| key | description |
|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). On HP aCC compilers, `compiler` is instead the plain string `hp`. |
| `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `hp`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). |
| `copyright` | The copyright line for the library as string. |
| `name` | The name of the library as string. |
| `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. |
@@ -39,7 +39,6 @@ inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
{
// cppcheck-suppress ignoredReturnValue
return ::strlen(cstr) + concat_length(rest...);
}
+91 -197
View File
@@ -110,11 +110,12 @@ struct is_std_optional<std::optional<T>> : std::true_type {};
@brief a class to store JSON values
@internal
@invariant The member variables @a m_value and @a m_type have the following
relationship:
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
@invariant The member variables @a m_data.m_value and @a m_data.m_type have
the following relationship:
- If `m_data.m_type == value_t::object`, then `m_data.m_value.object != nullptr`.
- If `m_data.m_type == value_t::array`, then `m_data.m_value.array != nullptr`.
- If `m_data.m_type == value_t::string`, then `m_data.m_value.string != nullptr`.
- If `m_data.m_type == value_t::binary`, then `m_data.m_value.binary != nullptr`.
The invariants are checked by member function assert_invariant().
@note ObjectType trick from https://stackoverflow.com/a/9860911
@@ -174,18 +175,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
private:
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
template<typename BasicJsonType>
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
template<typename BasicJsonType>
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
template<typename Iterator>
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
template<typename CharType>
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
template<typename InputType>
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
@@ -326,8 +321,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
std::to_string(__GNUC_PATCHLEVEL__))
}
};
#elif defined(__HP_cc) || defined(__HP_aCC)
result["compiler"] = "hp"
#elif defined(__HP_aCC)
result["compiler"] = {{"family", "hp"}, {"version", __HP_aCC}};
#elif defined(__IBMCPP__)
result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
#elif defined(_MSC_VER)
@@ -469,9 +464,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
binary | binary | pointer to @ref binary_t
null | null | *no value is stored*
@note Variable-length types (objects, arrays, and strings) are stored as
pointers. The size of the union should not exceed 64 bits if the default
value types are used.
@note Variable-length types (objects, arrays, strings, and binary
values) are stored as pointers. The size of the union should not exceed
64 bits if the default value types are used.
@since version 1.0.0
*/
@@ -723,7 +718,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
end of every constructor to make sure that created objects respect the
invariant. Furthermore, it has to be called each time the type of a JSON
value is changed, because the invariant expresses a relationship between
@a m_type and @a m_value.
@a m_data.m_type and @a m_data.m_value.
Furthermore, the parent relation is checked for arrays and objects: If
@a check_parents true and the value is an array or object, then the
@@ -744,7 +739,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#if JSON_DIAGNOSTICS
JSON_TRY
{
// cppcheck-suppress assertWithSideEffect
JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
{
return j.m_parent == this;
@@ -1584,8 +1578,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief create a null object
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
: basic_json(value_t::null)
basic_json(std::nullptr_t = nullptr) noexcept
{
assert_invariant();
}
@@ -1949,15 +1942,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief move constructor
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(basic_json&& other) noexcept
: json_base_class_t(std::forward<json_base_class_t>(other)),
m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
: json_base_class_t(std::move(static_cast<json_base_class_t&>(other))),
m_data(std::move(other.m_data))
#if JSON_DIAGNOSTIC_POSITIONS
, start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
, end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
, start_position(other.start_position)
, end_position(other.end_position)
#endif
{
// check that the passed value is valid
other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
other.assert_invariant(false);
// invalidate payload
other.m_data.m_type = value_t::null;
@@ -2524,7 +2517,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@ref number_unsigned_t, @ref number_float_t, or @ref binary_t.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@@ -3050,7 +3043,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
}
/// @brief access specified object element via JSON Pointer with default value
/// @brief access specified object element with default value
/// @sa https://json.nlohmann.me/api/basic_json/value/
template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
detail::enable_if_t <
@@ -3208,21 +3201,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
}
if (is_string())
{
AllocatorType<string_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
m_data.m_value.string = nullptr;
}
else if (is_binary())
{
AllocatorType<binary_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
m_data.m_value.binary = nullptr;
}
m_data.m_value.destroy(m_data.m_type);
m_data.m_value = {};
m_data.m_type = value_t::null;
assert_invariant();
break;
@@ -3274,27 +3254,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::string:
case value_t::binary:
{
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
}
if (is_string())
{
AllocatorType<string_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
m_data.m_value.string = nullptr;
}
else if (is_binary())
{
AllocatorType<binary_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
m_data.m_value.binary = nullptr;
}
m_data.m_value.destroy(m_data.m_type);
m_data.m_value = {};
m_data.m_type = value_t::null;
assert_invariant();
break;
@@ -4076,7 +4043,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{
return insert(std::move(pos), val);
// insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
{
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
JSON_THROW(invalid_iterator::create(202, "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));
}
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts copies of element into array
@@ -4417,7 +4399,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/swap/
void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
{
// swap only works for strings
// swap only works for binary values
if (JSON_HEDLEY_LIKELY(is_binary()))
{
using std::swap;
@@ -4433,7 +4415,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/swap/
void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
{
// swap only works for strings
// swap only works for binary values
if (JSON_HEDLEY_LIKELY(is_binary()))
{
using std::swap;
@@ -4913,7 +4895,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
auto p = parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -4930,7 +4913,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
auto p = parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -4943,7 +4927,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
auto p = parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -5151,6 +5136,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
#endif
private:
/*!
@brief shared implementation of the binary from_cbor/from_msgpack/
from_ubjson/from_bjdata/from_bon8/from_bson overloads
Building the @ref binary_reader as a named local, rather than as a
temporary that @ref detail::json_sax_dom_parser::parse is called on in
the same expression, avoids a false-positive cppcheck accessMoved
warning in each of the 16 callers.
*/
template<typename InputAdapterType>
static basic_json from_binary_impl(InputAdapterType ia, const input_format_t format,
const bool strict, const bool allow_exceptions,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
detail::json_sax_dom_parser<basic_json, InputAdapterType> sdp(result, allow_exceptions);
binary_reader<InputAdapterType> reader(std::move(ia), format);
if (!reader.sax_parse(format, &sdp, strict, tag_handler))
{
result = value_t::discarded;
}
return result;
}
//////////////////////////////////////////
// binary serialization/deserialization //
//////////////////////////////////////////
@@ -5323,14 +5333,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5343,14 +5346,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
template<typename T>
@@ -5371,15 +5367,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
/// @brief create a JSON value from an input in MessagePack format
@@ -5390,14 +5378,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::msgpack, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5409,14 +5390,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::msgpack, strict, allow_exceptions);
}
template<typename T>
@@ -5435,15 +5409,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in UBJSON format
@@ -5454,14 +5420,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::ubjson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5473,14 +5432,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::ubjson, strict, allow_exceptions);
}
template<typename T>
@@ -5499,15 +5451,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BJData format
@@ -5518,14 +5462,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bjdata, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5537,14 +5474,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BON8 format
@@ -5555,14 +5485,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bon8).sax_parse(input_format_t::bon8, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bon8, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BON8 format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5574,14 +5497,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bon8).sax_parse(input_format_t::bon8, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BSON format
@@ -5592,14 +5508,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -5611,14 +5520,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bson, strict, allow_exceptions);
}
template<typename T>
@@ -5637,15 +5539,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions);
}
/// @}
+91 -198
View File
@@ -5029,7 +5029,6 @@ inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
{
// cppcheck-suppress ignoredReturnValue
return ::strlen(cstr) + concat_length(rest...);
}
@@ -26191,11 +26190,12 @@ struct is_std_optional<std::optional<T>> : std::true_type {};
@brief a class to store JSON values
@internal
@invariant The member variables @a m_value and @a m_type have the following
relationship:
- If `m_type == value_t::object`, then `m_value.object != nullptr`.
- If `m_type == value_t::array`, then `m_value.array != nullptr`.
- If `m_type == value_t::string`, then `m_value.string != nullptr`.
@invariant The member variables @a m_data.m_value and @a m_data.m_type have
the following relationship:
- If `m_data.m_type == value_t::object`, then `m_data.m_value.object != nullptr`.
- If `m_data.m_type == value_t::array`, then `m_data.m_value.array != nullptr`.
- If `m_data.m_type == value_t::string`, then `m_data.m_value.string != nullptr`.
- If `m_data.m_type == value_t::binary`, then `m_data.m_value.binary != nullptr`.
The invariants are checked by member function assert_invariant().
@note ObjectType trick from https://stackoverflow.com/a/9860911
@@ -26255,18 +26255,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
private:
using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
template<typename BasicJsonType>
using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
template<typename BasicJsonType>
using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
template<typename Iterator>
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
template<typename CharType>
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
template<typename InputType>
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
@@ -26407,8 +26401,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
std::to_string(__GNUC_PATCHLEVEL__))
}
};
#elif defined(__HP_cc) || defined(__HP_aCC)
result["compiler"] = "hp"
#elif defined(__HP_aCC)
result["compiler"] = {{"family", "hp"}, {"version", __HP_aCC}};
#elif defined(__IBMCPP__)
result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
#elif defined(_MSC_VER)
@@ -26550,9 +26544,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
binary | binary | pointer to @ref binary_t
null | null | *no value is stored*
@note Variable-length types (objects, arrays, and strings) are stored as
pointers. The size of the union should not exceed 64 bits if the default
value types are used.
@note Variable-length types (objects, arrays, strings, and binary
values) are stored as pointers. The size of the union should not exceed
64 bits if the default value types are used.
@since version 1.0.0
*/
@@ -26804,7 +26798,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
end of every constructor to make sure that created objects respect the
invariant. Furthermore, it has to be called each time the type of a JSON
value is changed, because the invariant expresses a relationship between
@a m_type and @a m_value.
@a m_data.m_type and @a m_data.m_value.
Furthermore, the parent relation is checked for arrays and objects: If
@a check_parents true and the value is an array or object, then the
@@ -26825,7 +26819,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#if JSON_DIAGNOSTICS
JSON_TRY
{
// cppcheck-suppress assertWithSideEffect
JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
{
return j.m_parent == this;
@@ -27665,8 +27658,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief create a null object
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
: basic_json(value_t::null)
basic_json(std::nullptr_t = nullptr) noexcept
{
assert_invariant();
}
@@ -28030,15 +28022,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @brief move constructor
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(basic_json&& other) noexcept
: json_base_class_t(std::forward<json_base_class_t>(other)),
m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
: json_base_class_t(std::move(static_cast<json_base_class_t&>(other))),
m_data(std::move(other.m_data))
#if JSON_DIAGNOSTIC_POSITIONS
, start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
, end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
, start_position(other.start_position)
, end_position(other.end_position)
#endif
{
// check that the passed value is valid
other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
other.assert_invariant(false);
// invalidate payload
other.m_data.m_type = value_t::null;
@@ -28605,7 +28597,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@ref number_unsigned_t, @ref number_float_t, or @ref binary_t.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@@ -29131,7 +29123,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
}
/// @brief access specified object element via JSON Pointer with default value
/// @brief access specified object element with default value
/// @sa https://json.nlohmann.me/api/basic_json/value/
template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
detail::enable_if_t <
@@ -29289,21 +29281,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
}
if (is_string())
{
AllocatorType<string_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
m_data.m_value.string = nullptr;
}
else if (is_binary())
{
AllocatorType<binary_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
m_data.m_value.binary = nullptr;
}
m_data.m_value.destroy(m_data.m_type);
m_data.m_value = {};
m_data.m_type = value_t::null;
assert_invariant();
break;
@@ -29355,27 +29334,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
case value_t::string:
case value_t::binary:
{
if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|| !last.m_it.primitive_iterator.is_end()))
{
JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
}
if (is_string())
{
AllocatorType<string_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
m_data.m_value.string = nullptr;
}
else if (is_binary())
{
AllocatorType<binary_t> alloc;
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
m_data.m_value.binary = nullptr;
}
m_data.m_value.destroy(m_data.m_type);
m_data.m_value = {};
m_data.m_type = value_t::null;
assert_invariant();
break;
@@ -30157,7 +30123,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/insert/
iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
{
return insert(std::move(pos), val);
// insert only works for arrays
if (JSON_HEDLEY_LIKELY(is_array()))
{
// check if iterator pos fits to this JSON value
if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
{
JSON_THROW(invalid_iterator::create(202, "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));
}
JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
}
/// @brief inserts copies of element into array
@@ -30498,7 +30479,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/swap/
void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
{
// swap only works for strings
// swap only works for binary values
if (JSON_HEDLEY_LIKELY(is_binary()))
{
using std::swap;
@@ -30514,7 +30495,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/swap/
void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
{
// swap only works for strings
// swap only works for binary values
if (JSON_HEDLEY_LIKELY(is_binary()))
{
using std::swap;
@@ -30994,7 +30975,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
auto p = parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -31011,7 +30993,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
auto p = parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -31024,7 +31007,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_trailing_commas = false)
{
basic_json result;
parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
auto p = parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
p.parse(true, result);
return result;
}
@@ -31232,6 +31216,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
}
#endif
private:
/*!
@brief shared implementation of the binary from_cbor/from_msgpack/
from_ubjson/from_bjdata/from_bon8/from_bson overloads
Building the @ref binary_reader as a named local, rather than as a
temporary that @ref detail::json_sax_dom_parser::parse is called on in
the same expression, avoids a false-positive cppcheck accessMoved
warning in each of the 16 callers.
*/
template<typename InputAdapterType>
static basic_json from_binary_impl(InputAdapterType ia, const input_format_t format,
const bool strict, const bool allow_exceptions,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
detail::json_sax_dom_parser<basic_json, InputAdapterType> sdp(result, allow_exceptions);
binary_reader<InputAdapterType> reader(std::move(ia), format);
if (!reader.sax_parse(format, &sdp, strict, tag_handler))
{
result = value_t::discarded;
}
return result;
}
//////////////////////////////////////////
// binary serialization/deserialization //
//////////////////////////////////////////
@@ -31404,14 +31413,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31424,14 +31426,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
template<typename T>
@@ -31452,15 +31447,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::cbor, strict, allow_exceptions, tag_handler);
}
/// @brief create a JSON value from an input in MessagePack format
@@ -31471,14 +31458,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::msgpack, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31490,14 +31470,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::msgpack, strict, allow_exceptions);
}
template<typename T>
@@ -31516,15 +31489,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::msgpack, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in UBJSON format
@@ -31535,14 +31500,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::ubjson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31554,14 +31512,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::ubjson, strict, allow_exceptions);
}
template<typename T>
@@ -31580,15 +31531,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::ubjson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BJData format
@@ -31599,14 +31542,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bjdata, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31618,14 +31554,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bjdata, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BON8 format
@@ -31636,14 +31565,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bon8).sax_parse(input_format_t::bon8, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bon8, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BON8 format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31655,14 +31577,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bon8).sax_parse(input_format_t::bon8, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bon8, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BSON format
@@ -31673,14 +31588,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::forward<InputType>(i));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::forward<InputType>(i)), input_format_t::bson, strict, allow_exceptions);
}
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
@@ -31692,14 +31600,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = detail::input_adapter(std::move(first), std::move(last));
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(detail::input_adapter(std::move(first), std::move(last)), input_format_t::bson, strict, allow_exceptions);
}
template<typename T>
@@ -31718,15 +31619,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool strict = true,
const bool allow_exceptions = true)
{
basic_json result;
auto ia = i.get();
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
{
result = value_t::discarded;
}
return result;
return from_binary_impl(i.get(), input_format_t::bson, strict, allow_exceptions);
}
/// @}
+43
View File
@@ -618,6 +618,49 @@ TEST_CASE("modifiers")
}
}
SECTION("rvalue at position moves rather than copies")
{
// regression test: insert(pos, basic_json&&) used to forward to
// insert(pos, const basic_json&) because the named rvalue
// reference parameter is itself an lvalue, so it always
// deep-copied its argument instead of moving it
json j_big = std::string(1000, 'x');
const auto* const original_buffer = j_big.get_ref<const std::string&>().data();
auto it = j_array.insert(j_array.begin(), std::move(j_big));
CHECK(j_array.size() == 5);
CHECK(*it == json(std::string(1000, 'x')));
CHECK((*it).get_ref<const std::string&>().data() == original_buffer);
// the moved-from value is null, the same as after push_back(&&)
CHECK(j_big.is_null()); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved)
}
SECTION("self-aliasing insertion")
{
SECTION("without reallocation")
{
json j_self = {1, 2, 3, 4};
j_self.get_ref<json::array_t&>().reserve(j_self.size() + 1);
auto it = j_self.insert(j_self.begin(), std::move(j_self[1]));
CHECK(j_self.size() == 5);
CHECK(*it == json(2));
CHECK(j_self == json({2, 1, nullptr, 3, 4}));
}
SECTION("with reallocation")
{
json j_self = {1, 2, 3, 4};
j_self.get_ref<json::array_t&>().shrink_to_fit();
auto it = j_self.insert(j_self.begin(), std::move(j_self[1]));
CHECK(j_self.size() == 5);
CHECK(*it == json(2));
CHECK(j_self == json({2, 1, nullptr, 3, 4}));
}
}
SECTION("copies at position")
{
SECTION("insert before begin()")