Compare commits

..
Author SHA1 Message Date
Niels Lohmann 02d05057a5 docs: macro chooser generates adl_serializer for non-default-constructible types
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 11:17:22 +01:00
Niels Lohmann 444dba381f docs: add figures, table captions and a macro chooser
- Figures with numbered captions: SAX stepper, json_view layout and edit
  stepper, exception map, JSON pointer and patch walkers, QA pipeline,
  scaling and binary size charts, roadmap lanes, release timeline,
  integration decision tree and namespace builder
- Table captions (nj-table-caption) on 9 pages
- Compile times: modules and PCH charts, filesystem section, re-measured
  Figure 1, links between features/modules.md and compile_times.md
- Interactive macro chooser for features/arbitrary_types.md
- Link check: exclude URLs that answer the plugin with 400/401/419 or are
  dead (customers.md)

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-26 10:42:00 +01:00
Niels Lohmann 44f1bec789 docs: new design for the documentation site
Apply the brand to the Material for MkDocs site: Inter and JetBrains Mono
served by the site (upright and real italic), brand colours, blue header band
with the syntax pattern, wordmark in the header, new home page (hero, cards,
animated feature tour), 404 page, polish for tabs, search, footer, focus
rings, tables and code blocks, and theme features (code copy, previous/next
footer, TOC follow, search suggestions).

Draw the number railroad diagram, the parser callback events and the iterator
illustrations as inline SVGs that follow the light and dark scheme. The
generator scripts are in docs/mkdocs/scripts/figures; the feature slideshow
(json-light.svg, json-dark.svg, replacing json.gif on the home page) is built
by docs/mkdocs/scripts/slideshow. Decision nodes in five flowcharts become
hexagons, which need far less room.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-25 20:40:26 +01:00
155 changed files with 9511 additions and 8838 deletions

No files matched your search

-2
View File
@@ -111,8 +111,6 @@ context which existing file needs to be extended, and only very few cases requir
When fixing a bug, edit `unit-regression3.cpp` and add a section referencing the fixed issue.
`unit-regression2.cpp` holds the older tests; the two files exist because a single one grew large enough for the
MinGW linker to fail relocating it, so please keep adding to the smaller file rather than growing the larger one.
Tests that call `sax_parse` go into `unit-sax_parse.cpp` rather than into a large test file: every call instantiates
the parser and the binary reader that recover from errors, which grows a test file considerably.
#### Exceptions
+2 -2
View File
@@ -495,7 +495,7 @@ bool key(string_t& val);
bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
```
The return value of each function determines whether parsing should proceed. For `parse_error`, returning `true` [recovers from the error](https://json.nlohmann.me/features/parsing/error_recovery/): the parser repairs the input and continues.
The return value of each function determines whether parsing should proceed.
To implement your own SAX handler, proceed as follows:
@@ -503,7 +503,7 @@ To implement your own SAX handler, proceed as follows:
2. Create an object of your SAX interface class, e.g. `my_sax`.
3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.
Note the `sax_parse` function only returns a `bool` indicating whether the input was parsed without errors and no SAX event returned `false`. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error -- it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error -- it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
### STL-like access
@@ -113,19 +113,22 @@ basic_json(basic_json&& other) noexcept;
```mermaid
flowchart TD
A(["initializer_list init"]) --> B{"empty, or every element is a 2-element<br/>array whose first element is a string?"}
B -->|"yes"| C{"type_deduction"}
B -->|"no"| D{"type_deduction"}
A(["initializer_list init"]) --> B{{"empty, or every element is a 2-element<br/>array whose first element is a string?"}}
B -->|"yes"| C{{"type_deduction"}}
B -->|"no"| D{{"type_deduction"}}
C -->|"true"| OBJ["create object"]
C -->|"false"| E{"manual_type"}
C -->|"false"| E{{"manual_type"}}
E -->|"object"| OBJ
E -->|"array"| ARR["create array"]
D -->|"true"| ARR
D -->|"false"| F{"manual_type"}
D -->|"false"| F{{"manual_type"}}
F -->|"array"| ARR
F -->|"object"| ERR["throw type_error.301"]
```
<p class="nj-caption" markdown>Decision flow for an initializer list: hexagons are checks, edge labels are their
outcomes, and rectangles are the resulting value or exception.</p>
The rules aim to create the best fit between a C++ initializer list and JSON values. The rationale is as follows:
1. The empty initializer list is written as `#!cpp {}` which is exactly an empty JSON object.
+6 -1
View File
@@ -7,7 +7,12 @@ const_iterator begin() const noexcept;
Returns an iterator to the first element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`begin()` points to the first element and `end()` to the position after the last element;
the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
+6 -1
View File
@@ -6,7 +6,12 @@ const_iterator cbegin() const noexcept;
Returns an iterator to the first element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`cbegin()` points to the first element, like `begin()`, and `end()` to the position after
the last element; the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
+6 -1
View File
@@ -6,7 +6,12 @@ const_iterator cend() const noexcept;
Returns an iterator to one past the last element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`cend()` points to the position after the last element, like `end()`, and `begin()` to
the first element; the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
+7 -1
View File
@@ -6,7 +6,13 @@ const_reverse_iterator crbegin() const noexcept;
Returns an iterator to the reverse-beginning; that is, the last element.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`crbegin()` points to the last element, like `rbegin()`, and `rend()` to the position
before the first element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows
link each reverse iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
+7 -1
View File
@@ -7,7 +7,13 @@ const_reverse_iterator crend() const noexcept;
Returns an iterator to the reverse-end; that is, one before the first element. This element acts as a placeholder,
attempting to access it results in undefined behavior.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`crend()` points to the position before the first element, like `rend()`, and `rbegin()`
to the last element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows link
each reverse iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
+6 -1
View File
@@ -7,7 +7,12 @@ const_iterator end() const noexcept;
Returns an iterator to one past the last element.
![Illustration from cppreference.com](../../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>`end()` points to the position after the last element and `begin()` to the first element;
the dashed cell is the past-the-last position, which must not be dereferenced.</p>
## Return value
@@ -40,6 +40,9 @@ classDiagram
style json_exception fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::exception`.</p>
Subclasses:
- [`parse_error`](parse_error.md) for exceptions indicating a parse error
@@ -40,6 +40,9 @@ classDiagram
style json_invalid_iterator fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::invalid_iterator`.</p>
## Member functions
- **what** - returns explanatory string
@@ -40,6 +40,9 @@ classDiagram
style json_other_error fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::other_error`.</p>
## Member functions
- **what** - returns explanatory string
@@ -41,6 +41,9 @@ classDiagram
style json_out_of_range fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::out_of_range`.</p>
## Member functions
- **what** - returns explanatory string
@@ -43,6 +43,9 @@ classDiagram
style json_parse_error fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::parse_error`.</p>
## Member functions
- **what** - returns explanatory string
@@ -22,7 +22,12 @@ The parser callback distinguishes the following events:
## Examples
![Example when certain parse events are triggered](../../images/callback_events.png)
<div class="nj-fig-wrap" markdown>
--8<-- "images/callback_events.svg"
</div>
<p class="nj-caption" markdown>Each coloured dot marks where the parser reports a `parse_event_t` event while reading
the JSON text on the left; the legend on the right names the event per colour.</p>
??? example
@@ -23,7 +23,12 @@ table describes the values of the parameters `depth`, `event`, and `parsed`.
| `parse_event_t::array_end` | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array |
| `parse_event_t::value` | the parser finished reading a JSON value | depth of the value | the parsed JSON value |
![Example when certain parse events are triggered](../../images/callback_events.png)
<div class="nj-fig-wrap" markdown>
--8<-- "images/callback_events.svg"
</div>
<p class="nj-caption" markdown>Parse events for a small JSON text: each coloured dot marks the position at which the
parser calls the callback, and the legend on the right names the event per colour.</p>
Discarding a value (i.e., returning `#!cpp false`) has different effects depending on the context in which function was
called:
+7 -1
View File
@@ -7,7 +7,13 @@ const_reverse_iterator rbegin() const noexcept;
Returns an iterator to the reverse-beginning; that is, the last element.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`rbegin()` points to the last element and `rend()` to the position before the first
element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows link each reverse
iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
+7 -1
View File
@@ -8,7 +8,13 @@ const_reverse_iterator rend() const noexcept;
Returns an iterator to the reverse-end; that is, one before the first element. This element acts as a placeholder,
attempting to access it results in undefined behavior.
![Illustration from cppreference.com](../../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>`rend()` points to the position before the first element and `rbegin()` to the last
element. The upper row is the reversed sequence and the lower row the forward sequence; dashed arrows link each reverse
iterator to the forward iterator it stores, and dashed cells are past-the-last positions.</p>
## Return value
+1 -4
View File
@@ -104,9 +104,7 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
## Return value
`#!cpp true` if the input was parsed without errors and no SAX event returned `#!cpp false`; `#!cpp false` otherwise.
In particular, the result is `#!cpp false` for input with errors, even if the SAX parser recovered from all of them
(see [error recovery](../../features/parsing/error_recovery.md)).
return value of the last processed SAX event
## Exception safety
@@ -163,7 +161,6 @@ use the same file with stdio functions, but it must not wait for another thread
- Added `ignore_trailing_commas` in version 3.13.0.
- Added `tag_handler` in version 3.13.0.
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
- Recovering from parse errors (see [`parse_error`](../json_sax/parse_error.md)) added in version 3.13.0.
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
- `JSON_PRECISE_STREAM_POSITION` added in version 3.13.0 to optionally leave a `#!cpp std::istream` positioned right
after the parsed value when `strict` is `#!cpp false`.
@@ -41,6 +41,9 @@ classDiagram
style json_type_error fill:#CCCCFF
```
<p class="nj-caption" markdown>Class hierarchy of the library's exceptions; arrows point from a derived class to its
base class, and the highlighted box is `basic_json::type_error`.</p>
## Member functions
- **what** - returns explanatory string
@@ -48,6 +48,9 @@ functions [`is_null`](is_null.md), [`is_object`](is_object.md), [`is_array`](is_
F --> G[binary]
```
<p class="nj-caption" markdown>Arrows point from a type to the next greater type in the ordering used by
`operator<`.</p>
!!! note "Types of numbers"
There are three enumerators for numbers (`number_integer`, `number_unsigned`, and `number_float`) to distinguish
@@ -36,6 +36,9 @@ flowchart LR
parent["parent_pointer() returns /a/b"] -.-> B
```
<p class="nj-caption" markdown>Boxes are the reference tokens in order; dotted arrows show which token each member
function reads, removes, or adds to.</p>
The diagram shows the reference tokens of the JSON pointer `/a/b/c`.
## Member types
+4 -2
View File
@@ -7,8 +7,7 @@ struct json_sax;
This class describes the SAX interface used by [sax_parse](../basic_json/sax_parse.md). Each function is called in
different situations while the input is parsed. The boolean return value informs the parser whether to continue
processing the input; for [`parse_error`](parse_error.md), it decides whether to
[recover from the error](../../features/parsing/error_recovery.md).
processing the input.
For instance, parsing the JSON text `{"a": [1, true]}` triggers the following callbacks, in order:
@@ -26,6 +25,9 @@ sequenceDiagram
P->>H: end_object()
```
<p class="nj-caption" markdown>Each arrow is one call from the parser to the SAX handler, from top to bottom in the
order the calls happen.</p>
Note `elements` is passed as `#!cpp std::numeric_limits<std::size_t>::max()` (i.e., "unknown") for JSON text input;
only binary formats such as CBOR or MessagePack may report the actual number of elements in `start_object`/
`start_array`. Also note that `1` is reported via `number_unsigned` rather than `number_integer` because it has no
+2 -26
View File
@@ -21,18 +21,11 @@ A parse error occurred.
## Return value
Whether to recover from the error:
- `#!cpp false` stops parsing.
- `#!cpp true` recovers from the error: the error is repaired and parsing continues. If that is not possible, which
happens in the binary formats when the end of the item with the error is unknown, the value read so far is completed
and parsing stops. See [error recovery](../../features/parsing/error_recovery.md) for how errors are repaired.
Either way, [`sax_parse`](../basic_json/sax_parse.md) returns `#!cpp false`.
Whether parsing should proceed (**must return `#!cpp false`**).
## Examples
??? example "Example: (1) the SAX interface"
??? example
The example below shows how the SAX interface is used.
@@ -46,29 +39,12 @@ Either way, [`sax_parse`](../basic_json/sax_parse.md) returns `#!cpp false`.
--8<-- "examples/sax_parse.output"
```
??? example "Example: (2) recovering from errors"
The example below shows how a SAX parser recovers from errors.
```cpp
--8<-- "examples/sax_parse__error_recovery.cpp"
```
Output:
```
--8<-- "examples/sax_parse__error_recovery.output"
```
## See also
- [sax_parse](../basic_json/sax_parse.md) - SAX parser
- [Parsing and Exceptions](../../features/parsing/parse_exceptions.md) - the article on handling parse errors without
exceptions
- [Error Recovery](../../features/parsing/error_recovery.md) - the article on recovering from parse errors
## Version history
- Added in version 3.2.0.
- Returning `#!cpp true` recovers from the error since version 3.13.0; before, parsing stopped, but the result of
[`sax_parse`](../basic_json/sax_parse.md) could be wrong.
@@ -41,6 +41,8 @@ flowchart LR
E --> F[Trusted caller]
```
<p class="nj-caption" markdown>The trust boundary: untrusted input enters on the left through the parser, the SAX interface, or the binary readers, and only a value tree reaches the trusted caller on the right.</p>
## Secure design
- **Strict parsing.** The parser accepts exactly the JSON grammar of [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259).
@@ -4,6 +4,15 @@ Ensuring quality is paramount for this project, particularly because [numerous o
depend on it. Each commit to the library undergoes rigorous checks against the following requirements, and any
violations will result in a failed build.
The overview shows the checks a change passes on its way from a push or pull request to a release; the sections below
describe each of them.
<div class="nj-fig-wrap" markdown>
--8<-- "images/qa_pipeline.svg"
</div>
<p class="nj-caption" markdown>The checks grouped by the stage at which they run, from push or pull request through the merge into develop to a release. The badge on each card says whether the check runs on every push or PR, on a schedule, or continuously.</p>
## C++ language compliance and compiler compatibility
!!! success "Requirement: Compiler support"
+12
View File
@@ -91,6 +91,14 @@ Version 4.0 is therefore the sum of these macros: you can try it on the 3.x rele
to its 4.0 value and fixing what no longer compiles or behaves differently. Once your code works with all of them, it
is ready for version 4.0.
Each macro has a default value in 3.x and a different value in version 4.0. Define the macro to the 4.0 value to try it on the 3.x release train today; version 4.0 makes that value the default:
<div class="nj-fig-wrap" markdown>
--8<-- "images/roadmap_lanes.svg"
</div>
<p class="nj-caption" markdown>Each row is one macro: the 3.x release that added it, its default in 3.x, and its value in version 4.0 (highlighted) or "removed". Versions on the 3.x lane are not to scale.</p>
The following macros guard changes that are planned to become the default in version 4.0:
| Macro | 3.x default | 4.0 behavior | CMake option | Added |
@@ -105,6 +113,8 @@ The following macros guard changes that are planned to become the default in ver
| [`JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md) | `0` | `1`: a `basic_json` value can no longer be created from a one-element tuple of a reference to it, such as `std::forward_as_tuple(j)`| [`JSON_DisableTupleReferenceConversion`](../integration/cmake.md#json_disabletuplereferenceconversion) | 3.13.0 |
| [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) | `0` | removed: the deprecated functions are removed (see below); the `from_*(ptr, len)` overloads stay deleted | [`JSON_DeleteDeprecatedFunctions`](../integration/cmake.md#json_deletedeprecatedfunctions) | 3.13.0 |
<p class="nj-table-caption" markdown>Opt-in macros for the version 4.0 behavior. "3.x default" is the value the library uses when the macro is not defined, "Added" is the release that introduced the macro, and – means there is no CMake option.</p>
For example, the following makes a 3.x release behave like version 4.0 with respect to these changes:
```cpp
@@ -146,6 +156,8 @@ to the `strict` parameter.
| Comparing a [`json_pointer`](../api/json_pointer/index.md) with a string via [`operator==`](../api/json_pointer/operator_eq.md) or [`operator!=`](../api/json_pointer/operator_ne.md) | 3.11.2 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
| [`from_bjdata`](../api/basic_json/from_bjdata.md) and [`from_bon8`](../api/basic_json/from_bon8.md) with `(ptr, len)` | 3.13.0 | [Parsing](../integration/migration_guide.md#parsing) |
<p class="nj-table-caption" markdown>Deprecated functions, with the release that deprecated each one and the section of the migration guide that shows its replacement.</p>
The deprecated legacy comparison of discarded values is controlled by a macro and therefore listed in the table above.
New breaking changes will follow the same path: they are added to these tables when they land in a 3.x release.
+782
View File
@@ -0,0 +1,782 @@
/* nlohmann/json brand for Material for MkDocs (values from brand/kit/tokens.css) */
@font-face {
font-family: "Inter";
src: url("fonts/Inter.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
}
@font-face {
font-family: "Inter";
src: url("fonts/Inter-Italic.woff2") format("woff2");
font-style: italic;
font-weight: 100 900;
font-display: swap;
}
@font-face {
font-family: "JetBrains Mono";
src: url("fonts/JetBrainsMono.woff2") format("woff2");
font-weight: 100 800;
font-display: swap;
}
@font-face {
font-family: "JetBrains Mono";
src: url("fonts/JetBrainsMono-Italic.woff2") format("woff2");
font-style: italic;
font-weight: 400;
font-display: swap;
}
:root {
--md-text-font: "Inter";
--md-code-font: "JetBrains Mono";
}
/* light */
[data-md-color-scheme="default"] {
--nj-blue: #1747a6;
--nj-blue-deep: #10357d;
--nj-blue-soft: #eaf1fd;
--nj-band: #1747a6;
--nj-red: #d93a3f;
--nj-red-soft: #fdeced;
--nj-string: #b4322a;
--nj-comment: #646d7a;
--md-primary-fg-color: var(--nj-band);
--md-primary-fg-color--light: #1d55c4;
--md-primary-fg-color--dark: #10357d;
--md-accent-fg-color: var(--nj-blue-deep);
--md-accent-fg-color--transparent: rgba(23, 71, 166, .1);
--md-typeset-a-color: var(--nj-blue);
--md-default-fg-color: #0f1419;
--md-default-fg-color--light: #4a515c;
--md-default-fg-color--lighter: #8a919c;
--md-default-fg-color--lightest: #e3e6eb;
--md-typeset-color: #0f1419;
--md-code-bg-color: #f5f7fa;
--md-code-fg-color: #0f1419;
}
/* dark */
[data-md-color-scheme="slate"] {
--nj-blue: #7aa7f5;
--nj-blue-deep: #a9c6f8;
--nj-blue-soft: #16233b;
--nj-band: #173e8c;
--nj-red: #f06a6e;
--nj-red-soft: #3a1c1e;
--nj-string: #f08a7e;
--nj-comment: #8b929e;
--md-hue: 220;
--md-primary-fg-color: var(--nj-band);
--md-primary-fg-color--light: #163f93;
--md-primary-fg-color--dark: #0c2556;
--md-accent-fg-color: var(--nj-blue-deep);
--md-accent-fg-color--transparent: rgba(122, 167, 245, .12);
--md-typeset-a-color: var(--nj-blue);
--md-default-bg-color: #0f1218;
--md-default-fg-color: #f2f4f7;
--md-default-fg-color--light: #b3b9c4;
--md-default-fg-color--lighter: #7b828e;
--md-default-fg-color--lightest: #272c36;
--md-typeset-color: #f2f4f7;
--md-code-bg-color: #171b23;
--md-code-fg-color: #f2f4f7;
--md-footer-bg-color: #0b0e13;
--md-footer-bg-color--dark: #08090d;
}
/* syntax colours (all at least 4.5:1 on the code panel in both schemes) */
[data-md-color-scheme="default"] {
--nj-hl-keyword: #1747a6;
--nj-hl-type: #0d6e72;
--nj-hl-function: #6b3fb8;
--nj-hl-string: #23793a;
--nj-hl-escape: #0f5d2a;
--nj-hl-key: #10357d;
--nj-hl-number: #b04a07;
--nj-hl-preproc: #a3247a;
}
[data-md-color-scheme="slate"] {
--nj-hl-keyword: #7aa7f5;
--nj-hl-type: #4fd1c5;
--nj-hl-function: #c4a3ff;
--nj-hl-string: #7ed491;
--nj-hl-escape: #b2ecc0;
--nj-hl-key: #a9c6f8;
--nj-hl-number: #f5a65b;
--nj-hl-preproc: #f48fc8;
}
.md-typeset .highlight :is(.k, .kd, .kn, .kr, .kp, .kv, .ow) { color: var(--nj-hl-keyword); font-weight: 600; }
.md-typeset .highlight :is(.kt, .nc, .nn, .na) { color: var(--nj-hl-type); }
.md-typeset .highlight :is(.nf, .fm, .nb, .bp) { color: var(--nj-hl-function); }
.md-typeset .highlight :is(.s, .s1, .s2, .sb, .sc, .sd, .sh, .sx, .sr, .ss, .sa, .dl, .cpf) { color: var(--nj-hl-string); }
.md-typeset .highlight :is(.se, .si) { color: var(--nj-hl-escape); font-weight: 600; }
.md-typeset .highlight .nt { color: var(--nj-hl-key); }
.md-typeset .highlight :is(.m, .mi, .mf, .mh, .mo, .mb, .il, .kc) { color: var(--nj-hl-number); }
.md-typeset .highlight .kc { font-weight: 500; }
.md-typeset .highlight .cp { color: var(--nj-hl-preproc); }
.md-typeset .highlight :is(.c, .c1, .cm, .ch, .cs) { color: var(--nj-comment); font-style: italic; }
.md-typeset .highlight :is(.o, .p) { color: var(--md-default-fg-color--light); }
.md-typeset .highlight :is(.n, .nx, .nv, .no, .ni, .nl, .py) { color: var(--md-code-fg-color); }
.md-typeset .highlight .err { color: inherit; background: none; }
/* typography: Inter with cv11/ss03, bold headlines with negative tracking */
body {
font-feature-settings: "cv11", "ss03";
}
.md-typeset {
font-size: .85rem; /* 17 px body */
line-height: 1.65;
}
.md-typeset h1 {
color: var(--md-typeset-color);
font-weight: 800;
letter-spacing: -.035em;
line-height: 1.1;
}
.md-typeset h2 {
font-weight: 800;
letter-spacing: -.025em;
line-height: 1.15;
}
.md-typeset h3 {
font-weight: 700;
letter-spacing: -.015em;
}
.md-typeset table:not([class]) {
font-variant-numeric: tabular-nums;
}
/* header and tabs: one blue band with the faint syntax pattern; wordmark instead of the site name.
A veil over the tile keeps the glyphs from running through the navigation text; the hero shows the pattern at full strength. */
.md-header, .md-tabs {
--nj-veil: linear-gradient(color-mix(in srgb, var(--md-primary-fg-color) 62%, transparent), color-mix(in srgb, var(--md-primary-fg-color) 62%, transparent));
background-color: var(--md-primary-fg-color);
background-image: var(--nj-veil), url("pattern-on-blue.svg");
background-size: auto, 160px 160px;
background-position: 0 0, 0 0;
}
.md-tabs {
background-position: 0 0, 0 -48px; /* continue the header's tile */
}
.md-header__button.md-logo img {
width: auto;
height: 1.5rem;
}
.md-header__topic:first-child .md-ellipsis { /* the wordmark replaces the site name at every width */
display: none;
}
@media screen and (max-width: 76.234375em) { /* Material hides the header logo here: show the wordmark on phones, too */
.md-header__button.md-logo {
display: block;
margin: 0 0 0 .2rem;
padding: .4rem .2rem;
}
.md-header__button[for="__drawer"] {
order: -1;
}
}
.md-nav__button.md-logo img {
width: auto;
height: 1.4rem;
}
/* shapes: 6 px corners on blocks, 4 px on inline code */
.md-typeset pre > code, .md-typeset .highlight, .md-typeset .highlighttable,
.md-typeset .admonition, .md-typeset details, .md-typeset .tabbed-set,
.md-typeset .grid.cards > ul > li, .md-typeset .md-button {
border-radius: 6px;
}
.md-typeset code {
border-radius: 4px;
}
/* inline code: the font alone marks it, no grey box; linked code keeps the link colour */
.md-typeset :not(pre) > code {
padding: 0;
background-color: transparent;
box-shadow: none;
color: inherit;
font-size: .88em;
}
.md-typeset .highlight pre > code, .md-typeset .highlighttable {
border: 1px solid var(--md-default-fg-color--lightest);
}
/* callouts: 3 px left border; note/info/tip in blue on blue-soft, danger/bug in red on red-soft */
.md-typeset .admonition, .md-typeset details {
border-width: 0 0 0 3px;
box-shadow: none;
font-size: .8rem;
}
.md-typeset :is(.admonition, details):is(.note, .info, .tip, .abstract, .example, .question) {
border-color: var(--nj-blue);
background-color: var(--nj-blue-soft);
}
.md-typeset :is(.note, .info, .tip, .abstract, .example, .question) > :is(.admonition-title, summary) {
background-color: transparent;
}
.md-typeset :is(.note, .info, .tip, .abstract, .example, .question) > :is(.admonition-title, summary)::before {
background-color: var(--nj-blue);
}
.md-typeset :is(.admonition, details):is(.danger, .bug, .failure) {
border-color: var(--nj-red);
background-color: var(--nj-red-soft);
}
.md-typeset :is(.danger, .bug, .failure) > :is(.admonition-title, summary) {
background-color: transparent;
}
.md-typeset :is(.danger, .bug, .failure) > :is(.admonition-title, summary)::before {
background-color: var(--nj-red);
}
/* buttons */
.md-typeset .md-button--primary {
background-color: var(--nj-blue);
border-color: var(--nj-blue);
}
/* home page hero (overrides/home.html): blue band with the syntax pattern, headline, lead, buttons, code panel */
.nj-hero {
--nj-hero-to: #123a8a;
color: #fff;
background-color: var(--md-primary-fg-color);
background-image: url("pattern-on-blue.svg"), linear-gradient(160deg, var(--md-primary-fg-color), var(--nj-hero-to));
background-size: 160px 160px, auto;
background-position: 0 -96px, 0 0; /* continue the tile of header and tabs */
}
[data-md-color-scheme="slate"] .nj-hero {
--nj-hero-to: #0c2556;
}
.nj-hero__inner {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
gap: 2.4rem;
align-items: center;
padding: 3rem .8rem 3.6rem;
}
.nj-hero__kicker {
display: inline-block;
margin: 0;
padding: .15rem .55rem;
border: 1px solid rgba(255, 255, 255, .35);
border-radius: 4px;
color: #bcd3fb;
font-family: var(--md-code-font-family);
font-size: .65rem; /* 13 px */
font-weight: 500;
letter-spacing: .02em;
}
.nj-hero__title {
margin: 0 0 .8rem;
color: #fff;
font-size: clamp(1.7rem, 4.2vw, 3.2rem); /* 34-64 px */
font-weight: 800;
line-height: 1.02;
letter-spacing: -.035em;
}
.nj-hero__title span {
color: #bcd3fb;
}
.nj-hero__lead {
max-width: 22em;
margin: 0 0 2rem;
color: rgba(255, 255, 255, .9);
font-size: clamp(1.1rem, 2.2vw, 1.6rem); /* 22-32 px */
font-style: italic;
font-weight: 500;
line-height: 1.35;
letter-spacing: -.015em;
}
.nj-hero__actions {
display: flex;
flex-wrap: wrap;
gap: .6rem;
margin: 0;
}
.nj-hero .md-button.nj-hero__button {
margin: 0;
padding: .55em 1.3em;
border: 1px solid rgba(255, 255, 255, .6);
border-radius: 6px;
color: #fff;
font-size: .75rem;
font-weight: 600;
}
.nj-hero .md-button--primary.nj-hero__button {
border-color: #fff;
background-color: #fff;
color: var(--md-primary-fg-color);
}
.nj-hero .md-button.nj-hero__button:is(:hover, :focus) {
border-color: #fff;
background-color: rgba(255, 255, 255, .12);
color: #fff;
}
.nj-hero .md-button--primary.nj-hero__button:is(:hover, :focus) {
background-color: #eaf1fd;
color: var(--md-primary-fg-color);
}
.nj-hero__code {
border-radius: 6px;
background-color: var(--md-code-bg-color);
box-shadow: 0 12px 32px rgba(5, 18, 48, .35);
}
.nj-hero__code pre {
margin: 0;
padding: 1.1rem 1.3rem;
overflow-x: auto;
color: var(--md-code-fg-color);
font-family: var(--md-code-font-family);
font-size: .7rem; /* 14 px */
line-height: 1.7;
}
.nj-hero__code .nj-k { color: var(--nj-hl-type); }
.nj-hero__code .nj-s { color: var(--nj-hl-string); }
.nj-hero__code .nj-n { color: var(--nj-hl-number); }
.nj-hero__code .nj-c { color: var(--nj-comment); font-style: italic; }
@media screen and (max-width: 59.984375em) {
.nj-hero__inner {
grid-template-columns: minmax(0, 1fr);
gap: 1.8rem;
padding: 2rem .8rem 2.4rem;
}
}
@media screen and (max-width: 29.984375em) {
.nj-hero__code pre {
font-size: .6rem;
}
}
/* the hero carries the headline: keep the page's h1 for the title and screen readers only */
body:has(.nj-hero) .md-content__inner > h1 {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
}
/* cards: 1 px line border, 6 px corners, blue icon on soft blue, blue border on hover */
.md-typeset .grid.cards > ul > li {
padding: 1rem 1.1rem;
border: 1px solid var(--md-default-fg-color--lightest);
background-color: var(--md-default-bg-color);
transition: border-color 150ms, box-shadow 150ms, transform 150ms;
}
.md-typeset .grid.cards > ul > li:is(:hover, :focus-within) {
border-color: var(--nj-blue);
box-shadow: 0 6px 18px rgba(23, 71, 166, .12);
transform: translateY(-1px);
}
.md-typeset .grid.cards > ul > li > hr {
display: none;
}
.md-typeset .grid.cards .twemoji.lg {
box-sizing: content-box;
margin-right: .5rem;
padding: .3rem;
border-radius: 6px;
background-color: var(--nj-blue-soft);
color: var(--nj-blue);
}
.md-typeset .grid.cards > ul > li > p:first-child strong {
font-size: .9rem;
font-weight: 700;
letter-spacing: -.01em;
}
.md-typeset .grid.cards > ul > li > p:last-child a {
font-weight: 600;
}
@media (prefers-reduced-motion: reduce) {
.md-typeset .grid.cards > ul > li { transition: none; transform: none !important; }
}
/* home page: no table of contents, so keep the text at reading width and the cards in three columns */
body:has(.nj-hero) .md-content {
max-width: 58rem;
margin: 0 auto;
}
@media screen and (min-width: 60em) {
body:has(.nj-hero) .md-typeset .grid.cards {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
/* lists: Material's indent, bullets as small blue squares, numbers in the secondary text colour */
.md-typeset ul:not(.task-list, .md-annotation-list) > li {
position: relative;
list-style: none;
}
.md-typeset ul:not(.task-list, .md-annotation-list) > li::before {
content: "";
position: absolute;
top: .65em; /* middle of the first line at line-height 1.65 */
left: -.95em;
width: .36em;
height: .36em;
background-color: var(--nj-blue);
}
.md-typeset ol > li::marker {
color: var(--md-default-fg-color--light);
font-variant-numeric: tabular-nums;
}
.md-typeset .grid.cards > ul > li::before {
display: none;
}
/* wider page: Material's grid stops at 61rem (1220 px) */
.md-grid {
max-width: 72rem; /* 1440 px */
}
/* tables: full width, 1 px line border with 6 px corners, header row on the panel colour, 15 px text */
.md-typeset__table {
display: block; /* Material: inline-block, so tables only grow to their content */
}
.md-typeset table:not([class]) {
display: table;
width: 100%;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 6px;
font-size: .75rem;
line-height: 1.55;
}
.md-typeset table:not([class]) th {
padding: .65em 1em;
border-bottom: 1px solid var(--md-default-fg-color--lightest);
background-color: var(--md-code-bg-color);
color: var(--md-typeset-color);
font-weight: 600;
vertical-align: bottom;
}
.md-typeset table:not([class]) th:first-child { border-top-left-radius: 5px; }
.md-typeset table:not([class]) th:last-child { border-top-right-radius: 5px; }
.md-typeset table:not([class]) td {
padding: .65em 1em;
border-top: 1px solid var(--md-default-fg-color--lightest);
}
.md-typeset table:not([class]) tbody tr:first-child td {
border-top: 0;
}
.md-typeset table:not([class]) tbody tr:hover {
background-color: var(--nj-blue-soft);
box-shadow: none;
}
.md-typeset table:not([class]) td code {
white-space: nowrap;
}
/* numbers and header code stay on one line; a table wider than the screen scrolls sideways instead */
.md-typeset table:not([class]) :is(td, th):is([align="right"], [style*="right"]),
.md-typeset table:not([class]) th code {
white-space: nowrap;
}
@media screen and (max-width: 44.984375em) {
.md-typeset table:not([class]) {
font-size: .7rem;
}
.md-typeset table:not([class]) :is(th, td) {
padding: .55em .75em;
}
}
/* more room before headings (Material: h2 1.6em, h3 1.6em, h4-h6 1-1.25em) and at the end of each page (1.2rem) */
.md-typeset h2 { margin-top: 2.4em; }
.md-typeset h3 { margin-top: 2.2em; }
.md-typeset h2 + h3 { margin-top: .8em; }
.md-typeset :is(h4, h5, h6) { margin-top: 1.8em; }
.md-content__inner {
margin-bottom: 4.8rem; /* 96 px */
}
/* Mermaid diagrams: white boxes with a blue outline, grey lines, Inter; shapes and spacing in js/mermaid-brand.js */
:root > * {
--md-mermaid-font-family: var(--md-text-font-family), sans-serif;
--md-mermaid-edge-color: var(--md-default-fg-color--lighter);
--md-mermaid-node-bg-color: var(--md-default-bg-color);
--md-mermaid-node-fg-color: var(--nj-blue);
--md-mermaid-label-bg-color: var(--md-default-bg-color);
--md-mermaid-label-fg-color: var(--md-default-fg-color);
--md-mermaid-sequence-actor-bg-color: var(--nj-blue-soft);
--md-mermaid-sequence-actor-line-color: var(--md-default-fg-color--lighter);
--md-mermaid-sequence-note-bg-color: var(--md-code-bg-color);
--md-mermaid-sequence-note-border-color: var(--md-default-fg-color--lightest);
--md-mermaid-sequence-number-fg-color: #fff;
}
/* a diagram wider than the column scrolls sideways (js/mermaid-brand.js stops shrinking it at 80 %) */
.md-typeset .mermaid {
overflow-x: auto;
}
/* ---- polish pass ---- */
/* header: a search field that reads as a field on the band, tabs with an active marker, readable GitHub facts */
.md-header .md-search__form {
border: 1px solid rgba(255, 255, 255, .22);
border-radius: 6px;
background-color: rgba(255, 255, 255, .12);
transition: background-color 150ms, border-color 150ms;
}
.md-header .md-search__form:hover {
border-color: rgba(255, 255, 255, .4);
background-color: rgba(255, 255, 255, .2);
}
.md-search__output {
border-radius: 0 0 6px 6px;
box-shadow: 0 16px 40px rgba(5, 18, 48, .28);
}
.md-search-result__link:focus-visible, .md-search-result__more summary:focus-visible {
outline: 2px solid var(--nj-blue);
outline-offset: -2px;
}
.md-tabs__link {
font-size: .72rem;
font-weight: 500;
opacity: .85;
}
.md-tabs__item--active .md-tabs__link, .md-tabs__link:hover {
opacity: 1;
}
.md-tabs__item--active {
box-shadow: inset 0 -2px 0 #fff;
}
.md-source__facts {
font-size: .62rem;
}
/* footer: deep brand blue instead of neutral black (the dark scheme keeps its own near-black) */
[data-md-color-scheme="default"] {
--md-footer-bg-color: #0d2a66;
--md-footer-bg-color--dark: #0a2152;
}
.md-footer-meta .md-copyright, .md-footer-meta .md-copyright a {
color: rgba(255, 255, 255, .72);
}
.md-footer__link {
border-radius: 6px;
transition: background-color 150ms;
}
.md-footer__link:is(:hover, :focus-visible) {
background-color: rgba(255, 255, 255, .08);
}
/* page title: tighter to the first paragraph; page actions (view/edit source) stay in the background */
.md-typeset h1 {
margin-bottom: 1rem;
}
.md-content__button {
opacity: .55;
transition: opacity 150ms;
}
.md-content__button:is(:hover, :focus-visible) {
opacity: 1;
}
body:has(.nj-hero) .md-content__button {
display: none;
}
/* sidebars: bold marker for the current page, rail and marker for the table of contents */
.md-nav__link--active {
font-weight: 600;
}
.md-nav--secondary > .md-nav__list {
margin-left: -.1rem;
border-left: 1px solid color-mix(in srgb, var(--md-default-fg-color) 16%, transparent);
}
.md-nav--secondary .md-nav__link {
margin-left: -1px;
padding-left: .6rem;
border-left: 2px solid transparent;
}
.md-nav--secondary .md-nav__link--active {
border-left-color: var(--nj-blue);
color: var(--nj-blue);
}
.md-nav--secondary .md-nav__list .md-nav__list {
padding-left: .6rem;
}
.md-nav--secondary .md-nav__title {
font-size: .64rem;
letter-spacing: .04em;
text-transform: uppercase;
}
/* keyboard focus: one visible ring in the brand blue */
.md-typeset a:focus-visible, .md-typeset .md-button:focus-visible, .md-typeset summary:focus-visible,
.md-nav__link:focus-visible, .md-tabs__link:focus-visible, .md-top:focus-visible {
outline: 2px solid var(--nj-blue);
outline-offset: 2px;
border-radius: 3px;
}
.md-header :is(a, button, label):focus-visible, .nj-hero a:focus-visible {
outline: 2px solid #fff;
outline-offset: 2px;
}
/* inline code must not stretch the line box (JetBrains Mono has tall metrics), abbreviations stay quiet */
.md-typeset :not(pre) > code {
line-height: 1;
}
.md-typeset abbr {
border-bottom-color: var(--md-default-fg-color--lighter);
}
.md-typeset :is(h1, h2, h3, h4, a, .grid.cards > ul > li > p:first-child) abbr {
border-bottom-color: transparent;
}
/* number railroad diagram: inline SVG (docs/images/json_syntax_number.svg), follows the colour scheme */
.md-typeset .railroad-wrap, .md-typeset .nj-fig-wrap {
overflow-x: auto;
margin: 1.5rem 0;
}
.md-typeset svg.railroad {
display: block;
width: 100%;
min-width: 36rem;
max-width: 52rem;
margin-inline: auto;
color: var(--md-default-fg-color);
font-family: var(--md-text-font-family), sans-serif;
}
.railroad .rr-t { fill: color-mix(in srgb, var(--md-typeset-a-color) 10%, transparent); stroke: var(--md-typeset-a-color); stroke-width: 2; }
.railroad .rr-track, .railroad .rr-n { stroke: color-mix(in srgb, currentColor 60%, var(--md-default-bg-color)); stroke-opacity: 1; } /* opaque, so overlapping segments do not darken */
.railroad .rr-n { fill: color-mix(in srgb, currentColor 6%, transparent); stroke-width: 2; }
.railroad .rr-bg { fill: var(--md-default-bg-color); }
.railroad .rr-arrow { fill: currentColor; fill-opacity: .6; }
.railroad text { fill: currentColor; text-anchor: middle; }
.railroad .rr-c { font-family: var(--md-code-font-family), monospace; font-size: 16px; font-weight: 500; }
.railroad .rr-b { font-size: 14.5px; font-weight: 500; }
.railroad .rr-l { font-size: 14px; text-anchor: start; fill-opacity: .6; }
.railroad .rr-name { font-size: 17px; font-weight: 700; fill-opacity: 1; }
/* figures drawn as inline SVG (docs/images/callback_events.svg, range-*.svg): they follow the colour scheme */
.md-typeset svg.nj-fig {
display: block;
width: 100%;
height: auto;
margin-inline: auto;
color: var(--md-default-fg-color);
font-family: var(--md-text-font-family), sans-serif;
}
.md-typeset svg.nj-fig--range { min-width: 30rem; max-width: 40rem; }
.md-typeset svg.nj-fig--cb { max-width: 30rem; }
.nj-fig { --fg-line: color-mix(in srgb, currentColor 55%, var(--md-default-bg-color)); }
.nj-fig .fg-cell { fill: color-mix(in srgb, var(--md-typeset-a-color) 14%, var(--md-default-bg-color)); stroke: var(--fg-line); stroke-width: 1.5; }
.nj-fig .fg-cell--end { fill: none; stroke-dasharray: 4 3; }
.nj-fig .fg-pill { fill: color-mix(in srgb, var(--md-typeset-a-color) 10%, var(--md-default-bg-color)); stroke: var(--md-typeset-a-color); stroke-width: 1.5; }
.nj-fig .fg-pilltext { fill: var(--md-typeset-a-color); font-family: var(--md-code-font-family), monospace; font-size: 14px; font-weight: 500; text-anchor: middle; }
.nj-fig .fg-arrow { stroke: var(--fg-line); stroke-width: 1.5; fill: none; }
.nj-fig .fg-arrow--dash { stroke-dasharray: 3 3; }
.nj-fig .fg-head { fill: var(--fg-line); }
.nj-fig .fg-note { fill: currentColor; fill-opacity: .7; font-size: 13.5px; text-anchor: middle; }
.nj-fig .fg-note--r { text-anchor: end; }
.nj-fig .fg-note--l { text-anchor: start; }
.nj-fig .fg-h { fill: currentColor; fill-opacity: .7; font-size: 15px; font-weight: 600; }
.nj-fig .fg-code { fill: currentColor; font-family: var(--md-code-font-family), monospace; font-size: 16px; white-space: pre; }
.nj-fig .fg-leg { font-size: 15px; }
.nj-fig { --cb-os: #4eb05a; --cb-oe: #1a6b34; --cb-k: #e5534b; --cb-as: #f0c000; --cb-ae: #b07d00; --cb-v: #1f6fd1; }
[data-md-color-scheme="slate"] .nj-fig { --cb-os: #7ee787; --cb-oe: #2ea043; --cb-k: #ff7b72; --cb-as: #f2cc60; --cb-ae: #c69026; --cb-v: #58a6ff; }
.nj-fig .cb-os { fill: var(--cb-os); }
.nj-fig .cb-oe { fill: var(--cb-oe); }
.nj-fig .cb-k { fill: var(--cb-k); }
.nj-fig .cb-as { fill: var(--cb-as); }
.nj-fig .cb-ae { fill: var(--cb-ae); }
.nj-fig .cb-v { fill: var(--cb-v); }
.md-typeset img[src*="json-light"], .md-typeset img[src*="json-dark"] {
border-radius: 8px;
}
.md-typeset img {
max-width: 100%;
height: auto;
}
/* home page: content uses the same column as every other page */
body:has(.nj-hero) .md-content {
max-width: none;
margin: 0;
}
.md-typeset .grid.cards {
width: auto;
}
/* 404 page (overrides/404.html) */
.nj-404 {
max-width: 30rem;
padding: 2rem 0 3rem;
}
.nj-404__code {
margin: 0 0 .4rem;
color: var(--nj-blue);
font-family: var(--md-code-font-family);
font-size: .8rem;
font-weight: 500;
}
.md-typeset .nj-404 h1 {
margin-bottom: .8rem;
}
.nj-404 .md-button {
margin: .4rem .4rem 0 0;
}
/* touch targets and phones */
@media screen and (max-width: 59.984375em) {
.md-nav__link {
padding-block: .2rem;
}
}
@media screen and (max-width: 29.984375em) {
.md-typeset h1 {
font-size: 1.7em;
}
.md-typeset .highlight pre > code {
font-size: .68rem;
}
}
/* figure captions: "Figure N." in bold, close to the figure, set in from the text column; figures and tables are
numbered per page, each with its own counter */
.md-content__inner { counter-reset: nj-figure nj-table; }
.md-typeset :is(.nj-caption, .nj-charts-caption) {
max-width: none;
margin: .3rem 2rem 1.5rem;
font-size: .75rem;
line-height: 1.5;
text-align: left;
color: var(--md-default-fg-color--light);
}
.md-typeset :is(.nj-fig-wrap, .railroad-wrap, .nj-charts-grid-wrap) + :is(.nj-caption, .nj-charts-caption) { margin-top: -1.1rem; }
.md-typeset .nj-charts-grid-wrap + :is(.nj-caption, .nj-charts-caption) { margin-top: .3rem; }
.md-typeset :is(.nj-caption, .nj-charts-caption)::before {
counter-increment: nj-figure;
content: "Figure " counter(nj-figure) ". ";
font-weight: 700;
color: var(--md-default-fg-color);
}
@media screen and (max-width: 44.9375em) {
.md-typeset :is(.nj-caption, .nj-charts-caption) { margin-inline: 1rem; }
}
/* table captions: "Table N." in bold, directly below the table, in the figure caption style */
.md-typeset .nj-table-caption {
max-width: none;
margin: .3rem 2rem 1.5rem;
font-size: .75rem;
line-height: 1.5;
text-align: left;
color: var(--md-default-fg-color--light);
}
.md-typeset :is(.md-typeset__scrollwrap, .md-typeset__table) + .nj-table-caption { margin-top: -.4rem; }
.md-typeset .nj-table-caption::before {
counter-increment: nj-table;
content: "Table " counter(nj-table) ". ";
font-weight: 700;
color: var(--md-default-fg-color);
}
@media screen and (max-width: 44.9375em) {
.md-typeset .nj-table-caption { margin-inline: 1rem; }
}
+142
View File
@@ -0,0 +1,142 @@
/* figures: charts (docs/images/compile_times.svg, binary_sizes_*.svg, ordered_json_scaling.svg from
scripts/figures/charts.py) and the number literal explorer on features/types/number_handling.md */
/* series colours: categorical slots validated for CVD separation on the light and the slate surface */
.nj-charts, .nj-charts-key {
--nj-charts-c1: #2a78d6;
--nj-charts-c2: #eb6834;
--nj-charts-c3: #1baf7a;
--nj-charts-c4: #eda100;
--nj-charts-c5: #e87ba4;
--nj-charts-c6: #008300;
--nj-charts-ink2: var(--md-default-fg-color--light);
--nj-charts-grid: color-mix(in srgb, currentColor 12%, var(--md-default-bg-color));
--nj-charts-base: color-mix(in srgb, currentColor 35%, var(--md-default-bg-color));
}
[data-md-color-scheme="slate"] :is(.nj-charts, .nj-charts-key) {
--nj-charts-c1: #3987e5;
--nj-charts-c2: #d95926;
--nj-charts-c3: #199e70;
--nj-charts-c4: #c98500;
--nj-charts-c5: #d55181;
--nj-charts-c6: #008300;
}
/* concepts: two compilers, two object types */
.nj-charts { --nj-charts-clang-c: var(--nj-charts-c1); --nj-charts-gcc-c: var(--nj-charts-c2);
--nj-charts-json-c: var(--nj-charts-c1); --nj-charts-ojson-c: var(--nj-charts-c2); }
.md-typeset svg.nj-charts--compile, .md-typeset svg.nj-charts--scaling { max-width: 26rem; }
.md-typeset svg.nj-charts--sizes { max-width: 26rem; }
.nj-charts text { fill: currentColor; font-size: 13px; }
.nj-charts .nj-charts-leg { font-size: 13.5px; }
.nj-charts .nj-charts-rowlabel { font-size: 13.5px; font-weight: 500; }
.nj-charts .nj-charts-code { font-family: var(--md-code-font-family), monospace; font-size: 12.5px; }
.nj-charts .nj-charts-sub { fill: var(--nj-charts-ink2); font-weight: 400; }
.nj-charts .nj-charts-fmt { text-anchor: end; font-weight: 400; }
.nj-charts .nj-charts-best { font-weight: 700; }
.nj-charts .nj-charts-panel { font-family: var(--md-code-font-family), monospace; font-size: 14px; font-weight: 600; }
.nj-charts .nj-charts-tick { fill: var(--nj-charts-ink2); font-size: 12px; text-anchor: middle; font-variant-numeric: tabular-nums; }
.nj-charts .nj-charts-tick--l { text-anchor: start; }
.nj-charts .nj-charts-tick--r { text-anchor: end; }
.nj-charts .nj-charts-val { font-size: 12px; font-variant-numeric: tabular-nums;
paint-order: stroke; stroke: var(--md-default-bg-color); stroke-width: 4px; stroke-linejoin: round; }
.nj-charts .nj-charts-factor { fill: var(--nj-charts-ink2); font-size: 12px; font-weight: 600; text-anchor: middle; }
.nj-charts .nj-charts-note { fill: var(--nj-charts-ink2); font-size: 12px; }
.nj-charts .nj-charts-grid { stroke: var(--nj-charts-grid); stroke-width: 1; }
.nj-charts .nj-charts-zero, .nj-charts .nj-charts-axis { stroke: var(--nj-charts-base); stroke-width: 1.5; }
.nj-charts .nj-charts-ref { stroke: currentColor; stroke-width: 1.5; }
.nj-charts .nj-charts-c1 { fill: var(--nj-charts-c1); }
.nj-charts .nj-charts-c2 { fill: var(--nj-charts-c2); }
.nj-charts .nj-charts-c3 { fill: var(--nj-charts-c3); }
.nj-charts .nj-charts-c4 { fill: var(--nj-charts-c4); }
.nj-charts .nj-charts-c5 { fill: var(--nj-charts-c5); }
.nj-charts .nj-charts-c6 { fill: var(--nj-charts-c6); }
.nj-charts .nj-charts-dim { fill-opacity: .45; }
.nj-charts .nj-charts-clang { fill: var(--nj-charts-clang-c); }
.nj-charts .nj-charts-gcc { fill: var(--nj-charts-gcc-c); }
.nj-charts polyline.nj-charts-json, .nj-charts line.nj-charts-json { stroke: var(--nj-charts-json-c); stroke-width: 2; fill: none; }
.nj-charts polyline.nj-charts-ojson, .nj-charts line.nj-charts-ojson { stroke: var(--nj-charts-ojson-c); stroke-width: 2; fill: none; }
.nj-charts .nj-charts-json-dot { fill: var(--nj-charts-json-c); stroke: var(--md-default-bg-color); stroke-width: 2; }
.nj-charts .nj-charts-ojson-dot { fill: var(--nj-charts-ojson-c); stroke: var(--md-default-bg-color); stroke-width: 2; }
/* single wide charts: larger text on phones, where the SVG is scaled down */
@media screen and (max-width: 44.9375em) {
svg.nj-charts.nj-charts--compile text, svg.nj-charts.nj-charts--scaling text { font-size: 15px; }
svg.nj-charts.nj-charts--compile .nj-charts-code { font-size: 14px; }
svg.nj-charts:is(.nj-charts--compile, .nj-charts--scaling) :is(.nj-charts-tick, .nj-charts-val, .nj-charts-factor, .nj-charts-note) { font-size: 14px; }
}
/* small multiples: two panels per row, one on narrow screens */
.md-typeset .nj-charts-grid-wrap {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1rem 2rem;
margin: 1.5rem 0 .5rem;
}
.md-typeset .nj-charts-grid-wrap > .nj-fig-wrap { margin: 0; }
/* number literal explorer */
.md-typeset .nj-charts-num-ui {
margin: 1rem 0 .75rem;
padding: .8rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 8px;
}
.md-typeset .nj-charts-num-ui label { display: block; font-weight: 600; font-size: .75rem; margin-bottom: .3rem; }
.md-typeset .nj-charts-num-input {
width: 100%;
box-sizing: border-box;
min-height: 44px;
padding: .4rem .6rem;
font-family: var(--md-code-font-family), monospace;
font-size: .8rem;
color: var(--md-default-fg-color);
background: var(--md-code-bg-color);
border: 1px solid var(--md-default-fg-color--lighter);
border-radius: 6px;
}
.md-typeset .nj-charts-num-input:focus-visible, .md-typeset .nj-charts-num-chip:focus-visible {
outline: 2px solid var(--md-typeset-a-color);
outline-offset: 2px;
}
.md-typeset .nj-charts-num-ui ul.nj-charts-num-chips:not([hidden]) { display: flex; flex-wrap: wrap; gap: .35rem; margin: .6rem 0; padding: 0; list-style: none; }
.md-typeset .nj-charts-num-ui ul.nj-charts-num-chips > li { margin: 0; padding: 0; list-style: none; }
.md-typeset .nj-charts-num-ui ul.nj-charts-num-chips > li::before, .md-typeset .nj-charts-num-ui ul.nj-charts-num-chips > li::marker { content: none; }
.md-typeset .nj-charts-num-chip {
min-height: 44px;
max-width: 100%;
padding: .25rem .6rem;
overflow-wrap: anywhere;
font-family: var(--md-code-font-family), monospace;
font-size: .7rem;
color: var(--md-typeset-a-color);
background: color-mix(in srgb, var(--md-typeset-a-color) 8%, var(--md-default-bg-color));
border: 1px solid color-mix(in srgb, var(--md-typeset-a-color) 35%, var(--md-default-bg-color));
border-radius: 6px;
cursor: pointer;
text-align: left;
}
.md-typeset .nj-charts-num-chip[aria-pressed="true"] {
color: var(--md-default-bg-color);
background: var(--md-typeset-a-color);
border-color: var(--md-typeset-a-color);
}
.md-typeset .nj-charts-num-out {
display: grid;
grid-template-columns: max-content 1fr;
gap: .2rem .8rem;
margin: 0;
font-size: .75rem;
overflow-wrap: anywhere;
}
.md-typeset .nj-charts-num-out dt { color: var(--md-default-fg-color--light); margin: 0; }
.md-typeset .nj-charts-num-out dd { margin: 0; }
.md-typeset .nj-charts-num-miss { font-size: .75rem; color: var(--md-default-fg-color--light); margin: 0; }
.md-typeset .nj-charts-num tr.nj-charts-num-hit td { background: var(--md-accent-fg-color--transparent); }
/* direct line labels replace the legend */
.nj-charts .nj-charts-name-json { fill: var(--nj-charts-json-c); font-weight: 600; }
.nj-charts .nj-charts-name-ojson { fill: var(--nj-charts-ojson-c); font-weight: 600; }
+75
View File
@@ -0,0 +1,75 @@
/* figures: exceptions (home/exceptions.md exception map, community/quality_assurance.md pipeline) */
/* the generated SVGs hold a wide and a narrow drawing; show one of them */
.md-typeset svg.nj-exceptions-map--wide, .md-typeset svg.nj-exceptions-qa--wide { max-width: 47.5rem; }
.md-typeset svg.nj-exceptions-map--narrow, .md-typeset svg.nj-exceptions-qa--narrow { display: none; max-width: 24rem; }
@media screen and (max-width: 37.5em) {
.md-typeset svg.nj-exceptions-map--wide, .md-typeset svg.nj-exceptions-qa--wide { display: none; }
.md-typeset svg.nj-exceptions-map--narrow, .md-typeset svg.nj-exceptions-qa--narrow { display: block; }
}
/* shared */
.nj-fig { --nj-exceptions-line: color-mix(in srgb, currentColor 45%, var(--md-default-bg-color)); }
.nj-fig .nj-exceptions-edge { stroke: var(--nj-exceptions-line); stroke-width: 1.5; fill: none; }
.nj-fig .nj-exceptions-tri { fill: var(--md-default-bg-color); stroke: var(--nj-exceptions-line); stroke-width: 1.3; }
.nj-fig .nj-exceptions-box {
fill: color-mix(in srgb, currentColor 4%, var(--md-default-bg-color));
stroke: color-mix(in srgb, currentColor 30%, var(--md-default-bg-color));
stroke-width: 1.5;
}
.nj-fig .nj-exceptions-box--fam {
fill: color-mix(in srgb, var(--md-typeset-a-color) 9%, var(--md-default-bg-color));
stroke: color-mix(in srgb, var(--md-typeset-a-color) 55%, var(--md-default-bg-color));
}
.nj-fig .nj-exceptions-name { fill: currentColor; font-family: var(--md-code-font-family), monospace; font-size: 14px; font-weight: 600; }
.nj-fig .nj-exceptions-sub { fill: currentColor; fill-opacity: .68; font-size: 12.5px; }
/* exception map: id chips are links */
.nj-fig .nj-exceptions-chip rect {
fill: color-mix(in srgb, var(--md-typeset-a-color) 7%, var(--md-default-bg-color));
stroke: color-mix(in srgb, var(--md-typeset-a-color) 40%, var(--md-default-bg-color));
stroke-width: 1.2;
transition: fill .15s;
}
.nj-fig .nj-exceptions-chip--named rect {
fill: color-mix(in srgb, var(--md-typeset-a-color) 16%, var(--md-default-bg-color));
stroke: var(--md-typeset-a-color);
}
.nj-fig .nj-exceptions-id { fill: var(--md-typeset-a-color); font-family: var(--md-code-font-family), monospace; font-size: 13px; font-weight: 600; }
.nj-fig .nj-exceptions-label { fill: currentColor; font-size: 12.5px; font-weight: 500; }
.nj-fig a:hover rect, .nj-fig a:focus-visible rect {
fill: color-mix(in srgb, var(--md-typeset-a-color) 28%, var(--md-default-bg-color));
}
.nj-fig a:focus { outline: none; }
.nj-fig a:focus-visible rect { stroke: var(--md-typeset-a-color); stroke-width: 2.5; }
.nj-fig a:hover .nj-exceptions-name, .nj-fig a:focus-visible .nj-exceptions-name { text-decoration: underline; }
@media (prefers-reduced-motion: reduce) {
.nj-fig .nj-exceptions-chip rect { transition: none; }
}
/* quality assurance pipeline */
.nj-fig { --nj-exceptions-push: var(--md-typeset-a-color); --nj-exceptions-sched: #a86400; --nj-exceptions-cont: #1a7f37; }
[data-md-color-scheme="slate"] .nj-fig { --nj-exceptions-sched: #e3a33b; --nj-exceptions-cont: #56c46e; }
.nj-fig .nj-exceptions-groupbox {
fill: color-mix(in srgb, currentColor 2.5%, var(--md-default-bg-color));
stroke: color-mix(in srgb, currentColor 22%, var(--md-default-bg-color));
stroke-width: 1.2;
stroke-dasharray: 5 4;
}
.nj-fig .nj-exceptions-group { fill: currentColor; fill-opacity: .68; font-size: 13px; font-weight: 600; letter-spacing: .02em; }
.nj-fig .nj-exceptions-card .nj-exceptions-box { fill: var(--md-default-bg-color); }
.nj-fig .nj-exceptions-ctitle { fill: currentColor; font-size: 15px; font-weight: 700; }
.nj-fig .nj-exceptions-line { fill: currentColor; fill-opacity: .8; font-size: 12.5px; }
.nj-fig .nj-exceptions-badge { stroke-width: 1.2; }
.nj-fig .nj-exceptions-badgetext { font-size: 11px; font-weight: 600; text-anchor: middle; }
.nj-fig .nj-exceptions-badge--push { fill: color-mix(in srgb, var(--nj-exceptions-push) 12%, var(--md-default-bg-color)); stroke: var(--nj-exceptions-push); }
.nj-fig .nj-exceptions-badge--sched { fill: color-mix(in srgb, var(--nj-exceptions-sched) 12%, var(--md-default-bg-color)); stroke: var(--nj-exceptions-sched); }
.nj-fig .nj-exceptions-badge--cont { fill: color-mix(in srgb, var(--nj-exceptions-cont) 12%, var(--md-default-bg-color)); stroke: var(--nj-exceptions-cont); }
.nj-fig .nj-exceptions-badgetext--push { fill: var(--nj-exceptions-push); }
.nj-fig .nj-exceptions-badgetext--sched { fill: var(--nj-exceptions-sched); }
.nj-fig .nj-exceptions-badgetext--cont { fill: var(--nj-exceptions-cont); }
.nj-fig .nj-exceptions-stage { fill: var(--md-typeset-a-color); }
.nj-fig .nj-exceptions-stagetext { fill: #fff; font-size: 14px; font-weight: 700; text-anchor: middle; }
.nj-fig .nj-exceptions-stagesub { fill: #fff; fill-opacity: .85; font-size: 12px; text-anchor: middle; }
[data-md-color-scheme="slate"] .nj-fig .nj-exceptions-stage { fill: #1747a6; }
.nj-fig .nj-exceptions-qa .fg-head, .nj-exceptions-qa .fg-head { fill: var(--nj-exceptions-line); }
+176
View File
@@ -0,0 +1,176 @@
/* figures: integration */
/* namespace name builder (features/namespace.md, js/fig-integration.js) */
.md-typeset .nj-integration-ns {
--nj-int-line: color-mix(in srgb, currentColor 30%, var(--md-default-bg-color));
display: block;
width: auto;
max-width: none;
margin: 1.5rem 0;
padding: .9rem 1rem;
text-align: left;
border: 1px solid var(--nj-int-line);
border-radius: 8px;
}
.md-typeset .nj-integration-ns__strip {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: .5rem .15rem;
}
.md-typeset .nj-integration-ns__seg {
display: inline-flex;
flex-direction: column;
align-items: center;
min-width: 0;
}
.md-typeset .nj-integration-ns__seg code {
padding: .25em .5em;
border: 1.5px solid var(--nj-int-line);
border-radius: 6px;
background: var(--md-default-bg-color);
color: var(--md-default-fg-color);
font-size: .8rem;
font-weight: 600;
word-break: normal;
}
.md-typeset .nj-integration-ns__seg small {
max-width: 10rem;
margin-top: .25rem;
color: var(--md-default-fg-color--light);
font-size: .58rem;
line-height: 1.25;
text-align: center;
overflow-wrap: anywhere;
}
.md-typeset .nj-integration-ns__seg--sep code {
border-color: transparent;
padding-inline: .1em;
}
.md-typeset .nj-integration-ns__seg--abi code {
border-color: var(--md-typeset-a-color);
background: color-mix(in srgb, var(--md-typeset-a-color) 12%, var(--md-default-bg-color));
color: var(--md-typeset-a-color);
}
.md-typeset .nj-integration-ns__seg--tag code {
border-style: dashed;
border-color: var(--md-typeset-a-color);
color: var(--md-typeset-a-color);
}
.md-typeset .nj-integration-ns__seg--ver code {
background: color-mix(in srgb, currentColor 8%, var(--md-default-bg-color));
}
.md-typeset .nj-integration-ns figcaption {
max-width: none;
margin: .8rem 0 0;
font-size: .75rem;
text-align: left;
color: var(--md-default-fg-color--light);
}
.md-typeset .nj-integration-ns__controls {
margin-top: 1rem;
padding-top: .8rem;
border-top: 1px solid var(--nj-int-line);
font-size: .7rem;
}
.md-typeset .nj-integration-ns__version select {
min-height: 2rem;
margin-left: .3rem;
padding: 0 .4rem;
border: 1px solid var(--nj-int-line);
border-radius: 6px;
background: var(--md-default-bg-color);
color: var(--md-default-fg-color);
font: inherit;
}
.md-typeset .nj-integration-ns__list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 21rem), 1fr));
gap: 0 1rem;
margin: .7rem 0 0;
padding: 0;
border: 0;
}
.md-typeset .nj-integration-ns__list legend {
padding: 0;
margin-bottom: .3rem;
font-weight: 600;
}
.md-typeset .nj-integration-ns__opt {
display: grid;
grid-template-columns: 1.1rem 1fr;
align-items: center;
gap: 0 .55rem;
min-height: 2.2rem;
padding: .15rem 0;
cursor: pointer;
}
.md-typeset .nj-integration-ns__meta {
grid-column: 2;
display: flex;
flex-wrap: wrap;
gap: 0 .45rem;
}
.md-typeset .nj-integration-ns__opt input {
grid-row: 1 / span 2;
width: 1.1rem;
height: 1.1rem;
margin: 0;
accent-color: var(--md-typeset-a-color);
}
.md-typeset .nj-integration-ns__opt input:focus-visible {
outline: 2px solid var(--md-accent-fg-color);
outline-offset: 2px;
}
.md-typeset .nj-integration-ns__opt code {
font-size: .64rem;
overflow-wrap: anywhere;
}
.md-typeset .nj-integration-ns__hint {
color: var(--md-typeset-a-color);
font-family: var(--md-code-font-family);
font-size: .64rem;
}
.md-typeset .nj-integration-ns__since {
color: var(--md-default-fg-color--light);
font-size: .6rem;
}
.md-typeset .nj-integration-ns__opt.is-unavailable {
cursor: not-allowed;
opacity: .5;
}
@media screen and (max-width: 44.984375em) {
.md-typeset .nj-integration-ns__opt {
min-height: 2.75rem;
}
}
/* roadmap lanes and release timeline (scripts/figures/integration.py, release_timeline.py) */
.md-typeset svg.nj-fig--lanes { min-width: 44rem; max-width: 46rem; }
.md-typeset svg.nj-fig--timeline { min-width: 44rem; max-width: 52rem; }
.nj-fig .nj-int-lane { fill: color-mix(in srgb, var(--md-typeset-a-color) 10%, var(--md-default-bg-color)); stroke: var(--md-typeset-a-color); stroke-width: 1.5; }
.nj-fig .nj-int-lane--future { fill: none; stroke-dasharray: 6 4; }
.nj-fig .nj-int-lanetext { fill: var(--md-typeset-a-color); font-size: 15px; font-weight: 700; }
.nj-fig .nj-int-text { fill: currentColor; font-size: 13px; }
.nj-fig .nj-int-mute { fill: currentColor; fill-opacity: .7; font-size: 12.5px; }
.nj-fig .nj-int-macro { fill: currentColor; font-family: var(--md-code-font-family), monospace; font-size: 12.5px; }
.nj-fig .nj-int-val { fill: currentColor; font-family: var(--md-code-font-family), monospace; font-size: 13px; font-weight: 600; }
.nj-fig .nj-int-row { fill: color-mix(in srgb, currentColor 4%, var(--md-default-bg-color)); }
.nj-fig .nj-int-track { fill: color-mix(in srgb, currentColor 14%, var(--md-default-bg-color)); stroke: color-mix(in srgb, currentColor 45%, var(--md-default-bg-color)); stroke-width: 1.2; }
.nj-fig .nj-int-track--on { fill: var(--md-typeset-a-color); stroke: var(--md-typeset-a-color); }
.nj-fig .nj-int-knob { fill: var(--md-default-bg-color); stroke: color-mix(in srgb, currentColor 45%, var(--md-default-bg-color)); stroke-width: 1.2; }
.nj-fig .nj-int-knob--on { stroke: var(--md-typeset-a-color); }
.nj-fig .nj-int-axis { stroke: color-mix(in srgb, currentColor 45%, var(--md-default-bg-color)); stroke-width: 1.5; }
.nj-fig .nj-int-grid { stroke: color-mix(in srgb, currentColor 14%, var(--md-default-bg-color)); stroke-width: 1; }
.nj-fig .nj-int-minor { fill: var(--md-typeset-a-color); stroke: var(--md-default-bg-color); stroke-width: 1.5; }
.nj-fig .nj-int-patch { fill: var(--md-default-bg-color); stroke: var(--md-typeset-a-color); stroke-width: 1.5; }
.nj-fig .nj-int-major { fill: currentColor; fill-opacity: .7; font-size: 13px; font-weight: 600; }
.nj-fig .nj-int-label { fill: currentColor; font-size: 12px; font-weight: 600; text-anchor: middle; }
.nj-fig .nj-int-year { fill: currentColor; fill-opacity: .7; font-size: 12px; text-anchor: middle; }
.nj-fig .nj-int-leader { stroke: color-mix(in srgb, currentColor 30%, var(--md-default-bg-color)); stroke-width: 1; }
.nj-fig .nj-int-hit { fill: transparent; }
/* roadmap: value pills (3.x default -> 4.0 value) */
.nj-fig .nj-int-pill { fill: color-mix(in srgb, currentColor 8%, var(--md-default-bg-color)); stroke: color-mix(in srgb, currentColor 35%, var(--md-default-bg-color)); stroke-width: 1.2; }
.nj-fig .nj-int-pill--v4 { fill: var(--md-typeset-a-color); stroke: var(--md-typeset-a-color); }
.nj-fig .nj-int-val--v4 { fill: var(--md-default-bg-color); }
+107
View File
@@ -0,0 +1,107 @@
/* figures: jsonview (features/json_view.md; SVGs from scripts/figures/json_view_layout.py, stepper in js/fig-jsonview.js) */
/* one colour per concept, the same in every figure: structure (object/array, views) blue, keys navy, strings green,
numbers orange, decoded strings purple, owned edit storage teal, dangling/invalid red */
.nj-jsonview, .nj-jsonview-cmp {
--jv-struct: var(--nj-blue);
--jv-key: var(--nj-hl-key);
--jv-str: var(--nj-hl-string);
--jv-num: var(--nj-hl-number);
--jv-dec: var(--nj-hl-function);
--jv-own: var(--nj-hl-type);
--jv-bad: var(--nj-red);
--jv-line: color-mix(in srgb, currentColor 55%, var(--md-default-bg-color));
}
.md-typeset svg.nj-jsonview { min-width: 34rem; max-width: 42rem; }
.nj-jsonview .nj-jsonview-c-struct { --c: var(--jv-struct); }
.nj-jsonview .nj-jsonview-c-key { --c: var(--jv-key); }
.nj-jsonview .nj-jsonview-c-str { --c: var(--jv-str); }
.nj-jsonview .nj-jsonview-c-num { --c: var(--jv-num); }
.nj-jsonview .nj-jsonview-c-dec { --c: var(--jv-dec); }
.nj-jsonview .nj-jsonview-c-own { --c: var(--jv-own); }
.nj-jsonview .nj-jsonview-c-bad { --c: var(--jv-bad); }
.nj-jsonview .nj-jsonview-c-line { --c: var(--jv-line); }
.nj-jsonview text { fill: currentColor; font-size: 13px; }
.nj-jsonview text[class*="nj-jsonview-c-"] { fill: var(--c); }
.nj-jsonview .nj-jsonview-h { font-size: 15px; font-weight: 600; fill-opacity: .85; }
.nj-jsonview .nj-jsonview-sm2 { font-size: 14px; }
.nj-jsonview .nj-jsonview-note { font-size: 13px; fill-opacity: .75; }
.nj-jsonview .nj-jsonview-strong { font-weight: 600; fill-opacity: 1; }
.nj-jsonview .nj-jsonview-tiny { font-size: 10.5px; fill-opacity: .7; }
.nj-jsonview .nj-jsonview-mono { font-family: var(--md-code-font-family), monospace; font-size: 13px; }
.nj-jsonview .nj-jsonview-sm { font-size: 12px; }
.nj-jsonview .nj-jsonview-xs { font-size: 11px; }
.nj-jsonview .nj-jsonview-muted { fill-opacity: .75; }
.nj-jsonview .nj-jsonview-byte { font-size: 12px; }
.nj-jsonview .nj-jsonview-kind { font-size: 12.5px; font-weight: 700; }
.nj-jsonview .nj-jsonview-box { fill: var(--md-default-bg-color); stroke: var(--jv-line); stroke-width: 1.5; }
.nj-jsonview .nj-jsonview-heap { fill: color-mix(in srgb, currentColor 7%, var(--md-default-bg-color)); stroke: var(--jv-line); stroke-width: 1.5; stroke-dasharray: 5 3; }
.nj-jsonview .nj-jsonview-ribbon { fill: color-mix(in srgb, currentColor 4%, var(--md-default-bg-color)); stroke: var(--jv-line); stroke-width: 1.2; }
.nj-jsonview .nj-jsonview-span { fill: color-mix(in srgb, var(--c) 18%, var(--md-default-bg-color)); }
.nj-jsonview .nj-jsonview-frame { fill: none; stroke: var(--jv-line); stroke-width: 1.2; stroke-dasharray: 6 4; }
.nj-jsonview .nj-jsonview-store { fill: color-mix(in srgb, var(--jv-own) 6%, var(--md-default-bg-color)); stroke: color-mix(in srgb, var(--jv-own) 55%, var(--md-default-bg-color)); stroke-width: 1.2; stroke-dasharray: 6 4; }
.nj-jsonview .nj-jsonview-node { fill: color-mix(in srgb, var(--c) 12%, var(--md-default-bg-color)); stroke: var(--c); stroke-width: 1.5; }
.nj-jsonview .nj-jsonview-node.nj-jsonview-hot { stroke-width: 3; }
.nj-jsonview .nj-jsonview-node.nj-jsonview-gap { fill: var(--md-default-bg-color); stroke: var(--jv-bad); stroke-dasharray: 4 3; }
.nj-jsonview .nj-jsonview-node.nj-jsonview-free { fill: none; stroke-dasharray: 3 3; }
.nj-jsonview .nj-jsonview-sep { stroke: var(--jv-line); stroke-width: 1; fill: none; }
.nj-jsonview .nj-jsonview-arr { stroke: var(--c); stroke-width: 1.5; fill: none; }
.nj-jsonview .nj-jsonview-dash { stroke-dasharray: 4 3; }
.nj-jsonview .nj-jsonview-head { fill: var(--c); }
.nj-jsonview .nj-jsonview-bar { fill: color-mix(in srgb, var(--jv-struct) 30%, var(--md-default-bg-color)); stroke: var(--jv-struct); stroke-width: 1.2; }
.nj-jsonview .nj-jsonview-bad {
fill: color-mix(in srgb, var(--jv-bad) 20%, var(--md-default-bg-color));
stroke: var(--jv-bad); stroke-width: 1.2; stroke-dasharray: 4 2;
}
.nj-jsonview .nj-jsonview-evt { stroke: var(--jv-bad); stroke-width: 2; fill: none; }
.nj-jsonview .nj-jsonview-evt--ok { stroke: var(--jv-struct); stroke-dasharray: 4 3; }
.nj-jsonview .nj-jsonview-onbad, .nj-jsonview .nj-jsonview-onok { font-size: 11.5px; fill-opacity: 1; }
/* the edit stepper: without JS all frames are shown one below the other */
.nj-jsonview-steps { margin: 1.5rem 0; }
.md-typeset .nj-jsonview-step { display: block; width: 100%; max-width: none; margin: 0 0 1.5rem; }
.nj-jsonview-step > figcaption {
margin: .25rem 0 0; font-size: .75rem; color: var(--md-default-fg-color--light); text-align: left;
max-width: none;
}
.nj-jsonview-step > figcaption code { font-size: .95em; }
.nj-jsonview-step .nj-jsonview-scroll { overflow-x: auto; }
.md-typeset .nj-jsonview-steps.is-enhanced .nj-jsonview-step { display: none; margin: 0; }
.md-typeset .nj-jsonview-steps.is-enhanced .nj-jsonview-step.is-current { display: block; }
.nj-jsonview-controls { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: 0 0 .6rem; }
.nj-jsonview-controls button {
min-height: 2.2rem; min-width: 2.2rem; padding: 0 .8rem;
font: inherit; font-size: .7rem; font-weight: 600; cursor: pointer;
color: var(--md-typeset-a-color); background: var(--md-default-bg-color);
border: 1.5px solid var(--md-typeset-a-color); border-radius: .4rem;
}
.nj-jsonview-controls button:hover:not(:disabled) { background: color-mix(in srgb, var(--md-typeset-a-color) 10%, var(--md-default-bg-color)); }
.nj-jsonview-controls button:focus-visible { outline: 2px solid var(--md-accent-fg-color); outline-offset: 2px; }
.nj-jsonview-controls button:disabled { opacity: .45; cursor: default; }
.nj-jsonview-controls button[aria-current="step"], .nj-jsonview-controls button[aria-current="step"]:hover { color: var(--md-default-bg-color); background: var(--md-typeset-a-color); }
.nj-jsonview-controls .nj-jsonview-status { font-size: .7rem; color: var(--md-default-fg-color--light); margin-left: .25rem; }
@media (max-width: 44.9375em) {
.nj-jsonview-controls button { min-height: 44px; min-width: 44px; }
}
@media (prefers-reduced-motion: no-preference) {
.nj-jsonview-steps.is-enhanced .nj-jsonview-step.is-current { animation: nj-jsonview-fade .25s ease-out; }
}
@keyframes nj-jsonview-fade { from { opacity: .3; } to { opacity: 1; } }
/* json vs ordered_json vs editable document */
.nj-jsonview-cmp { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6rem; margin: 1.2rem 0; }
.nj-jsonview-cmp > div {
border: 1px solid var(--md-default-fg-color--lightest); border-radius: .4rem; padding: .5rem .6rem .6rem;
background: var(--md-code-bg-color); min-width: 0;
}
.nj-jsonview-cmp > div.nj-jsonview-cmp--best { border-color: var(--jv-struct); }
.nj-jsonview-cmp .nj-jsonview-cmp-h { font-size: .7rem; font-weight: 600; margin: 0 0 .1rem; }
.nj-jsonview-cmp .nj-jsonview-cmp-v { font-size: .64rem; color: var(--md-default-fg-color--light); margin: 0 0 .4rem; }
.md-typeset .nj-jsonview-cmp pre { margin: 0; font-family: var(--md-code-font-family), monospace; font-size: .68rem; line-height: 1.5; white-space: pre; overflow-x: auto; background: none; color: var(--md-code-fg-color); }
.nj-jsonview-cmp .nj-jsonview-bad { color: var(--jv-bad); font-weight: 600; text-decoration: underline wavy; text-underline-offset: 3px; }
.nj-jsonview-cmp .nj-jsonview-ok { color: var(--jv-own); font-weight: 600; }
@media (max-width: 44.9375em) {
.nj-jsonview-cmp { grid-template-columns: minmax(0, 1fr); }
}
+98
View File
@@ -0,0 +1,98 @@
/* figures: macro chooser (js/fig-macros.js) on features/arbitrary_types.md; colours come from the brand
variables in brand.css, which switch with the light/slate scheme */
.nj-macro-chooser {
--nj-mc-line: color-mix(in srgb, currentColor 18%, var(--md-default-bg-color));
--nj-mc-panel: color-mix(in srgb, currentColor 3%, var(--md-default-bg-color));
--nj-mc-ink2: var(--md-default-fg-color--light);
margin: 1.2em 0 1.6em;
font-size: .74rem;
}
.md-typeset .nj-macro-chooser .nj-mc-fallback > :first-child { margin-top: 0; }
.nj-mc-app { border: 1px solid var(--nj-mc-line); border-radius: .3rem; background: var(--nj-mc-panel);
padding: .9rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.nj-mc-form, .nj-mc-out, .nj-mc-editor, .nj-mc-members, .nj-mc-mbody { grid-template-columns: minmax(0, 1fr); }
.nj-mc-form { display: grid; gap: 1rem; margin: 0; }
/* questions as segmented radio groups */
.nj-mc-questions { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(14.5rem, 100%), 1fr)); gap: .7rem .9rem; }
.nj-mc-q { border: 0; margin: 0; padding: 0; min-width: 0; }
.nj-mc-q legend { font-weight: 600; padding: 0; margin-bottom: .3rem; font-size: .7rem; }
.nj-mc-seg { display: flex; border: 1px solid var(--nj-mc-line); border-radius: .25rem; overflow: hidden;
background: var(--md-default-bg-color); }
.nj-mc-seg input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.nj-mc-seg label { flex: 1 1 0; display: flex; align-items: center; justify-content: center; text-align: center;
min-height: 2.1rem; padding: .25rem .5rem; cursor: pointer; line-height: 1.25; font-size: .7rem;
color: var(--md-default-fg-color); transition: background-color .15s, color .15s; }
.nj-mc-seg label + input + label { border-left: 1px solid var(--nj-mc-line); }
.nj-mc-seg label:hover { background: var(--nj-blue-soft); }
.nj-mc-seg input:checked + label { background: var(--nj-blue); color: var(--md-default-bg-color); font-weight: 600; }
.nj-mc-seg input:focus-visible + label { outline: 2px solid var(--md-accent-fg-color); outline-offset: -3px; }
.nj-mc-q:disabled .nj-mc-seg { opacity: .45; }
.nj-mc-q:disabled label { cursor: not-allowed; }
.nj-mc-q:disabled label:hover { background: transparent; }
.md-typeset .nj-mc-qnote { margin: .3rem 0 0; font-size: .64rem; line-height: 1.4; color: var(--nj-mc-ink2); }
/* type editor */
.nj-mc-editor { display: grid; gap: .6rem; border-top: 1px solid var(--nj-mc-line); padding-top: .9rem; }
.nj-mc-names { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr)); gap: .6rem .9rem; }
.nj-mc-field { display: grid; gap: .2rem; }
.nj-mc-field label { font-weight: 600; font-size: .7rem; }
.nj-mc-field[hidden] { display: none; }
.nj-macro-chooser input[type="text"] { font-family: var(--md-code-font-family), monospace; font-size: .7rem;
min-height: 2.1rem; padding: .2rem .45rem; min-width: 0; width: 100%; box-sizing: border-box;
border: 1px solid var(--nj-mc-line); border-radius: .2rem; background: var(--md-default-bg-color);
color: var(--md-default-fg-color); }
.nj-macro-chooser input[type="text"]:focus { outline: 2px solid var(--md-accent-fg-color); outline-offset: 0; border-color: transparent; }
.nj-mc-members { display: grid; gap: .35rem; }
.nj-mc-mbody { display: grid; gap: .35rem; }
.nj-mc-mrow { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) 2.2rem; gap: .4rem; align-items: center; }
.nj-mc-custom .nj-mc-mrow { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr) 2.2rem; }
.nj-mc-mrow .nj-mc-keycol { display: none; }
.nj-mc-custom .nj-mc-mrow .nj-mc-keycol { display: block; }
.nj-mc-mhead { font-weight: 600; font-size: .66rem; color: var(--nj-mc-ink2); }
.nj-mc-mhead .nj-mc-keycol[hidden] { display: none; }
.nj-macro-chooser button { font: inherit; cursor: pointer; border-radius: .2rem; }
.nj-macro-chooser button:focus-visible { outline: 2px solid var(--md-accent-fg-color); outline-offset: 2px; }
.nj-mc-rm { width: 2.2rem; height: 2.1rem; border: 1px solid var(--nj-mc-line); background: var(--md-default-bg-color);
color: var(--nj-mc-ink2); font-size: 1rem; line-height: 1; padding: 0; }
.nj-mc-rm:hover { color: var(--nj-red); border-color: var(--nj-red); }
.nj-mc-add, .nj-mc-copy { justify-self: start; min-height: 2.1rem; padding: .2rem .8rem; font-size: .7rem; font-weight: 600;
border: 1px solid var(--nj-blue); background: var(--md-default-bg-color); color: var(--nj-blue); }
.nj-mc-add:hover, .nj-mc-copy:hover { background: var(--nj-blue-soft); }
/* output */
.nj-mc-out { display: grid; gap: .7rem; }
.nj-mc-result { border-left: .2rem solid var(--nj-blue); background: var(--nj-blue-soft); border-radius: 0 .2rem .2rem 0;
padding: .55rem .8rem; }
.nj-mc-result.nj-mc-bad { border-left-color: var(--nj-red); background: var(--nj-red-soft); }
.md-typeset .nj-mc-result p { margin: 0; }
.md-typeset .nj-mc-result p + p { margin-top: .3rem; }
.md-typeset .nj-mc-label { font-size: .64rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--nj-mc-ink2); }
.md-typeset .nj-mc-macro code { font-size: .8rem; font-weight: 600; background: transparent; padding: 0;
overflow-wrap: anywhere; color: var(--md-default-fg-color); }
.md-typeset .nj-mc-why { line-height: 1.5; }
.md-typeset .nj-mc-hints { margin: 0; padding-left: 1.1rem; font-size: .68rem; color: var(--nj-mc-ink2); }
.md-typeset .nj-mc-hints li { margin: 0; }
.nj-mc-hints[hidden], .nj-mc-code[hidden] { display: none; }
.nj-mc-codebar { display: flex; align-items: center; gap: .6rem; margin-bottom: .3rem; }
.nj-mc-codetitle { font-weight: 600; font-size: .7rem; margin-right: auto; }
.nj-mc-copystatus { font-size: .66rem; color: var(--nj-mc-ink2); }
.md-typeset .nj-mc-code .highlight { margin: 0; }
.md-typeset .nj-mc-code pre { margin: 0; }
.md-typeset .nj-mc-code pre > code { max-height: 34rem; }
@media (max-width: 44.9375em) {
.nj-mc-app { padding: .7rem; }
.nj-mc-seg label, .nj-macro-chooser input[type="text"], .nj-mc-add, .nj-mc-copy { min-height: 2.75rem; }
.nj-mc-rm { width: 2.75rem; height: 2.75rem; }
.nj-mc-mrow, .nj-mc-custom .nj-mc-mrow { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 2.75rem; }
.nj-mc-custom .nj-mc-mrow .nj-mc-keycol { grid-column: 1 / 3; }
.nj-mc-custom .nj-mc-mhead { display: none; }
}
@media (prefers-reduced-motion: reduce) {
.nj-mc-seg label { transition: none; }
}
+459
View File
@@ -0,0 +1,459 @@
/* figures: pointer (features/json_pointer.md, json_patch.md, merge_patch.md; widgets in js/fig-pointer.js) */
/* value types: the colours of the code highlighting (brand.css), so a string looks the same everywhere */
.nj-pointer-walk, .nj-pointer-fl, .nj-patch {
--nj-pointer-s: var(--nj-hl-string);
--nj-pointer-n: var(--nj-hl-number);
--nj-pointer-b: var(--nj-hl-function);
--nj-pointer-line: color-mix(in srgb, var(--md-default-fg-color) 28%, var(--md-default-bg-color));
--nj-pointer-ok: #23793a;
--nj-pointer-ok-soft: #e6f4ea;
}
[data-md-color-scheme="slate"] :is(.nj-pointer-walk, .nj-pointer-fl, .nj-patch) {
--nj-pointer-ok: #7ed491;
--nj-pointer-ok-soft: #14301d;
}
/* ---------- pointer walker ---------- */
.md-typeset .nj-pointer-walk {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem 1.6rem;
margin: 1.5rem 0;
padding: 1rem 1.1rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 6px;
font-size: .75rem;
}
@media screen and (min-width: 45em) {
.md-typeset .nj-pointer-walk--js {
grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
}
.md-typeset .nj-pointer-walk--js .nj-pointer-panel { order: 2; }
}
.md-typeset .nj-pointer-static {
margin: 0;
color: var(--md-default-fg-color--light);
}
.md-typeset .nj-pointer-walk code {
font-size: .95em;
}
/* tree: elbow lines drawn by each item (::before up to its row, ::after down to the next sibling) */
.md-typeset .nj-pointer-walk ul.nj-pointer-tree,
.md-typeset .nj-pointer-walk .nj-pointer-tree ul {
margin: 0;
padding: 0;
list-style: none;
}
.md-typeset .nj-pointer-walk .nj-pointer-tree ul {
padding-left: 1.5rem;
}
.md-typeset .nj-pointer-walk .nj-pointer-tree li {
position: relative;
margin: 0;
padding: 0;
list-style: none;
--nj-pointer-mid: .95rem;
}
.md-typeset .nj-pointer-walk .nj-pointer-tree li::before,
.md-typeset .nj-pointer-walk .nj-pointer-tree li::after {
content: none;
}
.md-typeset .nj-pointer-walk .nj-pointer-tree ul > li::before {
content: "";
position: absolute;
top: 0;
left: -1rem;
width: .8rem;
height: var(--nj-pointer-mid);
border: 0 solid var(--nj-pointer-line);
border-width: 0 0 2px 2px;
border-bottom-left-radius: 4px;
background: none;
}
.md-typeset .nj-pointer-walk .nj-pointer-tree ul > li:not(:last-child)::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -1rem;
border-left: 2px solid var(--nj-pointer-line);
}
.md-typeset .nj-pointer-walk .nj-pointer-tree ul > li.is-on::before {
z-index: 1;
border-color: var(--md-typeset-a-color);
}
.md-typeset .nj-pointer-walk .nj-pointer-tree ul > li.is-pass::after {
z-index: 1;
border-left-color: var(--md-typeset-a-color);
}
.md-typeset .nj-pointer-walk .nj-pointer-n {
display: inline-block;
margin: .15rem 0;
padding: .2rem .5rem;
border: 1px solid transparent;
border-radius: 6px;
background: none;
color: var(--md-default-fg-color);
font: inherit;
font-family: var(--md-code-font-family), monospace;
font-size: .95em;
line-height: 1.5;
text-align: left;
}
.md-typeset .nj-pointer-walk button.nj-pointer-n {
cursor: pointer;
}
.md-typeset .nj-pointer-walk button.nj-pointer-n:hover {
border-color: var(--md-default-fg-color--lightest);
}
.md-typeset .nj-pointer-walk :is(button):focus-visible {
outline: 2px solid var(--md-typeset-a-color);
outline-offset: 2px;
}
.nj-pointer-k { color: var(--nj-hl-key); }
.nj-pointer-t {
color: var(--md-default-fg-color--light);
font-family: var(--md-text-font-family), sans-serif;
font-size: .88em;
font-style: italic;
}
.nj-pointer-v--s { color: var(--nj-pointer-s); }
.nj-pointer-v--n { color: var(--nj-pointer-n); }
.nj-pointer-v--b { color: var(--nj-pointer-b); }
.md-typeset .nj-pointer-walk li.is-on > .nj-pointer-n {
border-color: color-mix(in srgb, var(--md-typeset-a-color) 45%, transparent);
}
.md-typeset .nj-pointer-walk li.is-target > .nj-pointer-n {
border-color: var(--md-typeset-a-color);
background-color: var(--nj-blue-soft);
box-shadow: 0 0 0 1px var(--md-typeset-a-color);
}
/* the value a container pointer identifies includes its subtree */
.md-typeset .nj-pointer-walk li.is-target li > .nj-pointer-n {
background-color: var(--nj-blue-soft);
}
.md-typeset .nj-pointer-walk li.is-miss > .nj-pointer-n {
border-color: var(--nj-red);
border-style: dashed;
}
/* panel: pointer bar, result, example pointers */
.nj-pointer-lbl {
margin: 0 0 .35rem;
color: var(--md-default-fg-color--light);
font-size: .62rem;
font-weight: 600;
letter-spacing: .04em;
text-transform: uppercase;
}
.nj-pointer-lbl span {
font-weight: 500;
letter-spacing: 0;
text-transform: none;
}
.nj-pointer-bar {
display: flex;
flex-wrap: wrap;
margin-bottom: .6rem;
}
.md-typeset .nj-pointer-seg {
margin: 0 -1px 0 0;
padding: .3rem .55rem;
border: 1px solid var(--md-typeset-a-color);
background-color: var(--md-default-bg-color);
color: var(--md-typeset-a-color);
cursor: pointer;
font: inherit;
}
.md-typeset .nj-pointer-seg:first-child { border-radius: 6px 0 0 6px; }
.md-typeset .nj-pointer-seg:last-child { border-radius: 0 6px 6px 0; }
.md-typeset .nj-pointer-seg:only-child { border-radius: 6px; }
.md-typeset .nj-pointer-seg code { color: inherit; font-size: 1em; }
.md-typeset .nj-pointer-seg--root code { color: var(--md-default-fg-color--light); }
.md-typeset .nj-pointer-seg.is-after {
border-color: var(--md-default-fg-color--lighter);
color: var(--md-default-fg-color--light);
border-style: dashed;
}
.md-typeset .nj-pointer-seg[aria-pressed="true"] {
position: relative;
background-color: var(--md-typeset-a-color);
color: var(--md-default-bg-color);
}
.md-typeset .nj-pointer-seg--root[aria-pressed="true"] code { color: inherit; }
.nj-pointer-out {
min-height: 3.2em;
margin-bottom: .9rem;
padding: .5rem .7rem;
border-left: 3px solid var(--md-typeset-a-color);
border-radius: 0 6px 6px 0;
background-color: var(--md-code-bg-color);
line-height: 1.6;
overflow-wrap: anywhere;
}
.md-typeset .nj-pointer-out .nj-pointer-val { color: var(--md-typeset-a-color); font-weight: 600; }
.nj-pointer-out .nj-pointer-note { color: var(--md-default-fg-color--light); }
.nj-pointer-out .nj-pointer-err { color: var(--nj-red); font-weight: 600; }
.nj-pointer-presets {
display: flex;
flex-wrap: wrap;
gap: .35rem;
}
.md-typeset .nj-pointer-chip {
padding: .2rem .5rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 6px;
background-color: var(--md-default-bg-color);
color: var(--md-default-fg-color);
cursor: pointer;
font: inherit;
}
.md-typeset .nj-pointer-chip:hover { border-color: var(--md-typeset-a-color); }
.md-typeset .nj-pointer-chip[aria-pressed="true"] {
border-color: var(--md-typeset-a-color);
background-color: var(--nj-blue-soft);
color: var(--md-typeset-a-color);
}
.md-typeset .nj-pointer-chip code { color: inherit; font-size: 1em; }
@media (pointer: coarse), screen and (max-width: 44.984375em) {
.md-typeset :is(.nj-pointer-seg, .nj-pointer-chip, .nj-patch-btn) { min-height: 44px; min-width: 44px; }
.md-typeset .nj-pointer-walk button.nj-pointer-n { min-height: 40px; }
}
/* ---------- flatten / unflatten figure (scripts/figures/json_pointer_flatten.py) ---------- */
.md-typeset svg.nj-pointer-fl { min-width: 28rem; max-width: 44rem; }
.nj-pointer-fl .nj-pointer-fl-edge { fill: none; stroke: var(--fg-line); stroke-width: 1.5; }
.nj-pointer-fl .nj-pointer-fl-link { fill: none; stroke-width: 1.5; stroke-opacity: .75; }
.nj-pointer-fl .nj-pointer-fl-link.nj-pointer-fl--s, .nj-pointer-fl .nj-pointer-fl-dot.nj-pointer-fl--s { stroke: var(--nj-pointer-s); }
.nj-pointer-fl .nj-pointer-fl-link.nj-pointer-fl--n, .nj-pointer-fl .nj-pointer-fl-dot.nj-pointer-fl--n { stroke: var(--nj-pointer-n); }
.nj-pointer-fl .nj-pointer-fl-link.nj-pointer-fl--b, .nj-pointer-fl .nj-pointer-fl-dot.nj-pointer-fl--b { stroke: var(--nj-pointer-b); }
.nj-pointer-fl .nj-pointer-fl-dot { fill: var(--md-default-bg-color); stroke-width: 2; }
.nj-pointer-fl tspan.nj-pointer-fl--s { fill: var(--nj-pointer-s); }
.nj-pointer-fl tspan.nj-pointer-fl--n { fill: var(--nj-pointer-n); }
.nj-pointer-fl tspan.nj-pointer-fl--b { fill: var(--nj-pointer-b); }
.nj-pointer-fl .nj-pointer-fl-k, .nj-pointer-fl .nj-pointer-fl-inner, .nj-pointer-fl .nj-pointer-fl-key { fill: var(--nj-hl-key); }
.nj-pointer-fl .nj-pointer-fl-op {
fill: var(--md-typeset-a-color);
font-family: var(--md-code-font-family), monospace;
font-size: 15px;
font-weight: 600;
text-anchor: middle;
}
/* ---------- JSON Patch stepper ---------- */
.md-typeset .nj-patch--js .md-typeset__scrollwrap,
.md-typeset .nj-patch--js > .md-typeset__table,
.md-typeset .nj-patch--js > table {
display: none;
}
.md-typeset .nj-patch-stage {
margin: 1.5rem 0;
padding: 1rem 1.1rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 6px;
font-size: .75rem;
}
.nj-patch-cols {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem 1.4rem;
}
@media screen and (min-width: 50em) {
.nj-patch-cols { grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); }
}
.nj-patch-h {
margin: 0 0 .35rem;
color: var(--md-default-fg-color--light);
font-size: .62rem;
font-weight: 600;
letter-spacing: .04em;
text-transform: uppercase;
}
.nj-patch-doc {
--nj-patch-lh: 1.9rem;
--nj-patch-pad: .5rem;
position: relative;
padding: var(--nj-patch-pad) .6rem var(--nj-patch-pad) 2rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 6px;
background-color: var(--md-code-bg-color);
font-family: var(--md-code-font-family), monospace;
font-size: .95em;
}
.nj-patch-line {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0 .6rem;
min-height: var(--nj-patch-lh);
margin: 0 -.3rem;
padding: 0 .3rem;
border-radius: 4px;
white-space: pre;
}
.nj-patch-code { white-space: pre; }
.nj-patch-k { color: var(--nj-hl-key); }
.nj-patch-s { color: var(--nj-pointer-s); }
.nj-patch-note {
padding: 0 .4rem;
border-radius: 4px;
font-family: var(--md-text-font-family), sans-serif;
font-size: .82em;
font-weight: 600;
white-space: nowrap;
}
.nj-patch-line--add { background-color: var(--nj-pointer-ok-soft); box-shadow: inset 3px 0 0 var(--nj-pointer-ok); }
.nj-patch-line--add .nj-patch-note { color: var(--nj-pointer-ok); }
.nj-patch-line--del { background-color: var(--nj-red-soft); box-shadow: inset 3px 0 0 var(--nj-red); }
.nj-patch-line--del .nj-patch-code { text-decoration: line-through; text-decoration-color: var(--nj-red); text-decoration-thickness: 2px; opacity: .75; }
.nj-patch-line--del .nj-patch-note { color: var(--nj-red); }
.nj-patch-line--mod .nj-patch-note { color: var(--nj-pointer-ok); }
.nj-patch-line--test { background-color: var(--nj-blue-soft); box-shadow: inset 3px 0 0 var(--md-typeset-a-color); }
.nj-patch-line--test .nj-patch-note { color: var(--md-typeset-a-color); }
.nj-patch-ins { padding: .05rem .15rem; border-radius: 3px; background-color: var(--nj-pointer-ok-soft); box-shadow: 0 0 0 1.5px var(--nj-pointer-ok); }
.nj-patch-src { padding: .05rem .15rem; border-radius: 3px; box-shadow: 0 0 0 1.5px var(--md-typeset-a-color); }
/* move/copy connector in the left gutter: a bracket from the source line to the target line */
.nj-patch-arc {
position: absolute;
left: .55rem;
width: .8rem;
border: 2px solid var(--md-typeset-a-color);
border-right: 0;
border-radius: 6px 0 0 6px;
}
.nj-patch-arc::after {
content: "";
position: absolute;
right: -2px;
border: 5px solid transparent;
border-left: 7px solid var(--md-typeset-a-color);
}
.nj-patch-arc--down::after { bottom: -6px; }
.nj-patch-arc--up::after { top: -6px; }
.md-typeset .nj-patch-ops {
margin: 0;
padding: 0;
list-style: none;
counter-reset: nj-patch;
}
.md-typeset .nj-patch-ops > li {
position: relative;
margin: 0 0 .3rem;
padding: .35rem .5rem .35rem 2rem;
border: 1px solid transparent;
border-radius: 6px;
counter-increment: nj-patch;
line-height: 1.5;
}
.md-typeset .nj-patch-ops > li::before {
content: counter(nj-patch);
position: absolute;
top: .35rem;
left: .6rem;
color: var(--md-default-fg-color--lighter);
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.md-typeset .nj-patch-ops code { font-size: .9em; overflow-wrap: anywhere; }
.md-typeset .nj-patch-ops > li.is-done { opacity: .6; }
.md-typeset .nj-patch-ops > li.is-cur {
border-color: var(--md-typeset-a-color);
background-color: var(--nj-blue-soft);
}
.md-typeset .nj-patch-ops > li.is-cur::before { color: var(--md-typeset-a-color); }
.nj-patch-op { color: var(--nj-hl-keyword); font-weight: 600; }
.nj-patch-path { color: var(--nj-pointer-s); }
.md-typeset .nj-patch-ops > li.is-cur .nj-patch-path {
padding: 0 .15rem;
border-radius: 3px;
background-color: var(--md-typeset-a-color);
color: var(--md-default-bg-color);
}
.nj-patch-ctrl {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: .4rem;
margin-top: .9rem;
}
.md-typeset .nj-patch-btn {
padding: .3rem .9rem;
border: 1px solid var(--md-default-fg-color--lighter);
border-radius: 6px;
background-color: var(--md-default-bg-color);
color: var(--md-default-fg-color);
cursor: pointer;
font: inherit;
font-weight: 600;
}
.md-typeset .nj-patch-btn--primary {
border-color: var(--md-typeset-a-color);
background-color: var(--md-typeset-a-color);
color: var(--md-default-bg-color);
}
.md-typeset .nj-patch-btn:disabled { opacity: .45; cursor: default; }
.md-typeset .nj-patch-btn:focus-visible { outline: 2px solid var(--md-typeset-a-color); outline-offset: 2px; }
.nj-patch-count {
margin-left: auto;
color: var(--md-default-fg-color--light);
font-variant-numeric: tabular-nums;
}
.md-typeset .nj-patch-status {
min-height: 3.2em;
margin: .6rem 0 0;
color: var(--md-default-fg-color--light);
}
@media (prefers-reduced-motion: no-preference) {
.nj-patch-doc--anim :is(.nj-patch-line--add, .nj-patch-line--del, .nj-patch-line--test, .nj-patch-ins, .nj-patch-arc) {
animation: nj-patch-in 450ms ease-out;
}
}
@keyframes nj-patch-in {
from { opacity: 0; transform: translateX(-.4rem); }
to { opacity: 1; transform: none; }
}
/* ---------- merge patch table ---------- */
.nj-pointer-mpt {
--nj-pointer-mp-set: var(--nj-hl-keyword);
--nj-pointer-mp-add: #23793a;
--nj-pointer-mp-del: var(--nj-red);
--nj-pointer-mp-rec: var(--nj-hl-function);
--nj-pointer-mp-arr: var(--nj-hl-number);
--nj-pointer-mp-keep: var(--md-default-fg-color--light);
}
[data-md-color-scheme="slate"] .nj-pointer-mpt { --nj-pointer-mp-add: #7ed491; }
.md-typeset .nj-pointer-mpt td { vertical-align: top; }
.md-typeset .nj-pointer-mpt td:first-child { white-space: nowrap; }
.nj-pointer-mp {
display: inline-block;
padding: .05rem .5rem;
border: 1px solid currentColor;
border-radius: 999px;
background-color: color-mix(in srgb, currentColor 10%, var(--md-default-bg-color));
font-size: .92em;
font-weight: 600;
line-height: 1.5;
white-space: nowrap;
}
.nj-pointer-mp--set { color: var(--nj-pointer-mp-set); }
.nj-pointer-mp--add { color: var(--nj-pointer-mp-add); }
.nj-pointer-mp--del { color: var(--nj-pointer-mp-del); }
.nj-pointer-mp--rec { color: var(--nj-pointer-mp-rec); }
.nj-pointer-mp--arr { color: var(--nj-pointer-mp-arr); }
.nj-pointer-mp--keep { color: var(--nj-pointer-mp-keep); }
.nj-pointer-mp-none { color: var(--md-default-fg-color--light); font-style: italic; }
.md-typeset .nj-pointer-mpt table:not([class]) td code { white-space: normal; }
.md-typeset .nj-pointer-mpt table:not([class]) td:nth-child(-n+2) code { white-space: nowrap; }
/* the result cell takes a tint of the rule's colour */
.md-typeset .nj-pointer-mpt tr:has(.nj-pointer-mp--set) td:last-child { background-color: color-mix(in srgb, var(--nj-pointer-mp-set) 8%, transparent); }
.md-typeset .nj-pointer-mpt tr:has(.nj-pointer-mp--add) td:last-child { background-color: color-mix(in srgb, var(--nj-pointer-mp-add) 8%, transparent); }
.md-typeset .nj-pointer-mpt tr:has(.nj-pointer-mp--del) td:last-child { background-color: color-mix(in srgb, var(--nj-pointer-mp-del) 8%, transparent); }
.md-typeset .nj-pointer-mpt tr:has(.nj-pointer-mp--rec) td:last-child { background-color: color-mix(in srgb, var(--nj-pointer-mp-rec) 8%, transparent); }
.md-typeset .nj-pointer-mpt tr:has(.nj-pointer-mp--arr) td:last-child { background-color: color-mix(in srgb, var(--nj-pointer-mp-arr) 8%, transparent); }
+207
View File
@@ -0,0 +1,207 @@
/* figures: sax (SAX event stepper on features/parsing/sax_interface.md, js/fig-sax.js; memory_over_time.svg and
chunk_buffering.svg on features/parsing/large_and_partial_input.md). Event colours are the --cb-* variables of the
parser-callback figure in brand.css, which .nj-fig provides. */
/* ---------- stepper ---------- */
.md-typeset .nj-sax {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: .9rem 1.4rem;
margin: 1.5rem 0;
padding: 1rem 1.1rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 8px;
background: var(--md-default-bg-color);
font-size: .74rem;
}
@media screen and (min-width: 45em) {
.md-typeset .nj-sax {
grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
grid-template-areas: "ctl ctl" "text text" "ev state" "status status";
}
.md-typeset .nj-sax > .nj-sax__controls { grid-area: ctl; }
.md-typeset .nj-sax > .nj-sax__lane--text { grid-area: text; }
.md-typeset .nj-sax > .nj-sax__lane--events { grid-area: ev; }
.md-typeset .nj-sax > .nj-sax__lane--state { grid-area: state; }
.md-typeset .nj-sax > .nj-sax__status { grid-area: status; }
}
.md-typeset .nj-sax p { margin: 0; }
.md-typeset .nj-sax .nj-sax__h {
margin: 0 0 .45rem;
color: var(--md-default-fg-color--light);
font-size: .68rem;
font-weight: 600;
letter-spacing: .02em;
}
.md-typeset .nj-sax .nj-sax__h code { font-size: .95em; }
.md-typeset .nj-sax .nj-sax__text code {
display: inline-block;
max-width: 100%;
overflow-x: auto;
padding: .35rem .6rem;
font-size: .95rem;
white-space: pre;
word-break: normal;
}
.nj-sax .nj-sax-unread { color: var(--md-default-fg-color--light); }
.nj-sax .nj-sax-unread--never { color: var(--md-default-fg-color--lighter); text-decoration: line-through; text-decoration-color: var(--md-default-fg-color--lighter); }
.nj-sax .nj-sax-read { color: var(--md-code-fg-color); }
.nj-sax .nj-sax-tok { border-radius: 3px; box-shadow: inset 0 -3px 0 var(--nj-sax-ev, var(--cb-v)); background: color-mix(in srgb, var(--nj-sax-ev, var(--cb-v)) 22%, transparent); }
.nj-sax .nj-sax-tok--os, .nj-sax .nj-sax-ev--os { --nj-sax-ev: var(--cb-os); }
.nj-sax .nj-sax-tok--oe, .nj-sax .nj-sax-ev--oe { --nj-sax-ev: var(--cb-oe); }
.nj-sax .nj-sax-tok--k, .nj-sax .nj-sax-ev--k { --nj-sax-ev: var(--cb-k); }
.nj-sax .nj-sax-tok--as, .nj-sax .nj-sax-ev--as { --nj-sax-ev: var(--cb-as); }
.nj-sax .nj-sax-tok--ae, .nj-sax .nj-sax-ev--ae { --nj-sax-ev: var(--cb-ae); }
.nj-sax .nj-sax-tok--v, .nj-sax .nj-sax-ev--v { --nj-sax-ev: var(--cb-v); }
/* event ticker */
.md-typeset .nj-sax ol.nj-sax__events {
margin: 0;
padding: 0;
list-style: none;
counter-reset: nj-sax;
}
.md-typeset .nj-sax ol.nj-sax__events > li {
position: relative;
margin: 0 0 .2rem;
padding: .12rem .4rem .12rem 2.6rem;
border-radius: 5px;
counter-increment: nj-sax;
line-height: 1.5;
}
.md-typeset .nj-sax ol.nj-sax__events > li::before {
content: counter(nj-sax);
position: absolute;
left: .35rem;
top: .2rem;
width: 1.1rem;
color: var(--md-default-fg-color--lighter);
font-size: .64rem;
font-variant-numeric: tabular-nums;
text-align: right;
}
.md-typeset .nj-sax ol.nj-sax__events > li::after {
content: "";
position: absolute;
left: 1.75rem;
top: 50%;
width: .55rem;
height: .55rem;
margin-top: -.275rem;
border-radius: 50%;
background: var(--nj-sax-ev);
}
.md-typeset .nj-sax ol.nj-sax__events code { background: none; padding: 0; font-size: .8rem; }
.nj-sax .nj-sax-ev--todo { opacity: .42; }
.nj-sax .nj-sax-ev--skip { opacity: .42; text-decoration: line-through; }
.nj-sax .nj-sax-ev--skip::after { background: var(--md-default-fg-color--lighter) !important; }
.nj-sax .nj-sax-ev--cur { background: color-mix(in srgb, var(--nj-sax-ev) 16%, transparent); }
.md-typeset .nj-sax .nj-sax-ev--false > code::after {
content: " \2192 false";
color: var(--nj-red);
font-weight: 600;
}
/* handler state */
.md-typeset .nj-sax pre.nj-sax__tree { margin: 0 0 .6rem; }
.md-typeset .nj-sax pre.nj-sax__tree > code { padding: .5rem .7rem; font-size: .76rem; line-height: 1.45; }
.nj-sax .nj-sax-hit { border-radius: 3px; background: color-mix(in srgb, var(--nj-blue) 22%, transparent); box-shadow: 0 0 0 1px color-mix(in srgb, var(--nj-blue) 55%, transparent); }
.nj-sax .nj-sax-dim { color: var(--md-default-fg-color--lighter); }
.md-typeset .nj-sax .nj-sax__stackh { margin: 0 0 .3rem; color: var(--md-default-fg-color--light); font-size: .66rem; font-weight: 600; }
.md-typeset .nj-sax ol.nj-sax__stack {
display: flex;
flex-direction: column-reverse;
gap: .25rem;
margin: 0 0 .6rem;
padding: 0;
list-style: none;
}
.md-typeset .nj-sax ol.nj-sax__stack > li {
margin: 0;
padding: .2rem .5rem;
border: 1px solid var(--md-default-fg-color--lightest);
border-left: 3px solid var(--nj-blue);
border-radius: 4px;
}
.md-typeset .nj-sax ol.nj-sax__stack > li.nj-sax-dim { border-left-color: var(--md-default-fg-color--lightest); }
.md-typeset .nj-sax ol.nj-sax__stack code { background: none; padding: 0; }
.md-typeset .nj-sax .nj-sax__note { color: var(--md-default-fg-color--light); font-size: .75rem; line-height: 1.5; }
.md-typeset .nj-sax dl.nj-sax__kv {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: .35rem .8rem;
margin: 0 0 .6rem;
}
.md-typeset .nj-sax dl.nj-sax__kv dt { color: var(--md-default-fg-color--light); font-weight: 600; }
.md-typeset .nj-sax dl.nj-sax__kv dd { margin: 0; }
/* controls */
.nj-sax .nj-sax__controls { display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center; }
.nj-sax .nj-sax__btns, .nj-sax .nj-sax__modes { display: flex; flex-wrap: wrap; gap: .35rem; }
.nj-sax .nj-sax__modes { margin-left: auto; }
.md-typeset .nj-sax .nj-sax-btn {
min-height: 2.2rem;
padding: .3rem .8rem;
border: 1px solid color-mix(in srgb, var(--nj-blue) 55%, var(--md-default-bg-color));
border-radius: 6px;
background: var(--md-default-bg-color);
color: var(--nj-blue);
font: inherit;
font-weight: 600;
cursor: pointer;
}
.md-typeset .nj-sax .nj-sax-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--nj-blue) 10%, var(--md-default-bg-color)); }
.md-typeset .nj-sax .nj-sax-btn--main, .md-typeset .nj-sax .nj-sax-btn[aria-pressed="true"] {
border-color: var(--nj-band);
background: var(--nj-band);
color: #fff;
}
.md-typeset .nj-sax .nj-sax-btn--main:hover:not(:disabled), .md-typeset .nj-sax .nj-sax-btn[aria-pressed="true"]:hover {
background: var(--md-primary-fg-color--light);
}
.md-typeset .nj-sax .nj-sax-btn:disabled { opacity: .4; cursor: default; }
.md-typeset .nj-sax .nj-sax-btn:focus-visible, .nj-sax .nj-sax__stop input:focus-visible {
outline: 2px solid var(--nj-blue);
outline-offset: 2px;
}
.nj-sax .nj-sax__stop { display: inline-flex; gap: .45rem; align-items: center; min-height: 2.2rem; cursor: pointer; }
.nj-sax .nj-sax__stop input { width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--nj-red); }
.nj-sax .nj-sax__stop:has(input:disabled) { opacity: .45; cursor: default; }
.md-typeset .nj-sax .nj-sax__status {
padding-top: .6rem;
border-top: 1px solid var(--md-default-fg-color--lightest);
color: var(--md-default-fg-color--light);
font-size: .72rem;
min-height: 2.6em;
}
@media screen and (max-width: 44.984375em) {
.md-typeset .nj-sax { padding: .8rem; }
.md-typeset .nj-sax .nj-sax-btn { min-height: 44px; min-width: 44px; }
.nj-sax .nj-sax__stop { min-height: 44px; }
.nj-sax .nj-sax__modes { margin-left: 0; }
}
@media (prefers-reduced-motion: no-preference) {
.nj-sax .nj-sax__events > li { transition: opacity .2s, background-color .2s; }
}
/* ---------- static SVG figures ---------- */
.md-typeset svg.nj-fig--sax-mem { min-width: 34rem; max-width: 40rem; }
.md-typeset svg.nj-fig--sax-buf { min-width: 36rem; max-width: 42rem; }
.nj-fig .nj-sax-axis { fill: none; stroke: var(--fg-line); stroke-width: 1.5; }
.nj-fig .nj-sax-illus { font-style: italic; }
.nj-fig .nj-sax-curve { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.nj-fig .nj-sax-c-dom { --nj-sax-c: var(--nj-red); }
.nj-fig .nj-sax-c-doc { --nj-sax-c: var(--nj-hl-type); }
.nj-fig .nj-sax-c-cb { --nj-sax-c: var(--nj-hl-number); }
.nj-fig .nj-sax-c-sax { --nj-sax-c: var(--nj-blue); }
.nj-fig .nj-sax-curve.nj-sax-c-doc { stroke-dasharray: 9 5; }
.nj-fig .nj-sax-curve { stroke: var(--nj-sax-c); }
.nj-fig .nj-sax-lab { fill: var(--nj-sax-c); font-size: 14.5px; font-weight: 700; }
.nj-fig .nj-sax-old { fill: color-mix(in srgb, currentColor 10%, var(--md-default-bg-color)); }
.nj-fig .nj-sax-new { fill: color-mix(in srgb, var(--md-typeset-a-color) 18%, var(--md-default-bg-color)); stroke: var(--md-typeset-a-color); stroke-width: 1; }
.nj-fig .nj-sax-buf { fill: currentColor; font-family: var(--md-code-font-family), monospace; font-size: 14px; white-space: pre; }
.nj-fig .nj-sax-sep { stroke: var(--fg-line); stroke-width: 1; stroke-dasharray: 3 3; }
.nj-fig .nj-sax-status { font-size: 14px; font-weight: 600; }
.nj-fig .nj-sax-s-wait { fill: var(--nj-blue); }
.nj-fig .nj-sax-s-ok { fill: var(--nj-hl-string); }
.nj-fig .nj-sax-s-err { fill: var(--nj-red); }
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><g font-family='Menlo,monospace' font-size='26' font-weight='600' fill='#ffffff' fill-opacity='0.10'><text x='14' y='34'>{</text><text x='92' y='22'>]</text><text x='136' y='60'>:</text><text x='52' y='82'>[</text><text x='118' y='112'>,</text><text x='20' y='140'>}</text><text x='78' y='150'>:</text><text x='140' y='158'>{</text></g></svg>

After

Width:  |  Height:  |  Size: 408 B

@@ -1,43 +0,0 @@
#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// a SAX parser that creates a JSON value like json::parse does, but that
// recovers from parse errors instead of stopping at the first one
class recovering_parser : public nlohmann::detail::json_sax_dom_parser<json>
{
public:
explicit recovering_parser(json& result)
: nlohmann::detail::json_sax_dom_parser<json>(result, false)
{}
bool parse_error(std::size_t position,
const std::string& /*last_token*/,
const json::exception& ex)
{
std::cout << "byte " << position << ": " << ex.what() << '\n';
// repair the input and continue
return true;
}
};
int main()
{
// JSON text with several mistakes that ends too early
const std::string text = R"({
"name": "Hello World",
"tags": ["a" "b",],
"valid": tru,
"size": 1.,
"nested": {"x": 1)";
json result;
recovering_parser sax(result);
const bool valid = json::sax_parse(text, &sax);
std::cout << "\nvalid JSON: " << std::boolalpha << valid << '\n'
<< std::setw(4) << result << std::endl;
}
@@ -1,19 +0,0 @@
byte 49: [json.exception.parse_error.101] parse error at line 3, column 20: syntax error while parsing array - unexpected string literal; expected ']'
byte 51: [json.exception.parse_error.101] parse error at line 3, column 22: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
byte 70: [json.exception.parse_error.101] parse error at line 4, column 17: syntax error while parsing value - invalid literal; last read: '"valid": tru,'
byte 86: [json.exception.parse_error.101] parse error at line 5, column 15: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.,'
byte 109: [json.exception.parse_error.101] parse error at line 6, column 22: syntax error while parsing object - unexpected end of input; expected '}'
valid JSON: false
{
"name": "Hello World",
"nested": {
"x": 1
},
"size": 1,
"tags": [
"a",
"b"
],
"valid": null
}
+32 -5
View File
@@ -124,26 +124,28 @@ For all the macros, the first parameter is the name of the class/struct. The `DE
```mermaid
flowchart TD
A["choosing a NLOHMANN_DEFINE_* macro"] --> B{"adding fields to a base class?"}
A["choosing a NLOHMANN_DEFINE_* macro"] --> B{{"adding fields to a base class?"}}
B -->|"yes"| C["...DERIVED_TYPE..."]
B -->|"no"| D["...TYPE..."]
C --> E{"need access to private members?"}
C --> E{{"need access to private members?"}}
D --> E
E -->|"yes"| F["...INTRUSIVE... (used inside the class)"]
E -->|"no"| G["...NON_INTRUSIVE... (used in the namespace)"]
F --> H{"only serializing, never parsing back?"}
F --> H{{"only serializing, never parsing back?"}}
G --> H
H -->|"yes"| I["...ONLY_SERIALIZE"]
H -->|"no"| J{"allow missing keys when parsing?"}
H -->|"no"| J{{"allow missing keys when parsing?"}}
J -->|"yes"| K["...WITH_DEFAULT"]
J -->|"no"| L["plain (missing keys throw)"]
I --> M{"need custom JSON key names?"}
I --> M{{"need custom JSON key names?"}}
K --> M
L --> M
M -->|"yes"| N["...WITH_NAMES"]
M -->|"no"| O["done"]
```
<p class="nj-caption" markdown>Decision tree for choosing a `NLOHMANN_DEFINE_*` macro: answer the questions from top to bottom; each answer picks one part of the macro name, and the parts are combined in this order. The table below lists the resulting macros.</p>
| Need access to private members | Need only serialization | Allow missing values when de-serializing | macro |
|------------------------------------------------------------------|------------------------------------------------------------------|------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| <div style="color: green;">:octicons-check-circle-fill-24:</div> | <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: red;">:octicons-x-circle-fill-24:</div> | [**NLOHMANN_DEFINE_TYPE_INTRUSIVE**](../api/macros/nlohmann_define_type_intrusive.md) |
@@ -153,6 +155,8 @@ flowchart TD
| <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: green;">:octicons-check-circle-fill-24:</div> | [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT**](../api/macros/nlohmann_define_type_non_intrusive.md) |
| <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: green;">:octicons-check-circle-fill-24:</div> | <div style="color: grey;">:octicons-skip-fill-24:</div> | [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE**](../api/macros/nlohmann_define_type_non_intrusive.md) |
<p class="nj-table-caption" markdown>Macros for classes and structs without a base class. A green check means yes, a red cross means no, and a grey skip sign means the column does not apply, as a macro that only serializes never reads values.</p>
For _derived_ classes and structs, use the following macros
| Need access to private members | Need only serialization | Allow missing values when de-serializing | macro |
@@ -164,12 +168,33 @@ For _derived_ classes and structs, use the following macros
| <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: green;">:octicons-check-circle-fill-24:</div> | [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT**](../api/macros/nlohmann_define_derived_type.md) |
| <div style="color: red;">:octicons-x-circle-fill-24:</div> | <div style="color: green;">:octicons-check-circle-fill-24:</div> | <div style="color: grey;">:octicons-skip-fill-24:</div> | [**NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE**](../api/macros/nlohmann_define_derived_type.md) |
<p class="nj-table-caption" markdown>Macros for derived classes and structs, read as Table 1.</p>
!!! info "Implementation limits"
- The current macro implementations are limited to at most 63 member variables. If you want to serialize/deserialize
types with more than 63 member variables, you need to define the `to_json`/`from_json` functions manually.
- For the `WITH_NAMES` variants the limit is halved to 31 member variables.
To pick the macro for your own type and get code to start from, answer the questions below.
<div class="nj-macro-chooser" data-variant="full" markdown>
<div class="nj-mc-fallback" markdown>
- Members are private: use an `INTRUSIVE` macro inside the class ([reference](../api/macros/nlohmann_define_type_intrusive.md){ data-nj-mc="intrusive" }).
- All members are public, or you cannot edit the class: use a `NON_INTRUSIVE` macro in the class's namespace ([reference](../api/macros/nlohmann_define_type_non_intrusive.md){ data-nj-mc="non_intrusive" }).
- The class adds members to a serializable base class: use a `DERIVED_TYPE` macro with the base class as second argument ([reference](../api/macros/nlohmann_define_derived_type.md){ data-nj-mc="derived" }).
- Missing keys should keep their default values: append `_WITH_DEFAULT`; otherwise a missing key throws.
- You only convert to JSON: append `_ONLY_SERIALIZE` instead.
- JSON keys differ from the member names: append `_WITH_NAMES` and write `"key", member` pairs ([reference](../api/macros/nlohmann_define_type_with_names.md){ data-nj-mc="with_names" }).
- Private members of a class you cannot edit: no macro works; write the conversion by hand ([third-party types](#how-do-i-convert-third-party-types){ data-nj-mc="third_party" }).
- The type is not default constructible and is converted in both directions: no macro works; specialize `adl_serializer` with a `from_json` that returns the value, or append `_ONLY_SERIALIZE` if you only convert to JSON ([non-default-constructible types](#how-can-i-use-get-for-non-default-constructiblenon-copyable-types){ data-nj-mc="non_default" }).
</div>
</div>
<p class="nj-caption" markdown>Macro chooser: each answer selects one part of the macro name; the generated program defines the type, calls the macro and converts a value to JSON and back. Combinations that no macro supports show the alternative instead of code.</p>
??? example "Example: using the `NLOHMANN_DEFINE_TYPE_*` macros"
The `to_json`/`from_json` functions for the `person` struct above can be created with:
@@ -299,6 +324,8 @@ flowchart LR
B -->|"user specialization replaces the default"| E["user's adl_serializer specialization for T"]
```
<p class="nj-caption" markdown>How a conversion between `json` and a type `T` is dispatched: the default `adl_serializer` calls the free `to_json`/`from_json` functions found by argument-dependent lookup, while a user specialization of `adl_serializer` replaces this path.</p>
The library uses **JSON Serializers** to convert types to JSON.
The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)).
@@ -53,7 +53,25 @@ See [binary values](../binary_values.md) for more information.
| UBJSON (size) | 58.6 % | 92.3 % | 86.8 % | 97.4 % |
| UBJSON (size+type) | 55.9 % | 92.3 % | 85.0 % | 95.0 % |
Sizes compared to minified JSON value; the smallest size per file is printed in bold.
<p class="nj-table-caption" markdown>Size of each test file in each format, in percent of the minified JSON value; the smallest size per file is printed in bold. The (size) and (size+type) rows are written with the `use_size` and `use_type` options of [`to_bjdata`](../../api/basic_json/to_bjdata.md) and [`to_ubjson`](../../api/basic_json/to_ubjson.md).</p>
<div class="nj-charts-grid-wrap" markdown>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_canada.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_twitter.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_citm_catalog.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_jeopardy.svg"
</div>
</div>
<p class="nj-charts-caption" markdown>The table above as charts: size per base format relative to minified JSON (vertical line at
100 %); the smallest format per file is drawn in a stronger colour than the others. The size and size+type variants of BJData and UBJSON are
omitted here; see the table.</p>
## See also
@@ -25,6 +25,8 @@ class vector ["std::vector<uint8_t>"]
vector <|-- binary_t
```
<p class="nj-caption" markdown>Class diagram of `json::binary_t`: it derives from `std::vector<uint8_t>` and adds functions to set, clear, query, and test an optional subtype.</p>
By default, binary values are stored as `std::vector<std::uint8_t>`. This type can be changed by providing a template
parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as
[`json::binary_t`](../api/basic_json/binary_t.md):
@@ -89,3 +89,5 @@ non-existing, an exception is thrown.
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown |
| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown |
<p class="nj-table-caption" markdown>Result of [`at`](../../api/basic_json/at.md) in each scenario, for a non-const and a const value.</p>
@@ -12,16 +12,23 @@ Testing whether a key or index exists before accessing it is also possible, with
[`contains`](../../api/basic_json/contains.md) or [`find`](../../api/basic_json/find.md) (which returns an iterator to
the value, or `end()` if it is not found).
How do I get a value out? Start at the top and follow the first question that applies:
```mermaid
flowchart TD
A["accessing a value"] --> B{"must it exist?"}
B -->|"yes, missing is an error"| C["at() -- throws"]
B -->|"yes, but checking is my job"| D["operator[] -- unchecked"]
B -->|"no, a fallback is fine"| E["value() -- default value"]
A --> F{"just testing first?"}
F -->|"yes"| G["contains() / find()"]
A["getting a value out"] --> P{{"nested path such as /server/port?"}}
P -->|"yes"| JP["JSON Pointer: at(ptr), value(ptr, default), contains(ptr)"]
P -->|"no, one key or index"| T{{"only testing whether it exists?"}}
T -->|"yes"| CF["contains() / find()"]
T -->|"no"| M{{"may it be missing?"}}
M -->|"yes, a fallback is fine"| V["value(key, default)"]
M -->|"yes, and missing is an error"| AT["at(): throws out_of_range"]
M -->|"no, it exists and its type is known"| OP["operator[] and get#lt;T#gt;()"]
OP -.- W["non-const operator[] inserts null for a missing key"]
```
<p class="nj-caption" markdown>Decision tree for reading a value: the labels on the arrows are the answers to the questions, and the boxes name the functions to use. The dashed line marks a side effect of the non-const `operator[]`.</p>
## Does this key exist?
Use [`contains`](../../api/basic_json/contains.md) to test for a key; it does not modify the value and does not throw:
@@ -125,3 +125,5 @@ for (int i = 0; i < 1000; ++i) {
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode |
| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode |
<p class="nj-table-caption" markdown>Result of [`operator[]`](../../api/basic_json/operator%5B%5D.md) in each scenario, for a non-const and a const value.</p>
+10 -2
View File
@@ -9,7 +9,11 @@ As for other containers, [`begin()`](../api/basic_json/begin.md) returns an iter
placeholder and cannot be dereferenced. In case of null values, empty arrays, or empty objects, `begin()` will return
`end()`.
![Illustration from cppreference.com](../images/range-begin-end.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-begin-end.svg"
</div>
<p class="nj-caption" markdown>The range of `begin()` and `end()`: `begin()` refers to the first element, `end()` to the position after the last element, which must not be dereferenced.</p>
### Iteration order for objects
@@ -112,7 +116,11 @@ for (auto& [key, val] : j_object.items())
[`rbegin()`](../api/basic_json/rbegin.md) and [`rend()`](../api/basic_json/rend.md) return iterators in the reverse
sequence.
![Illustration from cppreference.com](../images/range-rbegin-rend.svg)
<div class="nj-fig-wrap" markdown>
--8<-- "images/range-rbegin-rend.svg"
</div>
<p class="nj-caption" markdown>The range of `rbegin()` and `rend()` over the same elements: `rbegin()` refers to the last element and `rend()` to the position before the first one. Each reverse iterator stores an iterator to the element after the one it refers to.</p>
??? example "Example: reverse iteration with `rbegin()` and `rend()`"
+20
View File
@@ -7,6 +7,24 @@ of operations to apply to a JSON document. Operations address locations in the d
[JSON Pointer](json_pointer.md) paths. With the [`patch`](../api/basic_json/patch.md) function, a JSON Patch is applied
to the current JSON value by executing all operations from the patch, yielding the patched document as a new value.
The following steps through one operation of each kind. The first three operations are those of the example below; the
other three continue on its result.
<div class="nj-patch" data-nj-patch markdown>
| Operation | Before | After |
|-------------------------------------------------------------|------------------------------------------------|-------------------------------------------------|
| `{"op": "replace", "path": "/baz", "value": "boo"}` | `{"baz": "qux", "foo": "bar"}` | `{"baz": "boo", "foo": "bar"}` |
| `{"op": "add", "path": "/hello", "value": ["world"]}` | `{"baz": "boo", "foo": "bar"}` | `{"baz": "boo", "foo": "bar", "hello": ["world"]}` |
| `{"op": "remove", "path": "/foo"}` | `{"baz": "boo", "foo": "bar", "hello": ["world"]}` | `{"baz": "boo", "hello": ["world"]}` |
| `{"op": "move", "from": "/baz", "path": "/hello/1"}` | `{"baz": "boo", "hello": ["world"]}` | `{"hello": ["world", "boo"]}` |
| `{"op": "copy", "from": "/hello/0", "path": "/greeting"}` | `{"hello": ["world", "boo"]}` | `{"greeting": "world", "hello": ["world", "boo"]}` |
| `{"op": "test", "path": "/greeting", "value": "world"}` | `{"greeting": "world", "hello": ["world", "boo"]}` | unchanged (a failed test throws) |
</div>
<p class="nj-caption" markdown>Stepper through the six operations: *Next* applies the next operation, *Back* undoes it, and *Reset* returns to the original document. The current operation is highlighted in the patch list, and the lines it changes are marked in the document.</p>
!!! tip "Applying a patch without copying"
[`patch`](../api/basic_json/patch.md) leaves the original value unchanged and returns the patched result as a copy.
@@ -39,6 +57,8 @@ flowchart LR
P -.->|"applied to source, yields"| T
```
<p class="nj-caption" markdown>How `diff` and `patch` relate: `diff(source, target)` yields a patch, and applying that patch to the source yields the target.</p>
!!! success "Invariant"
For two JSON values *source* and *target*, the following code yields always true:
+42
View File
@@ -18,6 +18,40 @@ Consider the following JSON document
}
```
Select a pointer (or a node of the tree) to walk it through this document; each segment of the pointer goes one level
deeper. The table below lists the same pointers.
<div class="nj-pointer-walk" data-nj-pointer-walk data-doc="{&quot;array&quot;:[&quot;A&quot;,&quot;B&quot;,&quot;C&quot;],&quot;nested&quot;:{&quot;one&quot;:1,&quot;two&quot;:2,&quot;three&quot;:[true,false]}}" role="group" aria-label="Pointer walker for the example document">
<p class="nj-pointer-static">Highlighted: the path of the pointer <code>/nested/three/1</code>, which identifies <code>false</code>.</p>
<ul class="nj-pointer-tree">
<li data-p="" class="is-on"><span class="nj-pointer-n"><span class="nj-pointer-k">root</span> <span class="nj-pointer-t">object</span></span>
<ul>
<li data-p="/array" class="is-pass"><span class="nj-pointer-n"><span class="nj-pointer-k">&quot;array&quot;</span> <span class="nj-pointer-t">array</span></span>
<ul>
<li data-p="/array/0"><span class="nj-pointer-n"><span class="nj-pointer-k">0</span>: <span class="nj-pointer-v nj-pointer-v--s">&quot;A&quot;</span></span></li>
<li data-p="/array/1"><span class="nj-pointer-n"><span class="nj-pointer-k">1</span>: <span class="nj-pointer-v nj-pointer-v--s">&quot;B&quot;</span></span></li>
<li data-p="/array/2"><span class="nj-pointer-n"><span class="nj-pointer-k">2</span>: <span class="nj-pointer-v nj-pointer-v--s">&quot;C&quot;</span></span></li>
</ul>
</li>
<li data-p="/nested" class="is-on"><span class="nj-pointer-n"><span class="nj-pointer-k">&quot;nested&quot;</span> <span class="nj-pointer-t">object</span></span>
<ul>
<li data-p="/nested/one" class="is-pass"><span class="nj-pointer-n"><span class="nj-pointer-k">&quot;one&quot;</span>: <span class="nj-pointer-v nj-pointer-v--n">1</span></span></li>
<li data-p="/nested/two" class="is-pass"><span class="nj-pointer-n"><span class="nj-pointer-k">&quot;two&quot;</span>: <span class="nj-pointer-v nj-pointer-v--n">2</span></span></li>
<li data-p="/nested/three" class="is-on"><span class="nj-pointer-n"><span class="nj-pointer-k">&quot;three&quot;</span> <span class="nj-pointer-t">array</span></span>
<ul>
<li data-p="/nested/three/0" class="is-pass"><span class="nj-pointer-n"><span class="nj-pointer-k">0</span>: <span class="nj-pointer-v nj-pointer-v--b">true</span></span></li>
<li data-p="/nested/three/1" class="is-on is-target"><span class="nj-pointer-n"><span class="nj-pointer-k">1</span>: <span class="nj-pointer-v nj-pointer-v--b">false</span></span></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<p class="nj-caption" markdown>The highlighted nodes are the path from the root to the selected level, and the line below the tree shows the value the pointer resolves to. Select a segment in the pointer bar to stop at a shallower level, or a node of the tree to select its pointer.</p>
Then every value inside the JSON document can be identified as follows:
| JSON Pointer | JSON value |
@@ -127,6 +161,14 @@ The reverse function, [`unflatten`](../api/basic_json/unflatten.md) recreates th
auto j_original = j_flat.unflatten();
```
Each leaf of the document becomes one key of the flat object, and `unflatten()` reverses the mapping:
<div class="nj-fig-wrap" markdown>
--8<-- "images/json_pointer_flatten.svg"
</div>
<p class="nj-caption" markdown>Left: the example document as a tree; right: the flat object it becomes. `flatten()` converts from left to right, `unflatten()` from right to left.</p>
## See also
- Class [`json_pointer`](../api/json_pointer/index.md)
+75 -2
View File
@@ -33,6 +33,14 @@ index. It gives you the read-only, type-inspection part of the `basic_json` inte
actual `basic_json` value for a subtree, [`materialize()`](../api/basic_json_view/materialize.md) builds exactly the
one [`parse()`](../api/basic_json/parse.md) would have produced for it.
The same small text, parsed both ways:
<div class="nj-fig-wrap" markdown>
--8<-- "images/json_view_layout.svg"
</div>
<p class="nj-caption" markdown>Top: the tree of separate heap allocations that `basic_json::parse()` builds. Bottom: `json_document::parse()` keeps the source text and builds one flat index of 16-byte nodes that point back into it, plus a buffer of decoded strings.</p>
## How to use it
Include `<nlohmann/json_view.hpp>` in addition to (or instead of) `<nlohmann/json.hpp>`. Parse into a
@@ -84,6 +92,12 @@ Moving the `basic_json_document<>` itself is fine and does **not** invalidate it
allocation that keeps its address across the move. Take a fresh view from [`root()`](../api/basic_json_document/root.md)
whenever any of the other conditions above was not met.
<div class="nj-fig-wrap" markdown>
--8<-- "images/json_view_lifetime.svg"
</div>
<p class="nj-caption" markdown>Four timelines of a document and its views, each bar showing when an object is alive or valid and when it dangles. Destroying the borrowed text, re-parsing, or shrinking the document invalidates the views taken before; moving the document does not.</p>
A view can dangle, exactly like a `#!cpp std::string_view`: nothing stops you from using it after its document is
gone. This is deliberate. A view is two pointers and trivially copyable; making it safe (a `#!cpp std::shared_ptr` in
the document and a `#!cpp std::weak_ptr` in each view) would make it larger, add reference counting to every copy,
@@ -274,6 +288,26 @@ or `ordered_json` value in place lossy. Say you parse a configuration file, patc
- **`ordered_json`** keeps the key order, but still rewrites every number the same way: parsing has already reduced
it to a `#!cpp double`/`#!cpp int64_t`, and there is no way back to how it was spelled in the source text.
The patch of the example below (set `"host"`, add `"retries"`) written back by each of them:
<div class="nj-jsonview-cmp" role="group" aria-label="The same patch written back by json, ordered_json, and json_editable_document">
<div><p class="nj-jsonview-cmp-h"><code>json</code></p><p class="nj-jsonview-cmp-v">keys sorted, numbers rewritten</p><pre>{<span class="nj-jsonview-bad">"host"</span>:"db2",
"name":"cache",
"port":6379,
"price":<span class="nj-jsonview-bad">19.9</span>,
"retries":3}</pre></div>
<div><p class="nj-jsonview-cmp-h"><code>ordered_json</code></p><p class="nj-jsonview-cmp-v">key order kept, numbers rewritten</p><pre>{"name":"cache",
"host":"db2",
"port":6379,
"price":<span class="nj-jsonview-bad">19.9</span>,
"retries":3}</pre></div>
<div class="nj-jsonview-cmp--best"><p class="nj-jsonview-cmp-h"><code>json_editable_document</code></p><p class="nj-jsonview-cmp-v">order and spelling kept</p><pre>{"name":"cache",
"host":"db2",
"port":6379,
"price":<span class="nj-jsonview-ok">19.90</span>,
"retries":3}</pre></div>
</div>
An editable document keeps both. [`dump()`](../api/basic_json_view/dump.md) of an edited document writes members in
document order -- a member [`set`](../api/basic_json_document/set.md) added goes at the end, exactly where it was
inserted, and an [`erase`](../api/basic_json_document/erase.md)d member simply leaves a gap: everything around it
@@ -301,8 +335,8 @@ parsed into for as long as it is not itself replaced. So every [view](../api/bas
an edit, including a previously obtained [`root()`](../api/basic_json_document/root.md), stays valid and, if it
still refers to the edited value, sees the edit; a view of a value a later edit drops or replaces just keeps showing
what it last held. New values go to storage the document allocates and owns on demand. The one thing an edit does
invalidate is the **iterators** taken over an edited array or object: the first time one of its elements is set,
appended to, inserted into, or erased, its elements move from the parsed, fixed layout to a growable block of links
invalidate is the **iterators** taken over an edited array or object: the first time an element is added to it,
inserted into it, erased from it, or replaced by a value that spans a different number of nodes, its elements move from the parsed, fixed layout to a growable block of links
so that [`push_back`](../api/basic_json_document/push_back.md) can later grow it in amortized constant time --
existing elements are not touched, but an iterator that was walking the old layout no longer matches. A string
obtained with
@@ -312,6 +346,43 @@ edits. See [`basic_json_document`'s Edits](../api/basic_json_document/index.md#e
throws (the *basic* guarantee, not the strong one `dump()` and the read-only functions provide). How edits are kept in
the index is described in the [architecture overview](../home/architecture.md#node-index-of-json-views).
Step through the edits of a small document (the node fields follow the [architecture overview](../home/architecture.md#node-index-of-json-views)):
<div class="nj-jsonview-steps" data-nj-jsonview-steps>
<figure class="nj-jsonview-step" data-label="After parsing">
<div class="nj-jsonview-scroll">
--8<-- "images/json_view_edit_0.svg"
</div>
<figcaption>Step 1 of 5. After parsing: nine nodes in the parsed index, no owned storage yet.</figcaption>
</figure>
<figure class="nj-jsonview-step" data-label="set an existing member">
<div class="nj-jsonview-scroll">
--8<-- "images/json_view_edit_1.svg"
</div>
<figcaption>Step 2 of 5. <code>doc.set(doc.root(), "port", 6380)</code> overwrites the node of the integer in place; no member is added or removed, so the object keeps its parsed layout.</figcaption>
</figure>
<figure class="nj-jsonview-step" data-label="erase an array element">
<div class="nj-jsonview-scroll">
--8<-- "images/json_view_edit_2.svg"
</div>
<figcaption>Step 3 of 5. <code>doc.erase(doc.root()["tags"], 0)</code>: the array is edited for the first time, so its elements move to a block of links in owned storage. The node of <code>"eu"</code> stays in the index, but nothing refers to it any more; iterators over the array taken before are invalid.</figcaption>
</figure>
<figure class="nj-jsonview-step" data-label="push_back onto the array">
<div class="nj-jsonview-scroll">
--8<-- "images/json_view_edit_3.svg"
</div>
<figcaption>Step 4 of 5. <code>doc.push_back(doc.root()["tags"], "new")</code>: the new string gets its own node, its text goes to the buffer of edited text, and a link to it is appended to the block of the array.</figcaption>
</figure>
<figure class="nj-jsonview-step" data-label="set a new member">
<div class="nj-jsonview-scroll">
--8<-- "images/json_view_edit_4.svg"
</div>
<figcaption>Step 5 of 5. <code>doc.set(doc.root(), "retries", 3)</code>: a new member, so the object moves to a block too: copies of its keys, links to the values it already had, then the new key and a link to the new integer.</figcaption>
</figure>
</div>
<p class="nj-caption" markdown>The node index and the owned storage of the document after each of five edits. Use *Back*, *Next*, or the numbered buttons to switch between the steps; without JavaScript all steps are shown one below the other.</p>
## Images
[`save()`](../api/basic_json_document/save.md) writes a document as an *image*: a byte buffer that
@@ -373,6 +444,8 @@ either.
| **Typical use** | general-purpose JSON handling: config, request/response bodies you build or modify, anything you hold onto | validating or projecting a text into your own data structure without ever holding the whole thing as JSON | large or high-volume input where you only need part of it, or need it repeatedly, and can keep the source text (or a copy) alive for as long as the document lives | a document you read, patch a few fields of, and write back -- a configuration file, for instance -- where the rest of it should come back exactly as it was |
| **Caching/reload** | not applicable -- re-parse, or roll your own serialization | not applicable | [`save()`](../api/basic_json_document/save.md)/[`load()`](../api/basic_json_document/load.md): cache the parsed index as an image and reload it without parsing | same, saving the document's current -- possibly edited -- state |
<p class="nj-table-caption" markdown>Each column is one way to work with JSON in this library, and each row compares one property of them.</p>
## Version history
- Added in version 3.13.0.
+29
View File
@@ -12,6 +12,35 @@ easier to read and write for object-shaped documents.
The function [`merge_diff`](../api/basic_json/merge_diff.md) creates a merge patch that changes one JSON value into
another.
The example below shows every rule in one patch, member by member:
<div class="nj-pointer-mpt" markdown>
| Rule | Key | Target | Patch | Result |
|------|-----|--------|-------|--------|
| <span class="nj-pointer-mp nj-pointer-mp--set">change value</span> | `title` | `#!json "Goodbye!"` | `#!json "Hello!"` | `#!json "Hello!"` |
| <span class="nj-pointer-mp nj-pointer-mp--add">add key</span> | `phoneNumber` | <span class="nj-pointer-mp-none">(no key)</span> | `#!json "+01-123-456-7890"` | `#!json "+01-123-456-7890"` |
| <span class="nj-pointer-mp nj-pointer-mp--del">null removes key</span> | `author.familyName` | `#!json "Doe"` | `#!json null` | <span class="nj-pointer-mp-none">(removed)</span> |
| <span class="nj-pointer-mp nj-pointer-mp--rec">object merges recursively</span> | `author` | `#!json {"givenName": "John", "familyName": "Doe"}` | `#!json {"familyName": null}` | `#!json {"givenName": "John"}` |
| <span class="nj-pointer-mp nj-pointer-mp--arr">array replaced whole</span> | `tags` | `#!json ["example", "sample"]` | `#!json ["example"]` | `#!json ["example"]` |
| <span class="nj-pointer-mp nj-pointer-mp--keep">unchanged key</span> | `content` | `#!json "This will be unchanged"` | <span class="nj-pointer-mp-none">(no key)</span> | `#!json "This will be unchanged"` |
</div>
An array in the patch replaces the array in the target, so a merge patch cannot change a single element. Each member of
the patch is applied like this; a patch that is not an object replaces the whole target.
```mermaid
flowchart LR
M["member of the patch"] --> N{{"value null?"}}
N -->|yes| D["delete the key"]
N -->|no| O{{"value an object?"}}
O -->|yes| R["merge recursively into the target's value"]
O -->|no| S["set the key to the value"]
```
<p class="nj-caption" markdown>How one member of a merge patch is applied: a `null` value deletes the key, an object is merged recursively, and any other value replaces the value of the key.</p>
!!! tip "Not a general deep merge"
A merge patch is not a general deep merge: a `#!json null` value in the patch deletes the key from the target.
+2
View File
@@ -4,6 +4,8 @@ This library has experimental support for C++ modules, introduced in C++20. The
Please be aware that the module is experimental and a full test is outstanding, and the exported symbols are subject to change.
Importing the module instead of including the header reduces the compile time of every translation unit that uses the library, at the price of building the module once. The [Compile times](../integration/compile_times.md#use-c20-modules) page has measurements and the one-off cost.
## Requirements
The `nlohmann.json` module requires that the build system is configured to build and resolve modules when imported. Obviously, as modules were introduced in C++20, this feature can only be used in C++20 and subsequent versions.
+18
View File
@@ -40,6 +40,22 @@ For example, the namespace name for version 3.11.2 with `JSON_DIAGNOSTICS` defin
nlohmann::json_abi_diag_v3_11_2
```
The name is assembled from these segments; pick a version and macros to see the resulting name:
<figure class="nj-integration-ns" data-nj-integration-ns aria-label="How the inline namespace name is assembled from its segments">
<div class="nj-integration-ns__strip" aria-live="polite">
<span class="nj-integration-ns__seg nj-integration-ns__seg--root"><code>nlohmann</code><small>root namespace</small></span>
<span class="nj-integration-ns__seg nj-integration-ns__seg--sep"><code>::</code><small>&nbsp;</small></span>
<span class="nj-integration-ns__seg nj-integration-ns__seg--abi"><code>json_abi</code><small>always</small></span>
<span class="nj-integration-ns__seg nj-integration-ns__seg--tag"><code>_diag</code><small>JSON_DIAGNOSTICS=1</small></span>
<span class="nj-integration-ns__seg nj-integration-ns__seg--ver"><code>_v3_11_2</code><small>version 3.11.2</small></span>
</div>
<figcaption>Version 3.11.2 with <code>JSON_DIAGNOSTICS</code> defined to <code>1</code>. ABI tags are appended in the order of the
list above, the version suffix comes last.</figcaption>
</figure>
<p class="nj-caption" markdown>The name of the inline namespace, assembled from its segments. Select a version and macros to see which ABI tags appear; a tag the chosen version does not have is disabled.</p>
## Purpose
Several incompatibilities have been observed. Amongst the most common ones is linking code compiled with different
@@ -57,6 +73,8 @@ graph
app --> library
```
<p class="nj-caption" markdown>The application uses the library with `JSON_DIAGNOSTICS=1` and links `some library`, which uses the same library version with `JSON_DIAGNOSTICS=0`. Arrows point from a component to what it uses.</p>
In releases prior to 3.11.0, mixing any version of the JSON library with different `JSON_DIAGNOSTICS` settings would
result in a crashing application. If `some_library` never passes instances of JSON library types to the application,
this scenario became safe in version 3.11.0 and above due to the inline namespace yielding distinct symbol names.
@@ -1,122 +0,0 @@
# Error Recovery
By default, parsing stops at the first error. With the [SAX interface](sax_interface.md), you can instead ask the
parser to *recover*: to repair the error and continue, so that you get as much as possible out of malformed input, for
instance a file that was cut off, JSON edited by hand, or the output of a language model.
## Recovering from errors
The SAX parser's [`parse_error`](../../api/json_sax/parse_error.md) function is called for every error. Its return value
decides what happens next:
- `#!cpp false` stops parsing. This is what the SAX parsers of the library do, so [`parse`](../../api/basic_json/parse.md)
and [`accept`](../../api/basic_json/accept.md) never recover.
- `#!cpp true` repairs the error and continues parsing.
When recovering, the SAX parser still receives well-formed events: every `start_object` or `start_array` is followed by
the matching `end_object` or `end_array`, and every `key` is followed by exactly one value. A SAX parser that creates a
JSON value, such as the one in the example below, therefore gets a complete value. Parsing always ends, and
[`sax_parse`](../../api/basic_json/sax_parse.md) returns `#!cpp false` for input that is not valid JSON, even if every
error was repaired. Each token is reported at most once, and the SAX parser can stop at any error by returning
`#!cpp false`.
!!! example
The example below derives a SAX parser from the library's parser for `json` values (`json_sax_dom_parser`),
and recovers from all errors.
```cpp
--8<-- "examples/sax_parse__error_recovery.cpp"
```
Output:
```
--8<-- "examples/sax_parse__error_recovery.output"
```
## How errors are repaired
Each error is repaired with the smallest local edit: a missing separator is inserted, a stray token is removed, what can
be read of a broken string or number is kept, and a value that cannot be read at all becomes `#!json null`.
| Mistake | Repair | Example | Result |
|---------------------------|--------------------------------------------------------------------------------|------------------------------------------|----------------------------|
| missing `,` or `:` | inserted | `#!json [1 2]`, `#!json {"a" 1}` | `[1,2]`, `{"a":1}` |
| missing value | `#!json null` for an object key or between commas in an array | `#!json {"a":}`, `#!json [1,,2]` | `{"a":null}`, `[1,null,2]` |
| trailing comma | removed | `#!json [1,2,]` | `[1,2]` |
| broken string | invalid escapes and bytes are replaced (see below); a line break ends the string | `#!json ["a\qb"]` | `["aqb"]` |
| broken number | the longest valid beginning is kept | `#!json [1., 2e+]` | `[1,2]` |
| unreadable value | `#!json null` | `#!json [1, NaN, tru]` | `[1,null,null]` |
| number too large | passed as infinity, together with its text | `#!json [1e999]` | infinity (see below) |
| stray `:` | removed | `#!json ["a":1]` | `["a",1]` |
| member without a key | skipped up to the next `,` or `}` | `#!json {1:2, "b":3}` | `{"b":3}` |
| wrong closing bracket | closes the innermost array or object | `#!json {"a":[1,2}, "b":3}` | `{"a":[1,2],"b":3}` |
| input ends too early | all open arrays and objects are closed | `#!json {"a":[1,2` | `{"a":[1,2]}` |
| text before the value | skipped | `#!json )]}'{"a":1}` | `{"a":1}` |
In a string, an unknown escape like `\q` stands for the escaped character (`q`), as in JavaScript. An invalid `\u`
escape, a lone surrogate, and ill-formed UTF-8 are each replaced by U+FFFD (REPLACEMENT CHARACTER), and control
characters are kept. A string without its closing quote ends at the next line break or at the end of the input.
The input after the top-level value is not repaired: as without recovery, it is reported as an error, and parsing stops.
## Binary formats
The binary formats ([BJData](../binary_formats/bjdata.md), [BON8](../binary_formats/bon8.md),
[BSON](../binary_formats/bson.md), [CBOR](../binary_formats/cbor.md), [MessagePack](../binary_formats/messagepack.md),
and [UBJSON](../binary_formats/ubjson.md)) have no delimiters to find the next value by. So what can be repaired depends
on whether the end of the item with the error is known, a distinction that
[RFC 8949, Section 5.3](https://www.rfc-editor.org/rfc/rfc8949.html#section-5.3) makes for CBOR, too.
If the item is complete, but cannot be passed on as it is, it is replaced, and parsing continues after it:
| Mistake | Formats | Repair |
|---------------------------------------------------------------------|-------------------------|-------------------------------------------------------------------------|
| tag, if `tag_handler` is `cbor_tag_handler_t::error` (the default) | CBOR | ignored |
| simple value other than `false`, `true`, and `null`, like undefined | CBOR | `#!json null` |
| number too large for a custom `number_float_t`, like `float` | all | infinity |
| character (`C`) that is not ASCII | BJData, UBJSON | U+FFFD |
| invalid high-precision number (`H`) | BJData, UBJSON | the longest valid beginning is kept, as for JSON text, or `#!json null` |
| high-precision number too large | BJData, UBJSON | passed as infinity, together with its text |
| object key that is not a string | BON8, CBOR, MessagePack | the member is skipped |
| element of a type the library does not read, like ObjectId or date | BSON | `#!json null` |
| string without its terminator | BSON | kept |
| document whose size does not match its content | BSON | kept |
CBOR tags and simple values are repaired as [RFC 8949, Section 6.1](https://www.rfc-editor.org/rfc/rfc8949.html#section-6.1)
suggests for converting CBOR to JSON. By default, [`sax_parse`](../../api/basic_json/sax_parse.md) reports every tag as
an error; when recovering, tags are then ignored like with
[`cbor_tag_handler_t::ignore`](../../api/basic_json/cbor_tag_handler_t.md). Strings that are not valid UTF-8 are no
error: like [`from_cbor`](../../api/basic_json/from_cbor.md) and the other functions by default, `sax_parse` passes
them on as they are.
After any other error, the end of the item is unknown: the input ended, a byte is not a valid type marker, or a size
cannot be right. Parsing then stops, and the value read so far is completed: a key that waits for its value gets
`#!json null`, and all open arrays and objects are closed. This keeps everything before the error of an input that was
cut off. The exception is BSON, which stores the size of every document: an element whose end is unknown gets
`#!json null`, the rest of its document is skipped, and parsing continues after the document.
## Limitations
- A repair is a guess. For example, `#!json {"a" "b": 1}` could be meant as `#!json {"a": "b"}` or as
`#!json {"a": null, "b": 1}`; it is repaired to the former. Treat recovered values as a best effort, and check the
reported errors.
- A closing bracket always closes the innermost array or object. If a bracket is missing rather than wrong, the
repair differs from the intention: `#!json {"a": {"b": [1, 2}, "c": 3}` is repaired to
`#!json {"a": {"b": [1, 2], "c": 3}}`, although `#!json {"a": {"b": [1, 2]}, "c": 3}` may have been meant.
- Keys without quotes, and strings in single quotes, are not supported; such members are skipped.
- In the binary formats, a member that is skipped because its key is not a string is lost, and so are the elements of a
BSON document after one whose end is unknown.
- A number that is too large for `number_float_t` is passed as positive or negative infinity. The SAX parser's
`number_float` also gets the number's text, but a JSON value cannot store it, and
[`dump`](../../api/basic_json/dump.md) serializes infinity as `#!json null`.
- When parsing is not strict (see [`sax_parse`](../../api/basic_json/sax_parse.md)), a repair may read parts of the
input after the value, for instance of the next value in a stream of concatenated values.
## See also
- [SAX interface](sax_interface.md) - implement a custom SAX handler
- [`parse_error`](../../api/json_sax/parse_error.md) - the SAX event for parse errors
- [`sax_parse`](../../api/basic_json/sax_parse.md) - generate SAX events
- [parsing and exceptions](parse_exceptions.md) - control error handling
+3 -2
View File
@@ -13,6 +13,8 @@ flowchart LR
A --> V["bool: is the input valid JSON?"]
```
<p class="nj-caption" markdown>The three entry points for parsing: `parse()` builds a `basic_json` value, optionally filtered by a parser callback, `sax_parse()` delivers events to a SAX handler, and `accept()` only checks whether the input is valid.</p>
## Input
The [`parse`](../../api/basic_json/parse.md) function reads a JSON value from an input. The input can be
@@ -139,7 +141,7 @@ See [Zero-copy JSON views](../json_view.md) for the concept and the trade-offs.
When the input is not valid JSON, the `parse` function throws an exception by default. If exceptions are undesired or
unavailable, the parser can instead return a discarded value, or [`accept`](../../api/basic_json/accept.md) can be used
to only check whether an input is valid JSON. See [parsing and exceptions](parse_exceptions.md) for the available
options. To get as much as possible out of malformed input, a SAX parser can [recover from errors](error_recovery.md).
options.
## See also
@@ -153,6 +155,5 @@ options. To get as much as possible out of malformed input, a SAX parser can [re
- [SAX interface](sax_interface.md) - implement a custom SAX handler
- [Zero-copy JSON views](../json_view.md) - parse into a read-only document and read it through views
- [parsing and exceptions](parse_exceptions.md) - control error handling
- [error recovery](error_recovery.md) - get as much as possible out of malformed input
- [parsing untrusted input](untrusted_input.md) - what to consider when parsing input from untrusted sources
- [Zero-copy JSON views](../json_view.md) - parse into a document and read it through a view
@@ -17,6 +17,8 @@ flowchart TD
H -->|"yes"| I["stop early with SAX, or read through a view"]
```
<p class="nj-caption" markdown>Questions about the input and the approach this page describes for each; an input can match more than one question.</p>
## Several values in one stream
For newline-delimited input, read line by line and parse each line, as described in [JSON Lines](json_lines.md). For
@@ -80,6 +82,14 @@ exception is one past the buffer size in the first case:
The example feeds a document in five chunks. The first four are reported as incomplete, and a syntax error is reported as
such, not as missing data.
The chunks of the example, and the bytes each attempt parses again:
<div class="nj-fig-wrap" markdown>
--8<-- "images/chunk_buffering.svg"
</div>
<p class="nj-caption" markdown>Each row is one parse attempt on the growing buffer: an error at the byte after the end of the buffer means the value is incomplete, an error before the end is a real syntax error. The last line adds up the bytes parsed over all attempts.</p>
!!! warning "Limits of buffering"
- The buffer must contain exactly one value. Data that belongs to the next value is a syntax error. Use framing if
@@ -93,6 +103,14 @@ such, not as missing data.
The input does not have to become one huge `json` value. The two tools below process it piece by piece.
How the memory use develops while a large array of records is parsed (illustrative, not a measurement):
<div class="nj-fig-wrap" markdown>
--8<-- "images/memory_over_time.svg"
</div>
<p class="nj-caption" markdown>Memory use over the number of records parsed: `parse()` keeps the whole tree, `json_document` the text plus its index, a discarding callback one record at a time, and SAX only what the handler keeps.</p>
### Handle and discard elements with a callback
A [parser callback](parser_callbacks.md) is called for every finished value. If it returns `#!cpp false`, the value is
@@ -68,8 +68,7 @@ bool parse_error(std::size_t position,
const json::exception& ex);
```
The return value decides whether to stop parsing (`#!cpp false`) or to repair the error and continue
(`#!cpp true`); see [error recovery](error_recovery.md) for the latter.
The return value indicates whether the parsing should continue, so the function should usually return `#!cpp false`.
??? example "Example: report parse errors without exceptions"
@@ -29,6 +29,8 @@ class sax_t ["json::sax_t"] {
}
```
<p class="nj-caption" markdown>The interface `json::sax_t`: one function per event, each returning `bool`; the functions marked with `*` are pure virtual.</p>
```cpp
// called when null is parsed
bool null();
@@ -60,8 +62,35 @@ bool key(string_t& val);
bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex);
```
The return value of each function determines whether parsing should proceed. For `parse_error`, returning
`#!cpp true` [recovers from the error](error_recovery.md).
The return value of each function determines whether parsing should proceed.
## Stepping through the events
The events for a small input, step by step, and what two different handlers do with them. Press *Play* or step with *Next*:
<div class="nj-sax nj-fig" id="sax-event-stepper" data-nj-sax role="group" aria-label="SAX events for the input {&quot;a&quot;:[1,true],&quot;b&quot;:&quot;x&quot;}, and the state of a handler after each event">
<div class="nj-sax__lane nj-sax__lane--text"><p class="nj-sax__h">input</p><p class="nj-sax__text"><code class="nj-sax__src">{"a":[1,true],"b":"x"}</code></p></div>
<div class="nj-sax__lane nj-sax__lane--events"><p class="nj-sax__h">events, in the order the parser calls them</p><ol class="nj-sax__events">
<li class="nj-sax-ev nj-sax-ev--os"><code>start_object(-1)</code></li>
<li class="nj-sax-ev nj-sax-ev--k"><code>key("a")</code></li>
<li class="nj-sax-ev nj-sax-ev--as"><code>start_array(-1)</code></li>
<li class="nj-sax-ev nj-sax-ev--v"><code>number_unsigned(1)</code></li>
<li class="nj-sax-ev nj-sax-ev--v"><code>boolean(true)</code></li>
<li class="nj-sax-ev nj-sax-ev--ae"><code>end_array()</code></li>
<li class="nj-sax-ev nj-sax-ev--k"><code>key("b")</code></li>
<li class="nj-sax-ev nj-sax-ev--v"><code>string("x")</code></li>
<li class="nj-sax-ev nj-sax-ev--oe"><code>end_object()</code></li>
</ol></div>
<div class="nj-sax__lane nj-sax__lane--state"><p class="nj-sax__h">handler: build a value tree, as <code>parse</code> does</p><div class="nj-sax__state"><pre class="nj-sax__tree"><code>{
"a": [
1,
true
],
"b": "x"
}</code></pre><p class="nj-sax__note">After <code>end_object()</code> the tree is complete and no container is open. The number of elements is passed as -1: the parser does not know it in advance.</p></div></div>
</div>
<p class="nj-caption" markdown>The three lanes show the input consumed so far, the events called so far, and the state of the selected handler (*build a tree* or *keep only /b*). Check *return false at this event* to stop the parse at the current event and see which events are no longer called.</p>
To implement your own SAX handler, proceed as follows:
@@ -69,7 +98,7 @@ To implement your own SAX handler, proceed as follows:
2. Create an object of your SAX interface class, e.g. `my_sax`.
3. Call `#!cpp bool json::sax_parse(input, &my_sax);` where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.
Note the `sax_parse` function only returns a `#!cpp bool` indicating whether the input was parsed without errors and no SAX event returned `#!cpp false`. It does not return `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file `json_sax.hpp`.
Note the `sax_parse` function only returns a `#!cpp bool` indicating the result of the last executed SAX event. It does not return `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file `json_sax.hpp`.
## See also
+18
View File
@@ -96,6 +96,17 @@ comparison for text-heavy documents (63.5%-87.5%), at the cost of an
whether it is worth the loss of human readability at all -- depends on the actual data; see the
[comparison tables](binary_formats/index.md#comparison) before choosing one.
<div class="nj-charts-grid-wrap" markdown>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_canada.svg"
</div>
<div class="nj-fig-wrap" markdown>
--8<-- "images/binary_sizes_jeopardy.svg"
</div>
</div>
<p class="nj-charts-caption" markdown>Two of the four panels from the [size comparison](binary_formats/index.md#sizes);
the smallest format per file is drawn in a stronger colour than the others.</p>
## Object type: `json` vs. `ordered_json`
The default [`json`](../api/json.md) type stores object keys in a `#!cpp std::map`, giving logarithmic-time lookup,
@@ -108,6 +119,13 @@ read. The [measurements on the `ordered_map` page](../api/ordered_map.md#complex
negligible at typical object sizes (2000 keys: 0.7 ms for `json` vs. 3.6 ms for `ordered_json`, a 5x factor) but grows
steeply for large, machine-generated objects (16 000 keys: 3.3 ms vs. 181.6 ms, a 54x factor).
<div class="nj-fig-wrap" markdown>
--8<-- "images/ordered_json_scaling.svg"
</div>
<p class="nj-charts-caption" markdown>Parsing a flat object of `n` keys, measured with `-O2 -DNDEBUG`; all
four sizes from the [table on the `ordered_map` page](../api/ordered_map.md#complexity), both
axes logarithmic.</p>
If insertion order matters *and* an object routinely has many thousands of keys, `ordered_json`'s quadratic build cost
may not be acceptable. The library's [`ObjectType` template parameter](types/template_parameters.md#objecttype) can be
set to a different container instead: `#!cpp nlohmann::fifo_map` keeps insertion order with a real lookup index
+2
View File
@@ -64,6 +64,8 @@ basic_json .. json_value
basic_json .. value_t
```
<p class="nj-caption" markdown>Storage of a `basic_json` value: the enumeration `value_t` holds the type, and the union `json_value` holds the value, as a pointer for objects, arrays, strings, and binary values and directly for booleans and numbers.</p>
## Template arguments
The data types to store a JSON value are derived from the template arguments passed to class `basic_json`:
@@ -27,7 +27,11 @@ JSON defines the syntax of numbers as follows:
The following railroad diagram from [json.org](https://json.org) visualizes the number syntax:
![Syntax for JSON numbers](../../images/json_syntax_number.png)
<div class="railroad-wrap" markdown>
--8<-- "images/json_syntax_number.svg"
</div>
<p class="nj-caption" markdown>Read the diagram from left to right: every path along the lines spells a valid number, made of an optional minus sign, an integer part, an optional fraction, and an optional exponent.</p>
### Number interoperability
@@ -69,15 +73,17 @@ otherwise, it uses unsigned integer storage.
```mermaid
flowchart TD
A["number literal"] --> B{"has a fraction (.) or exponent (e/E)?"}
A["number literal"] --> B{{"has a fraction (.) or exponent (e/E)?"}}
B -->|"yes"| F["number_float_t"]
B -->|"no"| C{"has a leading minus sign?"}
B -->|"no"| C{{"has a leading minus sign?"}}
C -->|"yes"| D["try number_integer_t"]
C -->|"no"| E["try number_unsigned_t"]
D -->|"overflow"| F
E -->|"overflow"| F
```
<p class="nj-caption" markdown>How the parser picks the storage type of a number literal: a fraction or exponent always gives `number_float_t`; otherwise the sign selects the signed or unsigned integer type, and a value that overflows it is stored as `number_float_t`.</p>
!!! info "Notes"
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
@@ -131,6 +137,32 @@ The JSON number grammar allows for different ways to express zero, and this libr
That is, `-0` is stored as a signed integer, but the serialization does not reproduce the `-`.
The literals mentioned on this page, parsed with `json::parse` and serialized with `dump()` (checked against the
library; pick one or type it to see the row):
<div class="nj-charts-num" markdown>
| Literal | Stored as (`type()`) | `dump()` |
|---------|----------------------|----------|
| `0` | `number_unsigned` (`std::uint64_t`) | `0` |
| `-0` | `number_integer` (`std::int64_t`) | `0` |
| `-0.0` | `number_float` (`double`) | `-0.0` |
| `1E3` | `number_float` (`double`) | `1000.0` |
| `-12345678912345789123456789` | `number_float` (`double`) | `-1.2345678912345788e+25` |
| `18446744073709551615` | `number_unsigned` (`std::uint64_t`) | `18446744073709551615` |
| `18446744073709551616` | `number_float` (`double`) | `1.8446744073709552e+19` |
| `-9223372036854775808` | `number_integer` (`std::int64_t`) | `-9223372036854775808` |
| `1E400` | exception `out_of_range.406` | (nothing, parsing fails) |
| `1E-400` | `number_float` (`double`) | `0.0` |
| `3.141592653589793238462643383279` | `number_float` (`double`) | `3.141592653589793` |
| `2555.5599999999999` | `number_float` (`double`) | `2555.56` |
| `0.0000972439793401814` | `number_float` (`double`) | `9.72439793401814e-05` |
| `12345E-5` | `number_float` (`double`) | `0.12345` |
</div>
<p class="nj-caption" markdown>Each row shows how a literal is stored and how `dump()` writes it back. The explorer only knows the literals in this list; other input is reported as not in the verified list.</p>
### Number serialization
- Integer numbers are serialized as is; that is, no scientific notation is used.
@@ -329,6 +361,8 @@ the stored number:
| [`type_name()`](../../api/basic_json/type_name.md) | `#!c "number"` | `#!c "number"` | `#!c "number"` | `#!c "string"` |
| [`type()`](../../api/basic_json/type.md) | `number_unsigned` | `number_integer` | `number_float` | `string` |
<p class="nj-table-caption" markdown>Return value of each function for a value that stores an unsigned integer, a signed integer, or a floating-point number, and for a string for comparison.</p>
### Template number types
The number types can be changed with template parameters.
+78 -2
View File
@@ -32,6 +32,8 @@ flowchart LR
oa --> output
```
<p class="nj-caption" markdown>Data flow through the library: input runs left to right through an input adapter and the lexer and parser (JSON text) or the `binary_reader` (binary formats) into SAX events, which build the value tree; the `serializer` or the `binary_writer` writes the tree to an output adapter.</p>
- **JSON text** is read by an [input adapter](#input-adapters), tokenized by the lexer, and turned into SAX events by
the parser.
- **Binary formats** (BJData, BON8, BSON, CBOR, MessagePack, UBJSON) are read by an input adapter and turned into the same SAX
@@ -192,6 +194,8 @@ packet-beta
96-127: "next"
```
<p class="nj-caption" markdown>Layout of one 16-byte node of a JSON view index. Each row is 32 bits wide, and the numbers are the bit offsets of the fields `kind`, `flags`, `extra`, `off`, `len`, and `next`.</p>
| Bytes | Field | Type | Contents |
|-------|---------|------------|-------------------------------------------------------------------------------------------------------------------------------|
| 0 | `kind` | `uint8_t` | the type, numbered as [`value_t`](../api/basic_json/value_t.md): 0 null, 1 object, 2 array, 3 string, 4 boolean, 5 signed integer, 6 unsigned integer, 7 float; 10 for a link (see below). There is no node for a discarded value: a [discarded](../api/basic_json_view/is_discarded.md) view has none |
@@ -201,6 +205,8 @@ packet-beta
| 8-11 | `len` | `uint32_t` | strings: the length after decoding; floats and literals: the length of the token; arrays and objects: the number of elements |
| 12-15 | `next` | `uint32_t` | arrays and objects: the number of nodes of the subtree, including the node itself |
<p class="nj-table-caption" markdown>Fields of a node, by their byte offset within the 16-byte node. Integers use bytes 8-15 differently, see below.</p>
- **Integers** keep their converted value in bytes 8-15 instead of `len` and `next`; the length of their token follows
from the number of digits in `extra` (and the sign). Non-negative integers are unsigned integers, as with
[`parse`](../api/basic_json/parse.md).
@@ -234,6 +240,8 @@ flowchart LR
n2 -. next .-> e
```
<p class="nj-caption" markdown>The five nodes of `#!json {"a": [1, 2.5]}` in document order. Solid arrows lead from each node to the one after it; dotted arrows show where `next` leads from the object and the array, past their subtrees.</p>
| Node | `kind` | `extra` | `off` | `len` | `next` |
|------|----------------------|---------|-------|-------|--------|
| 0 | 1 (object) | 0 | 0 | 1 | 5 |
@@ -242,6 +250,8 @@ flowchart LR
| 3 | 6 (unsigned integer) | 0x0001 | 7 | - | - |
| 4 | 7 (float) | 0x0101 | 10 | 3 | 0 |
<p class="nj-table-caption" markdown>Fields of the five nodes of `#!json {"a": [1, 2.5]}`. `off` is the byte offset in the text, and - marks the bytes 8-15 that hold the integer's value instead of `len` and `next`.</p>
All `flags` are 0. The integer's bytes 8-15 hold its value, 1; its `extra` says it has one digit. The float's `extra`
says it has one integer and one fraction digit, and its `len` is that of the token `2.5`.
@@ -287,8 +297,9 @@ template<class T>
std::size_t get_elements(T* dest, std::size_t count = 1);
```
The lexer detects two optional extensions at compile time. Only `iterator_input_adapter` provides them, and only for
random-access input of single-byte characters:
The lexer detects two optional extensions at compile time. `iterator_input_adapter` provides both, and only for
random-access input of single-byte characters. `input_stream_adapter` provides the second one (as a window onto the
streambuf's buffer) unless `JSON_DISABLE_STREAM_BULK_SCAN` is defined:
- `supports_seek`, `get_consumed_count()`, and `copy_consumed_range()` let the lexer reconstruct already consumed input
for error messages instead of copying every character it reads. With `get_read_count()` and
@@ -306,6 +317,40 @@ The function `input_adapter` picks the right adapter for the argument passed to
- `input_stream_adapter` reads from a `std::istream`.
- `file_input_adapter` reads from a `std::FILE*`.
The adapters have no common base class: the lexer and the parser are templates on the adapter type, and
`wide_string_input_adapter` wraps an `iterator_input_adapter`:
```mermaid
classDiagram
class input_adapter ["input adapter"] {
<<concept>>
+char_type
+get_character() int_type
+get_elements(T* dest, size_t count) size_t
}
class iterator_input_adapter {
-IteratorType current
-SentinelType end
}
class wide_string_input_adapter {
-BaseInputAdapter base_adapter
}
class input_stream_adapter {
-std::istream* is
-std::streambuf* sb
}
class file_input_adapter {
-std::FILE* m_file
}
input_adapter <|.. iterator_input_adapter
input_adapter <|.. wide_string_input_adapter
input_adapter <|.. input_stream_adapter
input_adapter <|.. file_input_adapter
wide_string_input_adapter o-- iterator_input_adapter : converts to UTF-8
```
<p class="nj-caption" markdown>The input adapters as a class diagram. The dotted arrows mean that each adapter implements the input adapter concept; the diamond shows that `wide_string_input_adapter` holds an `iterator_input_adapter`.</p>
## SAX interface
The parser does not build values itself. It reports what it reads as events to a [SAX](../features/parsing/sax_interface.md)
@@ -321,6 +366,7 @@ The library comes with two consumers in `detail/input/json_sax.hpp`:
The `binary_reader` emits the same events for binary formats, so [`sax_parse`](../api/basic_json/sax_parse.md) works
with a user-defined consumer for JSON and for all binary formats alike.
The [SAX event stepper](../features/parsing/sax_interface.md#sax-event-stepper) shows the events for a small input.
## Output adapters
@@ -339,6 +385,36 @@ The `serializer` (used by [`dump`](../api/basic_json/dump.md) and [`operator<<`]
- `output_stream_adapter` writes to a `std::ostream`.
- `output_string_adapter` appends to a string.
They implement the abstract class `output_adapter_protocol`. The class `output_adapter` creates the one that matches
its argument and holds it in a `std::shared_ptr` (`output_adapter_t`):
```mermaid
classDiagram
class output_adapter_protocol~CharType~ {
<<interface>>
+write_character(CharType c)*
+write_characters(const CharType* s, size_t length)*
}
class output_vector_adapter {
-std::vector& v
}
class output_stream_adapter {
-std::basic_ostream& stream
}
class output_string_adapter {
-StringType& str
}
class output_adapter {
-output_adapter_t oa
}
output_adapter_protocol <|-- output_vector_adapter
output_adapter_protocol <|-- output_stream_adapter
output_adapter_protocol <|-- output_string_adapter
output_adapter o-- output_adapter_protocol : shared_ptr
```
<p class="nj-caption" markdown>The output adapters as a class diagram. The three adapters derive from `output_adapter_protocol` (solid arrows), and `output_adapter` holds one of them through a `shared_ptr` (diamond).</p>
The `binary_writer` does not call an adapter for every byte. The `to_*` functions that return a `std::vector` write
into the vector through a sink (`output_vector_sink`) that is not virtual. The functions that take an output adapter
write through a sink (`output_adapter_sink`) that collects the output in a buffer of one kibibyte and passes it to the
+23 -23
View File
@@ -6,35 +6,35 @@
All exceptions inherit from class `json::exception` (which in turn inherits from `std::exception`). It is used as the base class for all exceptions thrown by the `basic_json` class. This class can hence be used as "wildcard" to catch exceptions.
``` mermaid
classDiagram
direction LR
class `std::exception` {
<<interface>>
}
The map shows the class tree and every exception id documented on this page; click an id to jump to its section.
class `json::exception` {
+const int id
+const char* what() const
}
<div class="nj-fig-wrap" markdown>
--8<-- "images/exception_map.svg"
</div>
class `json::parse_error` {
+const std::size_t byte
}
<p class="nj-caption" markdown>The exception classes from `std::exception` down to the five families, each with the ids it can throw. Every id chip links to the section that describes it.</p>
class `json::invalid_iterator`
class `json::type_error`
class `json::out_of_range`
class `json::other_error`
Which exception an element access throws depends on the function and on the type of the value:
`std::exception` <|-- `json::exception`
`json::exception` <|-- `json::parse_error`
`json::exception` <|-- `json::invalid_iterator`
`json::exception` <|-- `json::type_error`
`json::exception` <|-- `json::out_of_range`
`json::exception` <|-- `json::other_error`
```mermaid
flowchart LR
S{{"which call?"}} -->|"at(key)"| A{{"j is"}}
A -->|"object, key missing"| A1["out_of_range.403"]
A -->|"array or null"| A2["type_error.304"]
S -->|"at(index)"| B{{"j is"}}
B -->|"array, index >= size()"| B1["out_of_range.401"]
B -->|"object or null"| B2["type_error.304"]
S -->|"non-const operator[](key)"| C{{"j is"}}
C -->|"object or null"| C1["no exception: a missing key is inserted as null"]
C -->|"array"| C2["type_error.305"]
S -->|"value(key, default)"| D{{"j is"}}
D -->|"object, key missing"| D1["no exception: returns the default"]
D -->|"object, incompatible value type"| D2["type_error.302"]
D -->|"array or null"| D3["type_error.306"]
```
<p class="nj-caption" markdown>Exceptions thrown by element access. Start at the call on the left, follow the edge that matches the type of `j`, and read the exception id (or "no exception") in the box at the end.</p>
### Switch off exceptions
Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol [`JSON_NOEXCEPTION`](../api/macros/json_noexception.md). In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`).
+2
View File
@@ -192,6 +192,8 @@ The value is a `json`, and printing it produces JSON text. Convert it first: `#!
Use `contains` or `find`. Do not test with the non-const `operator[]`: like `std::map::operator[]`, it inserts a `null`
value for a missing key. See [Does this key exist?](../features/element_access/index.md#does-this-key-exist).
For choosing between `value`, `contains`/`find`, `at`, `operator[]`, and JSON Pointer, see the decision flow in
[Element access](../features/element_access/index.md).
### Reading a value with a fallback
+8
View File
@@ -14,6 +14,14 @@ changed in it. The API overview is generated from the "Version history" section
[API pages](../../api/basic_json/index.md); it is not a change log, but helps to see whether a feature is available in
the version you use.
All releases at a glance (hover a marker for its version and date):
<div class="nj-fig-wrap" markdown>
--8<-- "images/release_timeline.svg"
</div>
<p class="nj-caption" markdown>Releases from 1.0.0 to the latest one, on a time axis by year. Filled dots with a version label are minor or major releases, rings are patch releases.</p>
## Unreleased
| Release | Date | Summary |
@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--sizes" viewBox="0 0 340 220" role="img" aria-labelledby="nj-charts-bs-canada nj-charts-bs-canada-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-bs-canada">Size of canada.json in each binary format relative to minified J&#8203;SON</title>
<desc id="nj-charts-bs-canada-d">B&#8203;JData 53.2 %; B&#8203;ON8 50.5 %; B&#8203;SON 85.8 %; C&#8203;BOR 50.5 %; MessagePack 50.5 %; U&#8203;BJSON 53.2 %. Smallest: B&#8203;ON8 and C&#8203;BOR and MessagePack.</desc>
<text class="nj-charts-panel" x="8" y="18">canada.json</text>
<line class="nj-charts-grid" x1="104" y1="40" x2="104" y2="196"/>
<text class="nj-charts-tick" x="104" y="211">0 %</text>
<line class="nj-charts-grid" x1="186.727" y1="40" x2="186.727" y2="196"/>
<text class="nj-charts-tick" x="186.727" y="211">50 %</text>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="58.5">B&#8203;JData</text>
<path class="nj-charts-c1 nj-charts-dim" d="M104 46 H188.022 Q192.022 46 192.022 50 V58 Q192.022 62 188.022 62 H104 Z"><title>canada.json, B&#8203;JData: 53.2 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="84.5">B&#8203;ON8</text>
<path class="nj-charts-c2" d="M104 72 H183.555 Q187.555 72 187.555 76 V84 Q187.555 88 183.555 88 H104 Z"><title>canada.json, B&#8203;ON8: 50.5 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="110.5">B&#8203;SON</text>
<path class="nj-charts-c3 nj-charts-dim" d="M104 98 H241.96 Q245.96 98 245.96 102 V110 Q245.96 114 241.96 114 H104 Z"><title>canada.json, B&#8203;SON: 85.8 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="136.5">C&#8203;BOR</text>
<path class="nj-charts-c4" d="M104 124 H183.555 Q187.555 124 187.555 128 V136 Q187.555 140 183.555 140 H104 Z"><title>canada.json, C&#8203;BOR: 50.5 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="162.5">MessagePack</text>
<path class="nj-charts-c5" d="M104 150 H183.555 Q187.555 150 187.555 154 V162 Q187.555 166 183.555 166 H104 Z"><title>canada.json, MessagePack: 50.5 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="188.5">U&#8203;BJSON</text>
<path class="nj-charts-c6 nj-charts-dim" d="M104 176 H188.022 Q192.022 176 192.022 180 V188 Q192.022 192 188.022 192 H104 Z"><title>canada.json, U&#8203;BJSON: 53.2 % of minified J&#8203;SON</title></path>
<line class="nj-charts-ref" x1="269.455" y1="36" x2="269.455" y2="196"/>
<text class="nj-charts-tick nj-charts-tick--r" x="271.455" y="32">minified J&#8203;SON = 100 %</text>
<text class="nj-charts-tick" x="269.455" y="211">100 %</text>
<text class="nj-charts-val" x="197.022" y="58.5">53.2 %</text>
<text class="nj-charts-val nj-charts-best" x="192.555" y="84.5">50.5 %</text>
<text class="nj-charts-val" x="250.96" y="110.5">85.8 %</text>
<text class="nj-charts-val nj-charts-best" x="192.555" y="136.5">50.5 %</text>
<text class="nj-charts-val nj-charts-best" x="192.555" y="162.5">50.5 %</text>
<text class="nj-charts-val" x="197.022" y="188.5">53.2 %</text>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--sizes" viewBox="0 0 340 220" role="img" aria-labelledby="nj-charts-bs-citm_catalog nj-charts-bs-citm_catalog-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-bs-citm_catalog">Size of citm_catalog.json in each binary format relative to minified J&#8203;SON</title>
<desc id="nj-charts-bs-citm_catalog-d">B&#8203;JData 78.1 %; B&#8203;ON8 63.5 %; B&#8203;SON 95.8 %; C&#8203;BOR 68.4 %; MessagePack 68.5 %; U&#8203;BJSON 78.2 %. Smallest: B&#8203;ON8.</desc>
<text class="nj-charts-panel" x="8" y="18">citm_catalog.json</text>
<line class="nj-charts-grid" x1="104" y1="40" x2="104" y2="196"/>
<text class="nj-charts-tick" x="104" y="211">0 %</text>
<line class="nj-charts-grid" x1="186.727" y1="40" x2="186.727" y2="196"/>
<text class="nj-charts-tick" x="186.727" y="211">50 %</text>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="58.5">B&#8203;JData</text>
<path class="nj-charts-c1 nj-charts-dim" d="M104 46 H229.22 Q233.22 46 233.22 50 V58 Q233.22 62 229.22 62 H104 Z"><title>citm_catalog.json, B&#8203;JData: 78.1 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="84.5">B&#8203;ON8</text>
<path class="nj-charts-c2" d="M104 72 H205.064 Q209.064 72 209.064 76 V84 Q209.064 88 205.064 88 H104 Z"><title>citm_catalog.json, B&#8203;ON8: 63.5 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="110.5">B&#8203;SON</text>
<path class="nj-charts-c3 nj-charts-dim" d="M104 98 H258.505 Q262.505 98 262.505 102 V110 Q262.505 114 258.505 114 H104 Z"><title>citm_catalog.json, B&#8203;SON: 95.8 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="136.5">C&#8203;BOR</text>
<path class="nj-charts-c4 nj-charts-dim" d="M104 124 H213.171 Q217.171 124 217.171 128 V136 Q217.171 140 213.171 140 H104 Z"><title>citm_catalog.json, C&#8203;BOR: 68.4 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="162.5">MessagePack</text>
<path class="nj-charts-c5 nj-charts-dim" d="M104 150 H213.336 Q217.336 150 217.336 154 V162 Q217.336 166 213.336 166 H104 Z"><title>citm_catalog.json, MessagePack: 68.5 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="188.5">U&#8203;BJSON</text>
<path class="nj-charts-c6 nj-charts-dim" d="M104 176 H229.385 Q233.385 176 233.385 180 V188 Q233.385 192 229.385 192 H104 Z"><title>citm_catalog.json, U&#8203;BJSON: 78.2 % of minified J&#8203;SON</title></path>
<line class="nj-charts-ref" x1="269.455" y1="36" x2="269.455" y2="196"/>
<text class="nj-charts-tick nj-charts-tick--r" x="271.455" y="32">minified J&#8203;SON = 100 %</text>
<text class="nj-charts-tick" x="269.455" y="211">100 %</text>
<text class="nj-charts-val" x="238.22" y="58.5">78.1 %</text>
<text class="nj-charts-val nj-charts-best" x="214.064" y="84.5">63.5 %</text>
<text class="nj-charts-val" x="267.505" y="110.5">95.8 %</text>
<text class="nj-charts-val" x="222.171" y="136.5">68.4 %</text>
<text class="nj-charts-val" x="222.336" y="162.5">68.5 %</text>
<text class="nj-charts-val" x="238.385" y="188.5">78.2 %</text>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--sizes" viewBox="0 0 340 220" role="img" aria-labelledby="nj-charts-bs-jeopardy nj-charts-bs-jeopardy-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-bs-jeopardy">Size of jeopardy.json in each binary format relative to minified J&#8203;SON</title>
<desc id="nj-charts-bs-jeopardy-d">B&#8203;JData 96.6 %; B&#8203;ON8 87.5 %; B&#8203;SON 106.7 %; C&#8203;BOR 88 %; MessagePack 87.9 %; U&#8203;BJSON 96.6 %. Smallest: B&#8203;ON8.</desc>
<text class="nj-charts-panel" x="8" y="18">jeopardy.json</text>
<line class="nj-charts-grid" x1="104" y1="40" x2="104" y2="196"/>
<text class="nj-charts-tick" x="104" y="211">0 %</text>
<line class="nj-charts-grid" x1="186.727" y1="40" x2="186.727" y2="196"/>
<text class="nj-charts-tick" x="186.727" y="211">50 %</text>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="58.5">B&#8203;JData</text>
<path class="nj-charts-c1 nj-charts-dim" d="M104 46 H259.829 Q263.829 46 263.829 50 V58 Q263.829 62 259.829 62 H104 Z"><title>jeopardy.json, B&#8203;JData: 96.6 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="84.5">B&#8203;ON8</text>
<path class="nj-charts-c2" d="M104 72 H244.773 Q248.773 72 248.773 76 V84 Q248.773 88 244.773 88 H104 Z"><title>jeopardy.json, B&#8203;ON8: 87.5 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="110.5">B&#8203;SON</text>
<path class="nj-charts-c3 nj-charts-dim" d="M104 98 H276.54 Q280.54 98 280.54 102 V110 Q280.54 114 276.54 114 H104 Z"><title>jeopardy.json, B&#8203;SON: 106.7 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="136.5">C&#8203;BOR</text>
<path class="nj-charts-c4 nj-charts-dim" d="M104 124 H245.6 Q249.6 124 249.6 128 V136 Q249.6 140 245.6 140 H104 Z"><title>jeopardy.json, C&#8203;BOR: 88 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="162.5">MessagePack</text>
<path class="nj-charts-c5 nj-charts-dim" d="M104 150 H245.435 Q249.435 150 249.435 154 V162 Q249.435 166 245.435 166 H104 Z"><title>jeopardy.json, MessagePack: 87.9 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="188.5">U&#8203;BJSON</text>
<path class="nj-charts-c6 nj-charts-dim" d="M104 176 H259.829 Q263.829 176 263.829 180 V188 Q263.829 192 259.829 192 H104 Z"><title>jeopardy.json, U&#8203;BJSON: 96.6 % of minified J&#8203;SON</title></path>
<line class="nj-charts-ref" x1="269.455" y1="36" x2="269.455" y2="196"/>
<text class="nj-charts-tick nj-charts-tick--r" x="271.455" y="32">minified J&#8203;SON = 100 %</text>
<text class="nj-charts-tick" x="269.455" y="211">100 %</text>
<text class="nj-charts-val" x="268.829" y="58.5">96.6 %</text>
<text class="nj-charts-val nj-charts-best" x="253.773" y="84.5">87.5 %</text>
<text class="nj-charts-val" x="285.54" y="110.5">106.7 %</text>
<text class="nj-charts-val" x="254.6" y="136.5">88.0 %</text>
<text class="nj-charts-val" x="254.435" y="162.5">87.9 %</text>
<text class="nj-charts-val" x="268.829" y="188.5">96.6 %</text>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--sizes" viewBox="0 0 340 220" role="img" aria-labelledby="nj-charts-bs-twitter nj-charts-bs-twitter-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-bs-twitter">Size of twitter.json in each binary format relative to minified J&#8203;SON</title>
<desc id="nj-charts-bs-twitter-d">B&#8203;JData 91.1 %; B&#8203;ON8 83.8 %; B&#8203;SON 95.2 %; C&#8203;BOR 86.3 %; MessagePack 86 %; U&#8203;BJSON 91.3 %. Smallest: B&#8203;ON8.</desc>
<text class="nj-charts-panel" x="8" y="18">twitter.json</text>
<line class="nj-charts-grid" x1="104" y1="40" x2="104" y2="196"/>
<text class="nj-charts-tick" x="104" y="211">0 %</text>
<line class="nj-charts-grid" x1="186.727" y1="40" x2="186.727" y2="196"/>
<text class="nj-charts-tick" x="186.727" y="211">50 %</text>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="58.5">B&#8203;JData</text>
<path class="nj-charts-c1 nj-charts-dim" d="M104 46 H250.729 Q254.729 46 254.729 50 V58 Q254.729 62 250.729 62 H104 Z"><title>twitter.json, B&#8203;JData: 91.1 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt nj-charts-best" x="96" y="84.5">B&#8203;ON8</text>
<path class="nj-charts-c2" d="M104 72 H238.651 Q242.651 72 242.651 76 V84 Q242.651 88 238.651 88 H104 Z"><title>twitter.json, B&#8203;ON8: 83.8 % of minified J&#8203;SON (smallest)</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="110.5">B&#8203;SON</text>
<path class="nj-charts-c3 nj-charts-dim" d="M104 98 H257.513 Q261.513 98 261.513 102 V110 Q261.513 114 257.513 114 H104 Z"><title>twitter.json, B&#8203;SON: 95.2 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="136.5">C&#8203;BOR</text>
<path class="nj-charts-c4 nj-charts-dim" d="M104 124 H242.787 Q246.787 124 246.787 128 V136 Q246.787 140 242.787 140 H104 Z"><title>twitter.json, C&#8203;BOR: 86.3 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="162.5">MessagePack</text>
<path class="nj-charts-c5 nj-charts-dim" d="M104 150 H242.291 Q246.291 150 246.291 154 V162 Q246.291 166 242.291 166 H104 Z"><title>twitter.json, MessagePack: 86 % of minified J&#8203;SON</title></path>
<text class="nj-charts-rowlabel nj-charts-fmt" x="96" y="188.5">U&#8203;BJSON</text>
<path class="nj-charts-c6 nj-charts-dim" d="M104 176 H251.06 Q255.06 176 255.06 180 V188 Q255.06 192 251.06 192 H104 Z"><title>twitter.json, U&#8203;BJSON: 91.3 % of minified J&#8203;SON</title></path>
<line class="nj-charts-ref" x1="269.455" y1="36" x2="269.455" y2="196"/>
<text class="nj-charts-tick nj-charts-tick--r" x="271.455" y="32">minified J&#8203;SON = 100 %</text>
<text class="nj-charts-tick" x="269.455" y="211">100 %</text>
<text class="nj-charts-val" x="259.729" y="58.5">91.1 %</text>
<text class="nj-charts-val nj-charts-best" x="247.651" y="84.5">83.8 %</text>
<text class="nj-charts-val" x="266.513" y="110.5">95.2 %</text>
<text class="nj-charts-val" x="251.787" y="136.5">86.3 %</text>
<text class="nj-charts-val" x="251.291" y="162.5">86.0 %</text>
<text class="nj-charts-val" x="260.06" y="188.5">91.3 %</text>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

@@ -0,0 +1,39 @@
<svg class="nj-fig nj-fig--cb" viewBox="0 0 480 262" role="img" aria-labelledby="fig-cb-title" xmlns="http://www.w3.org/2000/svg">
<title id="fig-cb-title">Example of the parse events a callback sees for the J&#8203;SON text {&quot;name&quot;: &quot;Berlin&quot;, &quot;location&quot;: [52.519444, 13.406667]}: object_start after the opening brace, key after each key, array_start after the opening bracket, value after each value, array_end after the closing bracket, and object_end after the closing brace. Every array and object also produces a value event when it is complete.</title>
<text class="fg-h" x="16" y="28">J&#8203;SON to parse</text>
<text class="fg-h" x="320" y="28">callback events</text>
<text class="fg-code" x="16" y="74" xml:space="preserve">{</text>
<circle class="cb-os" cx="35.6" cy="69" r="5.5"/>
<text class="fg-code" x="35.2" y="102" xml:space="preserve">&quot;name&quot;</text>
<circle class="cb-k" cx="102.8" cy="97" r="5.5"/>
<text class="fg-code" x="112.8" y="102" xml:space="preserve">: &quot;Berlin&quot;</text>
<circle class="cb-v" cx="218.8" cy="97" r="5.5"/>
<text class="fg-code" x="228.8" y="102" xml:space="preserve">,</text>
<text class="fg-code" x="35.2" y="130" xml:space="preserve">&quot;location&quot;</text>
<circle class="cb-k" cx="141.2" cy="125" r="5.5"/>
<text class="fg-code" x="151.2" y="130" xml:space="preserve">: [</text>
<circle class="cb-as" cx="190" cy="125" r="5.5"/>
<text class="fg-code" x="54.4" y="158" xml:space="preserve">52.519444</text>
<circle class="cb-v" cx="150.8" cy="153" r="5.5"/>
<text class="fg-code" x="160.8" y="158" xml:space="preserve">,</text>
<text class="fg-code" x="54.4" y="186" xml:space="preserve">13.406667</text>
<circle class="cb-v" cx="150.8" cy="181" r="5.5"/>
<text class="fg-code" x="35.2" y="214" xml:space="preserve">]</text>
<circle class="cb-ae" cx="54.8" cy="209" r="5.5"/>
<circle class="cb-v" cx="74.8" cy="209" r="5.5"/>
<text class="fg-code" x="16" y="242" xml:space="preserve">}</text>
<circle class="cb-oe" cx="35.6" cy="237" r="5.5"/>
<circle class="cb-v" cx="55.6" cy="237" r="5.5"/>
<circle class="cb-os" cx="327" cy="69" r="6"/>
<text class="fg-code fg-leg" x="344" y="74">object_start</text>
<circle class="cb-k" cx="327" cy="99" r="6"/>
<text class="fg-code fg-leg" x="344" y="104">key</text>
<circle class="cb-oe" cx="327" cy="129" r="6"/>
<text class="fg-code fg-leg" x="344" y="134">object_end</text>
<circle class="cb-as" cx="327" cy="159" r="6"/>
<text class="fg-code fg-leg" x="344" y="164">array_start</text>
<circle class="cb-ae" cx="327" cy="189" r="6"/>
<text class="fg-code fg-leg" x="344" y="194">array_end</text>
<circle class="cb-v" cx="327" cy="219" r="6"/>
<text class="fg-code fg-leg" x="344" y="224">value</text>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@@ -0,0 +1,50 @@
<svg class="nj-fig nj-fig--sax-buf" viewBox="0 0 700 442" role="img" aria-labelledby="fig-sax-buf-title fig-sax-buf-desc" xmlns="http://www.w3.org/2000/svg">
<title id="fig-sax-buf-title">Buffering chunks until the value is complete: five chunks of {&quot;name&quot;: &quot;Mary&quot;, &quot;list&quot;: [1, 2, 3]} appended to a buffer.</title>
<desc id="fig-sax-buf-desc">After chunks 1 to 4 the buffer has 4, 12, 19, and 30 bytes, and parsing it fails at byte 5, 13, 20, and 31: one past the end, so the input is incomplete and the program waits for more. After chunk 5 the buffer of 35 bytes parses as one complete value. For the input [1, ] of 5 bytes the error is at byte 5, before the end, so it is a real syntax error. Every attempt parses the buffer from byte 1, so 4 + 12 + 19 + 30 + 35 = 100 bytes are parsed for a 35-byte value, and the work grows quadratically.</desc>
<text class="fg-h" x="16" y="24">chunk</text>
<text class="fg-h" x="96" y="24">buffer, parsed from byte 1 each time</text>
<text class="fg-h" x="420" y="24">result</text>
<text class="fg-note fg-note--l" x="16" y="67">chunk 1</text>
<rect class="nj-sax-new" x="96" y="50" width="36.6" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="67" xml:space="preserve">{&quot;na</text>
<path class="nj-sax-caret nj-sax-s-wait" d="M133.8 76 l-5 8 h10 z"/>
<text class="nj-sax-status nj-sax-s-wait" x="420" y="61">error at byte 5 = size + 1</text>
<text class="fg-note fg-note--l" x="420" y="77">incomplete: wait for more</text>
<text class="fg-note fg-note--l" x="16" y="117">chunk 2</text>
<rect class="nj-sax-old" x="93" y="100" width="36.6" height="24" rx="4"/>
<rect class="nj-sax-new" x="129.6" y="100" width="70.2" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="117" xml:space="preserve">{&quot;name&quot;: &quot;Ma</text>
<path class="nj-sax-caret nj-sax-s-wait" d="M201 126 l-5 8 h10 z"/>
<text class="nj-sax-status nj-sax-s-wait" x="420" y="111">error at byte 13 = size + 1</text>
<text class="fg-note fg-note--l" x="420" y="127">incomplete: wait for more</text>
<text class="fg-note fg-note--l" x="16" y="167">chunk 3</text>
<rect class="nj-sax-old" x="93" y="150" width="103.8" height="24" rx="4"/>
<rect class="nj-sax-new" x="196.8" y="150" width="61.8" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="167" xml:space="preserve">{&quot;name&quot;: &quot;Mary&quot;, &quot;l</text>
<path class="nj-sax-caret nj-sax-s-wait" d="M259.8 176 l-5 8 h10 z"/>
<text class="nj-sax-status nj-sax-s-wait" x="420" y="161">error at byte 20 = size + 1</text>
<text class="fg-note fg-note--l" x="420" y="177">incomplete: wait for more</text>
<text class="fg-note fg-note--l" x="16" y="217">chunk 4</text>
<rect class="nj-sax-old" x="93" y="200" width="162.6" height="24" rx="4"/>
<rect class="nj-sax-new" x="255.6" y="200" width="95.4" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="217" xml:space="preserve">{&quot;name&quot;: &quot;Mary&quot;, &quot;list&quot;: [1, 2</text>
<path class="nj-sax-caret nj-sax-s-wait" d="M352.2 226 l-5 8 h10 z"/>
<text class="nj-sax-status nj-sax-s-wait" x="420" y="211">error at byte 31 = size + 1</text>
<text class="fg-note fg-note--l" x="420" y="227">incomplete: wait for more</text>
<text class="fg-note fg-note--l" x="16" y="267">chunk 5</text>
<rect class="nj-sax-old" x="93" y="250" width="255" height="24" rx="4"/>
<rect class="nj-sax-new" x="348" y="250" width="45" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="267" xml:space="preserve">{&quot;name&quot;: &quot;Mary&quot;, &quot;list&quot;: [1, 2, 3]}</text>
<text class="nj-sax-status nj-sax-s-ok" x="420" y="261">parsed, size 35</text>
<text class="fg-note fg-note--l" x="420" y="277">complete: one value</text>
<path class="nj-sax-sep" d="M16 290 H684"/>
<text class="fg-note fg-note--l" x="16" y="325">other input</text>
<rect class="nj-sax-new" x="96" y="308" width="45" height="24" rx="4"/>
<text class="nj-sax-buf" x="96" y="325" xml:space="preserve">[1, ]</text>
<path class="nj-sax-caret nj-sax-s-err" d="M133.8 334 l-5 8 h10 z"/>
<text class="nj-sax-status nj-sax-s-err" x="420" y="319">error at byte 5, size 5</text>
<text class="fg-note fg-note--l" x="420" y="335">before the end: a real error</text>
<text class="fg-note fg-note--l" x="16" y="366">Bytes parsed: 4 + 12 + 19 + 30 + 35 = 100 for a value of 35 bytes.</text>
<text class="fg-note fg-note--l" x="16" y="386">Every attempt starts again at byte 1, so the total work grows</text>
<text class="fg-note fg-note--l" x="16" y="406">quadratically with the size of the value.</text>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

+60
View File
@@ -0,0 +1,60 @@
<svg class="nj-fig nj-charts nj-charts--compile" viewBox="0 0 470 516" role="img" aria-labelledby="nj-charts-ct nj-charts-ct-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-ct">Change in compile time against the default configuration at -O0, Apple clang and G&#8203;CC 16</title>
<desc id="nj-charts-ct-d">Grouped horizontal bars, negative is faster. json_fwd.hpp instead of json.hpp on a header-only translation unit: Apple clang -62 %, G&#8203;CC 16 -82 %; extern template on a parsing translation unit: Apple clang -7 %, G&#8203;CC 16 -21 %; JSON_NO_AUTOMATIC_UDLS on a model translation unit: Apple clang -11 %, G&#8203;CC 16 -11 %; JSON_NO_AUTOMATIC_UDLS on a parsing translation unit: Apple clang -1 %, G&#8203;CC 16 -2 %; JSON_HAS_FILESYSTEM=0 + JSON_NO_IO on a model translation unit: Apple clang -8 %, G&#8203;CC 16 -11 %; JSON_HAS_FILESYSTEM=0 on a model translation unit: Apple clang -5 %, G&#8203;CC 16 -9 %; JSON_NO_IO on a model translation unit: Apple clang -2 %, G&#8203;CC 16 -2 %; JSON_USE_GLOBAL_UDLS=0 on a model translation unit: Apple clang 0 %, G&#8203;CC 16 -1 %.</desc>
<rect class="nj-charts-clang" x="8" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="26" y="20.5">Apple clang</text>
<rect class="nj-charts-gcc" x="126" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="144" y="20.5">G&#8203;CC 16</text>
<line class="nj-charts-grid" x1="47.4" y1="58" x2="47.4" y2="472"/>
<text class="nj-charts-tick" x="47.4" y="488">&#8722;80 %</text>
<line class="nj-charts-grid" x1="126.2" y1="58" x2="126.2" y2="472"/>
<text class="nj-charts-tick" x="126.2" y="488">&#8722;60 %</text>
<line class="nj-charts-grid" x1="205" y1="58" x2="205" y2="472"/>
<text class="nj-charts-tick" x="205" y="488">&#8722;40 %</text>
<line class="nj-charts-grid" x1="283.8" y1="58" x2="283.8" y2="472"/>
<text class="nj-charts-tick" x="283.8" y="488">&#8722;20 %</text>
<text class="nj-charts-tick" x="362.6" y="488">0 %</text>
<text class="nj-charts-tick nj-charts-tick--l" x="8" y="506">&#8592; faster</text>
<text class="nj-charts-tick nj-charts-tick--r" x="462" y="506">slower &#8594;</text>
<text class="nj-charts-rowlabel" x="8" y="62"><tspan class="nj-charts-code">json_fwd.hpp instead of json.hpp</tspan><tspan class="nj-charts-sub"> &#183; header-only TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 70 H122.32 Q118.32 70 118.32 74 V78 Q118.32 82 122.32 82 H362.6 Z"><title>json_fwd.hpp instead of json.hpp, header-only TU (Apple clang): &#8722;62 %</title></path>
<text class="nj-charts-val" x="367.6" y="80.5">&#8722;62 %</text>
<path class="nj-charts-gcc" d="M362.6 84 H43.52 Q39.52 84 39.52 88 V92 Q39.52 96 43.52 96 H362.6 Z"><title>json_fwd.hpp instead of json.hpp, header-only TU (G&#8203;CC 16): &#8722;82 %</title></path>
<text class="nj-charts-val" x="367.6" y="94.5">&#8722;82 %</text>
<text class="nj-charts-rowlabel" x="8" y="114"><tspan class="nj-charts-code">extern template</tspan><tspan class="nj-charts-sub"> &#183; parsing TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 122 H339.02 Q335.02 122 335.02 126 V130 Q335.02 134 339.02 134 H362.6 Z"><title>extern template, parsing TU (Apple clang): &#8722;7 %</title></path>
<text class="nj-charts-val" x="367.6" y="132.5">&#8722;7 %</text>
<path class="nj-charts-gcc" d="M362.6 136 H283.86 Q279.86 136 279.86 140 V144 Q279.86 148 283.86 148 H362.6 Z"><title>extern template, parsing TU (G&#8203;CC 16): &#8722;21 %</title></path>
<text class="nj-charts-val" x="367.6" y="146.5">&#8722;21 %</text>
<text class="nj-charts-rowlabel" x="8" y="166"><tspan class="nj-charts-code">JSON_NO_AUTOMATIC_UDLS</tspan><tspan class="nj-charts-sub"> &#183; model TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 174 H323.26 Q319.26 174 319.26 178 V182 Q319.26 186 323.26 186 H362.6 Z"><title>JSON_NO_AUTOMATIC_UDLS, model TU (Apple clang): &#8722;11 %</title></path>
<text class="nj-charts-val" x="367.6" y="184.5">&#8722;11 %</text>
<path class="nj-charts-gcc" d="M362.6 188 H323.26 Q319.26 188 319.26 192 V196 Q319.26 200 323.26 200 H362.6 Z"><title>JSON_NO_AUTOMATIC_UDLS, model TU (G&#8203;CC 16): &#8722;11 %</title></path>
<text class="nj-charts-val" x="367.6" y="198.5">&#8722;11 %</text>
<text class="nj-charts-rowlabel" x="8" y="218"><tspan class="nj-charts-code">JSON_NO_AUTOMATIC_UDLS</tspan><tspan class="nj-charts-sub"> &#183; parsing TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 226 H362.6 Q358.66 226 358.66 229.94 V234.06 Q358.66 238 362.6 238 H362.6 Z"><title>JSON_NO_AUTOMATIC_UDLS, parsing TU (Apple clang): &#8722;1 %</title></path>
<text class="nj-charts-val" x="367.6" y="236.5">&#8722;1 %</text>
<path class="nj-charts-gcc" d="M362.6 240 H358.72 Q354.72 240 354.72 244 V248 Q354.72 252 358.72 252 H362.6 Z"><title>JSON_NO_AUTOMATIC_UDLS, parsing TU (G&#8203;CC 16): &#8722;2 %</title></path>
<text class="nj-charts-val" x="367.6" y="250.5">&#8722;2 %</text>
<text class="nj-charts-rowlabel" x="8" y="270"><tspan class="nj-charts-code">JSON_HAS_FILESYSTEM=0 + JSON_NO_IO</tspan><tspan class="nj-charts-sub"> &#183; model TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 278 H335.08 Q331.08 278 331.08 282 V286 Q331.08 290 335.08 290 H362.6 Z"><title>JSON_HAS_FILESYSTEM=0 + JSON_NO_IO, model TU (Apple clang): &#8722;8 %</title></path>
<text class="nj-charts-val" x="367.6" y="288.5">&#8722;8 %</text>
<path class="nj-charts-gcc" d="M362.6 292 H323.26 Q319.26 292 319.26 296 V300 Q319.26 304 323.26 304 H362.6 Z"><title>JSON_HAS_FILESYSTEM=0 + JSON_NO_IO, model TU (G&#8203;CC 16): &#8722;11 %</title></path>
<text class="nj-charts-val" x="367.6" y="302.5">&#8722;11 %</text>
<text class="nj-charts-rowlabel" x="8" y="322"><tspan class="nj-charts-code">JSON_HAS_FILESYSTEM=0</tspan><tspan class="nj-charts-sub"> &#183; model TU</tspan></text>
<path class="nj-charts-clang" d="M362.6 330 H346.9 Q342.9 330 342.9 334 V338 Q342.9 342 346.9 342 H362.6 Z"><title>JSON_HAS_FILESYSTEM=0, model TU (Apple clang): &#8722;5 %</title></path>
<text class="nj-charts-val" x="367.6" y="340.5">&#8722;5 %</text>
<path class="nj-charts-gcc" d="M362.6 344 H331.14 Q327.14 344 327.14 348 V352 Q327.14 356 331.14 356 H362.6 Z"><title>JSON_HAS_FILESYSTEM=0, model TU (G&#8203;CC 16): &#8722;9 %</title></path>
<text class="nj-charts-val" x="367.6" y="354.5">&#8722;9 %</text>
<text class="nj-charts-rowlabel" x="8" y="374"><tspan class="nj-charts-code">JSON_NO_IO</tspan><tspan class="nj-charts-sub"> &#183; model TU*</tspan></text>
<path class="nj-charts-clang" d="M362.6 382 H358.72 Q354.72 382 354.72 386 V390 Q354.72 394 358.72 394 H362.6 Z"><title>JSON_NO_IO, model TU (Apple clang): &#8722;2 %</title></path>
<text class="nj-charts-val" x="367.6" y="392.5">&#8722;2 %</text>
<path class="nj-charts-gcc" d="M362.6 396 H358.72 Q354.72 396 354.72 400 V404 Q354.72 408 358.72 408 H362.6 Z"><title>JSON_NO_IO, model TU (G&#8203;CC 16): &#8722;2 %</title></path>
<text class="nj-charts-val" x="367.6" y="406.5">&#8722;2 %</text>
<text class="nj-charts-rowlabel" x="8" y="426"><tspan class="nj-charts-code">JSON_USE_GLOBAL_UDLS=0</tspan><tspan class="nj-charts-sub"> &#183; model TU*</tspan></text>
<path class="nj-charts-clang" d="M362.6 434 h0.5 v12 h-0.5 Z"><title>JSON_USE_GLOBAL_UDLS=0, model TU (Apple clang): 0 %</title></path>
<text class="nj-charts-val" x="367.6" y="444.5">0 %</text>
<path class="nj-charts-gcc" d="M362.6 448 H362.6 Q358.66 448 358.66 451.94 V456.06 Q358.66 460 362.6 460 H362.6 Z"><title>JSON_USE_GLOBAL_UDLS=0, model TU (G&#8203;CC 16): &#8722;1 %</title></path>
<text class="nj-charts-val" x="367.6" y="458.5">&#8722;1 %</text>
<line class="nj-charts-zero" x1="362.6" y1="58" x2="362.6" y2="472"/>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--compile" viewBox="0 0 440 282" role="img" aria-labelledby="nj-charts-mod nj-charts-mod-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-mod">Compile time per translation unit with import nlohmann.json at -O0, and the one-off cost of the module</title>
<desc id="nj-charts-mod-d">Horizontal bars, negative is faster, medians of nine runs, -std=c++20 for both. model TU, Apple clang: -48 % (1311 ms to 680 ms); model TU, G&#8203;CC 16: -47 % (2156 ms to 1153 ms); parsing TU, Apple clang: -42 % (1387 ms to 800 ms); parsing TU, G&#8203;CC 16: -36 % (2838 ms to 1810 ms); one-off build, Apple clang: 1630 ms; one-off build, G&#8203;CC 16: 2538 ms.</desc>
<rect class="nj-charts-clang" x="8" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="26" y="20.5">Apple clang</text>
<rect class="nj-charts-gcc" x="126" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="144" y="20.5">G&#8203;CC 16</text>
<line class="nj-charts-grid" x1="68.6667" y1="58" x2="68.6667" y2="160"/>
<text class="nj-charts-tick" x="68.6667" y="176">&#8722;50 %</text>
<line class="nj-charts-grid" x1="220.333" y1="58" x2="220.333" y2="160"/>
<text class="nj-charts-tick" x="220.333" y="176">&#8722;25 %</text>
<text class="nj-charts-tick" x="372" y="176">0 %</text>
<text class="nj-charts-tick nj-charts-tick--l" x="8" y="194">&#8592; faster per TU</text>
<text class="nj-charts-rowlabel" x="8" y="62">model TU<tspan class="nj-charts-sub"> &#183; import nlohmann.json</tspan></text>
<path class="nj-charts-clang" d="M372 70 H84.8 Q80.8 70 80.8 74 V78 Q80.8 82 84.8 82 H372 Z"><title>model TU, Apple clang: 1311 ms by default, 680 ms import nlohmann.json (&#8722;48 %)</title></path>
<text class="nj-charts-val" x="377" y="80.5">&#8722;48 %</text>
<path class="nj-charts-gcc" d="M372 84 H90.8667 Q86.8667 84 86.8667 88 V92 Q86.8667 96 90.8667 96 H372 Z"><title>model TU, G&#8203;CC 16: 2156 ms by default, 1153 ms import nlohmann.json (&#8722;47 %)</title></path>
<text class="nj-charts-val" x="377" y="94.5">&#8722;47 %</text>
<text class="nj-charts-rowlabel" x="8" y="114">parsing TU<tspan class="nj-charts-sub"> &#183; import nlohmann.json</tspan></text>
<path class="nj-charts-clang" d="M372 122 H121.2 Q117.2 122 117.2 126 V130 Q117.2 134 121.2 134 H372 Z"><title>parsing TU, Apple clang: 1387 ms by default, 800 ms import nlohmann.json (&#8722;42 %)</title></path>
<text class="nj-charts-val" x="377" y="132.5">&#8722;42 %</text>
<path class="nj-charts-gcc" d="M372 136 H157.6 Q153.6 136 153.6 140 V144 Q153.6 148 157.6 148 H372 Z"><title>parsing TU, G&#8203;CC 16: 2838 ms by default, 1810 ms import nlohmann.json (&#8722;36 %)</title></path>
<text class="nj-charts-val" x="377" y="146.5">&#8722;36 %</text>
<line class="nj-charts-zero" x1="372" y1="58" x2="372" y2="160"/>
<text class="nj-charts-rowlabel" x="8" y="222">One-off cost<tspan class="nj-charts-sub"> &#183; built once, reused by every TU</tspan></text>
<rect class="nj-charts-clang" x="8" y="232.5" width="10" height="10" rx="2.5"/>
<text class="nj-charts-val" x="24" y="242">Apple clang: 1630 ms once, saves 587 to 631 ms per TU</text>
<rect class="nj-charts-gcc" x="8" y="252.5" width="10" height="10" rx="2.5"/>
<text class="nj-charts-val" x="24" y="262">G&#8203;CC 16: 2538 ms once, saves 1003 to 1028 ms per TU</text>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -0,0 +1,30 @@
<svg class="nj-fig nj-charts nj-charts--compile" viewBox="0 0 440 282" role="img" aria-labelledby="nj-charts-pch nj-charts-pch-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-pch">Compile time per translation unit with a precompiled json.hpp at -O0, and the one-off cost of the PCH</title>
<desc id="nj-charts-pch-d">Horizontal bars, negative is faster, medians of nine runs, -std=c++17. model TU, Apple clang: -43 % (1045 ms to 594 ms); model TU, G&#8203;CC 16: -41 % (1789 ms to 1060 ms); parsing TU, Apple clang: -38 % (1148 ms to 714 ms); parsing TU, G&#8203;CC 16: -25 % (2498 ms to 1884 ms); one-off build, Apple clang: 771 ms; one-off build, G&#8203;CC 16: 2254 ms.</desc>
<rect class="nj-charts-clang" x="8" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="26" y="20.5">Apple clang</text>
<rect class="nj-charts-gcc" x="126" y="10" width="12" height="12" rx="3"/>
<text class="nj-charts-leg" x="144" y="20.5">G&#8203;CC 16</text>
<line class="nj-charts-grid" x1="68.6667" y1="58" x2="68.6667" y2="160"/>
<text class="nj-charts-tick" x="68.6667" y="176">&#8722;50 %</text>
<line class="nj-charts-grid" x1="220.333" y1="58" x2="220.333" y2="160"/>
<text class="nj-charts-tick" x="220.333" y="176">&#8722;25 %</text>
<text class="nj-charts-tick" x="372" y="176">0 %</text>
<text class="nj-charts-tick nj-charts-tick--l" x="8" y="194">&#8592; faster per TU</text>
<text class="nj-charts-rowlabel" x="8" y="62">model TU<tspan class="nj-charts-sub"> &#183; with PCH</tspan></text>
<path class="nj-charts-clang" d="M372 70 H115.133 Q111.133 70 111.133 74 V78 Q111.133 82 115.133 82 H372 Z"><title>model TU, Apple clang: 1045 ms by default, 594 ms with PCH (&#8722;43 %)</title></path>
<text class="nj-charts-val" x="377" y="80.5">&#8722;43 %</text>
<path class="nj-charts-gcc" d="M372 84 H127.267 Q123.267 84 123.267 88 V92 Q123.267 96 127.267 96 H372 Z"><title>model TU, G&#8203;CC 16: 1789 ms by default, 1060 ms with PCH (&#8722;41 %)</title></path>
<text class="nj-charts-val" x="377" y="94.5">&#8722;41 %</text>
<text class="nj-charts-rowlabel" x="8" y="114">parsing TU<tspan class="nj-charts-sub"> &#183; with PCH</tspan></text>
<path class="nj-charts-clang" d="M372 122 H145.467 Q141.467 122 141.467 126 V130 Q141.467 134 145.467 134 H372 Z"><title>parsing TU, Apple clang: 1148 ms by default, 714 ms with PCH (&#8722;38 %)</title></path>
<text class="nj-charts-val" x="377" y="132.5">&#8722;38 %</text>
<path class="nj-charts-gcc" d="M372 136 H224.333 Q220.333 136 220.333 140 V144 Q220.333 148 224.333 148 H372 Z"><title>parsing TU, G&#8203;CC 16: 2498 ms by default, 1884 ms with PCH (&#8722;25 %)</title></path>
<text class="nj-charts-val" x="377" y="146.5">&#8722;25 %</text>
<line class="nj-charts-zero" x1="372" y1="58" x2="372" y2="160"/>
<text class="nj-charts-rowlabel" x="8" y="222">One-off cost<tspan class="nj-charts-sub"> &#183; built once, reused by every TU</tspan></text>
<rect class="nj-charts-clang" x="8" y="232.5" width="10" height="10" rx="2.5"/>
<text class="nj-charts-val" x="24" y="242">Apple clang: 771 ms once, saves 434 to 451 ms per TU</text>
<rect class="nj-charts-gcc" x="8" y="252.5" width="10" height="10" rx="2.5"/>
<text class="nj-charts-val" x="24" y="262">G&#8203;CC 16: 2254 ms once, saves 614 to 729 ms per TU</text>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

+174
View File
@@ -0,0 +1,174 @@
<svg class="nj-fig nj-exceptions-map nj-exceptions-map--wide" viewBox="0 0 760 694" aria-labelledby="nj-exc-map-title-w nj-exc-map-desc-w" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title id="nj-exc-map-title-w">Exception id map</title>
<desc id="nj-exc-map-desc-w">Class tree: std::exception is the base of json::exception, which is the base of the five exception families parse_error (ids 1xx), invalid_iterator (2xx), type_error (3xx), out_of_range (4xx) and other_error (5xx). Each family lists the ids documented on this page, 68 in total; every id links to its section.</desc>
<defs><marker id="nj-exc-tri-w" viewBox="0 0 12 12" refX="11" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path class="nj-exceptions-tri" d="M1 1 L11 6 L1 11 z"/></marker></defs>
<line class="nj-exceptions-edge" x1="34" y1="656" x2="34" y2="158" marker-end="url(#nj-exc-tri-w)"/>
<rect class="nj-exceptions-box" x="12" y="12" width="200" height="52" rx="7"/><text class="nj-exceptions-name" x="24" y="34">std::exception</text><text class="nj-exceptions-sub" x="24" y="53">C++ standard library base</text>
<line class="nj-exceptions-edge" x1="34" y1="104" x2="34" y2="66" marker-end="url(#nj-exc-tri-w)"/>
<rect class="nj-exceptions-box" x="12" y="104" width="300" height="52" rx="7"/><text class="nj-exceptions-name" x="24" y="126">json::exception</text><text class="nj-exceptions-sub" x="24" y="145">id, what() · catch-all</text>
<line class="nj-exceptions-edge" x1="34" y1="222" x2="64" y2="222"/>
<a class="nj-exceptions-fam" xlink:href="#parse-errors" aria-label="json::parse_error, 1xx · 15 ids · adds member byte"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="196" width="214" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="218">json::parse_error</text><text class="nj-exceptions-sub" x="76" y="237">1xx · 15 ids · adds member byte</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error101" aria-label="json.exception.parse_error.101"><rect x="294" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="226.5">101</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error102" aria-label="json.exception.parse_error.102"><rect x="341.7" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="226.5">102</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error103" aria-label="json.exception.parse_error.103"><rect x="389.4" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="226.5">103</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error104" aria-label="json.exception.parse_error.104"><rect x="437.1" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="226.5">104</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error105" aria-label="json.exception.parse_error.105"><rect x="484.8" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="226.5">105</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error106" aria-label="json.exception.parse_error.106"><rect x="532.5" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="226.5">106</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error107" aria-label="json.exception.parse_error.107"><rect x="580.2" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="226.5">107</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error108" aria-label="json.exception.parse_error.108"><rect x="627.9" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="636.9" y="226.5">108</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error109" aria-label="json.exception.parse_error.109"><rect x="675.6" y="208" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="684.6" y="226.5">109</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error110" aria-label="json.exception.parse_error.110"><rect x="294" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="260.5">110</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error112" aria-label="json.exception.parse_error.112"><rect x="341.7" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="260.5">112</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error113" aria-label="json.exception.parse_error.113"><rect x="389.4" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="260.5">113</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error114" aria-label="json.exception.parse_error.114"><rect x="437.1" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="260.5">114</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error115" aria-label="json.exception.parse_error.115"><rect x="484.8" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="260.5">115</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error116" aria-label="json.exception.parse_error.116"><rect x="532.5" y="242" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="260.5">116</text></a>
<line class="nj-exceptions-edge" x1="34" y1="322" x2="64" y2="322"/>
<a class="nj-exceptions-fam" xlink:href="#iterator-errors" aria-label="json::invalid_iterator, 2xx · 14 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="296" width="214" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="318">json::invalid_iterator</text><text class="nj-exceptions-sub" x="76" y="337">2xx · 14 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator201" aria-label="json.exception.invalid_iterator.201"><rect x="294" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="326.5">201</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator202" aria-label="json.exception.invalid_iterator.202"><rect x="341.7" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="326.5">202</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator203" aria-label="json.exception.invalid_iterator.203"><rect x="389.4" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="326.5">203</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator204" aria-label="json.exception.invalid_iterator.204"><rect x="437.1" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="326.5">204</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator205" aria-label="json.exception.invalid_iterator.205"><rect x="484.8" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="326.5">205</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator206" aria-label="json.exception.invalid_iterator.206"><rect x="532.5" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="326.5">206</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator207" aria-label="json.exception.invalid_iterator.207"><rect x="580.2" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="326.5">207</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator208" aria-label="json.exception.invalid_iterator.208"><rect x="627.9" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="636.9" y="326.5">208</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator209" aria-label="json.exception.invalid_iterator.209"><rect x="675.6" y="308" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="684.6" y="326.5">209</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator210" aria-label="json.exception.invalid_iterator.210"><rect x="294" y="342" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="360.5">210</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator211" aria-label="json.exception.invalid_iterator.211"><rect x="341.7" y="342" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="360.5">211</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator212" aria-label="json.exception.invalid_iterator.212"><rect x="389.4" y="342" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="360.5">212</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator213" aria-label="json.exception.invalid_iterator.213"><rect x="437.1" y="342" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="360.5">213</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator214" aria-label="json.exception.invalid_iterator.214"><rect x="484.8" y="342" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="360.5">214</text></a>
<line class="nj-exceptions-edge" x1="34" y1="422" x2="64" y2="422"/>
<a class="nj-exceptions-fam" xlink:href="#type-errors" aria-label="json::type_error, 3xx · 21 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="396" width="214" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="418">json::type_error</text><text class="nj-exceptions-sub" x="76" y="437">3xx · 21 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error301" aria-label="json.exception.type_error.301"><rect x="294" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="426.5">301</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error302" aria-label="json.exception.type_error.302"><rect x="341.7" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="426.5">302</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error303" aria-label="json.exception.type_error.303"><rect x="389.4" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="426.5">303</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error304" aria-label="json.exception.type_error.304"><rect x="437.1" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="426.5">304</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error305" aria-label="json.exception.type_error.305"><rect x="484.8" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="426.5">305</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error306" aria-label="json.exception.type_error.306"><rect x="532.5" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="426.5">306</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error307" aria-label="json.exception.type_error.307"><rect x="580.2" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="426.5">307</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error308" aria-label="json.exception.type_error.308"><rect x="627.9" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="636.9" y="426.5">308</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error309" aria-label="json.exception.type_error.309"><rect x="675.6" y="408" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="684.6" y="426.5">309</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error310" aria-label="json.exception.type_error.310"><rect x="294" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="460.5">310</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error311" aria-label="json.exception.type_error.311"><rect x="341.7" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="460.5">311</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error312" aria-label="json.exception.type_error.312"><rect x="389.4" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="460.5">312</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error313" aria-label="json.exception.type_error.313"><rect x="437.1" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="460.5">313</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error314" aria-label="json.exception.type_error.314"><rect x="484.8" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="460.5">314</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error315" aria-label="json.exception.type_error.315"><rect x="532.5" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="460.5">315</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error316" aria-label="json.exception.type_error.316"><rect x="580.2" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="460.5">316</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error317" aria-label="json.exception.type_error.317"><rect x="627.9" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="636.9" y="460.5">317</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error318" aria-label="json.exception.type_error.318"><rect x="675.6" y="442" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="684.6" y="460.5">318</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error319" aria-label="json.exception.type_error.319"><rect x="294" y="476" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="494.5">319</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error320" aria-label="json.exception.type_error.320"><rect x="341.7" y="476" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="494.5">320</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error321" aria-label="json.exception.type_error.321"><rect x="389.4" y="476" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="494.5">321</text></a>
<line class="nj-exceptions-edge" x1="34" y1="556" x2="64" y2="556"/>
<a class="nj-exceptions-fam" xlink:href="#out-of-range" aria-label="json::out_of_range, 4xx · 16 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="530" width="214" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="552">json::out_of_range</text><text class="nj-exceptions-sub" x="76" y="571">4xx · 16 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range401" aria-label="json.exception.out_of_range.401"><rect x="294" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="560.5">401</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range402" aria-label="json.exception.out_of_range.402"><rect x="341.7" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="560.5">402</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range403" aria-label="json.exception.out_of_range.403"><rect x="389.4" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="560.5">403</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range404" aria-label="json.exception.out_of_range.404"><rect x="437.1" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="560.5">404</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range405" aria-label="json.exception.out_of_range.405"><rect x="484.8" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="560.5">405</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range406" aria-label="json.exception.out_of_range.406"><rect x="532.5" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="560.5">406</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range407" aria-label="json.exception.out_of_range.407"><rect x="580.2" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="560.5">407</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range408" aria-label="json.exception.out_of_range.408"><rect x="627.9" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="636.9" y="560.5">408</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range409" aria-label="json.exception.out_of_range.409"><rect x="675.6" y="542" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="684.6" y="560.5">409</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range410" aria-label="json.exception.out_of_range.410"><rect x="294" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="594.5">410</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range411" aria-label="json.exception.out_of_range.411"><rect x="341.7" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="594.5">411</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range412" aria-label="json.exception.out_of_range.412"><rect x="389.4" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="398.4" y="594.5">412</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range413" aria-label="json.exception.out_of_range.413"><rect x="437.1" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="446.1" y="594.5">413</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range414" aria-label="json.exception.out_of_range.414"><rect x="484.8" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="493.8" y="594.5">414</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range415" aria-label="json.exception.out_of_range.415"><rect x="532.5" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="541.5" y="594.5">415</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range416" aria-label="json.exception.out_of_range.416"><rect x="580.2" y="576" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="589.2" y="594.5">416</text></a>
<line class="nj-exceptions-edge" x1="34" y1="656" x2="64" y2="656"/>
<a class="nj-exceptions-fam" xlink:href="#further-exceptions" aria-label="json::other_error, 5xx · 2 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="630" width="214" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="652">json::other_error</text><text class="nj-exceptions-sub" x="76" y="671">5xx · 2 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionother_error501" aria-label="json.exception.other_error.501"><rect x="294" y="642" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="303" y="660.5">501</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionother_error502" aria-label="json.exception.other_error.502"><rect x="341.7" y="642" width="41.7" height="28" rx="6"/><text class="nj-exceptions-id" x="350.7" y="660.5">502</text></a>
</svg>
<svg class="nj-fig nj-exceptions-map nj-exceptions-map--narrow" viewBox="0 0 360 1152" aria-labelledby="nj-exc-map-title-n nj-exc-map-desc-n" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title id="nj-exc-map-title-n">Exception id map</title>
<desc id="nj-exc-map-desc-n">Class tree: std::exception is the base of json::exception, which is the base of the five exception families parse_error (ids 1xx), invalid_iterator (2xx), type_error (3xx), out_of_range (4xx) and other_error (5xx). Each family lists the ids documented on this page, 68 in total; every id links to its section.</desc>
<defs><marker id="nj-exc-tri-n" viewBox="0 0 12 12" refX="11" refY="6" markerWidth="11" markerHeight="11" orient="auto"><path class="nj-exceptions-tri" d="M1 1 L11 6 L1 11 z"/></marker></defs>
<line class="nj-exceptions-edge" x1="34" y1="1070" x2="34" y2="158" marker-end="url(#nj-exc-tri-n)"/>
<rect class="nj-exceptions-box" x="12" y="12" width="190" height="52" rx="7"/><text class="nj-exceptions-name" x="24" y="34">std::exception</text><text class="nj-exceptions-sub" x="24" y="53">C++ standard library base</text>
<line class="nj-exceptions-edge" x1="34" y1="104" x2="34" y2="66" marker-end="url(#nj-exc-tri-n)"/>
<rect class="nj-exceptions-box" x="12" y="104" width="250" height="52" rx="7"/><text class="nj-exceptions-name" x="24" y="126">json::exception</text><text class="nj-exceptions-sub" x="24" y="145">id, what() · catch-all</text>
<line class="nj-exceptions-edge" x1="34" y1="222" x2="64" y2="222"/>
<a class="nj-exceptions-fam" xlink:href="#parse-errors" aria-label="json::parse_error, 1xx · 15 ids · adds member byte"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="196" width="284" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="218">json::parse_error</text><text class="nj-exceptions-sub" x="76" y="237">1xx · 15 ids · adds member byte</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error101" aria-label="json.exception.parse_error.101"><rect x="64" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="279.5">101</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error102" aria-label="json.exception.parse_error.102"><rect x="111.7" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="279.5">102</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error103" aria-label="json.exception.parse_error.103"><rect x="159.4" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="279.5">103</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error104" aria-label="json.exception.parse_error.104"><rect x="207.1" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="279.5">104</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error105" aria-label="json.exception.parse_error.105"><rect x="254.8" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="279.5">105</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error106" aria-label="json.exception.parse_error.106"><rect x="302.5" y="258" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="279.5">106</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error107" aria-label="json.exception.parse_error.107"><rect x="64" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="319.5">107</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error108" aria-label="json.exception.parse_error.108"><rect x="111.7" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="319.5">108</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error109" aria-label="json.exception.parse_error.109"><rect x="159.4" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="319.5">109</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error110" aria-label="json.exception.parse_error.110"><rect x="207.1" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="319.5">110</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error112" aria-label="json.exception.parse_error.112"><rect x="254.8" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="319.5">112</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error113" aria-label="json.exception.parse_error.113"><rect x="302.5" y="298" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="319.5">113</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error114" aria-label="json.exception.parse_error.114"><rect x="64" y="338" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="359.5">114</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error115" aria-label="json.exception.parse_error.115"><rect x="111.7" y="338" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="359.5">115</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionparse_error116" aria-label="json.exception.parse_error.116"><rect x="159.4" y="338" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="359.5">116</text></a>
<line class="nj-exceptions-edge" x1="34" y1="424" x2="64" y2="424"/>
<a class="nj-exceptions-fam" xlink:href="#iterator-errors" aria-label="json::invalid_iterator, 2xx · 14 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="398" width="284" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="420">json::invalid_iterator</text><text class="nj-exceptions-sub" x="76" y="439">2xx · 14 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator201" aria-label="json.exception.invalid_iterator.201"><rect x="64" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="481.5">201</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator202" aria-label="json.exception.invalid_iterator.202"><rect x="111.7" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="481.5">202</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator203" aria-label="json.exception.invalid_iterator.203"><rect x="159.4" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="481.5">203</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator204" aria-label="json.exception.invalid_iterator.204"><rect x="207.1" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="481.5">204</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator205" aria-label="json.exception.invalid_iterator.205"><rect x="254.8" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="481.5">205</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator206" aria-label="json.exception.invalid_iterator.206"><rect x="302.5" y="460" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="481.5">206</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator207" aria-label="json.exception.invalid_iterator.207"><rect x="64" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="521.5">207</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator208" aria-label="json.exception.invalid_iterator.208"><rect x="111.7" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="521.5">208</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator209" aria-label="json.exception.invalid_iterator.209"><rect x="159.4" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="521.5">209</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator210" aria-label="json.exception.invalid_iterator.210"><rect x="207.1" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="521.5">210</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator211" aria-label="json.exception.invalid_iterator.211"><rect x="254.8" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="521.5">211</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator212" aria-label="json.exception.invalid_iterator.212"><rect x="302.5" y="500" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="521.5">212</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator213" aria-label="json.exception.invalid_iterator.213"><rect x="64" y="540" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="561.5">213</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptioninvalid_iterator214" aria-label="json.exception.invalid_iterator.214"><rect x="111.7" y="540" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="561.5">214</text></a>
<line class="nj-exceptions-edge" x1="34" y1="626" x2="64" y2="626"/>
<a class="nj-exceptions-fam" xlink:href="#type-errors" aria-label="json::type_error, 3xx · 21 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="600" width="284" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="622">json::type_error</text><text class="nj-exceptions-sub" x="76" y="641">3xx · 21 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error301" aria-label="json.exception.type_error.301"><rect x="64" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="683.5">301</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error302" aria-label="json.exception.type_error.302"><rect x="111.7" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="683.5">302</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error303" aria-label="json.exception.type_error.303"><rect x="159.4" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="683.5">303</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error304" aria-label="json.exception.type_error.304"><rect x="207.1" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="683.5">304</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error305" aria-label="json.exception.type_error.305"><rect x="254.8" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="683.5">305</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error306" aria-label="json.exception.type_error.306"><rect x="302.5" y="662" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="683.5">306</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error307" aria-label="json.exception.type_error.307"><rect x="64" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="723.5">307</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error308" aria-label="json.exception.type_error.308"><rect x="111.7" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="723.5">308</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error309" aria-label="json.exception.type_error.309"><rect x="159.4" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="723.5">309</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error310" aria-label="json.exception.type_error.310"><rect x="207.1" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="723.5">310</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error311" aria-label="json.exception.type_error.311"><rect x="254.8" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="723.5">311</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error312" aria-label="json.exception.type_error.312"><rect x="302.5" y="702" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="723.5">312</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error313" aria-label="json.exception.type_error.313"><rect x="64" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="763.5">313</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error314" aria-label="json.exception.type_error.314"><rect x="111.7" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="763.5">314</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error315" aria-label="json.exception.type_error.315"><rect x="159.4" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="763.5">315</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error316" aria-label="json.exception.type_error.316"><rect x="207.1" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="763.5">316</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error317" aria-label="json.exception.type_error.317"><rect x="254.8" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="763.5">317</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error318" aria-label="json.exception.type_error.318"><rect x="302.5" y="742" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="763.5">318</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error319" aria-label="json.exception.type_error.319"><rect x="64" y="782" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="803.5">319</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error320" aria-label="json.exception.type_error.320"><rect x="111.7" y="782" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="803.5">320</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptiontype_error321" aria-label="json.exception.type_error.321"><rect x="159.4" y="782" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="803.5">321</text></a>
<line class="nj-exceptions-edge" x1="34" y1="868" x2="64" y2="868"/>
<a class="nj-exceptions-fam" xlink:href="#out-of-range" aria-label="json::out_of_range, 4xx · 16 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="842" width="284" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="864">json::out_of_range</text><text class="nj-exceptions-sub" x="76" y="883">4xx · 16 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range401" aria-label="json.exception.out_of_range.401"><rect x="64" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="925.5">401</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range402" aria-label="json.exception.out_of_range.402"><rect x="111.7" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="925.5">402</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range403" aria-label="json.exception.out_of_range.403"><rect x="159.4" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="925.5">403</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range404" aria-label="json.exception.out_of_range.404"><rect x="207.1" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="925.5">404</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range405" aria-label="json.exception.out_of_range.405"><rect x="254.8" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="925.5">405</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range406" aria-label="json.exception.out_of_range.406"><rect x="302.5" y="904" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="925.5">406</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range407" aria-label="json.exception.out_of_range.407"><rect x="64" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="965.5">407</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range408" aria-label="json.exception.out_of_range.408"><rect x="111.7" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="965.5">408</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range409" aria-label="json.exception.out_of_range.409"><rect x="159.4" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="965.5">409</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range410" aria-label="json.exception.out_of_range.410"><rect x="207.1" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="965.5">410</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range411" aria-label="json.exception.out_of_range.411"><rect x="254.8" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="263.8" y="965.5">411</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range412" aria-label="json.exception.out_of_range.412"><rect x="302.5" y="944" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="311.5" y="965.5">412</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range413" aria-label="json.exception.out_of_range.413"><rect x="64" y="984" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="1005.5">413</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range414" aria-label="json.exception.out_of_range.414"><rect x="111.7" y="984" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="1005.5">414</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range415" aria-label="json.exception.out_of_range.415"><rect x="159.4" y="984" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="168.4" y="1005.5">415</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionout_of_range416" aria-label="json.exception.out_of_range.416"><rect x="207.1" y="984" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="216.1" y="1005.5">416</text></a>
<line class="nj-exceptions-edge" x1="34" y1="1070" x2="64" y2="1070"/>
<a class="nj-exceptions-fam" xlink:href="#further-exceptions" aria-label="json::other_error, 5xx · 2 ids"><rect class="nj-exceptions-box nj-exceptions-box--fam" x="64" y="1044" width="284" height="52" rx="7"/><text class="nj-exceptions-name" x="76" y="1066">json::other_error</text><text class="nj-exceptions-sub" x="76" y="1085">5xx · 2 ids</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionother_error501" aria-label="json.exception.other_error.501"><rect x="64" y="1106" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="73" y="1127.5">501</text></a>
<a class="nj-exceptions-chip" xlink:href="#jsonexceptionother_error502" aria-label="json.exception.other_error.502"><rect x="111.7" y="1106" width="41.7" height="34" rx="6"/><text class="nj-exceptions-id" x="120.7" y="1127.5">502</text></a>
</svg>

After

Width:  |  Height:  |  Size: 39 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 675" width="1200" height="675" role="img"><title>JSON for Modern C++: feature slideshow (animated, 20 slides, 15 s each)</title><style>.bg{fill:#fff} .tx{fill:#0f1419} .tx2{fill:#3d444f} .tx3{fill:#8a919c} .com{fill:#646d7a}.bl{fill:#1747a6} .blk{fill:#1747a6} .kw{fill:#1747a6} .ty{fill:#0d6e72} .fn{fill:#6b3fb8} .str{fill:#23793a} .num{fill:#b04a07} .pp{fill:#a3247a}.panel{fill:#f5f7fa;stroke:#e3e6eb;stroke-width:1} .rule{stroke:#e3e6eb;stroke-width:1}.wm-a{fill:#0f1419} .wm-s{fill:#1747a6}.on-a,.on-tx{fill:#fff} .red{fill:#d93a3f} .on-panel{fill:#fff;fill-opacity:.08;stroke:#fff;stroke-opacity:.16} .on-s{fill:#bcd3fb} .w70{fill:#fff;fill-opacity:.7} .on-tx2{fill:#dbe6fb} .chip{fill:#fff;fill-opacity:.14}.pat{fill:#fff;fill-opacity:.09}.h1{stop-color:#1d55c4} .h2{stop-color:#123a8a}.seg{fill:#e3e6eb} .seg-on{fill:#1747a6}.seg.on-band{fill:#fff;fill-opacity:.25} .seg-on.on-band{fill:#fff;fill-opacity:1}.bg{fill:#0f1218} .tx,.wm-a{fill:#f2f4f7} .tx2{fill:#c3c8d1} .tx3{fill:#7b828e} .com{fill:#8b929e}.bl,.blk,.wm-s,.seg-on,.kw{fill:#7aa7f5} .ty{fill:#4fd1c5} .fn{fill:#c4a3ff} .str{fill:#7ed491} .num{fill:#f5a65b} .pp{fill:#f48fc8}.panel{fill:#171b23;stroke:#272c36} .rule{stroke:#272c36} .seg{fill:#272c36}.red{fill:#c8383d} .h1{stop-color:#163f93} .h2{stop-color:#0c2556}.s{opacity:0;animation:show 300s linear infinite backwards}.fill{transform-box:fill-box;transform-origin:left;animation:fill 300s linear infinite backwards;animation-delay:inherit}.s0{animation-name:show0} .sl{animation-name:showl}@keyframes show{0%{opacity:0;animation-timing-function:cubic-bezier(.2,.6,.2,1)} 0.2000%{opacity:1} 5.2000%{opacity:1} 5.2100%{opacity:0} 100%{opacity:0}}@keyframes show0{0%{opacity:1} 5.2000%{opacity:1} 5.2100%{opacity:0} 100%{opacity:0}}@keyframes showl{0%{opacity:0;animation-timing-function:cubic-bezier(.2,.6,.2,1)} 0.2000%{opacity:1} 5.0000%{opacity:1} 5.2000%{opacity:0} 100%{opacity:0}}@keyframes fill{0%{transform:scaleX(0)} 5.0000%{transform:scaleX(1)} 100%{transform:scaleX(1)}}@media (prefers-reduced-motion:reduce){.s,.fill{animation:none} .s:first-of-type{opacity:1}}</style><defs><path id="g0" d="M233 0 46 730H148L269 238Q281 191 289 148Q298 105 302 81Q306 105 315 148Q324 191 335 239L452 730H554L366 0H233Z"/><path id="g1" d="M97 0V730H522V641H195V424H487V337H195V89H522V0H97Z"/><path id="g2" d="M89 0V730H315Q382 730 432 703Q483 677 510 629Q538 582 538 518Q538 445 501 391Q463 338 401 316L548 0H439L300 305H187V0H89ZM187 393H315Q370 393 403 427Q436 461 436 517Q436 574 403 608Q370 642 315 642H187V393Z"/><path id="g3" d="M304 -10Q233 -10 179 15Q126 41 97 88Q68 136 68 202H167Q167 144 204 111Q242 78 304 78Q364 78 399 112Q435 146 435 201Q435 243 412 274Q390 306 347 317L239 346Q168 366 126 419Q85 471 85 543Q85 602 112 646Q138 691 186 715Q234 740 297 740Q361 740 409 715Q457 691 485 647Q512 603 512 545H414Q414 593 381 623Q348 653 297 653Q245 653 214 623Q182 593 182 545Q182 507 203 480Q224 453 262 442L373 412Q448 392 490 336Q532 279 532 201Q532 137 504 89Q476 42 424 16Q373 -10 304 -10Z"/><path id="g4" d="M101 0V90H250V640H101V730H499V640H350V90H499V0H101Z"/><path id="g5" d="M300 -10Q200 -10 142 48Q84 106 84 212V518Q84 625 142 682Q200 740 300 740Q400 740 458 682Q516 625 516 519V212Q516 106 458 48Q400 -10 300 -10ZM300 78Q357 78 387 110Q417 142 417 202V528Q417 588 387 620Q357 652 300 652Q244 652 213 620Q183 588 183 528V202Q183 142 213 110Q244 78 300 78Z"/><path id="g6" d="M85 0V730H214L432 114Q429 141 427 179Q424 217 422 259Q421 301 421 337V730H515V0H386L170 616Q172 591 174 553Q176 516 178 474Q179 433 179 396V0H85Z"/><path id="g8" d="M290 -10Q187 -10 127 46Q67 103 67 200H166Q166 143 200 110Q233 78 291 78Q348 78 382 110Q415 143 415 200V251Q415 308 382 341Q349 375 291 375H209V458L385 641H89V730H496V640L291 428L293 462Q395 462 455 405Q515 349 515 251V200Q515 103 454 46Q394 -10 290 -10Z"/><path id="g9" d="M300 -10Q262 -10 238 13Q215 36 215 72Q215 111 238 134Q262 158 300 158Q338 158 362 134Q385 111 385 72Q385 36 362 13Q338 -10 300 -10Z"/><path id="ga" d="M88 0V90H284V641L88 495V607L254 730H383V90H543V0H88Z"/><path id="gb" d="M300 -10Q232 -10 182 17Q132 43 104 92Q77 141 77 206V524Q77 590 104 638Q132 687 182 713Q232 740 300 740Q369 740 419 713Q468 687 496 638Q523 590 523 524V206Q523 141 496 92Q468 43 418 17Q368 -10 300 -10ZM300 75Q358 75 393 111Q428 148 428 206V524Q428 582 393 619Q358 655 300 655Q242 655 207 619Q172 582 172 524V206Q172 148 207 111Q242 75 300 75ZM300 309Q272 309 255 324Q238 339 238 368Q238 396 255 411Q272 425 300 425Q328 425 345 411Q362 396 362 368Q362 339 345 324Q328 309 300 309Z"/><path id="gc" d="M180 688V0H134V1056H180V816H168Q204 944 310 1008Q417 1072 544 1072Q659 1072 746 1024Q834 975 884 889Q934 803 934 688V0H888V688Q888 840 792 933Q696 1026 544 1026Q440 1026 358 982Q275 939 228 862Q180 786 180 688Z"/><path id="gd" d="M180 1490V0H134V1490H180Z"/><path id="ge" d="M530 -16Q394 -16 289 54Q184 125 125 248Q66 371 6Line truncated

After

Width:  |  Height:  |  Size: 395 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1200 675" width="1200" height="675" role="img"><title>JSON for Modern C++: feature slideshow (animated, 20 slides, 15 s each)</title><style>.bg{fill:#fff} .tx{fill:#0f1419} .tx2{fill:#3d444f} .tx3{fill:#8a919c} .com{fill:#646d7a}.bl{fill:#1747a6} .blk{fill:#1747a6} .kw{fill:#1747a6} .ty{fill:#0d6e72} .fn{fill:#6b3fb8} .str{fill:#23793a} .num{fill:#b04a07} .pp{fill:#a3247a}.panel{fill:#f5f7fa;stroke:#e3e6eb;stroke-width:1} .rule{stroke:#e3e6eb;stroke-width:1}.wm-a{fill:#0f1419} .wm-s{fill:#1747a6}.on-a,.on-tx{fill:#fff} .red{fill:#d93a3f} .on-panel{fill:#fff;fill-opacity:.08;stroke:#fff;stroke-opacity:.16} .on-s{fill:#bcd3fb} .w70{fill:#fff;fill-opacity:.7} .on-tx2{fill:#dbe6fb} .chip{fill:#fff;fill-opacity:.14}.pat{fill:#fff;fill-opacity:.09}.h1{stop-color:#1d55c4} .h2{stop-color:#123a8a}.seg{fill:#e3e6eb} .seg-on{fill:#1747a6}.seg.on-band{fill:#fff;fill-opacity:.25} .seg-on.on-band{fill:#fff;fill-opacity:1}.s{opacity:0;animation:show 300s linear infinite backwards}.fill{transform-box:fill-box;transform-origin:left;animation:fill 300s linear infinite backwards;animation-delay:inherit}.s0{animation-name:show0} .sl{animation-name:showl}@keyframes show{0%{opacity:0;animation-timing-function:cubic-bezier(.2,.6,.2,1)} 0.2000%{opacity:1} 5.2000%{opacity:1} 5.2100%{opacity:0} 100%{opacity:0}}@keyframes show0{0%{opacity:1} 5.2000%{opacity:1} 5.2100%{opacity:0} 100%{opacity:0}}@keyframes showl{0%{opacity:0;animation-timing-function:cubic-bezier(.2,.6,.2,1)} 0.2000%{opacity:1} 5.0000%{opacity:1} 5.2000%{opacity:0} 100%{opacity:0}}@keyframes fill{0%{transform:scaleX(0)} 5.0000%{transform:scaleX(1)} 100%{transform:scaleX(1)}}@media (prefers-reduced-motion:reduce){.s,.fill{animation:none} .s:first-of-type{opacity:1}}</style><defs><path id="g0" d="M233 0 46 730H148L269 238Q281 191 289 148Q298 105 302 81Q306 105 315 148Q324 191 335 239L452 730H554L366 0H233Z"/><path id="g1" d="M97 0V730H522V641H195V424H487V337H195V89H522V0H97Z"/><path id="g2" d="M89 0V730H315Q382 730 432 703Q483 677 510 629Q538 582 538 518Q538 445 501 391Q463 338 401 316L548 0H439L300 305H187V0H89ZM187 393H315Q370 393 403 427Q436 461 436 517Q436 574 403 608Q370 642 315 642H187V393Z"/><path id="g3" d="M304 -10Q233 -10 179 15Q126 41 97 88Q68 136 68 202H167Q167 144 204 111Q242 78 304 78Q364 78 399 112Q435 146 435 201Q435 243 412 274Q390 306 347 317L239 346Q168 366 126 419Q85 471 85 543Q85 602 112 646Q138 691 186 715Q234 740 297 740Q361 740 409 715Q457 691 485 647Q512 603 512 545H414Q414 593 381 623Q348 653 297 653Q245 653 214 623Q182 593 182 545Q182 507 203 480Q224 453 262 442L373 412Q448 392 490 336Q532 279 532 201Q532 137 504 89Q476 42 424 16Q373 -10 304 -10Z"/><path id="g4" d="M101 0V90H250V640H101V730H499V640H350V90H499V0H101Z"/><path id="g5" d="M300 -10Q200 -10 142 48Q84 106 84 212V518Q84 625 142 682Q200 740 300 740Q400 740 458 682Q516 625 516 519V212Q516 106 458 48Q400 -10 300 -10ZM300 78Q357 78 387 110Q417 142 417 202V528Q417 588 387 620Q357 652 300 652Q244 652 213 620Q183 588 183 528V202Q183 142 213 110Q244 78 300 78Z"/><path id="g6" d="M85 0V730H214L432 114Q429 141 427 179Q424 217 422 259Q421 301 421 337V730H515V0H386L170 616Q172 591 174 553Q176 516 178 474Q179 433 179 396V0H85Z"/><path id="g8" d="M290 -10Q187 -10 127 46Q67 103 67 200H166Q166 143 200 110Q233 78 291 78Q348 78 382 110Q415 143 415 200V251Q415 308 382 341Q349 375 291 375H209V458L385 641H89V730H496V640L291 428L293 462Q395 462 455 405Q515 349 515 251V200Q515 103 454 46Q394 -10 290 -10Z"/><path id="g9" d="M300 -10Q262 -10 238 13Q215 36 215 72Q215 111 238 134Q262 158 300 158Q338 158 362 134Q385 111 385 72Q385 36 362 13Q338 -10 300 -10Z"/><path id="ga" d="M88 0V90H284V641L88 495V607L254 730H383V90H543V0H88Z"/><path id="gb" d="M300 -10Q232 -10 182 17Q132 43 104 92Q77 141 77 206V524Q77 590 104 638Q132 687 182 713Q232 740 300 740Q369 740 419 713Q468 687 496 638Q523 590 523 524V206Q523 141 496 92Q468 43 418 17Q368 -10 300 -10ZM300 75Q358 75 393 111Q428 148 428 206V524Q428 582 393 619Q358 655 300 655Q242 655 207 619Q172 582 172 524V206Q172 148 207 111Q242 75 300 75ZM300 309Q272 309 255 324Q238 339 238 368Q238 396 255 411Q272 425 300 425Q328 425 345 411Q362 396 362 368Q362 339 345 324Q328 309 300 309Z"/><path id="gc" d="M180 688V0H134V1056H180V816H168Q204 944 310 1008Q417 1072 544 1072Q659 1072 746 1024Q834 975 884 889Q934 803 934 688V0H888V688Q888 840 792 933Q696 1026 544 1026Q440 1026 358 982Q275 939 228 862Q180 786 180 688Z"/><path id="gd" d="M180 1490V0H134V1490H180Z"/><path id="ge" d="M530 -16Q394 -16 289 54Q184 125 125 248Q66 371 66 528Q66 686 125 808Q184 931 289 1002Q394 1072 530 1072Q666 1072 770 1002Q874 931 933 808Q992 686 992 528Q992 371 933 248Q874 125 770 54Q666 -16 530 -16ZM530 30Q652 30 746 94Q840 157 893 270Q946 382 946 528Q946 674 893 786Q840 899 746 962Q652 1026 530 1026Q408 1026 314 962Q219 899 166 786Q112 674 112 528Q112 382 166 270Q219 157 314 94Q408 30 530 30Z"/><path id="gf" d="MLine truncated

After

Width:  |  Height:  |  Size: 394 KiB

@@ -0,0 +1,52 @@
<svg class="nj-fig nj-pointer-fl" viewBox="0 0 760 442" role="img" aria-labelledby="fig-flat-title" xmlns="http://www.w3.org/2000/svg">
<title id="fig-flat-title">flatten() turns the nested example document into a flat object, and unflatten() turns it back. Left, the document as a tree: array with the elements A, B, C, and nested with one = 1, two = 2, and three with the elements true and false. Right, the flat object with one key per leaf: /array/0 = A, /array/1 = B, /array/2 = C, /nested/one = 1, /nested/two = 2, /nested/three/0 = true, /nested/three/1 = false. Each leaf is joined to its key by a line.</title>
<defs><marker id="fig-flat-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path class="fg-head" d="M0 1 L10 5 L0 9 z"/></marker></defs>
<text class="fg-h" x="20" y="26">nested value</text>
<text class="fg-h" x="470" y="26">flat object: key = J&#8203;SON Pointer</text>
<line class="fg-arrow" x1="250" y1="52" x2="450" y2="52" marker-end="url(#fig-flat-arrow)"/>
<text class="nj-pointer-fl-op" x="350" y="44">flatten()</text>
<line class="fg-arrow" x1="450" y1="420" x2="250" y2="420" marker-end="url(#fig-flat-arrow)"/>
<text class="nj-pointer-fl-op" x="350" y="412">unflatten()</text>
<path class="nj-pointer-fl-edge" d="M25 99 V115 H42"/>
<path class="nj-pointer-fl-edge" d="M51 127 V143 H68"/>
<path class="nj-pointer-fl-edge" d="M51 127 V171 H68"/>
<path class="nj-pointer-fl-edge" d="M51 127 V199 H68"/>
<path class="nj-pointer-fl-edge" d="M25 99 V227 H42"/>
<path class="nj-pointer-fl-edge" d="M51 239 V255 H68"/>
<path class="nj-pointer-fl-edge" d="M51 239 V283 H68"/>
<path class="nj-pointer-fl-edge" d="M51 239 V311 H68"/>
<path class="nj-pointer-fl-edge" d="M77 323 V339 H94"/>
<path class="nj-pointer-fl-edge" d="M77 323 V367 H94"/>
<path class="nj-pointer-fl-link nj-pointer-fl--s" d="M139.6 143 C259.6 143 340 171 460 171"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--s" cx="139.6" cy="143" r="3.5"/>
<text class="fg-code" x="470" y="176" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/array/0"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"A"</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--s" d="M139.6 171 C259.6 171 340 199 460 199"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--s" cx="139.6" cy="171" r="3.5"/>
<text class="fg-code" x="470" y="204" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/array/1"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"B"</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--s" d="M139.6 199 C259.6 199 340 227 460 227"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--s" cx="139.6" cy="199" r="3.5"/>
<text class="fg-code" x="470" y="232" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/array/2"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"C"</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--n" d="M158.8 255 C278.8 255 340 255 460 255"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--n" cx="158.8" cy="255" r="3.5"/>
<text class="fg-code" x="470" y="260" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/nested/one"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--n">1</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--n" d="M158.8 283 C278.8 283 340 283 460 283"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--n" cx="158.8" cy="283" r="3.5"/>
<text class="fg-code" x="470" y="288" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/nested/two"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--n">2</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--b" d="M175.2 339 C295.2 339 340 311 460 311"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--b" cx="175.2" cy="339" r="3.5"/>
<text class="fg-code" x="470" y="316" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/nested/three/0"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--b">true</tspan></text>
<path class="nj-pointer-fl-link nj-pointer-fl--b" d="M184.8 367 C304.8 367 340 339 460 339"/>
<circle class="nj-pointer-fl-dot nj-pointer-fl--b" cx="184.8" cy="367" r="3.5"/>
<text class="fg-code" x="470" y="344" xml:space="preserve"><tspan class="nj-pointer-fl-key">"/nested/three/1"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--b">false</tspan></text>
<text class="fg-h" x="20" y="92">root</text>
<text class="fg-code nj-pointer-fl-inner" x="46" y="120">"array"</text>
<text class="fg-code" x="72" y="148" xml:space="preserve"><tspan class="nj-pointer-fl-k">0</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"A"</tspan></text>
<text class="fg-code" x="72" y="176" xml:space="preserve"><tspan class="nj-pointer-fl-k">1</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"B"</tspan></text>
<text class="fg-code" x="72" y="204" xml:space="preserve"><tspan class="nj-pointer-fl-k">2</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--s">"C"</tspan></text>
<text class="fg-code nj-pointer-fl-inner" x="46" y="232">"nested"</text>
<text class="fg-code" x="72" y="260" xml:space="preserve"><tspan class="nj-pointer-fl-k">"one"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--n">1</tspan></text>
<text class="fg-code" x="72" y="288" xml:space="preserve"><tspan class="nj-pointer-fl-k">"two"</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--n">2</tspan></text>
<text class="fg-code nj-pointer-fl-inner" x="72" y="316">"three"</text>
<text class="fg-code" x="98" y="344" xml:space="preserve"><tspan class="nj-pointer-fl-k">0</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--b">true</tspan></text>
<text class="fg-code" x="98" y="372" xml:space="preserve"><tspan class="nj-pointer-fl-k">1</tspan>: <tspan class="nj-pointer-fl-v nj-pointer-fl--b">false</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

@@ -0,0 +1,66 @@
<svg class="railroad" viewBox="0 0 860 214" role="img" aria-labelledby="rr-title" xmlns="http://www.w3.org/2000/svg">
<title id="rr-title">Railroad diagram of the J&#8203;SON number syntax: optional minus, then 0 or a digit from 1 to 9 followed by digits, then an optional fraction (a dot and digits) and an optional exponent (e or E, an optional sign, and digits).</title>
<g class="rr-track" fill="none" stroke="currentColor" stroke-opacity=".6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 44 L850 44"/>
<path d="M24 44 L31 44 Q38 44 38 51 L38 82 Q38 92 48 92 L59 92"/>
<path d="M85 92 L96 92 Q106 92 106 82 L106 51 Q106 44 113 44 L120 44"/>
<path d="M120 44 L127 44 Q134 44 134 51 L134 82 Q134 92 144 92 L160 92"/>
<path d="M242 92 L370 92 Q380 92 380 82 L380 52 Q380 44 388 44 L396 44"/>
<path d="M242 92 L250 92 Q258 92 258 100 L258 126 Q258 136 268 136 L278 136"/>
<path d="M332 136 L340 136 Q348 136 348 128 L348 92"/>
<path d="M340 136 L340 160 Q340 170 330 170 L280 170 Q270 170 270 160 L270 136"/>
<path d="M396 44 L403 44 Q410 44 410 51 L410 84.5 Q410 92 417.5 92 L425 92"/>
<path d="M451 92 L462 92"/>
<path d="M524 92 L524 116 Q524 126 514 126 L466 126 Q456 126 456 116 L456 92"/>
<path d="M516 92 L523 92 Q530 92 530 85 L530 52 Q530 44 538 44 L546 44"/>
<path d="M546 44 L553 44 Q560 44 560 51 L560 83.5 Q560 92 568.5 92 L577 92"/>
<path d="M546 44 L553 44 Q560 44 560 51 L560 127.5 Q560 136 568.5 136 L577 136"/>
<path d="M603 92 L728 92"/>
<path d="M603 136 L611.5 136 Q620 136 620 127.5 L620 92"/>
<path d="M640 92 L647 92 Q654 92 654 99 L654 128 Q654 136 662 136 L670 136"/>
<path d="M640 92 L647 92 Q654 92 654 99 L654 172 Q654 180 662 180 L670 180"/>
<path d="M696 136 L704 136 Q712 136 712 128 L712 92"/>
<path d="M696 180 L704 180 Q712 180 712 172 L712 92"/>
<path d="M728 92 L746 92"/>
<path d="M808 92 L808 116 Q808 126 798 126 L748 126 Q738 126 738 116 L738 92"/>
<path d="M800 92 L808 92 Q816 92 816 84 L816 52 Q816 44 824 44 L832 44"/>
</g>
<polygon class="rr-arrow" points="2,38 12,44 2,50"/>
<polygon class="rr-arrow" points="846,38 858,44 846,50"/>
<circle class="rr-bg" cx="72" cy="92" r="13"/>
<circle class="rr-t" cx="72" cy="92" r="13"/>
<circle class="rr-bg" cx="257" cy="44" r="13"/>
<circle class="rr-t" cx="257" cy="44" r="13"/>
<rect class="rr-bg" x="160" y="78" width="82" height="28" rx="6"/>
<rect class="rr-n" x="160" y="78" width="82" height="28" rx="6"/>
<rect class="rr-bg" x="278" y="122" width="54" height="28" rx="6"/>
<rect class="rr-n" x="278" y="122" width="54" height="28" rx="6"/>
<circle class="rr-bg" cx="438" cy="92" r="13"/>
<circle class="rr-t" cx="438" cy="92" r="13"/>
<rect class="rr-bg" x="462" y="78" width="54" height="28" rx="6"/>
<rect class="rr-n" x="462" y="78" width="54" height="28" rx="6"/>
<circle class="rr-bg" cx="590" cy="92" r="13"/>
<circle class="rr-t" cx="590" cy="92" r="13"/>
<circle class="rr-bg" cx="590" cy="136" r="13"/>
<circle class="rr-t" cx="590" cy="136" r="13"/>
<circle class="rr-bg" cx="683" cy="136" r="13"/>
<circle class="rr-t" cx="683" cy="136" r="13"/>
<circle class="rr-bg" cx="683" cy="180" r="13"/>
<circle class="rr-t" cx="683" cy="180" r="13"/>
<rect class="rr-bg" x="746" y="78" width="54" height="28" rx="6"/>
<rect class="rr-n" x="746" y="78" width="54" height="28" rx="6"/>
<text class="rr-c" x="72" y="97">&#8722;</text>
<text class="rr-c" x="257" y="49">0</text>
<text class="rr-b" x="201" y="97">digit 1&#8211;9</text>
<text class="rr-b" x="305" y="141">digit</text>
<text class="rr-c" x="438" y="97">.</text>
<text class="rr-b" x="489" y="97">digit</text>
<text class="rr-c" x="590" y="97">e</text>
<text class="rr-c" x="590" y="141">E</text>
<text class="rr-c" x="683" y="141">&#8722;</text>
<text class="rr-c" x="683" y="185">+</text>
<text class="rr-b" x="773" y="97">digit</text>
<text class="rr-l rr-name" x="24" y="32">number</text>
<text class="rr-l" x="420" y="32">fraction</text>
<text class="rr-l" x="580" y="32">exponent</text>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,57 @@
<svg class="nj-fig nj-jsonview nj-jsonview-editfig" viewBox="0 0 840 372" role="img" aria-labelledby="fig-jve0-title fig-jve0-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jve0-title">Step 1 of 5: parsed</title>
<desc id="fig-jve0-title-d">After parse: nine nodes, nothing owned yet. The dump with number_format::source is {&quot;port&quot;:6379,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;eu&quot;,&quot;a\&quot;b&quot;]}.</desc>
<defs>
<marker id="jve0-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve0-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve0-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve0-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-note nj-jsonview-strong" x="16" y="22" xml:space="preserve">parsed index: fixed, never moves</text>
<text class="nj-jsonview-note" x="824" y="22" text-anchor="end" xml:space="preserve">the source text is never written</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="47" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="78" y="61" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="78" y="77" text-anchor="middle" xml:space="preserve">{ } 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="47" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="166" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="166" y="77" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="212" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="47" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="254" y="61" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="254" y="77" text-anchor="middle" xml:space="preserve">6379</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="47" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="342" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="342" y="77" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="47" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="430" y="61" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="430" y="77" text-anchor="middle" xml:space="preserve">19.90</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="47" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="518" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="518" y="77" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="47" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="606" y="61" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="606" y="77" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="652" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="47" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="694" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="694" y="77" text-anchor="middle" xml:space="preserve">&quot;eu&quot;</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="47" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-dec" x="782" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="782" y="77" text-anchor="middle" xml:space="preserve">a&quot;b</text>
<text class="nj-jsonview-note nj-jsonview-strong nj-jsonview-c-own" x="16" y="288" xml:space="preserve">owned storage: allocated on demand, never moves</text>
<rect class="nj-jsonview-store" x="10" y="192" width="820" height="54" rx="8"/>
<text class="nj-jsonview-note" x="26" y="224" xml:space="preserve">empty: a read-only json_document has none of this</text>
<path class="nj-jsonview-sep" d="M16 300 H824"/>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="318" xml:space="preserve">view v = root()[&quot;tags&quot;] (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="318" xml:space="preserve">valid, sees every edit</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="338" xml:space="preserve">iterator over tags (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="338" xml:space="preserve">valid</text>
<text class="nj-jsonview-mono nj-jsonview-xs nj-jsonview-muted" x="16" y="360" xml:space="preserve">dump(): {&quot;port&quot;:6379,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;eu&quot;,&quot;a\&quot;b&quot;]}</text>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

@@ -0,0 +1,57 @@
<svg class="nj-fig nj-jsonview nj-jsonview-editfig" viewBox="0 0 840 372" role="img" aria-labelledby="fig-jve1-title fig-jve1-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jve1-title">Step 2 of 5: doc.set(doc.root(), &quot;port&quot;, 6380)</title>
<desc id="fig-jve1-title-d">set: the node of the integer is overwritten in place. The dump with number_format::source is {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;eu&quot;,&quot;a\&quot;b&quot;]}.</desc>
<defs>
<marker id="jve1-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve1-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve1-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve1-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-note nj-jsonview-strong" x="16" y="22" xml:space="preserve">parsed index: fixed, never moves</text>
<text class="nj-jsonview-note" x="824" y="22" text-anchor="end" xml:space="preserve">the source text is never written</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="47" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="78" y="61" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="78" y="77" text-anchor="middle" xml:space="preserve">{ } 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="47" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="166" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="166" y="77" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-num" x="212" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="47" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="254" y="61" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="254" y="77" text-anchor="middle" xml:space="preserve">6380</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="47" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="342" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="342" y="77" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="47" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="430" y="61" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="430" y="77" text-anchor="middle" xml:space="preserve">19.90</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="47" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="518" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="518" y="77" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="47" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="606" y="61" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="606" y="77" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="652" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="47" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="694" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="694" y="77" text-anchor="middle" xml:space="preserve">&quot;eu&quot;</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="47" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-dec" x="782" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="782" y="77" text-anchor="middle" xml:space="preserve">a&quot;b</text>
<text class="nj-jsonview-note nj-jsonview-strong nj-jsonview-c-own" x="16" y="288" xml:space="preserve">owned storage: allocated on demand, never moves</text>
<rect class="nj-jsonview-store" x="10" y="192" width="820" height="54" rx="8"/>
<text class="nj-jsonview-note" x="26" y="224" xml:space="preserve">empty: a read-only json_document has none of this</text>
<path class="nj-jsonview-sep" d="M16 300 H824"/>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="318" xml:space="preserve">view v = root()[&quot;tags&quot;] (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="318" xml:space="preserve">valid, sees every edit</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="338" xml:space="preserve">iterator over tags (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="338" xml:space="preserve">valid</text>
<text class="nj-jsonview-mono nj-jsonview-xs nj-jsonview-muted" x="16" y="360" xml:space="preserve">dump(): {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;eu&quot;,&quot;a\&quot;b&quot;]}</text>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

@@ -0,0 +1,70 @@
<svg class="nj-fig nj-jsonview nj-jsonview-editfig" viewBox="0 0 840 372" role="img" aria-labelledby="fig-jve2-title fig-jve2-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jve2-title">Step 3 of 5: doc.erase(doc.root()[&quot;tags&quot;], 0)</title>
<desc id="fig-jve2-title-d">erase: the array moves to a block of links in owned storage. The dump with number_format::source is {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;]}.</desc>
<defs>
<marker id="jve2-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve2-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve2-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve2-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-note nj-jsonview-strong" x="16" y="22" xml:space="preserve">parsed index: fixed, never moves</text>
<text class="nj-jsonview-note" x="824" y="22" text-anchor="end" xml:space="preserve">the source text is never written</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="47" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="78" y="61" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="78" y="77" text-anchor="middle" xml:space="preserve">{ } 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="47" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="166" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="166" y="77" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="212" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="47" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="254" y="61" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="254" y="77" text-anchor="middle" xml:space="preserve">6380</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="47" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="342" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="342" y="77" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="47" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="430" y="61" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="430" y="77" text-anchor="middle" xml:space="preserve">19.90</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="47" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="518" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="518" y="77" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="47" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="606" y="61" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-tiny nj-jsonview-c-struct nj-jsonview-strong" x="643" y="47" text-anchor="end" xml:space="preserve">moved</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="606" y="77" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-gap nj-jsonview-c-str" x="652" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="47" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="694" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="694" y="77" text-anchor="middle" xml:space="preserve">&quot;eu&quot;</text>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="694" y="98" text-anchor="middle" xml:space="preserve">unreferenced</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="47" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-dec" x="782" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="782" y="77" text-anchor="middle" xml:space="preserve">a&quot;b</text>
<text class="nj-jsonview-note nj-jsonview-strong nj-jsonview-c-own" x="16" y="288" xml:space="preserve">owned storage: allocated on demand, never moves</text>
<rect class="nj-jsonview-store" x="10" y="192" width="820" height="54" rx="8"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-struct" x="16" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="66" y="207" text-anchor="end" xml:space="preserve">0&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="43" y="220" text-anchor="middle" xml:space="preserve">header</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="43" y="235" text-anchor="middle" xml:space="preserve">[ ] 1</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="73" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="123" y="207" text-anchor="end" xml:space="preserve">1&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="100" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="100" y="235" text-anchor="middle" xml:space="preserve">→ 8</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M100 196 C100 140 782 140 782 84" marker-end="url(#jve2-own)"/>
<rect class="nj-jsonview-node nj-jsonview-free nj-jsonview-c-own" x="130" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="157" y="224" text-anchor="middle" xml:space="preserve">free</text>
<path class="nj-jsonview-arr nj-jsonview-c-struct nj-jsonview-dash" d="M598 84 C598 140 43 140 43 196" marker-end="url(#jve2-struct)"/>
<path class="nj-jsonview-sep" d="M16 300 H824"/>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="318" xml:space="preserve">view v = root()[&quot;tags&quot;] (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="318" xml:space="preserve">valid, sees every edit</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="338" xml:space="preserve">iterator over tags (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-bad nj-jsonview-strong" x="320" y="338" xml:space="preserve">invalid: tags no longer uses the parsed layout</text>
<text class="nj-jsonview-mono nj-jsonview-xs nj-jsonview-muted" x="16" y="360" xml:space="preserve">dump(): {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;]}</text>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

@@ -0,0 +1,80 @@
<svg class="nj-fig nj-jsonview nj-jsonview-editfig" viewBox="0 0 840 372" role="img" aria-labelledby="fig-jve3-title fig-jve3-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jve3-title">Step 4 of 5: doc.push_back(doc.root()[&quot;tags&quot;], &quot;new&quot;)</title>
<desc id="fig-jve3-title-d">push_back: a new node, and a link appended to the block. The dump with number_format::source is {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;,&quot;new&quot;]}.</desc>
<defs>
<marker id="jve3-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve3-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve3-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve3-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-note nj-jsonview-strong" x="16" y="22" xml:space="preserve">parsed index: fixed, never moves</text>
<text class="nj-jsonview-note" x="824" y="22" text-anchor="end" xml:space="preserve">the source text is never written</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="47" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="78" y="61" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="78" y="77" text-anchor="middle" xml:space="preserve">{ } 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="47" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="166" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="166" y="77" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="212" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="47" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="254" y="61" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="254" y="77" text-anchor="middle" xml:space="preserve">6380</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="47" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="342" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="342" y="77" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="47" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="430" y="61" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="430" y="77" text-anchor="middle" xml:space="preserve">19.90</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="47" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="518" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="518" y="77" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="47" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="606" y="61" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-tiny nj-jsonview-c-struct nj-jsonview-strong" x="643" y="47" text-anchor="end" xml:space="preserve">moved</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="606" y="77" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-gap nj-jsonview-c-str" x="652" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="47" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="694" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="694" y="77" text-anchor="middle" xml:space="preserve">&quot;eu&quot;</text>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="694" y="98" text-anchor="middle" xml:space="preserve">unreferenced</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="47" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-dec" x="782" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="782" y="77" text-anchor="middle" xml:space="preserve">a&quot;b</text>
<text class="nj-jsonview-note nj-jsonview-strong nj-jsonview-c-own" x="16" y="288" xml:space="preserve">owned storage: allocated on demand, never moves</text>
<rect class="nj-jsonview-store" x="10" y="192" width="820" height="54" rx="8"/>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="16" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="66" y="207" text-anchor="end" xml:space="preserve">0&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="43" y="220" text-anchor="middle" xml:space="preserve">header</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="43" y="235" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-c-own" x="73" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="123" y="207" text-anchor="end" xml:space="preserve">1&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="100" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="100" y="235" text-anchor="middle" xml:space="preserve">→ 8</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M100 196 C100 140 782 140 782 84" marker-end="url(#jve3-own)"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="130" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="180" y="207" text-anchor="end" xml:space="preserve">2&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="157" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="157" y="235" text-anchor="middle" xml:space="preserve">→ 3&#x27;</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M157 242 C157 268 214 268 214 244" marker-end="url(#jve3-own)"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-str" x="187" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="237" y="207" text-anchor="end" xml:space="preserve">3&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="214" y="220" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="214" y="235" text-anchor="middle" xml:space="preserve">&quot;new&quot;</text>
<path class="nj-jsonview-arr nj-jsonview-c-struct nj-jsonview-dash" d="M598 84 C598 140 43 140 43 196" marker-end="url(#jve3-struct)"/>
<text class="nj-jsonview-note" x="588" y="282" text-anchor="end" xml:space="preserve">edited text</text>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="596" y="264" width="42" height="26" rx="4"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="602" y="282" xml:space="preserve">new</text>
<path class="nj-jsonview-sep" d="M16 300 H824"/>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="318" xml:space="preserve">view v = root()[&quot;tags&quot;] (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="318" xml:space="preserve">valid, sees every edit</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="338" xml:space="preserve">iterator over tags (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-bad nj-jsonview-strong" x="320" y="338" xml:space="preserve">invalid: tags no longer uses the parsed layout</text>
<text class="nj-jsonview-mono nj-jsonview-xs nj-jsonview-muted" x="16" y="360" xml:space="preserve">dump(): {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;,&quot;new&quot;]}</text>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

@@ -0,0 +1,126 @@
<svg class="nj-fig nj-jsonview nj-jsonview-editfig" viewBox="0 0 840 372" role="img" aria-labelledby="fig-jve4-title fig-jve4-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jve4-title">Step 5 of 5: doc.set(doc.root(), &quot;retries&quot;, 3)</title>
<desc id="fig-jve4-title-d">set of a new member: the object moves to a block as well. The dump with number_format::source is {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;,&quot;new&quot;],&quot;retries&quot;:3}.</desc>
<defs>
<marker id="jve4-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve4-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve4-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jve4-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-note nj-jsonview-strong" x="16" y="22" xml:space="preserve">parsed index: fixed, never moves</text>
<text class="nj-jsonview-note" x="824" y="22" text-anchor="end" xml:space="preserve">the source text is never written</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="47" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="78" y="61" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-tiny nj-jsonview-c-struct nj-jsonview-strong" x="115" y="47" text-anchor="end" xml:space="preserve">moved</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="78" y="77" text-anchor="middle" xml:space="preserve">{ } 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="47" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="166" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="166" y="77" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="212" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="47" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="254" y="61" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="254" y="77" text-anchor="middle" xml:space="preserve">6380</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="47" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="342" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="342" y="77" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="47" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="430" y="61" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="430" y="77" text-anchor="middle" xml:space="preserve">19.90</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="47" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="518" y="61" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="518" y="77" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="47" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="606" y="61" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-tiny nj-jsonview-c-struct nj-jsonview-strong" x="643" y="47" text-anchor="end" xml:space="preserve">moved</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="606" y="77" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-gap nj-jsonview-c-str" x="652" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="47" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="694" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="694" y="77" text-anchor="middle" xml:space="preserve">&quot;eu&quot;</text>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="694" y="98" text-anchor="middle" xml:space="preserve">unreferenced</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="34" width="84" height="50" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="47" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-dec" x="782" y="61" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="782" y="77" text-anchor="middle" xml:space="preserve">a&quot;b</text>
<text class="nj-jsonview-note nj-jsonview-strong nj-jsonview-c-own" x="16" y="288" xml:space="preserve">owned storage: allocated on demand, never moves</text>
<rect class="nj-jsonview-store" x="10" y="192" width="820" height="54" rx="8"/>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="16" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="66" y="207" text-anchor="end" xml:space="preserve">0&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="43" y="220" text-anchor="middle" xml:space="preserve">header</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="43" y="235" text-anchor="middle" xml:space="preserve">[ ] 2</text>
<rect class="nj-jsonview-node nj-jsonview-c-own" x="73" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="123" y="207" text-anchor="end" xml:space="preserve">1&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="100" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="100" y="235" text-anchor="middle" xml:space="preserve">→ 8</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M100 196 C100 140 782 140 782 84" marker-end="url(#jve4-own)"/>
<rect class="nj-jsonview-node nj-jsonview-c-own" x="130" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="180" y="207" text-anchor="end" xml:space="preserve">2&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="157" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="157" y="235" text-anchor="middle" xml:space="preserve">→ 3&#x27;</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M157 242 C157 268 214 268 214 244" marker-end="url(#jve4-own)"/>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="187" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="237" y="207" text-anchor="end" xml:space="preserve">3&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-str" x="214" y="220" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="214" y="235" text-anchor="middle" xml:space="preserve">&quot;new&quot;</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-num" x="244" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="294" y="207" text-anchor="end" xml:space="preserve">4&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-num" x="271" y="220" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="271" y="235" text-anchor="middle" xml:space="preserve">3</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-struct" x="301" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="351" y="207" text-anchor="end" xml:space="preserve">5&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-struct" x="328" y="220" text-anchor="middle" xml:space="preserve">header</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="328" y="235" text-anchor="middle" xml:space="preserve">{ } 4</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-key" x="358" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="408" y="207" text-anchor="end" xml:space="preserve">6&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="385" y="220" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="385" y="235" text-anchor="middle" xml:space="preserve">port</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="415" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="465" y="207" text-anchor="end" xml:space="preserve">7&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="442" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="442" y="235" text-anchor="middle" xml:space="preserve">→ 2</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M442 196 C442 140 254 140 254 84" marker-end="url(#jve4-own)"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-key" x="472" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="522" y="207" text-anchor="end" xml:space="preserve">8&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="499" y="220" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="499" y="235" text-anchor="middle" xml:space="preserve">price</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="529" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="579" y="207" text-anchor="end" xml:space="preserve">9&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="556" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="556" y="235" text-anchor="middle" xml:space="preserve">→ 4</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M556 196 C556 140 430 140 430 84" marker-end="url(#jve4-own)"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-key" x="586" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="636" y="207" text-anchor="end" xml:space="preserve">10&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="613" y="220" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="613" y="235" text-anchor="middle" xml:space="preserve">tags</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="643" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="693" y="207" text-anchor="end" xml:space="preserve">11&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="670" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="670" y="235" text-anchor="middle" xml:space="preserve">→ 6</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M670 196 C670 140 614 140 614 84" marker-end="url(#jve4-own)"/>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-key" x="700" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="750" y="207" text-anchor="end" xml:space="preserve">12&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-key" x="727" y="220" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="727" y="235" text-anchor="middle" xml:space="preserve">retries</text>
<rect class="nj-jsonview-node nj-jsonview-hot nj-jsonview-c-own" x="757" y="196" width="54" height="46" rx="5"/>
<text class="nj-jsonview-tiny" x="807" y="207" text-anchor="end" xml:space="preserve">13&#x27;</text>
<text class="nj-jsonview-kind nj-jsonview-xs nj-jsonview-c-own" x="784" y="220" text-anchor="middle" xml:space="preserve">link</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="784" y="235" text-anchor="middle" xml:space="preserve">→ 4&#x27;</text>
<path class="nj-jsonview-arr nj-jsonview-c-own" d="M784 242 C784 268 271 268 271 244" marker-end="url(#jve4-own)"/>
<path class="nj-jsonview-arr nj-jsonview-c-struct nj-jsonview-dash" d="M598 84 C598 140 43 140 43 196" marker-end="url(#jve4-struct)"/>
<path class="nj-jsonview-arr nj-jsonview-c-struct nj-jsonview-dash" d="M70 84 C70 140 328 140 328 196" marker-end="url(#jve4-struct)"/>
<text class="nj-jsonview-note" x="588" y="282" text-anchor="end" xml:space="preserve">edited text</text>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="596" y="264" width="112" height="26" rx="4"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="602" y="282" xml:space="preserve">newretries</text>
<path class="nj-jsonview-sep" d="M16 300 H824"/>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="318" xml:space="preserve">view v = root()[&quot;tags&quot;] (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-struct nj-jsonview-strong" x="320" y="318" xml:space="preserve">valid, sees every edit</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="16" y="338" xml:space="preserve">iterator over tags (taken after parse):</text>
<text class="nj-jsonview-note nj-jsonview-c-bad nj-jsonview-strong" x="320" y="338" xml:space="preserve">invalid: tags no longer uses the parsed layout</text>
<text class="nj-jsonview-mono nj-jsonview-xs nj-jsonview-muted" x="16" y="360" xml:space="preserve">dump(): {&quot;port&quot;:6380,&quot;price&quot;:19.90,&quot;tags&quot;:[&quot;a\&quot;b&quot;,&quot;new&quot;],&quot;retries&quot;:3}</text>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

@@ -0,0 +1,182 @@
<svg class="nj-fig nj-jsonview " viewBox="0 0 840 692" role="img" aria-labelledby="fig-jvl-title fig-jvl-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jvl-title">The same J&#8203;SON text parsed by basic_json::parse() and by json_document::parse()</title>
<desc id="fig-jvl-title-d">The text {&quot;port&quot;: 6379, &quot;price&quot;: 19.90, &quot;tags&quot;: [&quot;eu&quot;, &quot;a\&quot;b&quot;]}. Top: basic_json::parse() builds a tree: the root json value points to a std::map whose three nodes are separate heap allocations; the price is stored as the double 19.9; the tags array is a std::vector of two json values, each pointing to its own std::string. Bottom: json_document::parse() keeps the 54 bytes of source text and builds a flat index of nine 16-byte nodes in document order: object, key port, unsigned integer 6379 (the converted value is in the node), key price, float, key tags, array, string eu, and an escaped string. Keys, the float, and the plain string point back into the source text; the escaped string points into the document&#x27;s buffer of decoded strings. A json_view is two pointers: one to the document and one to a node, here the array.</desc>
<defs>
<marker id="jvl-line" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-line nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-str" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-str nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-key" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-key nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-num" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-num nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-dec" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-dec nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-own" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-own nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-struct" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-struct nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
<marker id="jvl-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<text class="nj-jsonview-h" x="16" y="26" xml:space="preserve">basic_json::parse(): a tree, every array, object, and string in its own heap allocation</text>
<rect class="nj-jsonview-box" x="16" y="98" width="60" height="34" rx="5"/>
<text class="nj-jsonview-mono" x="46" y="120" text-anchor="middle" xml:space="preserve">json</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M76 115 L106 115" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="108" y="98" width="84" height="34" rx="5"/>
<text class="nj-jsonview-mono" x="150" y="120" text-anchor="middle" xml:space="preserve">std::map</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M192 115 C192 115 226 67 226 67" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="228" y="50" width="180" height="34" rx="5"/>
<text class="nj-jsonview-mono nj-jsonview-c-key" x="240" y="72" xml:space="preserve">&quot;port&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-c-num" x="396" y="72" text-anchor="end" xml:space="preserve">6379</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M192 115 C192 115 226 115 226 115" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="228" y="98" width="180" height="34" rx="5"/>
<text class="nj-jsonview-mono nj-jsonview-c-key" x="240" y="120" xml:space="preserve">&quot;price&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-c-num" x="396" y="120" text-anchor="end" xml:space="preserve">19.9</text>
<text class="nj-jsonview-note" x="418" y="120" xml:space="preserve">double: 19.90 is gone</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M192 115 C192 115 226 163 226 163" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="228" y="146" width="180" height="34" rx="5"/>
<text class="nj-jsonview-mono nj-jsonview-c-key" x="240" y="168" xml:space="preserve">&quot;tags&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-c-line" x="396" y="168" text-anchor="end" xml:space="preserve">•</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M408 163 L442 163" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="444" y="146" width="104" height="34" rx="5"/>
<text class="nj-jsonview-mono" x="496" y="168" text-anchor="middle" xml:space="preserve">std::vector</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M548 163 L576 163" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="578" y="146" width="92" height="34" rx="5"/>
<path class="nj-jsonview-sep" d="M624 146 V180"/>
<text class="nj-jsonview-mono" x="601" y="168" text-anchor="middle" xml:space="preserve">json</text>
<text class="nj-jsonview-mono" x="647" y="168" text-anchor="middle" xml:space="preserve">json</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M601 146 C601 126 706 150 706 130" marker-end="url(#jvl-line)"/>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M647 180 C647 200 706 176 706 196" marker-end="url(#jvl-line)"/>
<rect class="nj-jsonview-heap" x="708" y="113" width="126" height="34" rx="5"/>
<text class="nj-jsonview-mono nj-jsonview-sm nj-jsonview-c-str" x="771" y="135" text-anchor="middle" xml:space="preserve">std::string eu</text>
<rect class="nj-jsonview-heap" x="708" y="179" width="126" height="34" rx="5"/>
<text class="nj-jsonview-mono nj-jsonview-sm nj-jsonview-c-str" x="771" y="201" text-anchor="middle" xml:space="preserve">std::string a&quot;b</text>
<rect class="nj-jsonview-heap" x="16" y="186" width="18" height="14" rx="3"/>
<text class="nj-jsonview-note" x="42" y="198" xml:space="preserve">a separate heap allocation</text>
<path class="nj-jsonview-sep" d="M16 234 H824"/>
<text class="nj-jsonview-h" x="16" y="262" xml:space="preserve">json_document::parse(): the source text stays where it is; one flat index of 16-byte nodes</text>
<text class="nj-jsonview-note" x="16" y="290" xml:space="preserve">source text, 54 bytes (borrowed, or owned by the document)</text>
<rect class="nj-jsonview-ribbon" x="42" y="300" width="756" height="26" rx="4"/>
<rect class="nj-jsonview-span nj-jsonview-c-key" x="71" y="302" width="54" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-num" x="169" y="302" width="54" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-key" x="267" y="302" width="68" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-num" x="379" y="302" width="68" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-key" x="491" y="302" width="54" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-str" x="617" y="302" width="26" height="22" rx="3"/>
<rect class="nj-jsonview-span nj-jsonview-c-dec" x="701" y="302" width="54" height="22" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-byte" x="49" y="317.5" text-anchor="middle" xml:space="preserve">{</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="63" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="77" y="317.5" text-anchor="middle" xml:space="preserve">p</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="91" y="317.5" text-anchor="middle" xml:space="preserve">o</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="105" y="317.5" text-anchor="middle" xml:space="preserve">r</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="119" y="317.5" text-anchor="middle" xml:space="preserve">t</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="133" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="147" y="317.5" text-anchor="middle" xml:space="preserve">:</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="175" y="317.5" text-anchor="middle" xml:space="preserve">6</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="189" y="317.5" text-anchor="middle" xml:space="preserve">3</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="203" y="317.5" text-anchor="middle" xml:space="preserve">7</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="217" y="317.5" text-anchor="middle" xml:space="preserve">9</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="231" y="317.5" text-anchor="middle" xml:space="preserve">,</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="259" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="273" y="317.5" text-anchor="middle" xml:space="preserve">p</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="287" y="317.5" text-anchor="middle" xml:space="preserve">r</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="301" y="317.5" text-anchor="middle" xml:space="preserve">i</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="315" y="317.5" text-anchor="middle" xml:space="preserve">c</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="329" y="317.5" text-anchor="middle" xml:space="preserve">e</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="343" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="357" y="317.5" text-anchor="middle" xml:space="preserve">:</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="385" y="317.5" text-anchor="middle" xml:space="preserve">1</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="399" y="317.5" text-anchor="middle" xml:space="preserve">9</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="413" y="317.5" text-anchor="middle" xml:space="preserve">.</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="427" y="317.5" text-anchor="middle" xml:space="preserve">9</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="441" y="317.5" text-anchor="middle" xml:space="preserve">0</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="455" y="317.5" text-anchor="middle" xml:space="preserve">,</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="483" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="497" y="317.5" text-anchor="middle" xml:space="preserve">t</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="511" y="317.5" text-anchor="middle" xml:space="preserve">a</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="525" y="317.5" text-anchor="middle" xml:space="preserve">g</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="539" y="317.5" text-anchor="middle" xml:space="preserve">s</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="553" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="567" y="317.5" text-anchor="middle" xml:space="preserve">:</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="595" y="317.5" text-anchor="middle" xml:space="preserve">[</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="609" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="623" y="317.5" text-anchor="middle" xml:space="preserve">e</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="637" y="317.5" text-anchor="middle" xml:space="preserve">u</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="651" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="665" y="317.5" text-anchor="middle" xml:space="preserve">,</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="693" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="707" y="317.5" text-anchor="middle" xml:space="preserve">a</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="721" y="317.5" text-anchor="middle" xml:space="preserve">\</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="735" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="749" y="317.5" text-anchor="middle" xml:space="preserve">b</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="763" y="317.5" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="777" y="317.5" text-anchor="middle" xml:space="preserve">]</text>
<text class="nj-jsonview-mono nj-jsonview-byte" x="791" y="317.5" text-anchor="middle" xml:space="preserve">}</text>
<text class="nj-jsonview-tiny" x="49" y="340" text-anchor="middle" xml:space="preserve">0</text>
<text class="nj-jsonview-tiny" x="189" y="340" text-anchor="middle" xml:space="preserve">10</text>
<text class="nj-jsonview-tiny" x="329" y="340" text-anchor="middle" xml:space="preserve">20</text>
<text class="nj-jsonview-tiny" x="469" y="340" text-anchor="middle" xml:space="preserve">30</text>
<text class="nj-jsonview-tiny" x="609" y="340" text-anchor="middle" xml:space="preserve">40</text>
<text class="nj-jsonview-tiny" x="749" y="340" text-anchor="middle" xml:space="preserve">50</text>
<rect class="nj-jsonview-frame" x="16" y="366" width="808" height="254" rx="10"/>
<text class="nj-jsonview-note nj-jsonview-strong" x="30" y="602" xml:space="preserve">json_document: owns the node index and the buffer of decoded strings</text>
<text class="nj-jsonview-note" x="30" y="500" xml:space="preserve">node index: 9 nodes × 16 bytes = 144 bytes, in document order</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="36" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="42" y="420" xml:space="preserve">0</text>
<text class="nj-jsonview-kind nj-jsonview-c-struct" x="78" y="434" text-anchor="middle" xml:space="preserve">object</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="78" y="451" text-anchor="middle" xml:space="preserve">len 3</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="78" y="465" text-anchor="middle" xml:space="preserve">next 9</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="124" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="130" y="420" xml:space="preserve">1</text>
<text class="nj-jsonview-kind nj-jsonview-c-key" x="166" y="434" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="166" y="451" text-anchor="middle" xml:space="preserve">off 2</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="166" y="465" text-anchor="middle" xml:space="preserve">len 4</text>
<path class="nj-jsonview-arr nj-jsonview-c-key" d="M166 406 C166 367 98 367 98 328" marker-end="url(#jvl-key)"/>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="212" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="218" y="420" xml:space="preserve">2</text>
<text class="nj-jsonview-kind nj-jsonview-c-num" x="254" y="434" text-anchor="middle" xml:space="preserve">uint</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="254" y="451" text-anchor="middle" xml:space="preserve">6379</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="254" y="465" text-anchor="middle" xml:space="preserve">(converted)</text>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="300" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="306" y="420" xml:space="preserve">3</text>
<text class="nj-jsonview-kind nj-jsonview-c-key" x="342" y="434" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="342" y="451" text-anchor="middle" xml:space="preserve">off 16</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="342" y="465" text-anchor="middle" xml:space="preserve">len 5</text>
<path class="nj-jsonview-arr nj-jsonview-c-key" d="M342 406 C342 367 301 367 301 328" marker-end="url(#jvl-key)"/>
<rect class="nj-jsonview-node nj-jsonview-c-num" x="388" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="394" y="420" xml:space="preserve">4</text>
<text class="nj-jsonview-kind nj-jsonview-c-num" x="430" y="434" text-anchor="middle" xml:space="preserve">float</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="430" y="451" text-anchor="middle" xml:space="preserve">off 24</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="430" y="465" text-anchor="middle" xml:space="preserve">len 5</text>
<path class="nj-jsonview-arr nj-jsonview-c-num" d="M430 406 C430 367 413 367 413 328" marker-end="url(#jvl-num)"/>
<rect class="nj-jsonview-node nj-jsonview-c-key" x="476" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="482" y="420" xml:space="preserve">5</text>
<text class="nj-jsonview-kind nj-jsonview-c-key" x="518" y="434" text-anchor="middle" xml:space="preserve">key</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="518" y="451" text-anchor="middle" xml:space="preserve">off 32</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="518" y="465" text-anchor="middle" xml:space="preserve">len 4</text>
<path class="nj-jsonview-arr nj-jsonview-c-key" d="M518 406 C518 367 518 367 518 328" marker-end="url(#jvl-key)"/>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="564" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="570" y="420" xml:space="preserve">6</text>
<text class="nj-jsonview-kind nj-jsonview-c-struct" x="606" y="434" text-anchor="middle" xml:space="preserve">array</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="606" y="451" text-anchor="middle" xml:space="preserve">len 2</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="606" y="465" text-anchor="middle" xml:space="preserve">next 3</text>
<rect class="nj-jsonview-node nj-jsonview-c-str" x="652" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="658" y="420" xml:space="preserve">7</text>
<text class="nj-jsonview-kind nj-jsonview-c-str" x="694" y="434" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="694" y="451" text-anchor="middle" xml:space="preserve">off 41</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="694" y="465" text-anchor="middle" xml:space="preserve">len 2</text>
<path class="nj-jsonview-arr nj-jsonview-c-str" d="M694 406 C694 367 630 367 630 328" marker-end="url(#jvl-str)"/>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="406" width="84" height="68" rx="5"/>
<text class="nj-jsonview-tiny" x="746" y="420" xml:space="preserve">8</text>
<text class="nj-jsonview-kind nj-jsonview-c-dec" x="782" y="434" text-anchor="middle" xml:space="preserve">string</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="782" y="451" text-anchor="middle" xml:space="preserve">escaped</text>
<text class="nj-jsonview-mono nj-jsonview-xs" x="782" y="465" text-anchor="middle" xml:space="preserve">len 3</text>
<text class="nj-jsonview-note" x="773" y="568" text-anchor="middle" xml:space="preserve">decoded strings</text>
<rect class="nj-jsonview-node nj-jsonview-c-dec" x="740" y="518" width="66" height="30" rx="4"/>
<text class="nj-jsonview-mono" x="751" y="538" text-anchor="middle" xml:space="preserve">a</text>
<text class="nj-jsonview-mono" x="773" y="538" text-anchor="middle" xml:space="preserve">&quot;</text>
<text class="nj-jsonview-mono" x="795" y="538" text-anchor="middle" xml:space="preserve">b</text>
<path class="nj-jsonview-arr nj-jsonview-c-dec" d="M782 474 C782 496 773 496 773 518" marker-end="url(#jvl-dec)"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="470" y="670" text-anchor="end" xml:space="preserve">json_view v = doc.root()[&quot;tags&quot;]</text>
<rect class="nj-jsonview-node nj-jsonview-c-struct" x="480" y="648" width="140" height="34" rx="6"/>
<path class="nj-jsonview-sep" d="M550 648 V682"/>
<text class="nj-jsonview-mono" x="515" y="670" text-anchor="middle" xml:space="preserve">doc*</text>
<text class="nj-jsonview-mono" x="585" y="670" text-anchor="middle" xml:space="preserve">node*</text>
<path class="nj-jsonview-arr nj-jsonview-c-struct" d="M515 648 L515 622" marker-end="url(#jvl-struct)"/>
<path class="nj-jsonview-arr nj-jsonview-c-struct" d="M585 648 C585 561 606 561 606 474" marker-end="url(#jvl-struct)"/>
<text class="nj-jsonview-note" x="30" y="524" xml:space="preserve">integers are converted while parsing and kept in their node;</text>
<text class="nj-jsonview-note" x="30" y="542" xml:space="preserve">floats and strings point back into the text</text>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

@@ -0,0 +1,61 @@
<svg class="nj-fig nj-jsonview " viewBox="0 0 840 572" role="img" aria-labelledby="fig-jvt-title fig-jvt-title-d" xmlns="http://www.w3.org/2000/svg">
<title id="fig-jvt-title">When a json_view becomes invalid</title>
<desc id="fig-jvt-title-d">Four timelines. First: a document borrows a std::string; when the string is destroyed, the document and every view taken from it dangle. Second: doc.read() re-parses the document; views taken before are invalid, a fresh view from root() is valid. Third: doc.shrink_to_fit() has the same effect. Fourth: moving the document does not invalidate its views; destroying the moved-to document does.</desc>
<defs>
<marker id="jvt-bad" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path class="nj-jsonview-c-bad nj-jsonview-head" d="M0 1 L10 5 L0 9 z"/></marker>
</defs>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="210" y="12" width="34" height="12" rx="3"/>
<text class="nj-jsonview-note" x="252" y="23" xml:space="preserve">alive / valid</text>
<rect class="nj-jsonview-bad" x="370" y="12" width="34" height="12" rx="3"/>
<text class="nj-jsonview-note" x="412" y="23" xml:space="preserve">dangling: using it is undefined behavior</text>
<path class="nj-jsonview-arr nj-jsonview-c-line" d="M210 44 L820 44"/>
<text class="nj-jsonview-tiny" x="820" y="38" text-anchor="end" xml:space="preserve">time →</text>
<text class="nj-jsonview-h nj-jsonview-sm2" x="16" y="74" xml:space="preserve">The borrowed text is destroyed</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="99" text-anchor="end" xml:space="preserve">std::string text</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="210" y="87" width="260" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="127" text-anchor="end" xml:space="preserve">json_document doc</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="270" y="115" width="200" height="16" rx="3"/>
<rect class="nj-jsonview-bad" x="470" y="115" width="350" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="155" text-anchor="end" xml:space="preserve">json_view v</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="330" y="143" width="140" height="16" rx="3"/>
<rect class="nj-jsonview-bad" x="470" y="143" width="350" height="16" rx="3"/>
<path class="nj-jsonview-evt" d="M470 82 V168"/>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="474" y="80" xml:space="preserve">text destroyed</text>
<text class="nj-jsonview-note nj-jsonview-onbad" x="476" y="155" xml:space="preserve">every view, and the document itself</text>
<text class="nj-jsonview-h nj-jsonview-sm2" x="16" y="202" xml:space="preserve">The document is re-parsed</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="227" text-anchor="end" xml:space="preserve">json_document doc</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="210" y="215" width="610" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="255" text-anchor="end" xml:space="preserve">json_view v</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="270" y="243" width="200" height="16" rx="3"/>
<rect class="nj-jsonview-bad" x="470" y="243" width="350" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="283" text-anchor="end" xml:space="preserve">v = doc.root()</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="530" y="271" width="290" height="16" rx="3"/>
<path class="nj-jsonview-evt" d="M470 210 V296"/>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="474" y="208" xml:space="preserve">doc.read(other)</text>
<text class="nj-jsonview-note nj-jsonview-onbad" x="476" y="255" xml:space="preserve">views taken before</text>
<text class="nj-jsonview-note nj-jsonview-onok" x="536" y="283" xml:space="preserve">a fresh view is valid again</text>
<text class="nj-jsonview-h nj-jsonview-sm2" x="16" y="330" xml:space="preserve">The document is shrunk</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="355" text-anchor="end" xml:space="preserve">json_document doc</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="210" y="343" width="610" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="383" text-anchor="end" xml:space="preserve">json_view v</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="270" y="371" width="200" height="16" rx="3"/>
<rect class="nj-jsonview-bad" x="470" y="371" width="350" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="411" text-anchor="end" xml:space="preserve">v = doc.root()</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="530" y="399" width="290" height="16" rx="3"/>
<path class="nj-jsonview-evt" d="M470 338 V424"/>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="474" y="336" xml:space="preserve">doc.shrink_to_fit()</text>
<text class="nj-jsonview-note nj-jsonview-onbad" x="476" y="383" xml:space="preserve">views taken before</text>
<text class="nj-jsonview-note nj-jsonview-onok" x="536" y="411" xml:space="preserve">a fresh view is valid again</text>
<text class="nj-jsonview-h nj-jsonview-sm2" x="16" y="458" xml:space="preserve">The document is moved, then destroyed</text>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="483" text-anchor="end" xml:space="preserve">json_document doc</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="210" y="471" width="210" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="511" text-anchor="end" xml:space="preserve">moved = std::move(doc)</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="420" y="499" width="260" height="16" rx="3"/>
<text class="nj-jsonview-mono nj-jsonview-sm" x="198" y="539" text-anchor="end" xml:space="preserve">json_view v</text>
<rect class="nj-jsonview-bar nj-jsonview-c-struct" x="270" y="527" width="410" height="16" rx="3"/>
<rect class="nj-jsonview-bad" x="680" y="527" width="140" height="16" rx="3"/>
<path class="nj-jsonview-evt nj-jsonview-evt--ok" d="M420 466 V552"/>
<text class="nj-jsonview-tiny" x="424" y="464" xml:space="preserve">std::move: views stay valid</text>
<path class="nj-jsonview-evt" d="M680 466 V552"/>
<text class="nj-jsonview-tiny nj-jsonview-c-bad" x="684" y="464" xml:space="preserve">moved is destroyed</text>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -0,0 +1,20 @@
<svg class="nj-fig nj-fig--sax-mem" viewBox="0 0 660 312" role="img" aria-labelledby="fig-sax-mem-title fig-sax-mem-desc" xmlns="http://www.w3.org/2000/svg">
<title id="fig-sax-mem-title">Illustrative memory use over time while a large array of records is parsed, not a measurement.</title>
<desc id="fig-sax-mem-desc">Four curves. D&#8203;OM, parse(): rises steadily until the whole tree is in memory. json_document: starts at about the size of the text, which it keeps, and grows a little while its index is built. Parser callback that discards every record: stays flat at the size of one record. S&#8203;AX: stays flat and lowest, because no value is built and only what the handler keeps is in memory.</desc>
<path class="nj-sax-axis" d="M56 36 V272 H448"/>
<text class="fg-h" x="16" y="24">memory</text>
<text class="fg-note fg-note--l" x="56" y="294">time: records parsed</text>
<text class="fg-note fg-note--r nj-sax-illus" x="648" y="24">illustrative, not a measurement</text>
<path class="nj-sax-curve nj-sax-c-dom" d="M56 268 L440 52"/>
<path class="nj-sax-curve nj-sax-c-doc" d="M56 168 L440 146"/>
<path class="nj-sax-curve nj-sax-c-cb" d="M56 250 L88 238 L88 250 L120 238 L120 250 L152 238 L152 250 L184 238 L184 250 L216 238 L216 250 L248 238 L248 250 L280 238 L280 250 L312 238 L312 250 L344 238 L344 250 L376 238 L376 250 L408 238 L408 250 L440 238 L440 250"/>
<path class="nj-sax-curve nj-sax-c-sax" d="M56 264 H440"/>
<text class="nj-sax-lab nj-sax-c-dom" x="456" y="48">D&#8203;OM: parse()</text>
<text class="fg-note fg-note--l" x="456" y="65">the whole tree</text>
<text class="nj-sax-lab nj-sax-c-doc" x="456" y="142">json_document</text>
<text class="fg-note fg-note--l" x="456" y="159">the text plus its index</text>
<text class="nj-sax-lab nj-sax-c-cb" x="456" y="227">callback, discard</text>
<text class="fg-note fg-note--l" x="456" y="244">one record at a time</text>
<text class="nj-sax-lab nj-sax-c-sax" x="456" y="269">S&#8203;AX</text>
<text class="fg-note fg-note--l" x="456" y="286">only what the handler keeps</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,31 @@
<svg class="nj-fig nj-charts nj-charts--scaling" viewBox="0 0 440 238" role="img" aria-labelledby="nj-charts-sc nj-charts-sc-d" xmlns="http://www.w3.org/2000/svg">
<title id="nj-charts-sc">Time to parse a flat object of n keys, json against ordered_json, logarithmic axes</title>
<desc id="nj-charts-sc-d">2000 keys: json 0.7 ms, ordered_json 3.6 ms (5x). 4000 keys: 0.8 ms and 14.0 ms (19x). 8000 keys: 1.6 ms and 67.8 ms (43x). 16000 keys: 3.3 ms and 181.6 ms (54x).</desc>
<line class="nj-charts-grid" x1="66" y1="176.187" x2="330" y2="176.187"/>
<text class="nj-charts-tick nj-charts-tick--r" x="60" y="180.187">1 ms</text>
<line class="nj-charts-grid" x1="66" y1="111.521" x2="330" y2="111.521"/>
<text class="nj-charts-tick nj-charts-tick--r" x="60" y="115.521">10 ms</text>
<line class="nj-charts-grid" x1="66" y1="46.8538" x2="330" y2="46.8538"/>
<text class="nj-charts-tick nj-charts-tick--r" x="60" y="50.8538">100 ms</text>
<line class="nj-charts-axis" x1="66" y1="210" x2="330" y2="210"/>
<text class="nj-charts-tick" x="66" y="226">2&#8201;000</text>
<text class="nj-charts-tick" x="154" y="226">4&#8201;000</text>
<text class="nj-charts-tick" x="242" y="226">8&#8201;000</text>
<text class="nj-charts-tick" x="330" y="226">16&#8201;000</text>
<polyline class="nj-charts-json" points="66,186.204 154,182.454 242,162.987 330,142.657"/>
<circle class="nj-charts-json-dot" cx="66" cy="186.204" r="4.5"><title>json, 2000 keys: 0.7 ms</title></circle>
<circle class="nj-charts-json-dot" cx="154" cy="182.454" r="4.5"><title>json, 4000 keys: 0.8 ms</title></circle>
<circle class="nj-charts-json-dot" cx="242" cy="162.987" r="4.5"><title>json, 8000 keys: 1.6 ms</title></circle>
<circle class="nj-charts-json-dot" cx="330" cy="142.657" r="4.5"><title>json, 16000 keys: 3.3 ms</title></circle>
<text class="nj-charts-val nj-charts-name-json" x="340" y="140.657">json</text>
<text class="nj-charts-val" x="340" y="155.657">3.3 ms</text>
<text class="nj-charts-val" x="72" y="202.204">0.7 ms</text>
<polyline class="nj-charts-ojson" points="66,140.213 154,102.071 242,57.7677 330,30.0977"/>
<circle class="nj-charts-ojson-dot" cx="66" cy="140.213" r="4.5"><title>ordered_json, 2000 keys: 3.6 ms</title></circle>
<circle class="nj-charts-ojson-dot" cx="154" cy="102.071" r="4.5"><title>ordered_json, 4000 keys: 14 ms</title></circle>
<circle class="nj-charts-ojson-dot" cx="242" cy="57.7677" r="4.5"><title>ordered_json, 8000 keys: 67.8 ms</title></circle>
<circle class="nj-charts-ojson-dot" cx="330" cy="30.0977" r="4.5"><title>ordered_json, 16000 keys: 181.6 ms</title></circle>
<text class="nj-charts-val nj-charts-name-ojson" x="340" y="28.0977">ordered_json</text>
<text class="nj-charts-val" x="340" y="43.0977">181.6 ms</text>
<text class="nj-charts-val" x="72" y="160.213">3.6 ms</text>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

+240
View File
@@ -0,0 +1,240 @@
<svg class="nj-fig nj-exceptions-qa nj-exceptions-qa--wide" viewBox="0 0 760 808" role="img" aria-labelledby="nj-qa-title-w nj-qa-desc-w" xmlns="http://www.w3.org/2000/svg">
<title id="nj-qa-title-w">Quality assurance pipeline</title>
<desc id="nj-qa-desc-w">Every push or pull request starts these checks in parallel: Build matrix (every push / PR): 50+ compilers: G&#8203;CC, Clang, M&#8203;SVC, AppleClang, Intel, NVIDIA, ... C++11, 14, 17, 20, 23, and 26 libc++ and libstdc++ warnings: Clang -Weverything, G&#8203;CC 300+ warnings; Unit tests (doctest) (every push / PR): every public A&#8203;PI function every exception id and message all Unicode code points single header and split headers custom number, string, array, and object types; Coverage (every push / PR): unit tests cover all lines of the code base; Static analysis (every push / PR, scheduled): Clang-Tidy, Cppcheck, Infer Clang Static Analyzer (52 checkers), I&#8203;WYU, Codacy CodeQL, Semgrep, Flawfinder (also scheduled); Dynamic analysis (every push / PR): runtime assertions Valgrind (Memcheck) address and undefined behavior sanitizers, integer overflow, nullability violations; Fuzzing (every PR, continuous): CIFuzz on every pull request OSS-Fuzz: billions of inputs every crash fixed with a reproducing unit test; Style (every push / PR): Artistic Style (astyle), enforced in the C&#8203;I cpplint with 61 rules; Docs and examples (every push / PR, scheduled): every documentation example is tested; changed output fails site built with warnings as errors; links checked regularly (scheduled); Integration, supply chain (every push / PR, scheduled): CMake 3.5, 3.31.6, and 4.0.0 Meson, Swift Package Manager dependency review on every PR Dependabot daily, OpenSSF Scorecard, R&#8203;EUSE. When they pass, the change is merged into develop; a release is made only when no vulnerability alert is open.</desc>
<defs><marker id="nj-qa-arrow-w" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path class="fg-head" d="M0 1 L10 5 L0 9 z"/></marker></defs>
<rect class="nj-exceptions-groupbox" x="12" y="70" width="736" height="594" rx="12"/>
<rect class="nj-exceptions-stage" x="265" y="8" width="230" height="34" rx="17"/>
<text class="nj-exceptions-stagetext" x="380" y="30">push or pull request</text>
<line class="nj-exceptions-edge" x1="380" y1="42" x2="380" y2="68" marker-end="url(#nj-qa-arrow-w)"/>
<text class="nj-exceptions-group" x="26" y="94">checks, run in parallel on GitHub Actions and AppVeyor</text>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="110" width="228" height="184" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="135">Build matrix</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="146" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="160">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="188">50+ compilers: G&#8203;CC, Clang, M&#8203;SVC,</text>
<text class="nj-exceptions-line" x="40" y="206">AppleClang, Intel, NVIDIA, ...</text>
<text class="nj-exceptions-line" x="40" y="224">C++11, 14, 17, 20, 23, and 26</text>
<text class="nj-exceptions-line" x="40" y="242">libc++ and libstdc++</text>
<text class="nj-exceptions-line" x="40" y="260">warnings: Clang -Weverything,</text>
<text class="nj-exceptions-line" x="40" y="278">G&#8203;CC 300+ warnings</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="266" y="110" width="228" height="184" rx="8"/>
<text class="nj-exceptions-ctitle" x="280" y="135">Unit tests (doctest)</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="280" y="146" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="335.25" y="160">every push / PR</text>
<text class="nj-exceptions-line" x="280" y="188">every public A&#8203;PI function</text>
<text class="nj-exceptions-line" x="280" y="206">every exception id and message</text>
<text class="nj-exceptions-line" x="280" y="224">all Unicode code points</text>
<text class="nj-exceptions-line" x="280" y="242">single header and split headers</text>
<text class="nj-exceptions-line" x="280" y="260">custom number, string, array,</text>
<text class="nj-exceptions-line" x="280" y="278">and object types</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="506" y="110" width="228" height="184" rx="8"/>
<text class="nj-exceptions-ctitle" x="520" y="135">Coverage</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="520" y="146" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="575.25" y="160">every push / PR</text>
<text class="nj-exceptions-line" x="520" y="188">unit tests cover all lines</text>
<text class="nj-exceptions-line" x="520" y="206">of the code base</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="306" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="331">Static analysis</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="342" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="356">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="156.5" y="342" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="192.85" y="356">scheduled</text>
<text class="nj-exceptions-line" x="40" y="384">Clang-Tidy, Cppcheck, Infer</text>
<text class="nj-exceptions-line" x="40" y="402">Clang Static Analyzer (52</text>
<text class="nj-exceptions-line" x="40" y="420">checkers), I&#8203;WYU, Codacy</text>
<text class="nj-exceptions-line" x="40" y="438">CodeQL, Semgrep, Flawfinder</text>
<text class="nj-exceptions-line" x="40" y="456">(also scheduled)</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="266" y="306" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="280" y="331">Dynamic analysis</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="280" y="342" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="335.25" y="356">every push / PR</text>
<text class="nj-exceptions-line" x="280" y="384">runtime assertions</text>
<text class="nj-exceptions-line" x="280" y="402">Valgrind (Memcheck)</text>
<text class="nj-exceptions-line" x="280" y="420">address and undefined behavior</text>
<text class="nj-exceptions-line" x="280" y="438">sanitizers, integer overflow,</text>
<text class="nj-exceptions-line" x="280" y="456">nullability violations</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="506" y="306" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="520" y="331">Fuzzing</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="520" y="342" width="66.4" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="553.2" y="356">every PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--cont" x="592.4" y="342" width="79" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--cont" x="631.9" y="356">continuous</text>
<text class="nj-exceptions-line" x="520" y="384">CIFuzz on every pull request</text>
<text class="nj-exceptions-line" x="520" y="402">OSS-Fuzz: billions of inputs</text>
<text class="nj-exceptions-line" x="520" y="420">every crash fixed with a</text>
<text class="nj-exceptions-line" x="520" y="438">reproducing unit test</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="484" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="509">Style</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="520" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="534">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="562">Artistic Style (astyle),</text>
<text class="nj-exceptions-line" x="40" y="580">enforced in the C&#8203;I</text>
<text class="nj-exceptions-line" x="40" y="598">cpplint with 61 rules</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="266" y="484" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="280" y="509">Docs and examples</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="280" y="520" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="335.25" y="534">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="396.5" y="520" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="432.85" y="534">scheduled</text>
<text class="nj-exceptions-line" x="280" y="562">every documentation example is</text>
<text class="nj-exceptions-line" x="280" y="580">tested; changed output fails</text>
<text class="nj-exceptions-line" x="280" y="598">site built with warnings</text>
<text class="nj-exceptions-line" x="280" y="616">as errors; links checked</text>
<text class="nj-exceptions-line" x="280" y="634">regularly (scheduled)</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="506" y="484" width="228" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="520" y="509">Integration, supply chain</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="520" y="520" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="575.25" y="534">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="636.5" y="520" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="672.85" y="534">scheduled</text>
<text class="nj-exceptions-line" x="520" y="562">CMake 3.5, 3.31.6, and 4.0.0</text>
<text class="nj-exceptions-line" x="520" y="580">Meson, Swift Package Manager</text>
<text class="nj-exceptions-line" x="520" y="598">dependency review on every PR</text>
<text class="nj-exceptions-line" x="520" y="616">Dependabot daily, OpenSSF</text>
<text class="nj-exceptions-line" x="520" y="634">Scorecard, R&#8203;EUSE</text>
</g>
<line class="nj-exceptions-edge" x1="380" y1="664" x2="380" y2="690" marker-end="url(#nj-qa-arrow-w)"/>
<rect class="nj-exceptions-stage nj-exceptions-stage--merge" x="265" y="692" width="230" height="34" rx="17"/>
<text class="nj-exceptions-stagetext" x="380" y="714">merge into develop</text>
<line class="nj-exceptions-edge" x1="380" y1="726" x2="380" y2="752" marker-end="url(#nj-qa-arrow-w)"/>
<rect class="nj-exceptions-stage nj-exceptions-stage--merge" x="230" y="754" width="300" height="46" rx="23"/>
<text class="nj-exceptions-stagetext" x="380" y="776">release</text>
<text class="nj-exceptions-stagesub" x="380" y="792">no open vulnerability alert</text>
</svg>
<svg class="nj-fig nj-exceptions-qa nj-exceptions-qa--narrow" viewBox="0 0 360 1786" role="img" aria-labelledby="nj-qa-title-n nj-qa-desc-n" xmlns="http://www.w3.org/2000/svg">
<title id="nj-qa-title-n">Quality assurance pipeline</title>
<desc id="nj-qa-desc-n">Every push or pull request starts these checks in parallel: Build matrix (every push / PR): 50+ compilers: G&#8203;CC, Clang, M&#8203;SVC, AppleClang, Intel, NVIDIA, ... C++11, 14, 17, 20, 23, and 26 libc++ and libstdc++ warnings: Clang -Weverything, G&#8203;CC 300+ warnings; Unit tests (doctest) (every push / PR): every public A&#8203;PI function every exception id and message all Unicode code points single header and split headers custom number, string, array, and object types; Coverage (every push / PR): unit tests cover all lines of the code base; Static analysis (every push / PR, scheduled): Clang-Tidy, Cppcheck, Infer Clang Static Analyzer (52 checkers), I&#8203;WYU, Codacy CodeQL, Semgrep, Flawfinder (also scheduled); Dynamic analysis (every push / PR): runtime assertions Valgrind (Memcheck) address and undefined behavior sanitizers, integer overflow, nullability violations; Fuzzing (every PR, continuous): CIFuzz on every pull request OSS-Fuzz: billions of inputs every crash fixed with a reproducing unit test; Style (every push / PR): Artistic Style (astyle), enforced in the C&#8203;I cpplint with 61 rules; Docs and examples (every push / PR, scheduled): every documentation example is tested; changed output fails site built with warnings as errors; links checked regularly (scheduled); Integration, supply chain (every push / PR, scheduled): CMake 3.5, 3.31.6, and 4.0.0 Meson, Swift Package Manager dependency review on every PR Dependabot daily, OpenSSF Scorecard, R&#8203;EUSE. When they pass, the change is merged into develop; a release is made only when no vulnerability alert is open.</desc>
<defs><marker id="nj-qa-arrow-n" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path class="fg-head" d="M0 1 L10 5 L0 9 z"/></marker></defs>
<rect class="nj-exceptions-groupbox" x="12" y="70" width="336" height="1572" rx="12"/>
<rect class="nj-exceptions-stage" x="65" y="8" width="230" height="34" rx="17"/>
<text class="nj-exceptions-stagetext" x="180" y="30">push or pull request</text>
<line class="nj-exceptions-edge" x1="180" y1="42" x2="180" y2="68" marker-end="url(#nj-qa-arrow-n)"/>
<text class="nj-exceptions-group" x="26" y="94">checks, run in parallel</text>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="110" width="308" height="184" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="135">Build matrix</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="146" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="160">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="188">50+ compilers: G&#8203;CC, Clang, M&#8203;SVC,</text>
<text class="nj-exceptions-line" x="40" y="206">AppleClang, Intel, NVIDIA, ...</text>
<text class="nj-exceptions-line" x="40" y="224">C++11, 14, 17, 20, 23, and 26</text>
<text class="nj-exceptions-line" x="40" y="242">libc++ and libstdc++</text>
<text class="nj-exceptions-line" x="40" y="260">warnings: Clang -Weverything,</text>
<text class="nj-exceptions-line" x="40" y="278">G&#8203;CC 300+ warnings</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="306" width="308" height="184" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="331">Unit tests (doctest)</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="342" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="356">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="384">every public A&#8203;PI function</text>
<text class="nj-exceptions-line" x="40" y="402">every exception id and message</text>
<text class="nj-exceptions-line" x="40" y="420">all Unicode code points</text>
<text class="nj-exceptions-line" x="40" y="438">single header and split headers</text>
<text class="nj-exceptions-line" x="40" y="456">custom number, string, array,</text>
<text class="nj-exceptions-line" x="40" y="474">and object types</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="502" width="308" height="112" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="527">Coverage</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="538" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="552">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="580">unit tests cover all lines</text>
<text class="nj-exceptions-line" x="40" y="598">of the code base</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="626" width="308" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="651">Static analysis</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="662" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="676">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="156.5" y="662" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="192.85" y="676">scheduled</text>
<text class="nj-exceptions-line" x="40" y="704">Clang-Tidy, Cppcheck, Infer</text>
<text class="nj-exceptions-line" x="40" y="722">Clang Static Analyzer (52</text>
<text class="nj-exceptions-line" x="40" y="740">checkers), I&#8203;WYU, Codacy</text>
<text class="nj-exceptions-line" x="40" y="758">CodeQL, Semgrep, Flawfinder</text>
<text class="nj-exceptions-line" x="40" y="776">(also scheduled)</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="804" width="308" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="829">Dynamic analysis</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="840" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="854">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="882">runtime assertions</text>
<text class="nj-exceptions-line" x="40" y="900">Valgrind (Memcheck)</text>
<text class="nj-exceptions-line" x="40" y="918">address and undefined behavior</text>
<text class="nj-exceptions-line" x="40" y="936">sanitizers, integer overflow,</text>
<text class="nj-exceptions-line" x="40" y="954">nullability violations</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="982" width="308" height="148" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="1007">Fuzzing</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="1018" width="66.4" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="73.2" y="1032">every PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--cont" x="112.4" y="1018" width="79" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--cont" x="151.9" y="1032">continuous</text>
<text class="nj-exceptions-line" x="40" y="1060">CIFuzz on every pull request</text>
<text class="nj-exceptions-line" x="40" y="1078">OSS-Fuzz: billions of inputs</text>
<text class="nj-exceptions-line" x="40" y="1096">every crash fixed with a</text>
<text class="nj-exceptions-line" x="40" y="1114">reproducing unit test</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="1142" width="308" height="130" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="1167">Style</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="1178" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="1192">every push / PR</text>
<text class="nj-exceptions-line" x="40" y="1220">Artistic Style (astyle),</text>
<text class="nj-exceptions-line" x="40" y="1238">enforced in the C&#8203;I</text>
<text class="nj-exceptions-line" x="40" y="1256">cpplint with 61 rules</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="1284" width="308" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="1309">Docs and examples</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="1320" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="1334">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="156.5" y="1320" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="192.85" y="1334">scheduled</text>
<text class="nj-exceptions-line" x="40" y="1362">every documentation example is</text>
<text class="nj-exceptions-line" x="40" y="1380">tested; changed output fails</text>
<text class="nj-exceptions-line" x="40" y="1398">site built with warnings</text>
<text class="nj-exceptions-line" x="40" y="1416">as errors; links checked</text>
<text class="nj-exceptions-line" x="40" y="1434">regularly (scheduled)</text>
</g>
<g class="nj-exceptions-card">
<rect class="nj-exceptions-box" x="26" y="1462" width="308" height="166" rx="8"/>
<text class="nj-exceptions-ctitle" x="40" y="1487">Integration, supply chain</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--push" x="40" y="1498" width="110.5" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--push" x="95.25" y="1512">every push / PR</text>
<rect class="nj-exceptions-badge nj-exceptions-badge--sched" x="156.5" y="1498" width="72.7" height="20" rx="10"/>
<text class="nj-exceptions-badgetext nj-exceptions-badgetext--sched" x="192.85" y="1512">scheduled</text>
<text class="nj-exceptions-line" x="40" y="1540">CMake 3.5, 3.31.6, and 4.0.0</text>
<text class="nj-exceptions-line" x="40" y="1558">Meson, Swift Package Manager</text>
<text class="nj-exceptions-line" x="40" y="1576">dependency review on every PR</text>
<text class="nj-exceptions-line" x="40" y="1594">Dependabot daily, OpenSSF</text>
<text class="nj-exceptions-line" x="40" y="1612">Scorecard, R&#8203;EUSE</text>
</g>
<line class="nj-exceptions-edge" x1="180" y1="1642" x2="180" y2="1668" marker-end="url(#nj-qa-arrow-n)"/>
<rect class="nj-exceptions-stage nj-exceptions-stage--merge" x="65" y="1670" width="230" height="34" rx="17"/>
<text class="nj-exceptions-stagetext" x="180" y="1692">merge into develop</text>
<line class="nj-exceptions-edge" x1="180" y1="1704" x2="180" y2="1730" marker-end="url(#nj-qa-arrow-n)"/>
<rect class="nj-exceptions-stage nj-exceptions-stage--merge" x="30" y="1732" width="300" height="46" rx="23"/>
<text class="nj-exceptions-stagetext" x="180" y="1754">release</text>
<text class="nj-exceptions-stagesub" x="180" y="1770">no open vulnerability alert</text>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

+27 -446
View File
@@ -1,447 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="545.89282"
height="156.9409"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="range-begin-end.svg">
<style type="text/css">
@media (prefers-color-scheme: dark) {
[style*="stroke:#000000"] { stroke: #e6e6e6 !important; }
[style*="fill:#000000"] { fill: #e6e6e6 !important; }
[style*="fill:#ffffff"] { fill: #1e1e1e !important; }
[style*="fill:#0000ff"] { fill: #7aa2ff !important; }
marker path { fill: #e6e6e6 !important; stroke: #e6e6e6 !important; }
stop[style*="#c1b1b1"] { stop-color: #5a5a5a !important; }
stop[style*="#b6b6b6"] { stop-color: #4a4a4a !important; }
stop[style*="#e3e3e3"] { stop-color: #2a2a2a !important; }
}
</style>
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path6525"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lend"
style="overflow:visible">
<path
id="path6519"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.8,0,0,-0.8,-10,0)"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
id="linearGradient5488">
<stop
style="stop-color:#c1b1b1;stop-opacity:1;"
offset="0"
id="stop5490" />
<stop
style="stop-color:#e3e3e3;stop-opacity:0;"
offset="1"
id="stop5492" />
</linearGradient>
<linearGradient
id="linearGradient4040">
<stop
style="stop-color:#b6b6b6;stop-opacity:1;"
offset="0"
id="stop4042" />
<stop
style="stop-color:#e3e3e3;stop-opacity:0;"
offset="1"
id="stop4044" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5488"
id="linearGradient6284"
gradientUnits="userSpaceOnUse"
x1="81"
y1="1001.3622"
x2="81"
y2="971.36218" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5488-2"
id="linearGradient6284-3"
gradientUnits="userSpaceOnUse"
x1="81"
y1="1001.3622"
x2="81"
y2="971.36218" />
<linearGradient
id="linearGradient5488-2">
<stop
style="stop-color:#c1b1b1;stop-opacity:1;"
offset="0"
id="stop5490-5" />
<stop
style="stop-color:#e3e3e3;stop-opacity:0;"
offset="1"
id="stop5492-8" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5488-0"
id="linearGradient6284-5"
gradientUnits="userSpaceOnUse"
x1="81"
y1="1001.3622"
x2="81"
y2="971.36218" />
<linearGradient
id="linearGradient5488-0">
<stop
style="stop-color:#c1b1b1;stop-opacity:1;"
offset="0"
id="stop5490-1" />
<stop
style="stop-color:#e3e3e3;stop-opacity:0;"
offset="1"
id="stop5492-3" />
</linearGradient>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend-8"
style="overflow:visible">
<path
inkscape:connector-curvature="0"
id="path6525-3"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
</marker>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5488"
id="linearGradient9026"
gradientUnits="userSpaceOnUse"
x1="81"
y1="1001.3622"
x2="81"
y2="971.36218" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="332.80082"
inkscape:cy="165.04542"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1680"
inkscape:window-height="993"
inkscape:window-x="0"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:snap-bbox="true"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="false"
inkscape:bbox-nodes="false"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:object-paths="true"
fit-margin-top="10"
fit-margin-right="10"
fit-margin-bottom="10"
fit-margin-left="10" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-26.107143,-893.4807)">
<g
id="g7184">
<path
inkscape:tile-y0="219"
inkscape:tile-x0="51"
inkscape:tile-h="30.00002"
inkscape:tile-w="29.999997"
inkscape:tile-cy="234.00001"
inkscape:tile-cx="65.999998"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3006"
d="m 80.999997,1001.3622 -29.999997,0 0,-30.00002 29.999997,0 z"
style="fill:url(#linearGradient9026);fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<use
height="300"
width="600"
style="fill:none"
id="use4010"
transform="translate(29.999997,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0" />
<use
id="use4012"
transform="translate(59.999994,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4014"
transform="translate(89.999991,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4016"
transform="translate(119.99999,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4018"
transform="translate(149.99998,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4020"
transform="translate(179.99998,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4022"
transform="translate(209.99998,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4024"
transform="translate(239.99998,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4026"
transform="translate(269.99997,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4028"
transform="translate(299.99997,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4030"
transform="translate(329.99997,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4032"
transform="translate(359.99996,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4034"
transform="translate(389.99996,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4036"
transform="translate(419.99996,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<use
id="use4038"
transform="translate(449.99995,0)"
xlink:href="#path3006"
inkscape:tiled-clone-of="#path3006"
y="0"
x="0"
width="600"
height="300" />
<path
inkscape:tile-y0="219"
inkscape:tile-x0="51"
inkscape:tile-h="30.00002"
inkscape:tile-w="29.999997"
inkscape:tile-cy="234.00001"
inkscape:tile-cx="65.999998"
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path3006-3"
d="m 560.99995,1001.3622 -30,0 0,-30.00002 30,0 z"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2, 2;stroke-dashoffset:0;marker-start:none" />
</g>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:55.00000119%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;fill:#000000;fill-opacity:1;stroke:none;font-family:Droid Sans;-inkscape-font-specification:Droid Sans"
x="392.94931"
y="1040.2404"
id="text6504"
sodipodi:linespacing="55.000001%"><tspan
sodipodi:role="line"
id="tspan6506"
x="392.94931"
y="1040.2404"
rotate="0 0 0 0 0 0 0 0 0.50000191 0 0 0 0 0 0 0 0 0 0 0 0 0"
dy="0"
dx="0"
style="font-size:12.80000019px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">Past-the-last element</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
d="m 531.84531,279.29187 c 14.75083,-11.1311 12.86656,-14.42379 15.15229,-29.29442"
id="path6510"
inkscape:connector-curvature="0"
transform="translate(0,752.36218)"
sodipodi:nodetypes="cc" />
<g
id="g7203"
transform="translate(-40,-18.482143)">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 128.39286,947.36218 -51.785717,0 0,-21.51786 51.785717,0 z"
id="use6288-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
inkscape:tile-x0="51"
inkscape:tile-y0="219" />
<text
transform="translate(0,752.36218)"
sodipodi:linespacing="55.000001%"
id="text7176"
y="189.10715"
x="80.535713"
style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:55.00000119%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"
xml:space="preserve"><tspan
y="189.10715"
x="80.535713"
id="tspan7178"
sodipodi:role="line">begin</tspan></text>
</g>
<g
id="g7238"
transform="translate(20.035895,11.306019)">
<path
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 538.39286,914.19254 -37.50001,0 0,-21.51786 37.50001,0 z"
id="use6288-9-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
inkscape:tile-x0="51"
inkscape:tile-y0="219" />
<text
sodipodi:linespacing="55.000001%"
id="text7176-3"
y="908.29968"
x="504.82141"
style="font-size:15px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:55.00000119%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"
xml:space="preserve"><tspan
y="908.29968"
x="504.82141"
id="tspan7178-7"
sodipodi:role="line">end</tspan></text>
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-mid:none;marker-end:url(#Arrow1Mend)"
d="M 60.16588,176.51786 C 64.809921,191.17027 67.41717,201.02245 68.196339,219"
id="path7243"
inkscape:connector-curvature="0"
transform="translate(0,752.36218)"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-mid:none;marker-end:url(#Arrow1Mend)"
d="m 540.40821,925.49856 c 2.63474,15.08647 5.72454,31.23577 6.06617,45.86362"
id="path7243-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
<svg class="nj-fig nj-fig--range" viewBox="0 0 600 150" role="img" aria-labelledby="fig-be-title" xmlns="http://www.w3.org/2000/svg">
<title id="fig-be-title">A row of fifteen elements followed by a dashed past-the-last position. begin() points to the first element and end() points to the past-the-last position.</title>
<defs><marker id="fig-be-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path class="fg-head" d="M0 1 L10 5 L0 9 z"/></marker></defs>
<rect class="fg-cell" x="30" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="64" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="98" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="132" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="166" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="200" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="234" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="268" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="302" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="336" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="370" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="404" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="438" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="472" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell" x="506" y="62" width="30" height="30" rx="5"/>
<rect class="fg-cell fg-cell--end" x="540" y="62" width="30" height="30" rx="5"/>
<rect class="fg-pill" x="15" y="8" width="60" height="24" rx="6"/>
<text class="fg-pilltext" x="45" y="24">begin</text>
<line class="fg-arrow" x1="45" y1="32" x2="45" y2="60" marker-end="url(#fig-be-arrow)"/>
<rect class="fg-pill" x="531" y="8" width="48" height="24" rx="6"/>
<text class="fg-pilltext" x="555" y="24">end</text>
<line class="fg-arrow" x1="555" y1="32" x2="555" y2="60" marker-end="url(#fig-be-arrow)"/>
<text class="fg-note fg-note--r" x="537" y="132">Past-the-last element</text>
<line class="fg-arrow" x1="555" y1="124" x2="555" y2="96" marker-end="url(#fig-be-arrow)"/>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

File diff suppressed because it is too large. Load diff

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,109 @@
<svg class="nj-fig nj-fig--timeline" viewBox="0 0 880 147" role="img" aria-labelledby="nj-int-tl-title" xmlns="http://www.w3.org/2000/svg">
<title id="nj-int-tl-title">Timeline of the 44 releases from v1.0.0 (2015-12-28) to v3.12.0 (2025-04-11): 17 minor or major releases, drawn as filled dots with their version above the axis, and 27 patch releases, drawn as rings.</title>
<line class="nj-int-grid" x1="24.0" y1="61" x2="24.0" y2="85"/>
<text class="nj-int-year" x="61.5" y="101">2015</text>
<line class="nj-int-grid" x1="99.6" y1="61" x2="99.6" y2="85"/>
<text class="nj-int-year" x="137.3" y="101">2016</text>
<line class="nj-int-grid" x1="175.4" y1="61" x2="175.4" y2="85"/>
<text class="nj-int-year" x="212.8" y="101">2017</text>
<line class="nj-int-grid" x1="250.9" y1="61" x2="250.9" y2="85"/>
<text class="nj-int-year" x="288.4" y="101">2018</text>
<line class="nj-int-grid" x1="326.5" y1="61" x2="326.5" y2="85"/>
<text class="nj-int-year" x="364.0" y="101">2019</text>
<line class="nj-int-grid" x1="402.1" y1="61" x2="402.1" y2="85"/>
<text class="nj-int-year" x="439.8" y="101">2020</text>
<line class="nj-int-grid" x1="477.9" y1="61" x2="477.9" y2="85"/>
<text class="nj-int-year" x="515.4" y="101">2021</text>
<line class="nj-int-grid" x1="553.5" y1="61" x2="553.5" y2="85"/>
<text class="nj-int-year" x="591.0" y="101">2022</text>
<line class="nj-int-grid" x1="629.1" y1="61" x2="629.1" y2="85"/>
<text class="nj-int-year" x="666.5" y="101">2023</text>
<line class="nj-int-grid" x1="704.6" y1="61" x2="704.6" y2="85"/>
<text class="nj-int-year" x="742.3" y="101">2024</text>
<line class="nj-int-grid" x1="780.4" y1="61" x2="780.4" y2="85"/>
<text class="nj-int-year" x="817.9" y="101">2025</text>
<line class="nj-int-grid" x1="856.0" y1="61" x2="856.0" y2="85"/>
<line class="nj-int-axis" x1="24" y1="77" x2="856" y2="77"/>
<path class="nj-int-axis" fill="none" d="M98.8 114 V119 H104.3 V114"/>
<text class="nj-int-major" x="98.8" y="136" text-anchor="start">1.x</text>
<path class="nj-int-axis" fill="none" d="M135.8 114 V119 H186.8 V114"/>
<text class="nj-int-major" x="161.3" y="136" text-anchor="middle">2.x</text>
<path class="nj-int-axis" fill="none" d="M247.8 114 V119 H801.1 V114"/>
<text class="nj-int-major" x="524.5" y="136" text-anchor="middle">3.x</text>
<line class="nj-int-leader" x1="98.8" y1="68" x2="98.8" y2="70"/>
<text class="nj-int-label" x="98.8" y="65">1.0</text>
<line class="nj-int-leader" x1="104.3" y1="51" x2="104.3" y2="70"/>
<text class="nj-int-label" x="104.3" y="48">1.1</text>
<line class="nj-int-leader" x1="135.8" y1="68" x2="135.8" y2="70"/>
<text class="nj-int-label" x="135.8" y="65">2.0</text>
<line class="nj-int-leader" x1="181.0" y1="68" x2="181.0" y2="70"/>
<text class="nj-int-label" x="181.0" y="65">2.1</text>
<line class="nj-int-leader" x1="247.8" y1="68" x2="247.8" y2="70"/>
<text class="nj-int-label" x="247.8" y="65">3.0</text>
<line class="nj-int-leader" x1="257.4" y1="51" x2="257.4" y2="70"/>
<text class="nj-int-label" x="257.4" y="48">3.1</text>
<line class="nj-int-leader" x1="298.8" y1="68" x2="298.8" y2="70"/>
<text class="nj-int-label" x="298.8" y="65">3.2</text>
<line class="nj-int-leader" x1="308.3" y1="51" x2="308.3" y2="70"/>
<text class="nj-int-label" x="308.3" y="48">3.3</text>
<line class="nj-int-leader" x1="313.5" y1="34" x2="313.5" y2="70"/>
<text class="nj-int-label" x="313.5" y="31">3.4</text>
<line class="nj-int-leader" x1="324.5" y1="68" x2="324.5" y2="70"/>
<text class="nj-int-label" x="324.5" y="65">3.5</text>
<line class="nj-int-leader" x1="342.7" y1="51" x2="342.7" y2="70"/>
<text class="nj-int-label" x="342.7" y="48">3.6</text>
<line class="nj-int-leader" x1="369.6" y1="68" x2="369.6" y2="70"/>
<text class="nj-int-label" x="369.6" y="65">3.7</text>
<line class="nj-int-leader" x1="436.3" y1="68" x2="436.3" y2="70"/>
<text class="nj-int-label" x="436.3" y="65">3.8</text>
<line class="nj-int-leader" x1="445.2" y1="51" x2="445.2" y2="70"/>
<text class="nj-int-label" x="445.2" y="48">3.9</text>
<line class="nj-int-leader" x1="525.1" y1="68" x2="525.1" y2="70"/>
<text class="nj-int-label" x="525.1" y="65">3.10</text>
<line class="nj-int-leader" x1="597.4" y1="68" x2="597.4" y2="70"/>
<text class="nj-int-label" x="597.4" y="65">3.11</text>
<line class="nj-int-leader" x1="801.1" y1="68" x2="801.1" y2="70"/>
<text class="nj-int-label" x="801.1" y="65">3.12</text>
<g><title>v2.0.1 released 2016-06-28</title><circle class="nj-int-hit" cx="136.6" cy="77" r="9"/><circle class="nj-int-patch" cx="136.6" cy="77" r="3.5"/></g>
<g><title>v2.0.2 released 2016-07-31</title><circle class="nj-int-hit" cx="143.5" cy="77" r="9"/><circle class="nj-int-patch" cx="143.5" cy="77" r="3.5"/></g>
<g><title>v2.0.3 released 2016-08-31</title><circle class="nj-int-hit" cx="149.9" cy="77" r="9"/><circle class="nj-int-patch" cx="149.9" cy="77" r="3.5"/></g>
<g><title>v2.0.4 released 2016-09-11</title><circle class="nj-int-hit" cx="152.2" cy="77" r="9"/><circle class="nj-int-patch" cx="152.2" cy="77" r="3.5"/></g>
<g><title>v2.0.5 released 2016-09-14</title><circle class="nj-int-hit" cx="152.8" cy="77" r="9"/><circle class="nj-int-patch" cx="152.8" cy="77" r="3.5"/></g>
<g><title>v2.0.6 released 2016-10-15</title><circle class="nj-int-hit" cx="159.2" cy="77" r="9"/><circle class="nj-int-patch" cx="159.2" cy="77" r="3.5"/></g>
<g><title>v2.0.7 released 2016-11-02</title><circle class="nj-int-hit" cx="162.9" cy="77" r="9"/><circle class="nj-int-patch" cx="162.9" cy="77" r="3.5"/></g>
<g><title>v2.0.8 released 2016-12-02</title><circle class="nj-int-hit" cx="169.2" cy="77" r="9"/><circle class="nj-int-patch" cx="169.2" cy="77" r="3.5"/></g>
<g><title>v2.0.9 released 2016-12-16</title><circle class="nj-int-hit" cx="172.1" cy="77" r="9"/><circle class="nj-int-patch" cx="172.1" cy="77" r="3.5"/></g>
<g><title>v2.0.10 released 2017-01-02</title><circle class="nj-int-hit" cx="175.6" cy="77" r="9"/><circle class="nj-int-patch" cx="175.6" cy="77" r="3.5"/></g>
<g><title>v2.1.1 released 2017-02-25</title><circle class="nj-int-hit" cx="186.8" cy="77" r="9"/><circle class="nj-int-patch" cx="186.8" cy="77" r="3.5"/></g>
<g><title>v3.0.1 released 2017-12-29</title><circle class="nj-int-hit" cx="250.3" cy="77" r="9"/><circle class="nj-int-patch" cx="250.3" cy="77" r="3.5"/></g>
<g><title>v3.1.1 released 2018-02-13</title><circle class="nj-int-hit" cx="259.9" cy="77" r="9"/><circle class="nj-int-patch" cx="259.9" cy="77" r="3.5"/></g>
<g><title>v3.1.2 released 2018-03-14</title><circle class="nj-int-hit" cx="265.9" cy="77" r="9"/><circle class="nj-int-patch" cx="265.9" cy="77" r="3.5"/></g>
<g><title>v3.7.1 released 2019-11-06</title><circle class="nj-int-hit" cx="390.5" cy="77" r="9"/><circle class="nj-int-patch" cx="390.5" cy="77" r="3.5"/></g>
<g><title>v3.7.2 released 2019-11-10</title><circle class="nj-int-hit" cx="391.3" cy="77" r="9"/><circle class="nj-int-patch" cx="391.3" cy="77" r="3.5"/></g>
<g><title>v3.7.3 released 2019-11-17</title><circle class="nj-int-hit" cx="392.8" cy="77" r="9"/><circle class="nj-int-patch" cx="392.8" cy="77" r="3.5"/></g>
<g><title>v3.9.1 released 2020-08-06</title><circle class="nj-int-hit" cx="447.2" cy="77" r="9"/><circle class="nj-int-patch" cx="447.2" cy="77" r="3.5"/></g>
<g><title>v3.10.1 released 2021-08-24</title><circle class="nj-int-hit" cx="526.6" cy="77" r="9"/><circle class="nj-int-patch" cx="526.6" cy="77" r="3.5"/></g>
<g><title>v3.10.2 released 2021-08-26</title><circle class="nj-int-hit" cx="527.0" cy="77" r="9"/><circle class="nj-int-patch" cx="527.0" cy="77" r="3.5"/></g>
<g><title>v3.10.3 released 2021-10-08</title><circle class="nj-int-hit" cx="535.9" cy="77" r="9"/><circle class="nj-int-patch" cx="535.9" cy="77" r="3.5"/></g>
<g><title>v3.10.4 released 2021-10-16</title><circle class="nj-int-hit" cx="537.5" cy="77" r="9"/><circle class="nj-int-patch" cx="537.5" cy="77" r="3.5"/></g>
<g><title>v3.10.5 released 2022-01-03</title><circle class="nj-int-hit" cx="553.9" cy="77" r="9"/><circle class="nj-int-patch" cx="553.9" cy="77" r="3.5"/></g>
<g><title>v3.11.2 released 2022-08-12</title><circle class="nj-int-hit" cx="599.6" cy="77" r="9"/><circle class="nj-int-patch" cx="599.6" cy="77" r="3.5"/></g>
<g><title>v3.11.3 released 2023-11-28</title><circle class="nj-int-hit" cx="697.6" cy="77" r="9"/><circle class="nj-int-patch" cx="697.6" cy="77" r="3.5"/></g>
<g><title>v1.0.0 released 2015-12-28</title><circle class="nj-int-hit" cx="98.8" cy="77" r="9"/><circle class="nj-int-minor" cx="98.8" cy="77" r="6"/></g>
<g><title>v1.1.0 released 2016-01-24</title><circle class="nj-int-hit" cx="104.3" cy="77" r="9"/><circle class="nj-int-minor" cx="104.3" cy="77" r="6"/></g>
<g><title>v2.0.0 released 2016-06-24</title><circle class="nj-int-hit" cx="135.8" cy="77" r="9"/><circle class="nj-int-minor" cx="135.8" cy="77" r="6"/></g>
<g><title>v2.1.0 released 2017-01-28</title><circle class="nj-int-hit" cx="181.0" cy="77" r="9"/><circle class="nj-int-minor" cx="181.0" cy="77" r="6"/></g>
<g><title>v3.0.0 released 2017-12-17</title><circle class="nj-int-hit" cx="247.8" cy="77" r="9"/><circle class="nj-int-minor" cx="247.8" cy="77" r="6"/></g>
<g><title>v3.1.0 released 2018-02-01</title><circle class="nj-int-hit" cx="257.4" cy="77" r="9"/><circle class="nj-int-minor" cx="257.4" cy="77" r="6"/></g>
<g><title>v3.2.0 released 2018-08-20</title><circle class="nj-int-hit" cx="298.8" cy="77" r="9"/><circle class="nj-int-minor" cx="298.8" cy="77" r="6"/></g>
<g><title>v3.3.0 released 2018-10-05</title><circle class="nj-int-hit" cx="308.3" cy="77" r="9"/><circle class="nj-int-minor" cx="308.3" cy="77" r="6"/></g>
<g><title>v3.4.0 released 2018-10-30</title><circle class="nj-int-hit" cx="313.5" cy="77" r="9"/><circle class="nj-int-minor" cx="313.5" cy="77" r="6"/></g>
<g><title>v3.5.0 released 2018-12-22</title><circle class="nj-int-hit" cx="324.5" cy="77" r="9"/><circle class="nj-int-minor" cx="324.5" cy="77" r="6"/></g>
<g><title>v3.6.0, v3.6.1 released 2019-03-20</title><circle class="nj-int-hit" cx="342.7" cy="77" r="9"/><circle class="nj-int-minor" cx="342.7" cy="77" r="6"/></g>
<g><title>v3.7.0 released 2019-07-28</title><circle class="nj-int-hit" cx="369.6" cy="77" r="9"/><circle class="nj-int-minor" cx="369.6" cy="77" r="6"/></g>
<g><title>v3.8.0 released 2020-06-14</title><circle class="nj-int-hit" cx="436.3" cy="77" r="9"/><circle class="nj-int-minor" cx="436.3" cy="77" r="6"/></g>
<g><title>v3.9.0 released 2020-07-27</title><circle class="nj-int-hit" cx="445.2" cy="77" r="9"/><circle class="nj-int-minor" cx="445.2" cy="77" r="6"/></g>
<g><title>v3.10.0 released 2021-08-17</title><circle class="nj-int-hit" cx="525.1" cy="77" r="9"/><circle class="nj-int-minor" cx="525.1" cy="77" r="6"/></g>
<g><title>v3.11.0, v3.11.1 released 2022-08-01</title><circle class="nj-int-hit" cx="597.4" cy="77" r="9"/><circle class="nj-int-minor" cx="597.4" cy="77" r="6"/></g>
<g><title>v3.12.0 released 2025-04-11</title><circle class="nj-int-hit" cx="801.1" cy="77" r="9"/><circle class="nj-int-minor" cx="801.1" cy="77" r="6"/></g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

+98
View File
@@ -0,0 +1,98 @@
<svg class="nj-fig nj-fig--lanes" viewBox="0 0 880 504" role="img" aria-labelledby="nj-int-lanes-title" xmlns="http://www.w3.org/2000/svg">
<title id="nj-int-lanes-title">Two lanes: the 3.x release train, whose minor and patch releases do not break code that uses the public A&#8203;PI, followed by version 4.0, which has no release date yet. Each breaking change is a macro that is available in 3.x today with its 3.x default and becomes the default in 4.0: JSON_USE_IMPLICIT_CONVERSIONS, added in 3.9.0, 3.x default 1, 4.0 value 0; JSON_USE_GLOBAL_UDLS, added in 3.11.0, 3.x default 1, 4.0 value 0; JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON, added in 3.11.0, 3.x default 0, 4.0 value 0, macro removed; JSON_BRACE_INIT_COPY_SEMANTICS, added in 3.13.0, 3.x default 0, 4.0 value 1; JSON_PRECISE_STREAM_POSITION, added in 3.13.0, 3.x default 0, 4.0 value 1; JSON_STRICT_NUL_HANDLING, added in 3.13.0, 3.x default 0, 4.0 value 1; JSON_STRICT_BINARY_UTF8, added in 3.13.0, 3.x default 0, 4.0 value 1; JSON_DISABLE_TUPLE_REFERENCE_CONVERSION, added in 3.13.0, 3.x default 0, 4.0 value 1; JSON_DELETE_DEPRECATED_FUNCTIONS, added in 3.13.0, 3.x default 0, 4.0 value 1, macro removed.</title>
<defs><marker id="nj-int-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path class="fg-head" d="M0 1 L10 5 L0 9 z"/></marker></defs>
<rect class="nj-int-lane" x="16" y="16" width="600" height="56" rx="10"/>
<text class="nj-int-lanetext" x="32" y="41">3.x release train</text>
<text class="nj-int-mute" x="32" y="60">available today</text>
<line class="nj-int-axis" x1="300" y1="30" x2="300" y2="44"/>
<text class="nj-int-mute" x="300" y="60" text-anchor="middle">3.9.0</text>
<line class="nj-int-axis" x1="445" y1="30" x2="445" y2="44"/>
<text class="nj-int-mute" x="445" y="60" text-anchor="middle">3.11.0</text>
<line class="nj-int-axis" x1="590" y1="30" x2="590" y2="44"/>
<text class="nj-int-mute" x="590" y="60" text-anchor="middle">3.13.0</text>
<line class="fg-arrow" x1="210" y1="37" x2="600" y2="37"/>
<line class="fg-arrow fg-arrow--dash" x1="618" y1="44" x2="660" y2="44" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-lane nj-int-lane--future" x="664" y="16" width="200" height="56" rx="10"/>
<text class="nj-int-lanetext" x="680" y="41">4.0</text>
<text class="nj-int-mute" x="680" y="60">no release date yet</text>
<text class="nj-int-text" x="16" y="98">A minor or patch release of 3.x does not break code that uses the public A&#8203;PI, unless that code opts in with a macro.</text>
<text class="nj-int-text" x="16" y="118">4.0 is not developed on a separate branch: it switches the defaults of these macros and removes the macros.</text>
<text class="fg-h" x="32" y="150">Macro</text>
<text class="fg-h" x="380" y="150">added</text>
<text class="fg-h" x="500" y="150" text-anchor="middle">3.x default</text>
<text class="nj-int-mute" x="632" y="150" text-anchor="middle">define to try today</text>
<text class="fg-h" x="764" y="150" text-anchor="middle">4.0 default</text>
<rect class="nj-int-row" x="16" y="170" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="189.5">JSON_USE_IMPLICIT_CONVERSIONS</text>
<text class="nj-int-mute" x="380" y="189.5">3.9.0</text>
<rect class="nj-int-pill" x="470" y="174" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="189.5" text-anchor="middle">1</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="185" x2="724" y2="185" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="174" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="189.5" text-anchor="middle">0</text>
<rect class="nj-int-row" x="16" y="204" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="223.5">JSON_USE_GLOBAL_UDLS</text>
<text class="nj-int-mute" x="380" y="223.5">3.11.0</text>
<rect class="nj-int-pill" x="470" y="208" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="223.5" text-anchor="middle">1</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="219" x2="724" y2="219" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="208" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="223.5" text-anchor="middle">0</text>
<rect class="nj-int-row" x="16" y="238" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="257.5">JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON</text>
<text class="nj-int-mute" x="380" y="257.5">3.11.0</text>
<rect class="nj-int-pill" x="470" y="242" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="257.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="253" x2="724" y2="253" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="242" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="257.5" text-anchor="middle">removed</text>
<rect class="nj-int-row" x="16" y="272" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="291.5">JSON_BRACE_INIT_COPY_SEMANTICS</text>
<text class="nj-int-mute" x="380" y="291.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="276" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="291.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="287" x2="724" y2="287" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="276" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="291.5" text-anchor="middle">1</text>
<rect class="nj-int-row" x="16" y="306" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="325.5">JSON_PRECISE_STREAM_POSITION</text>
<text class="nj-int-mute" x="380" y="325.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="310" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="325.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="321" x2="724" y2="321" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="310" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="325.5" text-anchor="middle">1</text>
<rect class="nj-int-row" x="16" y="340" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="359.5">JSON_STRICT_NUL_HANDLING</text>
<text class="nj-int-mute" x="380" y="359.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="344" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="359.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="355" x2="724" y2="355" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="344" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="359.5" text-anchor="middle">1</text>
<rect class="nj-int-row" x="16" y="374" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="393.5">JSON_STRICT_BINARY_UTF8</text>
<text class="nj-int-mute" x="380" y="393.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="378" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="393.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="389" x2="724" y2="389" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="378" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="393.5" text-anchor="middle">1</text>
<rect class="nj-int-row" x="16" y="408" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="427.5">JSON_DISABLE_TUPLE_REFERENCE_CONVERSION</text>
<text class="nj-int-mute" x="380" y="427.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="412" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="427.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="423" x2="724" y2="423" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="412" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="427.5" text-anchor="middle">1</text>
<rect class="nj-int-row" x="16" y="442" width="848" height="30" rx="6"/>
<text class="nj-int-macro" x="32" y="461.5">JSON_DELETE_DEPRECATED_FUNCTIONS</text>
<text class="nj-int-mute" x="380" y="461.5">3.13.0</text>
<rect class="nj-int-pill" x="470" y="446" width="60" height="22" rx="11"/>
<text class="nj-int-val" x="500" y="461.5" text-anchor="middle">0</text>
<line class="fg-arrow fg-arrow--dash" x1="544" y1="457" x2="724" y2="457" marker-end="url(#nj-int-arrow)"/>
<rect class="nj-int-pill nj-int-pill--v4" x="728" y="446" width="72" height="22" rx="11"/>
<text class="nj-int-val nj-int-val--v4" x="764" y="461.5" text-anchor="middle">removed</text>
<text class="nj-int-mute" x="16" y="496">Versions on the 3.x lane are the ones that added a macro, not to scale. &#8220;removed&#8221;: see the 4.0 behavior column of the table.</text>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-78 -1741 14091 2499" width="495" height="88" role="img" aria-label="nlohmann/json"><title>nlohmann/json</title><g transform="scale(1 -1)"><g fill="#ffffff"><path transform="translate(0.0 0)" d="M279.2 697.3V0H167.3V1104.2H276.1L276.4 850.4H255.4Q299 990.6 399.3 1055.2Q499.6 1119.9 626.3 1119.9Q739.7 1119.9 826.2 1072.4Q912.8 1024.9 962.1 935.2Q1011.4 845.5 1011.4 717.1V0H899.6V709.9Q899.6 851.3 818 933.9Q736.5 1016.6 601.8 1016.6Q510.1 1016.6 437 977.7Q363.8 938.9 321.5 867.2Q279.2 795.6 279.2 697.3Z"/><path transform="translate(1138.0 0)" d="M279.2 1490V0H167.3V1490H279.2Z"/><path transform="translate(1544.1 0)" d="M590.7 -23.1Q448.9 -23.1 339.6 50.3Q230.3 123.7 168.3 252.7Q106.3 381.6 106.3 548Q106.3 715.8 168.3 844.8Q230.3 973.8 339.6 1047.1Q448.9 1120.3 590.7 1120.3Q732.6 1120.3 841.7 1047.1Q950.9 973.8 1012.9 844.6Q1074.9 715.4 1074.9 548Q1074.9 381.6 1013.1 252.7Q951.3 123.7 842.1 50.3Q733 -23.1 590.7 -23.1ZM590.7 79.6Q705.6 79.6 788.9 141.9Q872.2 204.2 917.1 310.4Q962 416.7 962 548Q962 679.6 916.9 786Q871.8 892.4 788.5 955Q705.2 1017.6 590.7 1017.6Q476.7 1017.6 393.5 954.9Q310.3 892.2 265 786.1Q219.6 679.9 219.6 548Q219.6 416.6 264.8 310.4Q309.9 204.2 393.1 141.9Q476.2 79.6 590.7 79.6Z"/><path transform="translate(2684.1 0)" d="M279.2 697.3V0H167.3V1490H279.2V850.4H255.4Q299 990.6 399.3 1055.2Q499.6 1119.9 626.3 1119.9Q739.7 1119.9 826.4 1072.4Q913.2 1024.9 962.5 935.2Q1011.8 845.5 1011.8 717.1V0H899.6V709.9Q899.6 851.3 818 933.9Q736.5 1016.6 601.8 1016.6Q510.1 1016.6 437 977.7Q363.8 938.9 321.5 867.2Q279.2 795.6 279.2 697.3Z"/><path transform="translate(3822.2 0)" d="M167.3 0V1104.2H276.8L277.2 853.7H261.4Q285.1 945.7 337 1004.8Q388.9 1064 457.8 1093.1Q526.7 1122.2 599.7 1122.2Q722.9 1122.2 805.7 1046.7Q888.4 971.2 910.3 844.9H888.1Q907.9 930.7 959.4 992.8Q1011 1054.9 1085.3 1088.6Q1159.6 1122.2 1248.1 1122.2Q1349.1 1122.2 1427 1078Q1505 1033.7 1549.5 948.2Q1594 862.7 1594 738.2V0H1482.1V736.3Q1482.1 878 1408.3 948Q1334.4 1018.1 1221.8 1018.1Q1139.1 1018.1 1074.7 982.6Q1010.3 947 973.4 881.6Q936.6 816.3 936.6 726.7V0H824.7V745.3Q824.7 873 754.3 945.6Q683.9 1018.1 570.7 1018.1Q491.1 1018.1 424.8 981.1Q358.4 944 318.8 875.8Q279.2 807.7 279.2 713.4V0H167.3Z"/><path transform="translate(5542.2 0)" d="M560.3 -22.7Q425.4 -22.7 323.1 49.7Q220.8 122 163.6 251Q106.3 380.1 106.3 549.8Q106.3 718.7 164 847.4Q221.7 976 324.4 1047.9Q427.1 1119.9 561.9 1119.9Q657.4 1119.9 727.7 1085.2Q798.1 1050.6 845.2 994.3Q892.3 938.1 916.4 874.3H924.9V1104.2H1036.2V0H925.3V225.1H916.4Q891.1 161.2 843.7 104.4Q796.3 47.5 725.9 12.4Q655.4 -22.7 560.3 -22.7ZM574.9 79.9Q685.3 79.9 764.2 140.4Q843.1 200.8 885.1 307.1Q927.2 413.4 927.2 550.6Q927.2 687.8 885.1 793Q843.1 898.2 764.2 957.8Q685.3 1017.4 574.9 1017.4Q464.6 1017.4 384.9 957.2Q305.3 897.1 262.4 791.7Q219.6 686.2 219.6 550.6Q219.6 415 262.4 308.6Q305.3 202.3 384.9 141.1Q464.6 79.9 574.9 79.9Z"/><path transform="translate(6705.2 0)" d="M279.2 697.3V0H167.3V1104.2H276.1L276.4 850.4H255.4Q299 990.6 399.3 1055.2Q499.6 1119.9 626.3 1119.9Q739.7 1119.9 826.2 1072.4Q912.8 1024.9 962.1 935.2Q1011.4 845.5 1011.4 717.1V0H899.6V709.9Q899.6 851.3 818 933.9Q736.5 1016.6 601.8 1016.6Q510.1 1016.6 437 977.7Q363.8 938.9 321.5 867.2Q279.2 795.6 279.2 697.3Z"/><path transform="translate(7843.3 0)" d="M279.2 697.3V0H167.3V1104.2H276.1L276.4 850.4H255.4Q299 990.6 399.3 1055.2Q499.6 1119.9 626.3 1119.9Q739.7 1119.9 826.2 1072.4Q912.8 1024.9 962.1 935.2Q1011.4 845.5 1011.4 717.1V0H899.6V709.9Q899.6 851.3 818 933.9Q736.5 1016.6 601.8 1016.6Q510.1 1016.6 437 977.7Q363.8 938.9 321.5 867.2Q279.2 795.6 279.2 697.3Z"/><path transform="translate(9729.7 0)" d="M111.2 1104.2H459.2V-51.7Q459.4 -183.9 406.6 -264.4Q353.7 -344.9 255.5 -381.4Q157.2 -418 21.4 -418H-63.7V-152.7H-14.8Q55.3 -152.7 83.3 -125Q111.2 -97.4 111.2 -39.2V1104.2ZM285.1 1228.6Q208.7 1228.6 155.6 1278Q102.6 1327.5 102.6 1398.2Q102.6 1469.9 155.6 1518.8Q208.7 1567.8 285 1567.8Q361.5 1567.8 414.7 1518.9Q467.8 1470.1 467.8 1398.1Q467.8 1327.4 414.7 1278Q361.5 1228.6 285.1 1228.6Z"/><path transform="translate(10258.7 0)" d="M580.7 -22.1Q436.8 -22.1 326.1 19.4Q215.5 60.9 146.9 138.4Q78.2 215.9 61 323.7L388.3 363.3Q406.3 294.2 455.2 257.5Q504.1 220.8 589.7 220.8Q662.2 220.8 703.6 246.4Q745 271.9 745 313.9Q745 351.2 711.8 374.4Q678.7 397.6 610.3 410.8L416 447.9Q252.5 479.2 170.3 559.5Q88.1 639.9 88.1 767.7Q88.1 878 147.7 956.7Q207.4 1035.5 316.7 1077.7Q426.1 1119.9 575.6 1119.9Q717.4 1119.9 822.1 1080.8Q926.7 1041.7 989.4 969.8Q1052.1 897.9 1067.5 797.8L757.5 759.8Q745.3 815.8 699.4 848.2Q653.5 880.6 583.2 880.6Q518.8 880.6 476.8 855.3Q434.8 829.9 434.8 787.7Q434.8 753.9 462.5 729Q490.3 704.1 557.8 691L771.4 651.3Q937.2 620.2 1017.9 546.8Q1098.7 473.4 1098.7 352.5Q1098.7 239.1 1032.3 154.9Q965.9 70.8 849.2 24.3Q732.5 -22.1 580.7 -22.1Z"/><path transform="translate(11376.8 0)" d="M628.4 -21.6Q455.7 -21.6 329.7 49.8Q203.6 121.3 135.6 249.6Q67.7 378 67.7 548.9Q67.7 720.4 135.6 848.9Q203.6 977.3 329.7Line truncated

After

Width:  |  Height:  |  Size: 5.8 KiB

+8 -66
View File
@@ -1,63 +1,11 @@
---
template: home.html
hide:
- toc
---
# JSON for Modern C++
![JSON for Modern C++](images/json.gif)
JSON for Modern C++ is a header-only C++11 library that turns JSON into a first-class C++ data type, using the operator
magic of modern C++ so that creating, reading, and modifying JSON values feels as natural as it does in languages like
Python. The whole library is available as a single header, `json.hpp`, with no dependencies, no subproject, and no
complex build system to set up; a companion header, `json_fwd.hpp`, provides forward declarations to keep compile times
down, `<nlohmann/json_literals.hpp>` holds the user-defined string literals on their own, and
`<nlohmann/json_view.hpp>` adds zero-copy views and editable documents. See
[header-only integration](integration/index.md) for details. It is heavily unit-tested with 100% code
coverage, checked with Valgrind and the Clang Sanitizers for memory leaks, and continuously fuzz-tested by Google
OSS-Fuzz.
## Quick start
Add the single header to your project and use the library like this:
```cpp
#include <iostream>
#include <nlohmann/json.hpp>
using nlohmann::json;
int main()
{
// parse a JSON string
json j = json::parse(R"({"happy": true, "pi": 3.141})");
// access and modify values
j["name"] = "Niels";
j["list"] = {1, 0, 2};
// read a value into a C++ variable and use it
double pi = j["pi"].get<double>();
std::cout << "2 * pi = " << 2 * pi << '\n';
// serialize with an indent of 4 spaces
std::cout << j.dump(4) << '\n';
}
```
Get the library by copying the single header [`json.hpp`](https://github.com/nlohmann/json/releases) from the
releases page into a directory `nlohmann` on your include path, or by installing it with a package manager:
```sh
brew install nlohmann-json # Homebrew
vcpkg install nlohmann-json # vcpkg
```
```cmake
find_package(nlohmann_json 3.12.0 REQUIRED)
target_link_libraries(myproject PRIVATE nlohmann_json::nlohmann_json)
```
See [Integration](integration/index.md) for CMake in detail, all supported package managers (Conan, Meson, Bazel,
Conda, and more), and pkg-config.
## Explore the documentation
<div class="grid cards" markdown>
- :octicons-rocket-24:{ .lg .middle } __Features__
@@ -112,11 +60,5 @@ Conda, and more), and pkg-config.
</div>
!!! info "Unreleased changes"
This documentation is built from the `develop` branch and may describe changes that are not part of a release
yet. Their version numbers are followed by an <span class="unreleased-version">unreleased</span> badge; see
[Releases](home/releases/index.md) for what shipped in each version.
The library is licensed under the [MIT License](home/license.md). The source code, issue tracker, and discussions
are on [GitHub](https://github.com/nlohmann/json).
![JSON for Modern C++](images/json-light.svg#only-light)
![JSON for Modern C++](images/json-dark.svg#only-dark)
+13
View File
@@ -8,6 +8,19 @@ to point to the appropriate include directories and [`INTERFACE_COMPILE_FEATURES
for the necessary C++11 flags. Most [package managers](package_managers.md) that provide a CMake package configuration
for this library expose this same target.
All ways of adding the library described below end at this one target:
```mermaid
flowchart LR
FP["<b>find_package()</b><br>installed package"] --> T
AS["<b>add_subdirectory()</b><br>embedded source tree"] --> T
FC["<b>FetchContent</b><br>downloaded at configure time"] --> T
PM["<b>Package manager</b><br>its CMake package"] --> T
T["<b>nlohmann_json::nlohmann_json</b><br>one INTERFACE target"] --> L["<b>target_link_libraries()</b><br>link it PRIVATE"]
```
<p class="nj-caption" markdown>The four ways to add the library in CMake all lead to the same `nlohmann_json::nlohmann_json` interface target, which a project links with `target_link_libraries`. The CMake options below apply to `add_subdirectory()` and `FetchContent`; installed packages have their options fixed at install time.</p>
### External
To use this library from a CMake project, you can locate it directly with [`find_package()`](https://cmake.org/cmake/help/latest/command/find_package.html)
Loaded 100 of 155 files, more files were not shown because too many files have changed in this diff. Show more