Commit Graph
17 Commits
Author SHA1 Message Date
Niels Lohmann ec44ba1cd5 Bound the descent of the copy constructor
basic_json's copy constructor copied objects and arrays by handing the
container to its own copy constructor, which copy-constructs every element
and so reaches this constructor again, once per nesting level. A value
nested deeply enough exhausted the call stack and terminated the process
with a segmentation fault - no exception, nothing the caller could catch.
Parsing such a value works, as the parser is iterative, and so does
destroying one, as #1436 made destruction iterative.

Bound how far the copy descends rather than take the call stack away from
it. The first levels are copied exactly as they were - the containers copy
their own elements, which is by far the fastest way to fill them - and only
once the copy has descended 128 levels is the value below it finished
without the call stack, through an explicit worklist. Copying can therefore
no longer exhaust the stack, however deeply a value is nested, while a value
nested less deeply than the bound - all but a vanishing minority - is copied
by the very same code as before and pays only for one counter.

That counter lives in thread_local storage, as one shared between threads
would be raced. JSON_NO_THREAD_LOCAL switches it off for toolchains without
thread_local; copying then goes through the worklist right away, which
yields the same values but is measurably slower.

The deferred values are completed before the copy they belong to returns, so
a value copied while another copy is going on - by a custom base class, say -
is unaffected by the copy it is nested in.

operator= takes its argument by value, so copy assignment is fixed as well.

Copying is as fast as it was, within measurement noise (medians of 9
interleaved runs, clang -O3): -1.3% for an array of strings, +0.0% for a
flat object, +0.1% for a flat array of numbers, +0.3% for nested arrays,
+0.6% for nested objects and +1.2% for a twitter-like document. Copying a
three-key object costs about ten nanoseconds more, the counter. Deferring
every level instead, rather than only those below the bound, measured
between 3% and 9% slower depending on the shape of the value.

This fixes #5387 for the copy constructor. dump() is still recursive.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-02 19:02:36 +02:00
Niels Lohmann 5a05627b1f 🚨 fix warning (#5169) 2026-05-14 15:39:18 +02:00
Akhilesh Arora 93e49decbd Fix incomplete-type error in set_parents with ordered_json (#5167)
When iteration_proxy_value<iter_impl<ordered_json>> appears in a context
that requires it to be complete (function or lambda parameter), the
compiler instantiates basic_json<ordered_map> and walks into

    set_parents(iterator, typename iterator::difference_type)

while iterator is still incomplete, failing with "invalid use of
incomplete type".

basic_json::difference_type is already std::ptrdiff_t, so just naming
the underlying type directly avoids the dependent lookup. Behavior and
ABI are unchanged. This was the approach suggested in the issue thread.

Added a regression case in unit-ordered_json.cpp using the same trigger
pattern (lambda parameter naming the proxy type).

Fixes #3732

Signed-off-by: Akhilesh Arora <akhildawra@gmail.com>
2026-05-14 08:52:39 +02:00
Niels Lohmann 515d994acb 📄 adjust year (#5044)
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-01-01 20:00:39 +01:00
Niels Lohmann 54be9b04f0 📄 update REUSE (#4960) 2025-10-23 06:56:36 +02:00
Niels Lohmann 1705bfe914 🔖 set version to 3.12.0 (#4727)
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2025-04-11 10:41:14 +02:00
Niels Lohmann f06604fce0 Bump the copyright years (#4606)
* 📄 bump the copyright years

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📄 bump the copyright years

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* 📄 bump the copyright years

Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com>
2025-01-19 17:04:17 +01:00
Niels Lohmann 1b9a9d1f21 Update licenses (#4521)
* 📄 update licenses

* 📄 update licenses
2024-11-29 17:38:42 +01:00
Niels Lohmann 9cca280a4d JSON for Modern C++ 3.11.3 (#4222) 2023-11-28 22:36:31 +01:00
Niels Lohmann f56c6e2e30 Update documentation for the next release (#4216) 2023-11-26 15:51:19 +01:00
Niels Lohmann 836b7beca4 Fix CI, again (#4083) 2023-09-07 20:41:12 +02:00
Niels LohmannandFlorian Albrechtskirchinger 58bd97e2b1 Add clang-tools to required tools for ci_static_analysis_clang (#3724)
* 💚 add clang-tools to required tools for ci_static_analysis_clang

* 🚨 update Clang-Tidy warning selection

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings

* 🚨 fix Clang-Tidy warnings (#3738)

*  revert fix

*  revert fix

* 🚨 fix Clang-Tidy warnings (#3739)

Co-authored-by: Florian Albrechtskirchinger <falbrechtskirchinger@gmail.com>
2022-09-13 12:58:26 +02:00
Niels Lohmann 9d69186291 🔖 set version to 3.11.2 2022-08-12 15:04:06 +02:00
Niels Lohmann f2020da0dd 🔖 set version to 3.11.1 2022-08-01 23:27:58 +02:00
Niels Lohmann ce0e13ccea 🔖 set version to 3.11.0 2022-07-31 23:19:06 +02:00
Niels LohmannandFlorian Albrechtskirchinger 527da54dcb Use REUSE framework (#3546)
* 📄 add licenses

* 👷 add REUSE compliance check

* 📝 add badge for REUSE

Co-authored-by: Florian Albrechtskirchinger <falbrechtskirchinger@gmail.com>
2022-07-20 12:38:07 +02:00
Niels Lohmann b21c345179 Reorganize directories (#3462)
* 🚚 move files
* 🚚 rename doc folder to docs
* 🚚 rename test folder to tests
2022-05-01 09:41:50 +02:00