Compare commits

..
Author SHA1 Message Date
Niels Lohmann 26700c6dc3 Merge branch 'develop' into fix/json_pointer_create_object_5357
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-08 16:12:17 +02:00
Niels Lohmann b9a581e6d2 Merge branch 'develop' into fix/json_pointer_create_object_5357
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-07 20:12:05 +02:00
Niels Lohmann 0bd2d36f2a Merge remote-tracking branch 'origin/develop' into HEAD
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-04 17:19:42 +02:00
Niels Lohmann a2ca07a4b3 Merge branch 'develop' into fix/json_pointer_create_object_5357
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 20:58:31 +02:00
Niels Lohmann cda8d2b848 Clarify that the token 0 is a valid array index in operator[] docs
The note described valid array indices as "a nonempty sequence of digits
without a leading 0", which read literally excludes the token "0" itself,
contradicting both the code and the /foo/0/0/0 example in the next
sentence. Spell out the RFC 6901 grammar instead.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-09-27 18:20:28 +02:00
Niels Lohmann db1d0983e6 create objects for tokens that cannot be array indices (#5357)
When operator[](json_pointer) traverses a level that does not exist yet,
the null value is turned into an array or an object depending on the
reference token. The check only tested whether all characters are digits,
so tokens that can never be a valid array index selected an array and
then failed:

- "01" (and any other token with a leading '0') threw parse_error.106
- the empty token threw out_of_range.404

Both tokens are valid object keys, and both work when the level already
exists as an object, so creating the level changed the outcome. Test the
token against the RFC 6901, Sect. 4 grammar for array indices instead, so
that such tokens create an object. This only affects pointers that threw
before.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-08-04 08:51:54 +02:00
529 changed files with 38734 additions and 77233 deletions

No files matched your search

-3
View File
@@ -1,3 +0,0 @@
# generated files are collapsed in diffs and excluded from language statistics
single_include/** linguist-generated
nlohmann_json.natvis linguist-generated
+1 -1
View File
@@ -1,5 +1,5 @@
# JSON for Modern C++ was originally written by Niels Lohmann. # JSON for Modern C++ was originally written by Niels Lohmann.
# Since 2013, over 400 contributors have helped to improve the library. # Since 2013, over 250 contributors have helped to improve the library.
# This CODEOWNERS file is only to make sure that @nlohmann is requested # This CODEOWNERS file is only to make sure that @nlohmann is requested
# for a code review in case of a pull request. # for a code review in case of a pull request.
+14 -16
View File
@@ -98,7 +98,7 @@ $ ctest --test-dir build -j 10
The test suite should report: The test suite should report:
``` ```
100% tests passed, 0 tests failed out of <number of tests> 100% tests passed, 0 tests failed out of 98
``` ```
#### Add tests #### Add tests
@@ -149,17 +149,14 @@ make build -C docs/mkdocs # strict build: fails on broken links, anchor
make check_mermaid -C docs/mkdocs # checks the Mermaid diagrams (requires Node.js) make check_mermaid -C docs/mkdocs # checks the Mermaid diagrams (requires Node.js)
``` ```
The search index of the docset is generated from [`mkdocs.yml`](https://github.com/nlohmann/json/blob/develop/docs/mkdocs/mkdocs.yml) A new API page also needs an entry in [`docs/docset/docSet.sql`](https://github.com/nlohmann/json/blob/develop/docs/docset/docSet.sql),
and each page's title (H1) and declaration by the search index of the docset; `make build` reports missing entries.
[`docs/docset/generate_docset.py`](https://github.com/nlohmann/json/blob/develop/docs/docset/generate_docset.py);
`make build` reports API pages that cannot be classified.
### Amalgamate the source code ### Amalgamate the source code
The single-header files The single-header files
[`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp), [`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) and
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp), and [`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
are **generated** from the source files in the are **generated** from the source files in the
[`include/nlohmann` directory](https://github.com/nlohmann/json/tree/develop/include/nlohmann). **Do not** edit the [`include/nlohmann` directory](https://github.com/nlohmann/json/tree/develop/include/nlohmann). **Do not** edit the
files directly; instead, modify the include/nlohmann sources and regenerate the files by executing: files directly; instead, modify the include/nlohmann sources and regenerate the files by executing:
@@ -182,7 +179,7 @@ The amalgamation check in CI fails if any of these generated files is out of dat
## Recommended documentation ## Recommended documentation
- The library’s [README file](https://github.com/nlohmann/json/blob/develop/README.md) is an excellent starting point to - The library’s [README file](https://github.com/nlohmann/json/blob/master/README.md) is an excellent starting point to
understand its functionality. understand its functionality.
- The [documentation page](https://json.nlohmann.me) is the reference documentation of the library. - The [documentation page](https://json.nlohmann.me) is the reference documentation of the library.
- [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) is the reference for the JavaScript Object Notation (JSON) - [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) is the reference for the JavaScript Object Notation (JSON)
@@ -221,9 +218,9 @@ feature macros then allows users to test their code against the library in the n
### Break C++11 language conformance ### Break C++11 language conformance
This library is designed to work with C++11 and later. This means that any This library is designed to work with C++11 and later. This means that any
[supported C++11 compiler](https://github.com/nlohmann/json/blob/develop/README.md#supported-compilers) should compile [supported C++11 compiler](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers) should compile
the library without problems. Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual the library without problems. Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual
C++ 2013 and earlier are known not to work due to missing or incomplete C++11 support. Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support.
Please do not add features that do not work with the mentioned supported compilers. Please guard features from C++14 and Please do not add features that do not work with the mentioned supported compilers. Please guard features from C++14 and
later against the respective [`JSON_HAS_CPP_14`](https://json.nlohmann.me/api/macros/json_has_cpp_11/) macros. later against the respective [`JSON_HAS_CPP_14`](https://json.nlohmann.me/api/macros/json_has_cpp_11/) macros.
@@ -239,11 +236,12 @@ extension.
The following areas really need contribution and are always welcomed: The following areas really need contribution and are always welcomed:
- Extending the **continuous integration** toward more exotic compilers such as Android NDK, Intel's Compiler, or the - Extending the **continuous integration** toward more exotic compilers such as Android NDK, Intel's Compiler, or the
bleeding-edge versions of Clang. bleeding-edge versions Clang.
- Improving the efficiency of the **JSON parser**. The current parser is a hand-written iterative parser that keeps an - Improving the efficiency of the **JSON parser**. The current parser is implemented as a naive recursive descent parser
explicit stack instead of recursing, with hand-coded string handling. Speeding up the lexer or the value construction with hand-coded string handling. More sophisticated approaches like LALR parsers would be really appreciated. That
would be appreciated. Parser generators like Bison or ANTLR do not play nice with single-header files -- I really said, parser generators like Bison or ANTLR do not play nice with single-header files -- I really would like to keep
would like to keep the parser inside the `json.hpp` header. the parser inside the `json.hpp` header, and I am not aware of approaches similar to [`re2c`](http://re2c.org) for
parsing.
- Extending and updating existing **benchmarks** to include (the most recent version of) this library. Though efficiency - Extending and updating existing **benchmarks** to include (the most recent version of) this library. Though efficiency
is not everything, speed and memory consumption are very important characteristics for C++ developers, so having is not everything, speed and memory consumption are very important characteristics for C++ developers, so having
proper comparisons would be interesting. proper comparisons would be interesting.
+2 -2
View File
@@ -52,7 +52,7 @@ body:
If possible, provide a small and self-contained example that triggers If possible, provide a small and self-contained example that triggers
the bug. Please understand that we cannot analyze and debug large code the bug. Please understand that we cannot analyze and debug large code
bases. Please do not paste screenshots here. bases. Please do not paste screenshots here.
render: cpp render: Shell
- type: textarea - type: textarea
id: output id: output
attributes: attributes:
@@ -79,7 +79,7 @@ body:
description: > description: >
Which version of the library did you use? If it is a released version, Which version of the library did you use? If it is a released version,
please enter the version number (e.g., 3.12.0). Otherwise, please enter please enter the version number (e.g., 3.12.0). Otherwise, please enter
the commit hash. If you got the library from another source than the the commit hash. If you got the library from another source as the
GitHub repository (e.g., via a package manager), please also state GitHub repository (e.g., via a package manager), please also state
this. this.
validations: validations:
+1 -8
View File
@@ -29,13 +29,6 @@ updates:
- dependency-name: mermaid - dependency-name: mermaid
update-types: ["version-update:semver-major"] update-types: ["version-update:semver-major"]
- package-ecosystem: pip
directory: /.github/requirements
schedule:
interval: daily
cooldown:
default-days: 7
- package-ecosystem: pip - package-ecosystem: pip
directory: /tools/astyle directory: /tools/astyle
schedule: schedule:
@@ -43,7 +36,7 @@ updates:
cooldown: cooldown:
default-days: 7 default-days: 7
ignore: ignore:
# astyle is deliberately pinned (see tools/astyle/requirements.in): newer versions # astyle is deliberately pinned (see tools/astyle/requirements.txt): newer versions
# reformat the code, and the pinned version defines the formatting CI enforces # reformat the code, and the pinned version defines the formatting CI enforces
- dependency-name: astyle - dependency-name: astyle
+2 -9
View File
@@ -18,8 +18,7 @@ environment:
matrix: matrix:
# The Visual Studio 2017 jobs compile everything with /std:c++17, so they # The Visual Studio 2017 jobs compile everything with /std:c++17, so they
# only build the C++17 variant of each test, split into two jobs each to # only build the C++17 variant of each test, split into two jobs each to
# stay below AppVeyor's 60-minute limit per job. The Visual Studio 2019 # stay below AppVeyor's 60-minute limit per job.
# job builds the tests for all standards and is split for the same reason.
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
configuration: Debug configuration: Debug
platform: x86 platform: x86
@@ -51,13 +50,7 @@ environment:
configuration: Release configuration: Release
platform: x86 platform: x86
CXX_FLAGS: "/W4 /WX" CXX_FLAGS: "/W4 /WX"
CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF -DJSON_TestShard=0/2" CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF"
GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
configuration: Release
platform: x86
CXX_FLAGS: "/W4 /WX"
CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF -DJSON_TestShard=1/2"
GENERATOR: Visual Studio 16 2019 GENERATOR: Visual Studio 16 2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
-30
View File
@@ -21,17 +21,6 @@ labels:
files: files:
- "cmake/.*" - "cmake/.*"
# other build systems
- label: "CMake"
files:
- "(meson\\.build|meson_options\\.txt|BUILD\\.bazel|MODULE\\.bazel|Package\\.swift)"
- label: "documentation"
files:
- ".github/ISSUE_TEMPLATE/.*"
- ".github/config\\.yml"
- ".github/(CONTRIBUTING|SECURITY|CODE_OF_CONDUCT|PULL_REQUEST_TEMPLATE)\\.md"
- label: "CI" - label: "CI"
files: files:
- ".github/workflows/.*" - ".github/workflows/.*"
@@ -56,25 +45,6 @@ labels:
- label: "aspect: binary formats" - label: "aspect: binary formats"
title: "(?i)(bson|cbor|msgpack|messagepack|ubjson|bjdata|bon8|binary format)" title: "(?i)(bson|cbor|msgpack|messagepack|ubjson|bjdata|bon8|binary format)"
- label: "aspect: json_view"
files:
- "include/nlohmann/json_view\\.hpp"
- "include/nlohmann/detail/view/.*"
- "single_include/nlohmann/json_view\\.hpp"
- "tests/src/unit-json_view.*"
- "tests/src/json_view_test_helpers\\.hpp"
- "tests/src/fuzzer-(parse_json_view|json_view_image)\\.cpp"
- "tests/benchmarks/json_view/.*"
- "tools/amalgamate/config_json_view\\.json"
- "docs/mkdocs/docs/features/json_view\\.md"
- "docs/mkdocs/docs/api/basic_json_(document|view)/.*"
- "docs/mkdocs/docs/api/(ordered_)?json_(editable_)?(document|view)\\.md"
- "docs/mkdocs/docs/examples/(basic_json_(document|view)__|(ordered_)?json_(editable_)?(document|view)).*"
- "tests/benchmarks/src/benchmarks_view\\.cpp"
- label: "aspect: json_view"
title: "(?i)(json_view|json_document|zero-copy)"
- label: "python" - label: "python"
files: files:
- "\\.py$" - "\\.py$"
-1
View File
@@ -1 +0,0 @@
meson==1.12.1
-10
View File
@@ -1,10 +0,0 @@
#
# This file is autogenerated by pip-compile with Python 3.14
# by the following command:
#
# pip-compile --generate-hashes --no-emit-index-url --output-file=.github/requirements/meson.txt --strip-extras .github/requirements/meson.in
#
meson==1.12.1 \
--hash=sha256:930bc7542cbd9f57009e182fd014eba48cf1a0180a7b9006d2d32d8f168d8b02 \
--hash=sha256:ab0a6ca09f8ef70c564c8241fb5a23957886a0b53fb58412b5e07eaf07dba743
# via -r .github/requirements/meson.in
-1
View File
@@ -1 +0,0 @@
semgrep==1.168.0
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+34 -52
View File
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -31,13 +31,13 @@ jobs:
mkdir -p ./pr mkdir -p ./pr
echo ${{ github.event.number }} > ./pr/number echo ${{ github.event.number }} > ./pr/number
echo ${{ github.event.pull_request.user.login }} > ./pr/author echo ${{ github.event.pull_request.user.login }} > ./pr/author
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: pr name: pr
path: pr/ path: pr/
check: check:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
env: env:
MAIN_DIR: ${{ github.workspace }}/main MAIN_DIR: ${{ github.workspace }}/main
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
@@ -46,7 +46,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -67,22 +67,24 @@ jobs:
- name: Install astyle - name: Install astyle
run: | run: |
python3 -mvenv venv python3 -mvenv venv
venv/bin/pip3 install --require-hashes -r $MAIN_DIR/tools/astyle/requirements.txt venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
- name: Install generate_natvis dependencies - name: Install generate_natvis dependencies
run: pip3 install --require-hashes -r $MAIN_DIR/tools/generate_natvis/requirements.txt run: pip3 install -r $NATVIS_TOOL_DIR/requirements.txt
- name: Regenerate the tools/macro_builder tables in macro_scope.hpp - name: Regenerate the tools/macro_builder tables in macro_scope.hpp
run: | run: |
cd $MAIN_DIR cd $MAIN_DIR
# Built from this PR's own tools/macro_builder/main.cpp, not a # Built from this PR's own tools/macro_builder/main.cpp, not a
# develop checkout: unlike amalgamate.py, this tool has no other # develop checkout: unlike amalgamate.py and generate_natvis.py,
# source of truth to check against (its own README documents that # this tool has no other source of truth to check against (its
# it must reproduce macro_scope.hpp byte for byte), so there is # own README documents that it must reproduce macro_scope.hpp
# nothing to gain from checking out a separate copy, and doing so # byte for byte), so there is nothing to gain from checking out a
# would make this step fail on a PR that adds support for a new # separate copy, and doing so would make this step fail on a PR
# dispatch table until that PR itself merges to develop. # that adds support for a new dispatch table until that PR itself
# merges to develop, the same way generate_natvis.py's --version
# requirement briefly did.
TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX) TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX)
c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder" c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder"
"$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp" "$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp"
@@ -115,15 +117,13 @@ jobs:
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s . python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s . python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
# the configuration of json_view.hpp comes with the pull request until cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
# it is on develop; the tool itself is still develop's
python3 $TOOL_DIR/amalgamate.py -c $MAIN_DIR/tools/amalgamate/config_json_view.json -s .
# the header list of the Bazel "json" target must match the files in include/ # the header list of the Bazel "json" target must match the files in include/
cmake -P cmake/scripts/gen_bazel_build_file.cmake cmake -P cmake/scripts/gen_bazel_build_file.cmake
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \ ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
$INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp $INCLUDE_DIR/json_view.hpp $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp
# fail loudly if a directory is renamed or removed: find would only warn # fail loudly if a directory is renamed or removed: find would only warn
# about the missing path and silently drop its files from the check # about the missing path and silently drop its files from the check
@@ -138,43 +138,25 @@ jobs:
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \ ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) $(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
# json_literals.hpp is copied verbatim from the (now formatted) include/
# directory, like `make amalgamate` does
cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
- name: Regenerate nlohmann_json.natvis - name: Regenerate nlohmann_json.natvis
run: | run: |
cd $MAIN_DIR cd $MAIN_DIR
# The generator and its template are what this check verifies the # Pass --version explicitly so this step also works with the tool
# committed natvis file against (which namespaces it lists, and # copy from develop before this repository's own generate_natvis.py
# what each entry looks like), so run this PR's copy rather than # learns to derive the version itself: the older script requires
# the develop checkout's: with develop's, a PR that changes either # --version, and the newer one accepts it as an explicit override.
# could never pass. generate_natvis.py loads the template from its ABI_MACROS=include/nlohmann/detail/abi_macros.hpp
# own directory. Like the macro_builder step above, this only runs VERSION_MAJOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MAJOR' $ABI_MACROS | grep -o '[0-9]\+')
# PR content in a job without credentials. VERSION_MINOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MINOR' $ABI_MACROS | grep -o '[0-9]\+')
python3 tools/generate_natvis/generate_natvis.py $MAIN_DIR VERSION_PATCH=$(grep -m1 'define NLOHMANN_JSON_VERSION_PATCH' $ABI_MACROS | grep -o '[0-9]\+')
# The template is what this check verifies the committed natvis
- name: Check the nlohmann_json.natvis generator options # file against, so take it from this PR rather than from the
run: | # develop checkout: generate_natvis.py loads the template from its
cd $MAIN_DIR # own directory, and with develop's copy a PR that changes the
# The options for configurations outside the checked-in file write # template could never pass. Like the macro_builder step above,
# to a temporary file, so they do not affect the diff below. # this only renders PR content in a job without credentials.
GENERATOR=tools/generate_natvis/generate_natvis.py cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
python3 $GENERATOR --list-tags python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
TAG_COUNT=$(python3 $GENERATOR --list-tags | wc -l)
python3 $GENERATOR --abi-tags diag,_dp,_vns --abi-tags _diag --output $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_vns -->' $RUNNER_TEMP/abi_tags.natvis
grep -q '<!-- Namespace nlohmann::json_abi_diag_dp_vns_v[0-9_]* -->' $RUNNER_TEMP/abi_tags.natvis
test $(grep -c '<!-- Namespace ' $RUNNER_TEMP/abi_tags.natvis) -eq $(( $(grep -c '<!-- Namespace ' nlohmann_json.natvis) + 2 ))
python3 $GENERATOR --all --output $RUNNER_TEMP/all.natvis
test $(grep -c '<!-- Namespace ' $RUNNER_TEMP/all.natvis) -eq $(( (1 << TAG_COUNT) * 2 + 1 ))
if python3 $GENERATOR --abi-tags _unknown --output $RUNNER_TEMP/unknown.natvis; then
echo "generate_natvis.py accepted an unknown ABI tag"
exit 1
fi
- name: Build patch and check for differences - name: Build patch and check for differences
id: diff id: diff
@@ -183,7 +165,7 @@ jobs:
mkdir -p ${{ github.workspace }}/patch mkdir -p ${{ github.workspace }}/patch
git diff --patch --no-color > ${{ github.workspace }}/patch/amalgamation.patch git diff --patch --no-color > ${{ github.workspace }}/patch/amalgamation.patch
if [ -s ${{ github.workspace }}/patch/amalgamation.patch ]; then if [ -s ${{ github.workspace }}/patch/amalgamation.patch ]; then
echo "The source code has not been amalgamated/formatted correctly, or BUILD.bazel, nlohmann_json.natvis, or the macro_builder tables in macro_scope.hpp are out of date ('make amalgamate BUILD.bazel natvis' fixes all but the tables, see tools/macro_builder/README.md). Diff:" echo "The source code has not been amalgamated/formatted correctly or BUILD.bazel is out of date. Diff:"
cat ${{ github.workspace }}/patch/amalgamation.patch cat ${{ github.workspace }}/patch/amalgamation.patch
echo "has_diff=true" >> "$GITHUB_OUTPUT" echo "has_diff=true" >> "$GITHUB_OUTPUT"
else else
@@ -194,7 +176,7 @@ jobs:
# instead of installing the pinned astyle version locally. # instead of installing the pinned astyle version locally.
- name: Upload patch - name: Upload patch
if: steps.diff.outputs.has_diff == 'true' if: steps.diff.outputs.has_diff == 'true'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: amalgamation-patch name: amalgamation-patch
path: patch/amalgamation.patch path: patch/amalgamation.patch
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -35,7 +35,7 @@ jobs:
dry-run: false dry-run: false
language: c++ language: c++
- name: Upload Crash - name: Upload Crash
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure() && steps.build.outcome == 'success' if: failure() && steps.build.outcome == 'success'
with: with:
name: artifacts name: artifacts
+5 -5
View File
@@ -21,13 +21,13 @@ permissions:
jobs: jobs:
CodeQL-Build: CodeQL-Build:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
permissions: permissions:
security-events: write security-events: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -38,14 +38,14 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with: with:
languages: c-cpp languages: c-cpp
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
@@ -20,7 +20,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -37,14 +37,6 @@ jobs:
var matchArtifact = artifacts.data.artifacts.filter((artifact) => { var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr" return artifact.name == "pr"
})[0]; })[0];
// a run that failed before its jobs started (e.g. a stale queued
// run cancelled long after its push) has no artifact to report on
if (!matchArtifact) {
core.notice('Run ${{ github.event.workflow_run.id }} has no "pr" artifact; nothing to comment on.');
core.setOutput('found', 'false');
return;
}
core.setOutput('found', 'true');
var download = await github.rest.actions.downloadArtifact({ var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
@@ -59,11 +51,9 @@ jobs:
# Extract the untrusted PR artifact into a dedicated empty directory and # Extract the untrusted PR artifact into a dedicated empty directory and
# read only the two expected files by fixed path afterwards. This avoids a # read only the two expected files by fixed path afterwards. This avoids a
# malicious archive overwriting workspace files or escaping via ../ paths. # malicious archive overwriting workspace files or escaping via ../ paths.
- if: steps.download.outputs.found == 'true' - run: unzip -o pr.zip -d ./pr_artifact
run: unzip -o pr.zip -d ./pr_artifact
- name: 'Comment on PR' - name: 'Comment on PR'
if: steps.download.outputs.found == 'true'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -106,7 +96,7 @@ jobs:
issue_number: issue_number, issue_number: issue_number,
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
body: '## 🔴 Amalgamation check failed! 🔴\nThe source code has not been amalgamated and/or formatted correctly, or `BUILD.bazel`, `nlohmann_json.natvis`, or the macro_builder tables in `macro_scope.hpp` are out of date. `make amalgamate BUILD.bazel natvis` fixes all but the tables (see `tools/macro_builder/README.md`).' body: '## 🔴 Amalgamation check failed! 🔴\nThe source code has not been amalgamated and/or formatted correctly, or `BUILD.bazel` is out of date.'
+ (hasPatch ? '\n\n📎 A ready-to-apply patch is attached to the [failed workflow run](' + runUrl + ') as the `amalgamation-patch` artifact.' + (hasPatch ? '\n\n📎 A ready-to-apply patch is attached to the [failed workflow run](' + runUrl + ') as the `amalgamation-patch` artifact.'
+ ' Download it, then apply it locally from the repository root with:' + ' Download it, then apply it locally from the repository root with:'
+ '\n\n```shell\ngit apply amalgamation.patch\n```\n\n' + '\n\n```shell\ngit apply amalgamation.patch\n```\n\n'
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+2 -2
View File
@@ -31,7 +31,7 @@ jobs:
security-events: write security-events: write
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -47,6 +47,6 @@ jobs:
output: 'flawfinder_results.sarif' output: 'flawfinder_results.sarif'
- name: Upload analysis results to GitHub Security tab - name: Upload analysis results to GitHub Security tab
uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with: with:
sarif_file: ${{github.workspace}}/flawfinder_results.sarif sarif_file: ${{github.workspace}}/flawfinder_results.sarif
@@ -1,84 +0,0 @@
name: "json_view benchmarks"
# On demand only: runs the comparison of json_view with yyjson, simdjson, and
# Boost.JSON (tests/benchmarks/json_view/compare.py) on GitHub-hosted runners,
# for numbers from x86-64 and AArch64 Linux. It runs when started by hand, or
# when a pull request gets the label "benchmark" (on both architectures, with
# GCC and the default settings). Shared runners are noisy: the results show
# where json_view stands, but published numbers need a quiet machine (see
# tests/benchmarks/json_view/README.md).
on:
pull_request:
types: [labeled]
workflow_dispatch:
inputs:
runner:
description: "Runner image"
type: choice
options:
- ubuntu-24.04
- ubuntu-24.04-arm
default: ubuntu-24.04
compiler:
description: "Compiler"
type: choice
options:
- g++
- clang++
default: g++
native:
description: "Compile for the runner's CPU (-march=native)"
type: boolean
default: false
rounds:
description: "Rounds of bench_view"
type: number
default: 30
permissions:
contents: read
concurrency:
# (the label is part of the group: adding an unrelated label must not cancel a running benchmark)
group: json-view-benchmarks-${{ github.workflow }}-${{ github.ref }}-${{ github.event.label.name }}
cancel-in-progress: true
jobs:
compare:
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'benchmark'
strategy:
matrix:
runner: ${{ fromJSON(github.event_name == 'workflow_dispatch' && format('["{0}"]', inputs.runner) || '["ubuntu-24.04", "ubuntu-24.04-arm"]') }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
steps:
- name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Download test data
run: |
cmake -S . -B build -DJSON_BuildTests=On
cmake --build build --target download_test_data
- name: Run the comparison
env:
CXX: ${{ inputs.compiler || 'g++' }}
CC: ${{ inputs.compiler == 'clang++' && 'clang' || 'gcc' }}
ROUNDS: ${{ inputs.rounds || 30 }}
NATIVE: ${{ inputs.native && '--native' || '' }}
run: python3 tests/benchmarks/json_view/compare.py --data build/test_files --download --rounds "$ROUNDS" $NATIVE
- name: Summary
run: cat tests/benchmarks/json_view/results/*.md >> "$GITHUB_STEP_SUMMARY"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: json_view-benchmarks-${{ matrix.runner }}-${{ inputs.compiler || 'g++' }}
path: tests/benchmarks/json_view/results/
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+1 -2
View File
@@ -15,7 +15,6 @@ on:
- .github/SECURITY.md - .github/SECURITY.md
- cmake/clang_flags.cmake - cmake/clang_flags.cmake
- cmake/gcc_flags.cmake - cmake/gcc_flags.cmake
- include/nlohmann/detail/abi_macros.hpp
- tests/fmt_formatter/project/main.cpp - tests/fmt_formatter/project/main.cpp
- tools/astyle/.astylerc - tools/astyle/.astylerc
workflow_dispatch: workflow_dispatch:
@@ -37,7 +36,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+4 -4
View File
@@ -40,7 +40,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -50,7 +50,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e # v2.5.0 uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@@ -72,7 +72,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@@ -80,6 +80,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with: with:
sarif_file: results.sarif sarif_file: results.sarif
+4 -4
View File
@@ -33,10 +33,10 @@ jobs:
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Scan name: Scan
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -53,7 +53,7 @@ jobs:
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a # SEMGREP_APP_TOKEN is still passed through so registry auth works if a
# token is ever added. # token is ever added.
- name: Install Semgrep - name: Install Semgrep
run: python3 -m pip install --user --require-hashes -r .github/requirements/semgrep.txt run: python3 -m pip install --user semgrep==1.168.0
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error # `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
# is a safety net so the SARIF upload still runs if the scan itself errors. # is a safety net so the SARIF upload still runs if the scan itself errors.
@@ -65,7 +65,7 @@ jobs:
# Upload SARIF file generated in previous step # Upload SARIF file generated in previous step
- name: Upload SARIF file - name: Upload SARIF file
uses: github/codeql-action/upload-sarif@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0 uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with: with:
sarif_file: semgrep.sarif sarif_file: semgrep.sarif
if: always() if: always()
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
+35 -36
View File
@@ -25,24 +25,24 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
run: cmake --build build --target ci_test_gcc run: cmake --build build --target ci_test_gcc
ci_meson_install: ci_meson_install:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Check that Meson and pkg-config offer the CMake options - name: Check that Meson and pkg-config offer the CMake options
run: make check_build_options run: make check_build_options
- name: Install Meson - name: Install Meson
run: pip install --require-hashes -r .github/requirements/meson.txt run: pip install meson
- name: Install with Meson - name: Install with Meson
run: | run: |
meson setup build-meson --prefix=${{ github.workspace }}/install meson setup build-meson --prefix=${{ github.workspace }}/install
@@ -77,10 +77,10 @@ jobs:
cmake --build build-import-split cmake --build build-import-split
ci_infer: ci_infer:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -92,38 +92,37 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
run: cmake --build build --target ci_infer run: cmake --build build --target ci_infer
- name: Archive Infer report - name: Archive Infer report
if: always() if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: infer-report name: infer-report
path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt
if-no-files-found: ignore if-no-files-found: ignore
ci_static_analysis_ubuntu: ci_static_analysis_ubuntu:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
target: [ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind] target: [ci_test_amalgamation, ci_test_single_header, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind]
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
- name: Install Valgrind - name: Install Valgrind
if: matrix.target == 'ci_test_valgrind'
run: sudo apt-get update ; sudo apt-get install -y valgrind run: sudo apt-get update ; sudo apt-get install -y valgrind
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -142,7 +141,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -168,17 +167,17 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
run: cmake --build build --target ${{ matrix.target }} run: cmake --build build --target ${{ matrix.target }}
ci_test_coverage: ci_test_coverage:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -197,7 +196,7 @@ jobs:
- name: Build - name: Build
run: cmake --build build --target ci_test_coverage run: cmake --build build --target ci_test_coverage
- name: Archive coverage report - name: Archive coverage report
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with: with:
name: code-coverage-report name: code-coverage-report
path: ${{ github.workspace }}/build/html path: ${{ github.workspace }}/build/html
@@ -244,7 +243,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -262,7 +261,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -279,8 +278,8 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10 - name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10
run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV" run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }} if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
- name: Run CMake - name: Run CMake
@@ -299,7 +298,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -319,7 +318,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build with libc++ - name: Build with libc++
@@ -346,7 +345,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -366,7 +365,7 @@ jobs:
# import-std support. Its opt-in token is CMake-version-specific, so pin # import-std support. Its opt-in token is CMake-version-specific, so pin
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. # CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
- name: Get pinned CMake and ninja - name: Get pinned CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
with: with:
cmakeVersion: 4.3.4 cmakeVersion: 4.3.4
# Clang: the std library module is provided by libc++ (the image's libstdc++ # Clang: the std library module is provided by libc++ (the image's libstdc++
@@ -392,7 +391,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -409,7 +408,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
@@ -423,17 +422,17 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DJSON_CI=On run: cmake -S . -B build -DJSON_CI=On
- name: Build - name: Build
run: cmake --build build --target ci_nvhpc run: cmake --build build --target ci_nvhpc
ci_emscripten: ci_emscripten:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -443,20 +442,20 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Run CMake - name: Run CMake
run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja
- name: Build - name: Build
run: cmake --build build run: cmake --build build
ci_test_documentation: ci_test_documentation:
runs-on: ubuntu-26.04 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid] target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid]
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@ccd8616d44fd3846e67624a50d5aad6d37bf2d25 # v2.22.1 uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
with: with:
egress-policy: audit egress-policy: audit
@@ -465,7 +464,7 @@ jobs:
persist-credentials: false persist-credentials: false
# the git-revision-date-localized plugin needs the history; a shallow clone makes the strict build fail # the git-revision-date-localized plugin needs the history; a shallow clone makes the strict build fail
fetch-depth: ${{ matrix.target == 'ci_test_build_documentation' && '0' || '1' }} fetch-depth: ${{ matrix.target == 'ci_test_build_documentation' && '0' || '1' }}
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
if: matrix.target == 'ci_test_documentation_mermaid' if: matrix.target == 'ci_test_documentation_mermaid'
with: with:
node-version: 24 node-version: 24
@@ -484,7 +483,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Check that the job runs natively on arm64 - name: Check that the job runs natively on arm64
run: uname -m && test "$(uname -m)" = aarch64 run: uname -m && test "$(uname -m)" = aarch64
- name: Run CMake - name: Run CMake
+5 -16
View File
@@ -90,7 +90,7 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Get latest CMake and ninja - name: Get latest CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
- name: Set extra CXX_FLAGS for latest std_version - name: Set extra CXX_FLAGS for latest std_version
# /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which # /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which
# specializes std::tuple (newly diagnosed by the VS2026 v145 toolset) # specializes std::tuple (newly diagnosed by the VS2026 v145 toolset)
@@ -166,21 +166,12 @@ jobs:
# link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash # link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash
# before doctest prints its first line - 39 of 102 tests on clang 18. # before doctest prints its first line - 39 of 102 tests on clang 18.
# Keep the objects small by splitting the test files instead. # Keep the objects small by splitting the test files instead.
# The tests link with LLD: GNU ld fails on objects with more than 32767
# sections with "relocation truncated to fit: IMAGE_REL_AMD64_REL32
# against `.rdata'", as it stores the section an associative COMDAT
# section belongs to in 16 bits (x_associated in binutils'
# include/coff/internal.h) and so discards the jump tables of inline
# functions together with the wrong function. Each basic_json
# specialization and input type a test file instantiates adds many
# sections, so unit-msgpack.cpp and unit-regression2.cpp kept crossing
# that limit as the library grew.
- name: Run CMake - name: Run CMake
run: cmake -S . -B build ^ run: cmake -S . -B build ^
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^ -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
-DCMAKE_CXX_FLAGS="--target=x86_64-w64-mingw32 -stdlib=libstdc++ -pthread" ^ -DCMAKE_CXX_FLAGS="--target=x86_64-w64-mingw32 -stdlib=libstdc++ -pthread" ^
-DCMAKE_CXX_FLAGS_DEBUG="-g0" ^ -DCMAKE_CXX_FLAGS_DEBUG="-g0" ^
-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld -lwinpthread" ^ -DCMAKE_EXE_LINKER_FLAGS="-lwinpthread" ^
-G"MinGW Makefiles" ^ -G"MinGW Makefiles" ^
-DCMAKE_BUILD_TYPE=Debug ^ -DCMAKE_BUILD_TYPE=Debug ^
-DJSON_BuildTests=On -DJSON_BuildTests=On
@@ -189,7 +180,7 @@ jobs:
- name: Test - name: Test
run: cd build ; ctest -j 10 -C Debug --output-on-failure run: cd build ; ctest -j 10 -C Debug --output-on-failure
clang-cl: clang-cl-12:
runs-on: windows-2022 runs-on: windows-2022
strategy: strategy:
matrix: matrix:
@@ -216,13 +207,11 @@ jobs:
# import-std support. Its opt-in token is CMake-version-specific, so pin # import-std support. Its opt-in token is CMake-version-specific, so pin
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt. # CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
- name: Get pinned CMake and ninja - name: Get pinned CMake and ninja
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4 uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
with: with:
cmakeVersion: 4.3.4 cmakeVersion: 4.3.4
# CMAKE_CXX_FLAGS replaces CMake's MSVC defaults (which include /EHsc), and
# ci_module_cpp20 forwards it to the module build, so list /EHsc explicitly
- name: Run CMake (Debug) - name: Run CMake (Debug)
run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_CI=ON -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /EHsc /W4 /WX" run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_CI=ON -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
- name: Build - name: Build
run: cmake --build build --config Debug --target ci_module_cpp20 run: cmake --build build --config Debug --target ci_module_cpp20
+1 -17
View File
@@ -27,6 +27,7 @@
/docs/docset/JSON_for_Modern_C++.tgz /docs/docset/JSON_for_Modern_C++.tgz
/docs/docset/docSet.dsidx /docs/docset/docSet.dsidx
/docs/mkdocs/.cache/ /docs/mkdocs/.cache/
/docs/mkdocs/docs/__pycache__/
/docs/mkdocs/hooks/__pycache__/ /docs/mkdocs/hooks/__pycache__/
/docs/mkdocs/scripts/mermaid/node_modules/ /docs/mkdocs/scripts/mermaid/node_modules/
/docs/mkdocs/site/ /docs/mkdocs/site/
@@ -46,20 +47,3 @@ nlohmann_json.spdx
# Bazel-related # Bazel-related
MODULE.bazel.lock MODULE.bazel.lock
# backups left by `make check-amalgamation` or the ci_test_amalgamation target if they are interrupted
/BUILD.bazel~
/nlohmann_json.natvis~
/single_include/nlohmann/*.hpp~
/venv_astyle/
# release outputs of `make release`
/include.zip
/include.zip.asc
/json.tar.xz
/json.tar.xz.asc
/release_files/
/single_include/nlohmann/*.asc
# GCC module cache
/gcm.cache/
-4
View File
@@ -1,7 +1,6 @@
{ {
"_comment": "Used by the ci_infer CMake target (#5715 item 4b). fail-on-issue makes CI fail on Infer findings; disable-issue-type is a type-level baseline for the ~174 pre-existing findings (all PULSE_UNNECESSARY_COPY*/PULSE_RESOURCE_LEAK/PULSE_CONST_REFABLE, mostly in test code) triaged in run https://github.com/nlohmann/json/actions/runs/35829411620 on commit 1054b2097, so CI fails only on a NEW issue type. Remove an entry here once its findings have been fixed or explicitly accepted.", "_comment": "Used by the ci_infer CMake target (#5715 item 4b). fail-on-issue makes CI fail on Infer findings; disable-issue-type is a type-level baseline for the ~174 pre-existing findings (all PULSE_UNNECESSARY_COPY*/PULSE_RESOURCE_LEAK/PULSE_CONST_REFABLE, mostly in test code) triaged in run https://github.com/nlohmann/json/actions/runs/35829411620 on commit 1054b2097, so CI fails only on a NEW issue type. Remove an entry here once its findings have been fixed or explicitly accepted.",
"_comment_pulse": "Pulse stops exploring paths after pulse-max-disjuncts (default 20). With the default, basic_json::replace_value() (destroy + assert_invariant) exceeds the limit, Pulse loses the stored type, and reports false NULLPTR_DEREFERENCE findings for get_ptr() results in tests/src/unit-pointer_access.cpp.", "_comment_pulse": "Pulse stops exploring paths after pulse-max-disjuncts (default 20). With the default, basic_json::replace_value() (destroy + assert_invariant) exceeds the limit, Pulse loses the stored type, and reports false NULLPTR_DEREFERENCE findings for get_ptr() results in tests/src/unit-pointer_access.cpp.",
"_comment_view": "Infer's model of std::unique_ptr mixes up values that are returned by value and own one: basic_json_document (parse() results) and the `built` values of the build() helper in tests/src/unit-json_view_builder.cpp. It reports USE_AFTER_DELETE for one of them after the destructor of an unrelated object (e.g. ~built() on line 345 invalidating `shallow` on line 350 of that file, or two documents parsed in one lambda in tests/src/unit-json_view_dump.cpp). AddressSanitizer and Valgrind are clean on the same tests, so reports for the json_view test files are excluded; findings reported in the library headers are still reported.",
"pulse-max-disjuncts": 40, "pulse-max-disjuncts": 40,
"fail-on-issue": true, "fail-on-issue": true,
"disable-issue-type": [ "disable-issue-type": [
@@ -11,8 +10,5 @@
"PULSE_UNNECESSARY_COPY_OPTIONAL", "PULSE_UNNECESSARY_COPY_OPTIONAL",
"PULSE_RESOURCE_LEAK", "PULSE_RESOURCE_LEAK",
"PULSE_CONST_REFABLE" "PULSE_CONST_REFABLE"
],
"report-block-list-path-regex": [
"tests/src/unit-json_view.*\\.cpp"
] ]
} }
-28
View File
@@ -20,13 +20,11 @@ cc_library(
hdrs = [ hdrs = [
"include/nlohmann/adl_serializer.hpp", "include/nlohmann/adl_serializer.hpp",
"include/nlohmann/byte_container_with_subtype.hpp", "include/nlohmann/byte_container_with_subtype.hpp",
"include/nlohmann/detail/abi_config.hpp",
"include/nlohmann/detail/abi_macros.hpp", "include/nlohmann/detail/abi_macros.hpp",
"include/nlohmann/detail/bit_ops.hpp", "include/nlohmann/detail/bit_ops.hpp",
"include/nlohmann/detail/conversions/from_json.hpp", "include/nlohmann/detail/conversions/from_json.hpp",
"include/nlohmann/detail/conversions/to_chars.hpp", "include/nlohmann/detail/conversions/to_chars.hpp",
"include/nlohmann/detail/conversions/to_json.hpp", "include/nlohmann/detail/conversions/to_json.hpp",
"include/nlohmann/detail/conversions/zmij.hpp",
"include/nlohmann/detail/exceptions.hpp", "include/nlohmann/detail/exceptions.hpp",
"include/nlohmann/detail/hash.hpp", "include/nlohmann/detail/hash.hpp",
"include/nlohmann/detail/input/binary_reader.hpp", "include/nlohmann/detail/input/binary_reader.hpp",
@@ -37,7 +35,6 @@ cc_library(
"include/nlohmann/detail/input/parser.hpp", "include/nlohmann/detail/input/parser.hpp",
"include/nlohmann/detail/input/position_t.hpp", "include/nlohmann/detail/input/position_t.hpp",
"include/nlohmann/detail/input/pow5_table.hpp", "include/nlohmann/detail/input/pow5_table.hpp",
"include/nlohmann/detail/input/simd_scan.hpp",
"include/nlohmann/detail/input/string_scan.hpp", "include/nlohmann/detail/input/string_scan.hpp",
"include/nlohmann/detail/iterators/internal_iterator.hpp", "include/nlohmann/detail/iterators/internal_iterator.hpp",
"include/nlohmann/detail/iterators/iter_impl.hpp", "include/nlohmann/detail/iterators/iter_impl.hpp",
@@ -68,32 +65,9 @@ cc_library(
"include/nlohmann/detail/string_escape.hpp", "include/nlohmann/detail/string_escape.hpp",
"include/nlohmann/detail/string_utils.hpp", "include/nlohmann/detail/string_utils.hpp",
"include/nlohmann/detail/value_t.hpp", "include/nlohmann/detail/value_t.hpp",
"include/nlohmann/detail/view/builder.hpp",
"include/nlohmann/detail/view/compare.hpp",
"include/nlohmann/detail/view/document_data.hpp",
"include/nlohmann/detail/view/edit.hpp",
"include/nlohmann/detail/view/edit_storage.hpp",
"include/nlohmann/detail/view/errors.hpp",
"include/nlohmann/detail/view/image.hpp",
"include/nlohmann/detail/view/input.hpp",
"include/nlohmann/detail/view/iterator.hpp",
"include/nlohmann/detail/view/lookup.hpp",
"include/nlohmann/detail/view/macro_scope.hpp",
"include/nlohmann/detail/view/macro_unscope.hpp",
"include/nlohmann/detail/view/materialize.hpp",
"include/nlohmann/detail/view/node.hpp",
"include/nlohmann/detail/view/number.hpp",
"include/nlohmann/detail/view/object_index.hpp",
"include/nlohmann/detail/view/pointer.hpp",
"include/nlohmann/detail/view/scan.hpp",
"include/nlohmann/detail/view/serializer.hpp",
"include/nlohmann/detail/view/simd.hpp",
"include/nlohmann/detail/view/string_ref.hpp",
"include/nlohmann/detail/view/value.hpp",
"include/nlohmann/json.hpp", "include/nlohmann/json.hpp",
"include/nlohmann/json_fwd.hpp", "include/nlohmann/json_fwd.hpp",
"include/nlohmann/json_literals.hpp", "include/nlohmann/json_literals.hpp",
"include/nlohmann/json_view.hpp",
"include/nlohmann/ordered_map.hpp", "include/nlohmann/ordered_map.hpp",
"include/nlohmann/thirdparty/hedley/hedley.hpp", "include/nlohmann/thirdparty/hedley/hedley.hpp",
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp", "include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
@@ -107,8 +81,6 @@ cc_library(
hdrs = [ hdrs = [
"single_include/nlohmann/json.hpp", "single_include/nlohmann/json.hpp",
"single_include/nlohmann/json_fwd.hpp", "single_include/nlohmann/json_fwd.hpp",
"single_include/nlohmann/json_literals.hpp",
"single_include/nlohmann/json_view.hpp",
], ],
includes = ["single_include"], includes = ["single_include"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
+1 -1
View File
@@ -8,7 +8,7 @@ authors:
website: https://nlohmann.me website: https://nlohmann.me
title: "JSON for Modern C++" title: "JSON for Modern C++"
version: 3.12.0 version: 3.12.0
date-released: 2025-04-11 date-released: 2025-04-07
license: MIT license: MIT
repository-code: "https://github.com/nlohmann/json" repository-code: "https://github.com/nlohmann/json"
url: https://json.nlohmann.me url: https://json.nlohmann.me
+1 -1
View File
@@ -30,7 +30,7 @@ endif ()
option(NLOHMANN_JSON_BUILD_MODULES "Build C++ modules support" OFF) option(NLOHMANN_JSON_BUILD_MODULES "Build C++ modules support" OFF)
if(NLOHMANN_JSON_BUILD_MODULES) if(NLOHMANN_JSON_BUILD_MODULES)
if(NOT CMAKE_VERSION VERSION_LESS 3.28) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
message(STATUS "Building nlohmann.json C++ module") message(STATUS "Building nlohmann.json C++ module")
add_subdirectory(src/modules) add_subdirectory(src/modules)
else() else()
+4 -34
View File
@@ -6,7 +6,6 @@ This file describes the source for supporting files; that is, files that are not
- [GitHub](#github) - [GitHub](#github)
- [REUSE](#reuse) - [REUSE](#reuse)
- [Package Managers](#package-managers) - [Package Managers](#package-managers)
- [Debugging](#debugging)
## Continuous Integration ## Continuous Integration
@@ -15,7 +14,7 @@ This file describes the source for supporting files; that is, files that are not
The [GitHub Actions](https://docs.github.com/en/actions) workflows that build, test, and analyze the library. Each file in this folder defines one workflow: The [GitHub Actions](https://docs.github.com/en/actions) workflows that build, test, and analyze the library. Each file in this folder defines one workflow:
- `ubuntu.yml`, `macos.yml`, `windows.yml` — build and run the test suite on Linux, macOS, and Windows. - `ubuntu.yml`, `macos.yml`, `windows.yml` — build and run the test suite on Linux, macOS, and Windows.
- `check_amalgamation.yml` — verify on pull requests and pushes to `develop` that the generated files (the single-header amalgamation in `single_include`, `BUILD.bazel`, and `nlohmann_json.natvis`) are up to date. - `check_amalgamation.yml` — verify that the single-header amalgamation in `single_include` is up to date on pull requests.
- `comment_check_amalgamation.yml` — comment on a pull request when the amalgamation check failed. - `comment_check_amalgamation.yml` — comment on a pull request when the amalgamation check failed.
- `cifuzz.yml` — run short fuzzing sessions via [OSS-Fuzz CIFuzz](https://google.github.io/oss-fuzz/getting-started/continuous-integration/) on pull requests. - `cifuzz.yml` — run short fuzzing sessions via [OSS-Fuzz CIFuzz](https://google.github.io/oss-fuzz/getting-started/continuous-integration/) on pull requests.
- `codeql-analysis.yml` — run [CodeQL](https://codeql.github.com) code scanning. - `codeql-analysis.yml` — run [CodeQL](https://codeql.github.com) code scanning.
@@ -25,9 +24,7 @@ The [GitHub Actions](https://docs.github.com/en/actions) workflows that build, t
- `dependency-review.yml` — scan dependency changes in pull requests for known vulnerabilities. - `dependency-review.yml` — scan dependency changes in pull requests for known vulnerabilities.
- `labeler.yml` — the "Pull Request Labeler" workflow (see `.github/labeler.yml`). - `labeler.yml` — the "Pull Request Labeler" workflow (see `.github/labeler.yml`).
- `stale.yml` — comment on and close stale issues and pull requests. - `stale.yml` — comment on and close stale issues and pull requests.
- `publish_documentation.yml` — build and publish the documentation on pushes to the `develop` branch that touch the documentation sources (or the files it embeds). - `publish_documentation.yml` — build and publish the documentation on every merge to the `develop` branch.
- `check_docs_links.yml` — check the links of the documentation weekly, as external links can break without any change in this repository.
- `cancel_closed_pr_runs.yml` — cancel unfinished workflow runs of a pull request once it is closed or merged.
Further documentation: Further documentation:
@@ -269,9 +266,8 @@ meson setup builddir
ninja -C builddir ninja -C builddir
``` ```
`meson_options.txt` defines the options, which mirror the names of the CMake options that change the library's target (for example, `meson_options.txt` defines the options, which mirror the CMake options that change the library's target (for example,
`-DDiagnostics=true`); their defaults may differ (for example, `MultipleHeaders` defaults to `false` in Meson, while `-DDiagnostics=true`). Meson requires this file next to `meson.build`, so it is also part of `include.zip`. `make check_build_options`
`JSON_MultipleHeaders` is `ON` in CMake). Meson requires this file next to `meson.build`, so it is also part of `include.zip`. `make check_build_options`
([`tools/check_build_options`](tools/check_build_options/README.md)) checks in CI that both files and the pkg-config files ([`tools/check_build_options`](tools/check_build_options/README.md)) checks in CI that both files and the pkg-config files
stay in sync with the CMake options. stay in sync with the CMake options.
@@ -290,29 +286,3 @@ The module definition for [Bazel](https://bazel.build)'s [Bzlmod](https://bazel.
Further documentation: Further documentation:
- [Bazel modules](https://bazel.build/external/module) - [Bazel modules](https://bazel.build/external/module)
## Debugging
### `nlohmann_json.natvis`
The [Natvis](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects) file that
gives `json` values a friendly view in the Visual Studio debugger. The file is generated by
`tools/generate_natvis/generate_natvis.py` from the template `tools/generate_natvis/nlohmann_json.natvis.j2` and the ABI
tags and version in `include/nlohmann/detail/abi_macros.hpp`; change the script or the template rather than editing
the file by hand. The file can be updated by calling
```shell
make natvis
```
The "Check amalgamation" workflow fails if the file is out of date.
The file covers the namespace variants with up to two ABI tags. A Natvis file for other configurations can be
generated with the `--abi-tags` or `--all` options, for example
`make natvis NATVIS_ARGS="--abi-tags _diag,_dp,_vns --output my_nlohmann_json.natvis"`; see
[`tools/generate_natvis`](tools/generate_natvis/README.md). With MSVC, CMake adds the file to the `nlohmann_json`
target and installs it.
Further documentation:
- [Create custom views of C++ objects in the debugger using the Natvis framework](https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects)
-1
View File
@@ -1,6 +1,5 @@
module( module(
name = "nlohmann_json", name = "nlohmann_json",
version = "3.12.0",
compatibility_level = 1, compatibility_level = 1,
) )
+32 -52
View File
@@ -1,4 +1,4 @@
.PHONY: all amalgamate check-amalgamation check_build_options pretty install_astyle clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check run_benchmarks pvs_studio serve_header reuse spdx .PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check check_build_options
########################################################################## ##########################################################################
# configuration # configuration
@@ -26,7 +26,6 @@ AMALGAMATED_FILE=single_include/nlohmann/json.hpp
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
# json_literals.hpp only includes <nlohmann/json.hpp>, so it is copied verbatim # json_literals.hpp only includes <nlohmann/json.hpp>, so it is copied verbatim
AMALGAMATED_LITERALS_FILE=single_include/nlohmann/json_literals.hpp AMALGAMATED_LITERALS_FILE=single_include/nlohmann/json_literals.hpp
AMALGAMATED_VIEW_FILE=single_include/nlohmann/json_view.hpp
# the header with the argument-counting macros generated by tools/macro_builder # the header with the argument-counting macros generated by tools/macro_builder
MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp
@@ -38,22 +37,16 @@ MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp
# main target # main target
all: all:
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals,_view}.hpp from the include/nlohmann sources" @echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals}.hpp from the include/nlohmann sources"
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources" @echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
@echo "ChangeLog.md - generate ChangeLog file" @echo "ChangeLog.md - generate ChangeLog file"
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date" @echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
@echo "check_build_options - check that the Meson build and the pkg-config files offer the options of the CMake target"
@echo "clean - remove built files" @echo "clean - remove built files"
@echo "(fuzzers) - see tests/fuzzing.md, or run 'make -C tests fuzzers' to build the AFL fuzzers" @echo "fuzzing - see tests/fuzzing.md for how to build and run the fuzzers"
@echo "macro_builder_check - check that macro_scope.hpp matches tools/macro_builder's output" @echo "macro_builder_check - check that macro_scope.hpp matches tools/macro_builder's output"
@echo "natvis - regenerate nlohmann_json.natvis from the current ABI tags and version (pass generator options via NATVIS_ARGS, see tools/generate_natvis/README.md)" @echo "natvis - regenerate nlohmann_json.natvis from the current ABI tags and version"
@echo "pretty - beautify code with Artistic Style" @echo "pretty - beautify code with Artistic Style"
@echo "pvs_studio - run the PVS-Studio static analyzer and open the report"
@echo "release - create the release files (include.zip, json.tar.xz, single headers, signatures, hashes)"
@echo "reuse - annotate the source files with REUSE license headers and lint them"
@echo "run_benchmarks - build and run benchmarks" @echo "run_benchmarks - build and run benchmarks"
@echo "serve_header - serve the single header, re-amalgamated on demand (see tools/serve_header)"
@echo "spdx - generate the SPDX software bill of materials nlohmann_json.spdx"
@echo "update_hedley - download Hedley and regenerate hedley.hpp / hedley_undef.hpp" @echo "update_hedley - download Hedley and regenerate hedley.hpp / hedley_undef.hpp"
@echo "update_hedley_undef - rebuild hedley_undef.hpp from the JSON_HEDLEY_* #define names in hedley.hpp" @echo "update_hedley_undef - rebuild hedley_undef.hpp from the JSON_HEDLEY_* #define names in hedley.hpp"
@@ -97,10 +90,10 @@ install_astyle:
# call the Artistic Style pretty printer on all source files # call the Artistic Style pretty printer on all source files
pretty: install_astyle pretty: install_astyle
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE) docs/mkdocs/docs/examples/*.cpp docs/mkdocs/docs/examples/*.hpp $(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp docs/mkdocs/docs/examples/*.hpp
# create single header files and pretty print # create single header files and pretty print
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE) amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE)
$(MAKE) pretty $(MAKE) pretty
# call the amalgamation tool for json.hpp # call the amalgamation tool for json.hpp
@@ -115,24 +108,13 @@ $(AMALGAMATED_FWD_FILE): $(SRCS)
$(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp
cp include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE) cp include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE)
# call the amalgamation tool for json_view.hpp (keeps including json.hpp)
$(AMALGAMATED_VIEW_FILE): $(SRCS)
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_view.json -s . --verbose=yes
NATVIS_VENV=tools/generate_natvis/venv
# extra options for generate_natvis.py, e.g. NATVIS_ARGS="--abi-tags _diag,_dp,_vns --output my.natvis"
NATVIS_ARGS=
# regenerate nlohmann_json.natvis from the ABI tags and version in include/nlohmann/detail/abi_macros.hpp # regenerate nlohmann_json.natvis from the ABI tags and version in include/nlohmann/detail/abi_macros.hpp
# (the dependencies are installed into a virtual environment first)
natvis: natvis:
@test -d $(NATVIS_VENV) || python3 -mvenv $(NATVIS_VENV) python3 tools/generate_natvis/generate_natvis.py .
@$(NATVIS_VENV)/bin/python3 -c 'import jinja2' 2>/dev/null || $(NATVIS_VENV)/bin/pip3 install --quiet -r tools/generate_natvis/requirements.txt
$(NATVIS_VENV)/bin/python3 tools/generate_natvis/generate_natvis.py $(NATVIS_ARGS) .
# regenerate the two tools/macro_builder blocks of $(MACRO_SCOPE_HPP) (see its README.md) and diff against the # regenerate the two tools/macro_builder blocks of $(MACRO_SCOPE_HPP) (see its README.md) and diff against the
# checked-in header; phony, because it never writes $(MACRO_SCOPE_HPP) itself # checked-in header; phony, because it never writes $(MACRO_SCOPE_HPP) itself
macro_builder_check: install_astyle macro_builder_check:
@set -e; \ @set -e; \
TMPDIR=$$(mktemp -d ./macro_builder_check.XXXXXX); \ TMPDIR=$$(mktemp -d ./macro_builder_check.XXXXXX); \
trap 'rm -rf "$$TMPDIR"' EXIT; \ trap 'rm -rf "$$TMPDIR"' EXIT; \
@@ -149,27 +131,27 @@ macro_builder_check: install_astyle
check_build_options: check_build_options:
python3 tools/check_build_options/check_build_options.py . python3 tools/check_build_options/check_build_options.py .
# check if the single headers have been amalgamated from the nlohmann sources and if BUILD.bazel and # check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
# nlohmann_json.natvis are up to date; all checks are run, and the checked-in files are always restored
check-amalgamation: check-amalgamation:
@status=0; \ @mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
banner() { printf '===================================================================\n %s\n===================================================================\n' "$$1"; }; \ @mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE) BUILD.bazel nlohmann_json.natvis; do \ @mv $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~
mv "$$FILE" "$$FILE~" || exit 1; \ @$(MAKE) amalgamate
done; \ @diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
$(MAKE) amalgamate || status=1; \ @diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
$(MAKE) BUILD.bazel || status=1; \ @diff $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE) ; false)
$(MAKE) natvis || status=1; \ @mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE); do \ @mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
diff "$$FILE" "$$FILE~" || { banner "$$FILE is out of date! Amalgamation required! Please read the contribution guidelines in file .github/CONTRIBUTING.md."; status=1; }; \ @mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE)
done; \ @mv BUILD.bazel BUILD.bazel~
diff BUILD.bazel BUILD.bazel~ || { banner "BUILD.bazel is out of date! Please run 'make BUILD.bazel'."; status=1; }; \ @$(MAKE) BUILD.bazel
diff nlohmann_json.natvis nlohmann_json.natvis~ || { banner "nlohmann_json.natvis is out of date! Please run 'make natvis'."; status=1; }; \ @diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE) BUILD.bazel nlohmann_json.natvis; do \ @mv BUILD.bazel~ BUILD.bazel
mv "$$FILE~" "$$FILE"; \ @mv nlohmann_json.natvis nlohmann_json.natvis~
done; \ @$(MAKE) natvis
$(MAKE) macro_builder_check || status=1; \ @diff nlohmann_json.natvis nlohmann_json.natvis~ || (echo "===================================================================\n nlohmann_json.natvis is out of date! Please run 'make natvis'.\n===================================================================" ; mv nlohmann_json.natvis~ nlohmann_json.natvis ; false)
exit $$status @mv nlohmann_json.natvis~ nlohmann_json.natvis
@$(MAKE) macro_builder_check
# generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild # generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild
BUILD.bazel: BUILD.bazel:
@@ -206,7 +188,7 @@ json.tar.xz:
# We use `-X` to make the resulting ZIP file reproducible, see # We use `-X` to make the resulting ZIP file reproducible, see
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>. # <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
include.zip: BUILD.bazel include.zip: BUILD.bazel
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_VIEW_FILE) BUILD.bazel MODULE.bazel meson.build meson_options.txt LICENSE.MIT zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build meson_options.txt LICENSE.MIT
# Create the files for a release and add signatures and hashes. # Create the files for a release and add signatures and hashes.
release: include.zip json.tar.xz release: include.zip json.tar.xz
@@ -216,13 +198,11 @@ release: include.zip json.tar.xz
gpg --armor --detach-sig $(AMALGAMATED_FILE) gpg --armor --detach-sig $(AMALGAMATED_FILE)
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE) gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
gpg --armor --detach-sig $(AMALGAMATED_LITERALS_FILE) gpg --armor --detach-sig $(AMALGAMATED_LITERALS_FILE)
gpg --armor --detach-sig $(AMALGAMATED_VIEW_FILE)
gpg --armor --detach-sig json.tar.xz gpg --armor --detach-sig json.tar.xz
cp $(AMALGAMATED_FILE) release_files cp $(AMALGAMATED_FILE) release_files
cp $(AMALGAMATED_FWD_FILE) release_files cp $(AMALGAMATED_FWD_FILE) release_files
cp $(AMALGAMATED_LITERALS_FILE) release_files cp $(AMALGAMATED_LITERALS_FILE) release_files
cp $(AMALGAMATED_VIEW_FILE) release_files mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc $(AMALGAMATED_LITERALS_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc $(AMALGAMATED_LITERALS_FILE).asc $(AMALGAMATED_VIEW_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
cd release_files ; shasum -a 256 $$(find . -type f -not -name '*.asc' | sed 's|^\./||' | sort) > hashes.txt cd release_files ; shasum -a 256 $$(find . -type f -not -name '*.asc' | sed 's|^\./||' | sort) > hashes.txt
@@ -232,8 +212,8 @@ release: include.zip json.tar.xz
# clean up # clean up
clean: clean:
rm -fr *.dSYM tests/*.dSYM tests/parse_*_fuzzer rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM
rm -fr cmake-build-benchmarks cmake-build-pvs-studio release_files rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
$(MAKE) clean -Cdocs $(MAKE) clean -Cdocs
+458 -459
View File
File diff suppressed because it is too large. Load diff
+2 -8
View File
@@ -10,10 +10,10 @@ SPDX-FileCopyrightText = "2013-2026 Niels Lohmann <https://nlohmann.me>"
SPDX-License-Identifier = "MIT" SPDX-License-Identifier = "MIT"
[[annotations]] [[annotations]]
path = "include/nlohmann/thirdparty/hedley/hedley.hpp" path = "include/nlohmann/thirdparty/hedley.hpp"
precedence = "aggregate" precedence = "aggregate"
SPDX-FileCopyrightText = "2016-2021 Evan Nemerson <evan@nemerson.com>" SPDX-FileCopyrightText = "2016-2021 Evan Nemerson <evan@nemerson.com>"
SPDX-License-Identifier = "CC0-1.0" SPDX-License-Identifier = "CC0"
[[annotations]] [[annotations]]
path = "include/nlohmann/detail/meta/cpp_future.hpp" path = "include/nlohmann/detail/meta/cpp_future.hpp"
@@ -50,9 +50,3 @@ path = "tools/gdb_pretty_printer/**"
precedence = "aggregate" precedence = "aggregate"
SPDX-FileCopyrightText = "2020 Hannes Domani <https://github.com/ssbssa>" SPDX-FileCopyrightText = "2020 Hannes Domani <https://github.com/ssbssa>"
SPDX-License-Identifier = "MIT" SPDX-License-Identifier = "MIT"
[[annotations]]
path = "docs/docset/icon*.png"
precedence = "override"
SPDX-FileCopyrightText = "JSON logo (public domain), https://commons.wikimedia.org/wiki/File:JSON_vector_logo.svg"
SPDX-License-Identifier = "CC0-1.0"
+27 -46
View File
@@ -5,14 +5,15 @@ set(N 10)
# Needed tools. # Needed tools.
############################################################################### ###############################################################################
include(FindPython3)
find_package(Python3 COMPONENTS Interpreter) find_package(Python3 COMPONENTS Interpreter)
find_program(CLANG_TOOL NAMES clang++ clang++-HEAD clang++-22 clang++-21 clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11) find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-22 clang++-21 clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION) execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})") message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
find_program(CLANG_TIDY_TOOL NAMES clang-tidy clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11) find_program(CLANG_TIDY_TOOL NAMES clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION) execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}") string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})") message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
@@ -68,7 +69,9 @@ string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_V
message(STATUS "🔖 Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})") message(STATUS "🔖 Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})")
find_program(GENHTML_TOOL NAMES genhtml) find_program(GENHTML_TOOL NAMES genhtml)
find_program(SCAN_BUILD_TOOL NAMES scan-build scan-build-22 scan-build-21 scan-build-20 scan-build-19 scan-build-18 scan-build-17 scan-build-16 scan-build-15 scan-build-14 scan-build-13 scan-build-12 scan-build-11) find_program(PLOG_CONVERTER_TOOL NAMES plog-converter)
find_program(PVS_STUDIO_ANALYZER_TOOL NAMES pvs-studio-analyzer)
find_program(SCAN_BUILD_TOOL NAMES scan-build-15 scan-build-14 scan-build-13 scan-build-12 scan-build-11 scan-build)
# the individual source files # the individual source files
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp) file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
@@ -361,10 +364,10 @@ add_custom_target(ci_test_coverage
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32 COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32
COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc branch_coverage=1 --rc geninfo_unexecuted_blocks=1 --ignore-errors mismatch --ignore-errors unused --ignore-errors inconsistent COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc branch_coverage=1 --rc geninfo_unexecuted_blocks=1 --ignore-errors mismatch --ignore-errors unused
COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc branch_coverage=1 --ignore-errors unused --ignore-errors inconsistent COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc branch_coverage=1 --ignore-errors unused
COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept
COMMAND ${GENHTML_TOOL} --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage --ignore-errors inconsistent json.info.filtered.noexcept COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept
COMMENT "Compile and test with coverage" COMMENT "Compile and test with coverage"
) )
@@ -389,8 +392,8 @@ add_custom_target(ci_test_clang_sanitizer
# Check if header is amalgamated and sources are properly indented. # Check if header is amalgamated and sources are properly indented.
############################################################################### ###############################################################################
# Same file set as .github/workflows/check_amalgamation.yml, so this CMake target (which can be run locally) is held # Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
# to the same standard as the workflow (which runs for pull requests and for pushes to develop/master/release/*). # (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
file(GLOB_RECURSE INDENT_FILES file(GLOB_RECURSE INDENT_FILES
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp ${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp ${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
@@ -407,11 +410,10 @@ list(FILTER INDENT_FILES EXCLUDE REGEX "/tests/thirdparty/|/tests/abi/include/nl
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann) set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate) set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
add_custom_target(ci_test_amalgamation add_custom_target(ci_test_amalgamation
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~ ${include_dir}/json_view.hpp~ COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~ COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~ COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~ COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
COMMAND cp ${include_dir}/json_view.hpp ${include_dir}/json_view.hpp~
COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~ COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
@@ -421,21 +423,17 @@ add_custom_target(ci_test_amalgamation
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s . COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s . COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_view.json -s . COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp ${include_dir}/json_literals.hpp ${include_dir}/json_view.hpp
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
COMMAND diff ${include_dir}/json_view.hpp~ ${include_dir}/json_view.hpp
COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES} COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
COMMAND rm -f ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~ ${include_dir}/json_view.hpp~ ${PROJECT_SOURCE_DIR}/BUILD.bazel~
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Check amalgamation, formatting, and BUILD.bazel" COMMENT "Check amalgamation, formatting, and BUILD.bazel"
) )
@@ -488,13 +486,6 @@ add_custom_target(ci_clang_analyze
# Check code with Cppcheck. # Check code with Cppcheck.
############################################################################### ###############################################################################
# default_defines.hpp expands the Hedley macros to the compiler's feature-test operators, which Cppcheck does not know.
# Since Cppcheck 2.20, it rejects their invocations in #if conditions instead of evaluating them as 0.
file(WRITE ${CMAKE_BINARY_DIR}/cppcheck_feature_tests.hpp "")
foreach(OPERATOR __has_attribute __has_builtin __has_cpp_attribute __has_declspec_attribute __has_extension __has_feature __has_include __has_warning)
file(APPEND ${CMAKE_BINARY_DIR}/cppcheck_feature_tests.hpp "#define ${OPERATOR}(x) 0\n")
endforeach()
add_custom_target(ci_cppcheck add_custom_target(ci_cppcheck
COMMAND mkdir -p cppcheck COMMAND mkdir -p cppcheck
COMMAND clang -dM -E -x c++ -std=c++11 ${CMAKE_SOURCE_DIR}/include/nlohmann/thirdparty/hedley/hedley.hpp > default_defines.hpp 2> /dev/null COMMAND clang -dM -E -x c++ -std=c++11 ${CMAKE_SOURCE_DIR}/include/nlohmann/thirdparty/hedley/hedley.hpp > default_defines.hpp 2> /dev/null
@@ -503,7 +494,7 @@ add_custom_target(ci_cppcheck
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include --std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp --error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
--include=${CMAKE_BINARY_DIR}/cppcheck_feature_tests.hpp --cppcheck-build-dir=cppcheck --cppcheck-build-dir=cppcheck
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW -UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
-DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON -DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON
COMMENT "Check code with Cppcheck" COMMENT "Check code with Cppcheck"
@@ -620,8 +611,9 @@ foreach(SRC_FILE ${SRC_FILES})
add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp) add_executable(single_${RELATIVE_SRC_FILE} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/src_single/${RELATIVE_SRC_FILE}.cpp)
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include) target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11) target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
if(RELATIVE_SRC_FILE STREQUAL "json") if(RELATIVE_SRC_FILE STREQUAL "json" OR RELATIVE_SRC_FILE STREQUAL "json_literals")
# see below: report the diagnostics of json.hpp without --error, so they do not fail the build # see below: report the diagnostics of json.hpp and json_literals.hpp without --error, so they
# do not fail the build
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${IWYU_TOOL} -Xiwyu --max_line_length=300) set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${IWYU_TOOL} -Xiwyu --max_line_length=300)
else() else()
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}") set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
@@ -635,31 +627,18 @@ foreach(SRC_FILE ${SRC_FILES})
# reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it # reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it
# from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a # from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a
# nondeterministic suggestion for a header that already re-exports everything on purpose. # nondeterministic suggestion for a header that already re-exports everything on purpose.
if(NOT RELATIVE_SRC_FILE STREQUAL "json") # json_literals.hpp and json.hpp include each other on purpose (json.hpp includes it at its end
# unless JSON_NO_AUTOMATIC_UDLS is defined), and IWYU, not following the cycle, suggests replacing
# json.hpp with json_fwd.hpp although the literals need the complete basic_json; exclude it, too.
if(NOT RELATIVE_SRC_FILE STREQUAL "json" AND NOT RELATIVE_SRC_FILE STREQUAL "json_literals")
list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp) list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp)
endif() endif()
endforeach() endforeach()
# The checks above look at each header on its own. Client code that includes only <nlohmann/json.hpp>
# must not be told by include analyzers to include another nlohmann header for what it uses
# (issue #5812): json.hpp marks those includes "IWYU pragma: export", and both IWYU and clang-tidy's
# misc-include-cleaner (disabled in .clang-tidy for the library itself) check these clients.
file(GLOB CONSUMER_FILES ${PROJECT_SOURCE_DIR}/tests/iwyu_consumer/*.cpp)
foreach(CONSUMER_FILE ${CONSUMER_FILES})
get_filename_component(CONSUMER_NAME "${CONSUMER_FILE}" NAME_WE)
add_executable(iwyu_consumer_${CONSUMER_NAME} EXCLUDE_FROM_ALL ${CONSUMER_FILE})
target_include_directories(iwyu_consumer_${CONSUMER_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_compile_features(iwyu_consumer_${CONSUMER_NAME} PRIVATE cxx_std_11)
list(APPEND single_binaries iwyu_consumer_${CONSUMER_NAME})
list(APPEND single_binaries_tus ${CONSUMER_FILE})
endforeach()
if(IWYU_TOOL_PY) if(IWYU_TOOL_PY)
add_custom_target(ci_single_binaries add_custom_target(ci_single_binaries
DEPENDS ${single_binaries} DEPENDS ${single_binaries}
COMMAND ${IWYU_TOOL_PY} -p ${PROJECT_BINARY_DIR} ${single_binaries_tus} -- ${iwyu_options} COMMAND ${IWYU_TOOL_PY} -p ${PROJECT_BINARY_DIR} ${single_binaries_tus} -- ${iwyu_options}
COMMAND ${CLANG_TIDY_TOOL} -p ${PROJECT_BINARY_DIR} --checks=-*,misc-include-cleaner --warnings-as-errors=* ${CONSUMER_FILES}
VERBATIM
COMMENT "Check if headers are self-contained" COMMENT "Check if headers are self-contained"
) )
else() else()
@@ -740,7 +719,7 @@ ci_get_cmake(4.0.0 CMAKE_4_0_0_BINARY)
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0 # the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
JSON_DisableTupleReferenceConversion JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
JSON_StrictNulHandling JSON_StrictBinaryUTF8 JSON_DeleteDeprecatedFunctions) JSON_StrictNulHandling JSON_StrictBinaryUTF8 JSON_DeleteDeprecatedFunctions)
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0}) set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0}) set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
@@ -797,14 +776,17 @@ add_custom_target(ci_cmake_flags
# Use more installed compilers. # Use more installed compilers.
############################################################################### ###############################################################################
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6) foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17 clang++-18 clang++-19 clang++-20)
find_program(COMPILER_TOOL NAMES ${COMPILER}) find_program(COMPILER_TOOL NAMES ${COMPILER})
if (COMPILER_TOOL) if (COMPILER_TOOL)
unset(ADDITIONAL_FLAGS)
add_custom_target(ci_test_compiler_${COMPILER} add_custom_target(ci_test_compiler_${COMPILER}
COMMAND CXX=${COMPILER} ${CMAKE_COMMAND} COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_BuildTests=ON -DJSON_FastTests=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
${ADDITIONAL_FLAGS}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMENT "Compile and test with ${COMPILER}" COMMENT "Compile and test with ${COMPILER}"
@@ -818,6 +800,7 @@ add_custom_target(ci_test_compiler_default
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_BuildTests=ON -DJSON_FastTests=ON
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_default -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_default
${ADDITIONAL_FLAGS}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_default --parallel ${N} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_default --parallel ${N}
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_default && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_default && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure
COMMENT "Compile and test with default C++ compiler" COMMENT "Compile and test with default C++ compiler"
@@ -842,10 +825,8 @@ add_custom_target(ci_module_cpp20
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_CI=ON -DNLOHMANN_JSON_BUILD_MODULES=ON -DJSON_Install=ON -DJSON_CI=ON -DNLOHMANN_JSON_BUILD_MODULES=ON -DJSON_Install=ON
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
-S${PROJECT_SOURCE_DIR}/tests/module_cpp20 -B${PROJECT_BINARY_DIR}/ci_module_cpp20 -S${PROJECT_SOURCE_DIR}/tests/module_cpp20 -B${PROJECT_BINARY_DIR}/ci_module_cpp20
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/ci_module_cpp20 COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/ci_module_cpp20
VERBATIM
) )
############################################################################### ###############################################################################
-6
View File
@@ -4,11 +4,5 @@
# call converts -1 to size_t, which -fsanitize=integer reports as implicit-integer-sign-change. This is # call converts -1 to size_t, which -fsanitize=integer reports as implicit-integer-sign-change. This is
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119429, not a bug in this library. Only that check and only <format> are # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119429, not a bug in this library. Only that check and only <format> are
# excluded, so implicit sign changes in the library and the tests are still reported. # excluded, so implicit sign changes in the library and the tests are still reported.
#
# libstdc++'s <string_view> compares two views of different lengths through `_S_compare(size_type __n1, size_type
# __n2)`, which stores `__n1 - __n2` in a signed difference_type and clamps it to int. Any comparison with a shorter
# view wraps that subtraction on purpose, and -fsanitize=integer reports it as implicit-integer-sign-change. json_view
# compares keys as string views, so the same check is excluded for <string_view> as well.
[implicit-integer-sign-change] [implicit-integer-sign-change]
src:*/include/c++/*/format src:*/include/c++/*/format
src:*/include/c++/*/string_view
+1 -1
View File
@@ -1 +1 @@
cppcheck==1.5.3 cppcheck==1.5.1
-2
View File
@@ -49,8 +49,6 @@ cc_library(
hdrs = [ hdrs = [
"single_include/nlohmann/json.hpp", "single_include/nlohmann/json.hpp",
"single_include/nlohmann/json_fwd.hpp", "single_include/nlohmann/json_fwd.hpp",
"single_include/nlohmann/json_literals.hpp",
"single_include/nlohmann/json_view.hpp",
], ],
includes = ["single_include"], includes = ["single_include"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
+2 -2
View File
@@ -7,12 +7,12 @@ This URL provides the most recent documentation and also applies to previous ver
functions is not removed; instead, it is marked as deprecated. functions is not removed; instead, it is marked as deprecated.
If you want to view the documentation for a specific tag or commit hash, you can generate it locally as follows (example If you want to view the documentation for a specific tag or commit hash, you can generate it locally as follows (example
using tag `v3.12.0`): using tag `v3.10.2`):
```shell ```shell
git clone https://github.com/nlohmann/json.git git clone https://github.com/nlohmann/json.git
cd json cd json
git checkout v3.12.0 git checkout v3.10.2
make install_venv serve -C docs/mkdocs make install_venv serve -C docs/mkdocs
``` ```
+55 -11
View File
@@ -1,24 +1,48 @@
SHELL=/usr/bin/env bash SHELL=/usr/bin/env bash
PYTHON=../mkdocs/venv/bin/python3 SED ?= $(shell which gsed 2>/dev/null || which sed)
MKDOCS_PAGES=$(shell cd ../mkdocs/docs/ && find * -type f -name '*.md' | sort)
.PHONY: all .PHONY: all
all: JSON_for_Modern_C++.tgz all: JSON_for_Modern_C++.tgz
# generate the search index (the docset target does this itself, this is docSet.dsidx: docSet.sql
# only handy for inspecting the index) # generate index
docSet.dsidx: generate_docset.py sqlite3 docSet.dsidx <docSet.sql
$(PYTHON) generate_docset.py index docSet.dsidx
# build the documentation and turn it into a self-contained docset JSON_for_Modern_C++.docset: Info.plist docSet.dsidx
.PHONY: JSON_for_Modern_C++.docset rm -fr JSON_for_Modern_C++.docset JSON_for_Modern_C++.tgz
JSON_for_Modern_C++.docset: mkdir -p JSON_for_Modern_C++.docset/Contents/Resources/Documents/
cp icon*.png JSON_for_Modern_C++.docset
cp Info.plist JSON_for_Modern_C++.docset/Contents
# build and copy documentation
$(MAKE) install_venv -C ../mkdocs $(MAKE) install_venv -C ../mkdocs
$(MAKE) build -C ../mkdocs $(MAKE) build -C ../mkdocs
$(PYTHON) generate_docset.py docset ../mkdocs/site . cp -r ../mkdocs/site/* JSON_for_Modern_C++.docset/Contents/Resources/Documents
# patch CSS to hide navigation items
echo -e "\n\nheader, footer, nav.md-tabs, nav.md-tabs--active, div.md-sidebar--primary, a.md-content__button { display: none; }" >> "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)"
# fix spacing
echo -e "\n\ndiv.md-sidebar div.md-sidebar--secondary, div.md-main__inner { top: 0; margin-top: 0 }" >> "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)"
# remove "JSON for Modern C++" from page titles (fallback)
find JSON_for_Modern_C++.docset/Contents/Resources/Documents -type f -exec $(SED) -i 's| - JSON for Modern C++</title>|</title>|' {} +
# replace page titles with name from index, if available
for page in $(MKDOCS_PAGES); do \
case "$$page" in \
*/index.md) path=$${page/\/index.md/} ;; \
*) path=$${page/.md/} ;; \
esac; \
title=$$(sqlite3 docSet.dsidx "SELECT name FROM searchIndex WHERE path='$$path/index.html'" | tr '\n' ',' | $(SED) -e 's/,/, /g' -e 's/, $$/\n/'); \
if [ "x$$title" != "x" ]; then \
$(SED) -i "s%<title>.*</title>%<title>$$title</title>%" "JSON_for_Modern_C++.docset/Contents/Resources/Documents/$$path/index.html"; \
fi \
done
# clean up
rm JSON_for_Modern_C++.docset/Contents/Resources/Documents/sitemap.*
# copy index
cp docSet.dsidx JSON_for_Modern_C++.docset/Contents/Resources/
.PHONY: JSON_for_Modern_C++.tgz
JSON_for_Modern_C++.tgz: JSON_for_Modern_C++.docset JSON_for_Modern_C++.tgz: JSON_for_Modern_C++.docset
$(PYTHON) generate_docset.py tgz . tar --exclude='.DS_Store' -cvzf JSON_for_Modern_C++.tgz JSON_for_Modern_C++.docset
# install docset for Zeal documentation browser (https://zealdocs.org/) # install docset for Zeal documentation browser (https://zealdocs.org/)
.PHONY: install_docset_zeal .PHONY: install_docset_zeal
@@ -28,6 +52,26 @@ install_docset_zeal: JSON_for_Modern_C++.docset
mkdir -p $$docset_root; \ mkdir -p $$docset_root; \
cp -r JSON_for_Modern_C++.docset $$docset_root/ cp -r JSON_for_Modern_C++.docset $$docset_root/
# both targets below compare the docset search index with the mkdocs page
# set. They share the same normalization (docs/foo/index.md and
# docs/foo.md both become foo/index.html, the URL mkdocs itself would
# give the page; the top-level index.md is excluded, as it is not part
# of the hand-curated docSet.sql) and use comm(1) on two sorted lists
# instead of running a sqlite3 query, or an O(n*m) nested shell loop,
# once per page.
DOCSET_INDEX_PATHS=$(shell sqlite3 docSet.dsidx "SELECT DISTINCT path FROM searchIndex" | sort)
DOCSET_PAGE_PATHS=$(shell echo '$(MKDOCS_PAGES)' | tr ' ' '\n' | grep -v '^index\.md$$' | $(SED) -E 's@/index\.md$$@/index.html@; s@\.md$$@/index.html@' | sort)
# list mkdocs pages missing from the docset index
.PHONY: list_missing_pages
list_missing_pages: docSet.dsidx
@comm -23 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
# list paths in the docset index without a corresponding mkdocs page
.PHONY: list_removed_paths
list_removed_paths: docSet.dsidx
@comm -13 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
.PHONY: clean .PHONY: clean
clean: clean:
rm -f docSet.dsidx rm -f docSet.dsidx
+1 -3
View File
@@ -4,8 +4,7 @@ The folder contains the required files to create a [docset](https://kapeli.com/d
documentation browsers like [Dash](https://kapeli.com/dash), [Velocity](https://velocity.silverlakesoftware.com), or documentation browsers like [Dash](https://kapeli.com/dash), [Velocity](https://velocity.silverlakesoftware.com), or
[Zeal](https://zealdocs.org). [Zeal](https://zealdocs.org).
The docset (pages and search index) is generated by `generate_docset.py` from the mkdocs site and `mkdocs.yml`. It The docset can be created with
can be created with
```sh ```sh
make JSON_for_Modern_C++.docset make JSON_for_Modern_C++.docset
@@ -13,7 +12,6 @@ make JSON_for_Modern_C++.docset
The generated folder `JSON_for_Modern_C++.docset` can then be opened in the documentation browser. `make all` builds a The generated folder `JSON_for_Modern_C++.docset` can then be opened in the documentation browser. `make all` builds a
`JSON_for_Modern_C++.tgz` archive instead, and `make install_docset_zeal` installs the docset for Zeal directly. `JSON_for_Modern_C++.tgz` archive instead, and `make install_docset_zeal` installs the docset for Zeal directly.
`make docSet.dsidx` builds only the search index.
A recent version is also part of the [Dash user contributions](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B). A recent version is also part of the [Dash user contributions](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B).
+289
View File
@@ -0,0 +1,289 @@
DROP TABLE IF EXISTS searchIndex;
CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT);
CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);
-- API
INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer', 'Class', 'api/adl_serializer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer::from_json', 'Function', 'api/adl_serializer/from_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer::to_json', 'Function', 'api/adl_serializer/to_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype', 'Class', 'api/byte_container_with_subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::byte_container_with_subtype', 'Constructor', 'api/byte_container_with_subtype/byte_container_with_subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::clear_subtype', 'Method', 'api/byte_container_with_subtype/clear_subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::has_subtype', 'Method', 'api/byte_container_with_subtype/has_subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::operator!=', 'Operator', 'api/byte_container_with_subtype/operator_ne/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::operator==', 'Operator', 'api/byte_container_with_subtype/operator_eq/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::set_subtype', 'Method', 'api/byte_container_with_subtype/set_subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::subtype', 'Method', 'api/byte_container_with_subtype/subtype/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/basic_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('format_as', 'Function', 'api/basic_json/format_as/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::accept', 'Function', 'api/basic_json/accept/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array', 'Function', 'api/basic_json/array/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array_t', 'Type', 'api/basic_json/array_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::as_base_class', 'Method', 'api/basic_json/as_base_class/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::at', 'Method', 'api/basic_json/at/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::back', 'Method', 'api/basic_json/back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::basic_json', 'Constructor', 'api/basic_json/basic_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::begin', 'Method', 'api/basic_json/begin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary', 'Function', 'api/basic_json/binary/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary_t', 'Type', 'api/basic_json/binary_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::boolean_t', 'Type', 'api/basic_json/boolean_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbegin', 'Method', 'api/basic_json/cbegin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbor_tag_handler_t', 'Enum', 'api/basic_json/cbor_tag_handler_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cend', 'Method', 'api/basic_json/cend/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::clear', 'Method', 'api/basic_json/clear/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::contains', 'Method', 'api/basic_json/contains/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::count', 'Method', 'api/basic_json/count/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::crbegin', 'Method', 'api/basic_json/crbegin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::crend', 'Method', 'api/basic_json/crend/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::default_object_comparator_t', 'Type', 'api/basic_json/default_object_comparator_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::diff', 'Function', 'api/basic_json/diff/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::dump', 'Method', 'api/basic_json/dump/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::emplace', 'Method', 'api/basic_json/emplace/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::emplace_back', 'Method', 'api/basic_json/emplace_back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::empty', 'Method', 'api/basic_json/empty/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::end', 'Method', 'api/basic_json/end/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::end_pos', 'Method', 'api/basic_json/end_pos/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::erase', 'Method', 'api/basic_json/erase/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::error_handler_t', 'Enum', 'api/basic_json/error_handler_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::exception', 'Class', 'api/basic_json/exception/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::find', 'Method', 'api/basic_json/find/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::flatten', 'Method', 'api/basic_json/flatten/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_bjdata', 'Function', 'api/basic_json/from_bjdata/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_bson', 'Function', 'api/basic_json/from_bson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_cbor', 'Function', 'api/basic_json/from_cbor/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_msgpack', 'Function', 'api/basic_json/from_msgpack/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_bon8', 'Function', 'api/basic_json/from_bon8/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_ubjson', 'Function', 'api/basic_json/from_ubjson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::front', 'Method', 'api/basic_json/front/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get', 'Method', 'api/basic_json/get/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_allocator', 'Function', 'api/basic_json/get_allocator/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_binary', 'Method', 'api/basic_json/get_binary/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ptr', 'Method', 'api/basic_json/get_ptr/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ref', 'Method', 'api/basic_json/get_ref/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_to', 'Method', 'api/basic_json/get_to/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::input_format_t', 'Enum', 'api/basic_json/input_format_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::insert', 'Method', 'api/basic_json/insert/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::invalid_iterator', 'Class', 'api/basic_json/invalid_iterator/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_array', 'Method', 'api/basic_json/is_array/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_binary', 'Method', 'api/basic_json/is_binary/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_boolean', 'Method', 'api/basic_json/is_boolean/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_discarded', 'Method', 'api/basic_json/is_discarded/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_null', 'Method', 'api/basic_json/is_null/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number', 'Method', 'api/basic_json/is_number/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_float', 'Method', 'api/basic_json/is_number_float/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_integer', 'Method', 'api/basic_json/is_number_integer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_unsigned', 'Method', 'api/basic_json/is_number_unsigned/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_object', 'Method', 'api/basic_json/is_object/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_primitive', 'Method', 'api/basic_json/is_primitive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_string', 'Method', 'api/basic_json/is_string/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_structured', 'Method', 'api/basic_json/is_structured/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::items', 'Method', 'api/basic_json/items/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_base_class_t', 'Type', 'api/basic_json/json_base_class_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_serializer', 'Class', 'api/basic_json/json_serializer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::max_size', 'Method', 'api/basic_json/max_size/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::merge_patch', 'Method', 'api/basic_json/merge_patch/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::meta', 'Function', 'api/basic_json/meta/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_float_t', 'Type', 'api/basic_json/number_float_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_integer_t', 'Type', 'api/basic_json/number_integer_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_unsigned_t', 'Type', 'api/basic_json/number_unsigned_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object', 'Function', 'api/basic_json/object/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object_comparator_t', 'Type', 'api/basic_json/object_comparator_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object_t', 'Type', 'api/basic_json/object_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator ValueType', 'Operator', 'api/basic_json/operator_ValueType/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator value_t', 'Operator', 'api/basic_json/operator_value_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator[]', 'Operator', 'api/basic_json/operator[]/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator=', 'Operator', 'api/basic_json/operator=/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator+=', 'Operator', 'api/basic_json/operator+=/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator==', 'Operator', 'api/basic_json/operator_eq/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator!=', 'Operator', 'api/basic_json/operator_ne/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<', 'Operator', 'api/basic_json/operator_lt/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<=', 'Operator', 'api/basic_json/operator_le/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator>', 'Operator', 'api/basic_json/operator_gt/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator>=', 'Operator', 'api/basic_json/operator_ge/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<=>', 'Operator', 'api/basic_json/operator_spaceship/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::out_of_range', 'Class', 'api/basic_json/out_of_range/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::other_error', 'Class', 'api/basic_json/other_error/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse', 'Function', 'api/basic_json/parse/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse_error', 'Class', 'api/basic_json/parse_error/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse_event_t', 'Enum', 'api/basic_json/parse_event_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parser_callback_t', 'Type', 'api/basic_json/parser_callback_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::patch', 'Method', 'api/basic_json/patch/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::patch_inplace', 'Method', 'api/basic_json/patch_inplace/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::push_back', 'Method', 'api/basic_json/push_back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::rbegin', 'Method', 'api/basic_json/rbegin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::rend', 'Method', 'api/basic_json/rend/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::sax_parse', 'Function', 'api/basic_json/sax_parse/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::size', 'Method', 'api/basic_json/size/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::start_pos', 'Method', 'api/basic_json/start_pos/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::string_t', 'Type', 'api/basic_json/string_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::swap', 'Method', 'api/basic_json/swap/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type', 'Method', 'api/basic_json/type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type_error', 'Class', 'api/basic_json/type_error/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type_name', 'Method', 'api/basic_json/type_name/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::unflatten', 'Method', 'api/basic_json/unflatten/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::update', 'Method', 'api/basic_json/update/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_bjdata', 'Function', 'api/basic_json/to_bjdata/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_bson', 'Function', 'api/basic_json/to_bson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_cbor', 'Function', 'api/basic_json/to_cbor/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_msgpack', 'Function', 'api/basic_json/to_msgpack/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_bon8', 'Function', 'api/basic_json/to_bon8/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_string', 'Method', 'api/basic_json/to_string/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_ubjson', 'Function', 'api/basic_json/to_ubjson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value', 'Method', 'api/basic_json/value/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value_t', 'Enum', 'api/basic_json/value_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::with_t', 'Type', 'api/basic_json/with_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::~basic_json', 'Method', 'api/basic_json/~basic_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json', 'Class', 'api/json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer', 'Class', 'api/json_pointer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::back', 'Method', 'api/json_pointer/back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::empty', 'Method', 'api/json_pointer/empty/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::front', 'Method', 'api/json_pointer/front/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::json_pointer', 'Constructor', 'api/json_pointer/json_pointer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator==', 'Operator', 'api/json_pointer/operator_eq/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator!=', 'Operator', 'api/json_pointer/operator_ne/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator/', 'Operator', 'api/json_pointer/operator_slash/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator/=', 'Operator', 'api/json_pointer/operator_slasheq/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator string_t', 'Operator', 'api/json_pointer/operator_string_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator<=>', 'Operator', 'api/json_pointer/operator_spaceship/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::parent_pointer', 'Method', 'api/json_pointer/parent_pointer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::pop_back', 'Method', 'api/json_pointer/pop_back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::pop_front', 'Method', 'api/json_pointer/pop_front/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::push_back', 'Method', 'api/json_pointer/push_back/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::push_front', 'Method', 'api/json_pointer/push_front/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::string_t', 'Type', 'api/json_pointer/string_t/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::to_string', 'Method', 'api/json_pointer/to_string/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax', 'Class', 'api/json_sax/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::binary', 'Method', 'api/json_sax/binary/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::boolean', 'Method', 'api/json_sax/boolean/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_array', 'Method', 'api/json_sax/end_array/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_object', 'Method', 'api/json_sax/end_object/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::key', 'Method', 'api/json_sax/key/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::null', 'Method', 'api/json_sax/null/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_float', 'Method', 'api/json_sax/number_float/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_integer', 'Method', 'api/json_sax/number_integer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_unsigned', 'Method', 'api/json_sax/number_unsigned/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::parse_error', 'Method', 'api/json_sax/parse_error/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_array', 'Method', 'api/json_sax/start_array/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_object', 'Method', 'api/json_sax/start_object/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::string', 'Method', 'api/json_sax/string/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json', 'Literal', 'api/operator_literal_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json_pointer', 'Literal', 'api/operator_literal_json_pointer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('operator<<', 'Operator', 'api/operator_ltlt/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('operator>>', 'Operator', 'api/operator_gtgt/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_json', 'Class', 'api/ordered_json/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map', 'Class', 'api/ordered_map/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('std::formatter<basic_json>', 'Class', 'api/basic_json/std_formatter/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('std::hash<basic_json>', 'Class', 'api/basic_json/std_hash/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('std::swap<basic_json>', 'Function', 'api/basic_json/std_swap/index.html');
-- Features
INSERT INTO searchIndex(name, type, path) VALUES ('Arbitrary Type Conversions', 'Guide', 'features/arbitrary_types/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats', 'Guide', 'features/binary_formats/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: BJData', 'Guide', 'features/binary_formats/bjdata/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: BSON', 'Guide', 'features/binary_formats/bson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: CBOR', 'Guide', 'features/binary_formats/cbor/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: MessagePack', 'Guide', 'features/binary_formats/messagepack/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: BON8', 'Guide', 'features/binary_formats/bon8/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: UBJSON', 'Guide', 'features/binary_formats/ubjson/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Binary Values', 'Guide', 'features/binary_values/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Comments', 'Guide', 'features/comments/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Element Access', 'Guide', 'features/element_access/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Access with default value: value', 'Guide', 'features/element_access/default_value/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Checked access: at', 'Guide', 'features/element_access/checked_access/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Unchecked access: operator[]', 'Guide', 'features/element_access/unchecked_access/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Exceptions', 'Guide', 'home/exceptions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Migration Guide', 'Guide', 'integration/migration_guide/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Integration: CMake', 'Guide', 'integration/cmake/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Header only', 'Guide', 'integration/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Package Managers', 'Guide', 'integration/package_managers/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Pkg-config', 'Guide', 'integration/pkg-config/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Iterators', 'Guide', 'features/iterators/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON Merge Patch', 'Guide', 'features/merge_patch/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON Patch and Diff', 'Guide', 'features/json_patch/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON Pointer', 'Guide', 'features/json_pointer/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('nlohmann Namespace', 'Guide', 'features/namespace/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Types', 'Guide', 'features/types/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Types: Number Handling', 'Guide', 'features/types/number_handling/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Object Order', 'Guide', 'features/object_order/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Performance', 'Guide', 'features/performance/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing', 'Guide', 'features/parsing/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: JSON Lines', 'Guide', 'features/parsing/json_lines/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: Parser Callbacks', 'Guide', 'features/parsing/parser_callbacks/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: Parsing and Exceptions', 'Guide', 'features/parsing/parse_exceptions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: SAX Interface', 'Guide', 'features/parsing/sax_interface/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: Untrusted Input', 'Guide', 'features/parsing/untrusted_input/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Runtime Assertions', 'Guide', 'features/assertions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Specializing enum conversion', 'Guide', 'features/enum_conversion/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Supported Macros', 'Guide', 'features/macros/index.html');
-- Macros
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'api/macros/json_assert/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_BRACE_INIT_COPY_SEMANTICS', 'Macro', 'api/macros/json_brace_init_copy_semantics/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'api/macros/json_throw_user/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DELETE_DEPRECATED_FUNCTIONS', 'Macro', 'api/macros/json_delete_deprecated_functions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTIC_POSITIONS', 'Macro', 'api/macros/json_diagnostic_positions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_TUPLE_REFERENCE_CONVERSION', 'Macro', 'api/macros/json_disable_tuple_reference_conversion/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_20', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_23', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_26', 'Macro', 'api/macros/json_has_cpp_11/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_EXPERIMENTAL_FILESYSTEM', 'Macro', 'api/macros/json_has_filesystem/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_FILESYSTEM', 'Macro', 'api/macros/json_has_filesystem/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_RANGES', 'Macro', 'api/macros/json_has_ranges/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_STATIC_RTTI', 'Macro', 'api/macros/json_has_static_rtti/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_STD_FORMAT', 'Macro', 'api/macros/json_has_std_format/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_THREE_WAY_COMPARISON', 'Macro', 'api/macros/json_has_three_way_comparison/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NOEXCEPTION', 'Macro', 'api/macros/json_noexception/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_AUTOMATIC_UDLS', 'Macro', 'api/macros/json_no_automatic_udls/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_IO', 'Macro', 'api/macros/json_no_io/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_THREAD_LOCAL', 'Macro', 'api/macros/json_no_thread_local/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_PRECISE_STREAM_POSITION', 'Macro', 'api/macros/json_precise_stream_position/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_LIBRARY_VERSION_CHECK', 'Macro', 'api/macros/json_skip_library_version_check/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_UNSUPPORTED_COMPILER_CHECK', 'Macro', 'api/macros/json_skip_unsupported_compiler_check/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_STRICT_BINARY_UTF8', 'Macro', 'api/macros/json_strict_binary_utf8/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_STRICT_NUL_HANDLING', 'Macro', 'api/macros/json_strict_nul_handling/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_THROW_USER', 'Macro', 'api/macros/json_throw_user/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_TRY_USER', 'Macro', 'api/macros/json_throw_user/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_GLOBAL_UDLS', 'Macro', 'api/macros/json_use_global_udls/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_IMPLICIT_CONVERSIONS', 'Macro', 'api/macros/json_use_implicit_conversions/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON', 'Macro', 'api/macros/json_use_legacy_discarded_value_comparison/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS', 'Macro', 'api/macros/json_use_objects_for_enum_keyed_maps/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_SIMDUTF', 'Macro', 'api/macros/json_use_simdutf/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('Macros', 'Macro', 'api/macros/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_type_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE', 'Macro', 'api/macros/nlohmann_define_type_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_type_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_type_non_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE', 'Macro', 'api/macros/nlohmann_define_type_non_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_type_non_intrusive/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES', 'Macro', 'api/macros/nlohmann_define_type_with_names/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE', 'Macro', 'api/macros/nlohmann_json_namespace/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_BEGIN', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_END', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_NO_VERSION', 'Macro', 'api/macros/nlohmann_json_namespace_no_version/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM', 'Macro', 'api/macros/nlohmann_json_serialize_enum/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM_STRICT', 'Macro', 'api/macros/nlohmann_json_serialize_enum_strict/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MAJOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MINOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html');
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_PATCH', 'Macro', 'api/macros/nlohmann_json_version_major/index.html');
-532
View File
@@ -1,532 +0,0 @@
#!/usr/bin/env python3
"""Generate the Dash docset search index from the mkdocs sources."""
import argparse
import glob
import hashlib
import html
import os
import re
import shutil
import sqlite3
import sys
import tarfile
import urllib.parse
import urllib.request
import yaml
HERE = os.path.dirname(os.path.abspath(__file__))
MKDOCS_YML = os.path.join(HERE, '..', 'mkdocs', 'mkdocs.yml')
PAGES = os.path.join(HERE, '..', 'mkdocs', 'docs')
# api pages whose (name, type) cannot be derived by the heuristics
OVERRIDES = {
}
DOCSET = 'JSON_for_Modern_C++.docset'
TITLE_SUFFIX = ' - JSON for Modern C++</title>'
# CSS rules appended to the stylesheet: hide navigation items and fix spacing
# hide the navigation (the documentation browser has its own); Material's class selectors would win over element
# selectors, hence the classes and !important
CSS_PATCH = (
'\n\n.md-header, .md-footer, .md-tabs, .md-sidebar--primary, .md-content__button { display: none !important; }'
'\n\n.md-sidebar--secondary, .md-main__inner { top: 0 !important; margin-top: 0 !important; }'
)
USER_AGENT = ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/124.0 Safari/537.36')
CONTENT_TYPE_EXT = {'image/svg+xml': '.svg', 'image/png': '.png', 'image/jpeg': '.jpg',
'image/gif': '.gif', 'image/webp': '.webp'}
# remote loads that are allowed to remain (URL -> reason)
ALLOWED_REMOTE = {
# Material only loads this polyfill if the browser has no ResizeObserver
'https://unpkg.com/resize-observer-polyfill': 'fallback for browsers without ResizeObserver',
}
problems = []
def problem(page, reason) -> None:
"""Record a problem; all problems are reported at the end."""
problems.append(f'generate_docset.py: {page}: {reason}')
class Loader(yaml.SafeLoader):
"""YAML loader that tolerates the custom tags used in mkdocs.yml."""
Loader.add_multi_constructor('', lambda loader, suffix, node: None)
def walk_nav(items, groups=()):
"""Yield (group titles, nav title or None, md path) for all nav leaves."""
for item in items:
if isinstance(item, str):
yield list(groups), None, item
elif isinstance(item, dict):
for title, value in item.items():
if isinstance(value, list):
yield from walk_nav(value, groups + (str(title),))
else:
yield list(groups), str(title), value
def page_path(md_path) -> str:
"""Map a markdown path to the HTML path of the rendered page."""
if md_path.endswith('/index.md'):
return md_path[:-len('index.md')] + 'index.html'
return md_path[:-len('.md')] + '/index.html'
def read_page(md_path) -> str:
"""Read a page (resolving a snippet include), return '' if it does not exist."""
try:
with open(os.path.join(PAGES, md_path), encoding='utf-8') as f:
text = f.read()
m = re.match(r'--8<-- "(.+)"\s*$', text)
if m:
with open(os.path.join(PAGES, m.group(1)), encoding='utf-8') as f:
text = f.read()
return text
except OSError:
return ''
def clean(text) -> str:
"""Strip tags and entities from a heading and normalize whitespace."""
text = text.replace('\\>', '\x00') # escaped '>' is not the end of a tag
text = html.unescape(re.sub(r'</?[a-zA-Z][^>]*>', '', text)).replace('\x00', '>')
return re.sub(r'\s+', ' ', text).strip()
def strip_fences(text) -> str:
"""Remove fenced code blocks (their lines may start with '# ')."""
return re.sub(r'^(```|~~~).*?^\1[^\n]*$', '', text, flags=re.M | re.S)
def get_h1(text):
"""Return the cleaned first H1 of a page or None."""
body = strip_fences(text)
m = re.search(r'^# (.+)$', body, flags=re.M)
if m:
return clean(m.group(1))
m = re.search(r'<h1>(.*?)</h1>', body, flags=re.S)
return clean(m.group(1)) if m else None
def split_top_level(text, seps=','):
"""Split at separators that are not nested in <>, () or []."""
parts, depth, current = [], 0, ''
for c in text:
if c in '<([':
depth += 1
elif c in '>)]':
depth -= 1
if c in seps and depth <= 0:
parts.append(current)
current = ''
else:
current += c
parts.append(current)
return [p.strip() for p in parts if p.strip()]
OPERATOR_SYMBOLS = ('<=>', '<<', '>>', '<=', '>=', '<', '>')
def api_names(h1) -> list:
"""Derive the entry names from the H1 of an api page."""
# hide the angle brackets of operators from the nesting detection
for i, sym in enumerate(OPERATOR_SYMBOLS):
h1 = h1.replace('operator' + sym, f'operator\x01{i}\x01')
names = []
for part in split_top_level(h1):
name = part.replace('\\', '').replace('nlohmann::', '')
name = re.sub(r'\x01(\d)\x01', lambda m: OPERATOR_SYMBOLS[int(m.group(1))], name)
# drop qualifiers like "operator<<(basic_json)", but keep "operator()"
if not name.endswith('operator()'):
name = re.sub(r'(?<=\w|[<>=!+\-*/\[\]])\([^()]*\)$', '', name)
if name not in names:
names.append(name)
return names
def first_cpp_block(text):
"""Return the first ```cpp block following the H1."""
m = re.search(r'^# .*?^```cpp\n(.*?)^```', text, flags=re.M | re.S)
return m.group(1) if m else None
def api_type(name, decl):
"""Determine the Dash entry type from name and declaration."""
parts = name.split('::')
last = parts[-1]
if name.startswith('operator""'):
return 'Literal'
if last.startswith('operator'):
return 'Operator'
if decl is None:
return None
if re.search(r'\benum\b', decl):
return 'Enum'
if re.search(r'^\s*(template\s*<.*>\s*)?(class|struct)\s+\w+\s*(final\b|[:{;<]|$)', decl, flags=re.M):
return 'Class'
if re.search(r'\busing\s+\w+\s*=', decl) or 'typedef' in decl:
return 'Type'
if len(parts) > 1 and last == parts[-2]:
return 'Constructor'
if last.startswith('~'):
return 'Method'
if re.search(r'\bstatic\b', decl) or len(parts) == 1 or parts[0] == 'std':
return 'Function'
return 'Method'
def macro_names(h1) -> list:
"""Split the H1 of a macro page into macro names."""
return [n.strip() for n in re.split(r'[,/]', h1) if n.strip()]
def api_entries(md_path):
"""Return the (name, type) pairs of an api page."""
if md_path in OVERRIDES:
return OVERRIDES[md_path]
if md_path == 'api/macros/index.md':
return [('Macros', 'Macro')]
text = read_page(md_path)
h1 = get_h1(text)
if not h1:
problem(md_path, 'no H1 found')
return []
if md_path.startswith('api/macros/'):
return [(n, 'Macro') for n in macro_names(h1)]
names = api_names(h1)
if not names:
problem(md_path, 'no names found')
return []
decl = first_cpp_block(text)
result = []
for name in names:
kind = api_type(name, decl)
if kind is None:
problem(md_path, f'no type determinable for {name}')
else:
result.append((name, kind))
return result
def guide_entries(nav):
"""Yield (name, type, md path) for all non-api nav pages."""
for groups, title, md_path in walk_nav(nav):
if md_path.startswith('api/') or md_path == 'index.md':
continue
if not md_path.endswith('.md'):
continue
groups = groups[1:] # drop the top-level tab
if title is None:
title = get_h1(read_page(md_path))
if not title:
problem(md_path, 'no title found')
continue
# "Parsing: Parsing Untrusted Input" -> "Parsing: Untrusted Input"
if groups and title.startswith(groups[-1] + ' ') and title[len(groups[-1]) + 1:][:1].isupper():
title = title[len(groups[-1]) + 1:]
if md_path.endswith('/index.md') and groups and title == groups[-1]:
name = ': '.join(groups)
else:
name = ': '.join(groups + [title])
yield name, 'Guide', md_path
def build_entries() -> list:
"""Return the sorted list of (name, type, path) index entries."""
nav = load_mkdocs_yml()['nav']
entries = set()
for name, kind, md_path in guide_entries(nav):
entries.add((name, kind, page_path(md_path)))
api_root = os.path.join(PAGES, 'api')
on_disk = set()
for root, _, files in os.walk(api_root):
for file in files:
if file.endswith('.md'):
rel = os.path.relpath(os.path.join(root, file), PAGES)
on_disk.add(rel.replace(os.sep, '/'))
for _, _, md_path in walk_nav(nav):
if md_path.startswith('api/') and md_path not in on_disk:
problem(md_path, 'listed in nav but missing on disk')
for md_path in sorted(on_disk):
for name, kind in api_entries(md_path):
entries.add((name, kind, page_path(md_path)))
return sorted(entries)
def write_index(entries, out) -> None:
"""Write the entries into a SQLite search index."""
if os.path.exists(out):
os.remove(out)
con = sqlite3.connect(out)
con.execute('CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT)')
con.execute('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path)')
con.executemany('INSERT INTO searchIndex(name, type, path) VALUES (?, ?, ?)', entries)
con.commit()
con.close()
def html_files(root):
"""Yield all HTML files below root."""
for base, _, files in os.walk(root):
for file in files:
if file.endswith('.html'):
yield os.path.join(base, file)
def read(path) -> str:
with open(path, encoding='utf-8') as f:
return f.read()
def write(path, text) -> None:
with open(path, 'w', encoding='utf-8') as f:
f.write(text)
def remove_source_widget(docs) -> None:
"""Drop data-md-component=source so Material does not query api.github.com for the stars and version."""
pattern = re.compile(r'\sdata-md-component=(?:"source"|source\b)')
for path in html_files(docs):
text = read(path)
new = pattern.sub('', text)
if new != text:
write(path, new)
def patch_titles(docs, entries) -> None:
"""Strip the site name from all titles; use the index names where available."""
names = {}
for name, _, path in entries:
names.setdefault(path, []).append(name)
for file in html_files(docs):
rel = os.path.relpath(file, docs).replace(os.sep, '/')
text = read(file).replace(TITLE_SUFFIX, '</title>')
if rel in names:
title = html.escape(', '.join(names[rel]), quote=False)
text = re.sub(r'<title>.*?</title>', lambda _: f'<title>{title}</title>', text, count=1, flags=re.S)
write(file, text)
IMG_RE = re.compile(r'<img\b[^>]*>', re.I)
ATTR_RE = r'''(?:{0})\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+))'''
def attr(tag, name):
"""Return the value of an attribute in a tag or None."""
m = re.search(r'(?<![\w-])' + ATTR_RE.format(name), tag, flags=re.I)
return next(g for g in m.groups() if g is not None) if m else None
def is_remote(url) -> bool:
return re.match(r'(https?:)?//', url.strip(), flags=re.I) is not None
def download(url, docs) -> str:
"""Download url into assets/external and return the path relative to docs."""
u = urllib.parse.urlparse(url if not url.startswith('//') else 'https:' + url)
if u.scheme.lower() not in ('http', 'https'):
raise ValueError(f'not an http(s) URL: {url}')
req = urllib.request.Request(u.geturl(), headers={'User-Agent': USER_AGENT})
# (the scheme is checked above)
with urllib.request.urlopen(req, timeout=20) as r: # nosec B310
data = r.read()
ctype = r.headers.get_content_type()
path = urllib.parse.unquote(u.path).lstrip('/')
ext = os.path.splitext(path)[1]
if u.query or not ext or path.endswith('/'):
digest = hashlib.sha1(url.encode(), usedforsecurity=False).hexdigest()[:12]
path = os.path.join(os.path.dirname(path), digest + CONTENT_TYPE_EXT.get(ctype, ext or '.bin'))
rel = os.path.normpath(os.path.join('assets', 'external', u.hostname, path))
out = os.path.join(docs, rel)
os.makedirs(os.path.dirname(out), exist_ok=True)
with open(out, 'wb') as f:
f.write(data)
return rel.replace(os.sep, '/')
def localize_images(docs) -> None:
"""Download remote images and rewrite their src; drop them on failure."""
cache = {}
for file in html_files(docs):
text = read(file)
def repl(m):
tag = m.group(0)
src = attr(tag, 'src')
if src is None or not is_remote(src):
return tag
if src not in cache:
try:
cache[src] = download(src, docs)
except Exception as e: # noqa: BLE001
print(f'generate_docset.py: warning: cannot download {src}: {e}', file=sys.stderr)
cache[src] = None
if cache[src] is None:
return attr(tag, 'alt') or ''
local = os.path.relpath(os.path.join(docs, cache[src]), os.path.dirname(file))
local = local.replace(os.sep, '/')
return re.sub(ATTR_RE.format('src'), lambda _: f'src="{local}"', tag, count=1, flags=re.I)
new = IMG_RE.sub(repl, text)
if new != text:
write(file, new)
def load_mkdocs_yml() -> dict:
"""Load mkdocs.yml, ignoring tags like !ENV and !!python/name."""
with open(MKDOCS_YML, encoding='utf-8') as f:
# (Loader is a yaml.SafeLoader)
return yaml.load(f, Loader=Loader) # nosec B506
def localize_site_urls(docs, site_url) -> None:
"""Load assets that the theme's JavaScript references by absolute site URL from the docset.
The privacy plugin rewrites the mermaid loader to "<site_url>assets/external/unpkg.com/mermaid@11/...", so the
docset would fetch mermaid from the live site. __md_scope is the site root that Material defines in every page.
"""
pattern = re.compile(r'"' + re.escape(site_url) + r'(assets/[^"]*)"')
for base, _, files in os.walk(docs):
for file in (f for f in files if f.endswith('.js')):
path = os.path.join(base, file)
text = read(path)
new = pattern.sub(r'new URL("\1",__md_scope).href', text)
if new != text:
write(path, new)
def remote_loads(docs, site_url) -> list:
"""Return 'file: url' strings for resources that would be loaded remotely."""
found = []
cdn = re.compile(r'https://(?:unpkg\.com|cdn\.jsdelivr\.net|cdnjs\.cloudflare\.com|'
r'fonts\.googleapis\.com|fonts\.gstatic\.com)/[^\s"\'`)\\]*')
css_url = re.compile(r'url\(\s*["\']?((?:https?:)?//[^)"\']+)', re.I)
css_import = re.compile(r'@import\s+(?:url\(\s*)?["\']?((?:https?:)?//[^)"\'; ]+)', re.I)
for base, _, files in os.walk(docs):
for file in files:
path = os.path.join(base, file)
rel = os.path.relpath(path, docs)
urls = []
if file.endswith('.html'):
text = read(path)
for m in re.finditer(r'<[a-zA-Z][^>]*>', text):
tag = m.group(0)
for name in ('src', 'poster'):
v = attr(tag, name)
if v and is_remote(v):
urls.append(v)
v = attr(tag, 'srcset')
if v:
urls += [c.split()[0] for c in v.split(',') if c.strip() and is_remote(c.strip())]
if re.match(r'<link\b', tag, flags=re.I):
rel_attr = (attr(tag, 'rel') or '').lower()
v = attr(tag, 'href')
if v and is_remote(v) and re.search(r'stylesheet|icon|preload|modulepreload|manifest', rel_attr):
urls.append(v)
urls += css_url.findall(text) + css_import.findall(text)
elif file.endswith('.css'):
text = read(path)
urls += css_url.findall(text) + css_import.findall(text)
elif file.endswith('.js'):
text = read(path)
urls += cdn.findall(text)
urls += re.findall(re.escape(site_url) + r'assets/[^\s"\'`)\\]*', text)
found += [f'{rel}: {u}' for u in urls if u not in ALLOWED_REMOTE]
return found
def make_docset(site, out_dir) -> int:
entries = build_entries()
if problems:
print('\n'.join(problems), file=sys.stderr)
return 1
docset = os.path.join(out_dir, DOCSET)
docs = os.path.join(docset, 'Contents', 'Resources', 'Documents')
if os.path.exists(docset):
shutil.rmtree(docset)
shutil.copytree(site, docs)
for icon in ('icon.png', 'icon@2x.png'):
shutil.copy(os.path.join(HERE, icon), docset)
shutil.copy(os.path.join(HERE, 'Info.plist'), os.path.join(docset, 'Contents'))
write_index(entries, os.path.join(docset, 'Contents', 'Resources', 'docSet.dsidx'))
# patch CSS to hide navigation items and fix spacing
css = glob.glob(os.path.join(docs, 'assets', 'stylesheets', 'main.*.min.css'))
if len(css) != 1:
print(f'generate_docset.py: expected exactly one main.*.min.css, found {len(css)}', file=sys.stderr)
return 1
with open(css[0], 'a', encoding='utf-8') as f:
f.write(CSS_PATCH)
patch_titles(docs, entries)
remove_source_widget(docs)
for sitemap in glob.glob(os.path.join(docs, 'sitemap.*')):
os.remove(sitemap)
# make the docset self-contained
site_url = load_mkdocs_yml()['site_url']
localize_images(docs)
localize_site_urls(docs, site_url)
remote = remote_loads(docs, site_url)
if remote:
print('generate_docset.py: remote resources remain in the docset:', file=sys.stderr)
print('\n'.join(' ' + r for r in remote), file=sys.stderr)
return 1
return 0
def make_tgz(out_dir) -> int:
docset = os.path.join(out_dir, DOCSET)
if not os.path.isdir(docset):
print(f'generate_docset.py: {docset} does not exist', file=sys.stderr)
return 1
with tarfile.open(os.path.join(out_dir, 'JSON_for_Modern_C++.tgz'), 'w:gz') as tar:
tar.add(docset, arcname=DOCSET, filter=lambda i: None if os.path.basename(i.name) == '.DS_Store' else i)
return 0
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
sub = parser.add_subparsers(dest='command', required=True)
sub.add_parser('list', help='print the index entries as TSV')
p = sub.add_parser('index', help='write the SQLite search index')
p.add_argument('out')
p = sub.add_parser('docset', help='build the docset from a built mkdocs site')
p.add_argument('site_dir')
p.add_argument('out_dir')
p = sub.add_parser('tgz', help='pack the docset into a tarball')
p.add_argument('out_dir')
args = parser.parse_args()
if args.command == 'docset':
return make_docset(args.site_dir, args.out_dir)
if args.command == 'tgz':
return make_tgz(args.out_dir)
entries = build_entries()
if problems:
print('\n'.join(problems), file=sys.stderr)
return 1
if args.command == 'list':
for entry in entries:
print('\t'.join(entry))
elif args.command == 'index':
write_index(entries, args.out)
return 0
if __name__ == '__main__':
sys.exit(main())
-1
View File
@@ -17,7 +17,6 @@ build: style_check
style_check: style_check:
@cd docs ; ../venv/bin/python3 ../scripts/check_structure.py @cd docs ; ../venv/bin/python3 ../scripts/check_structure.py
@venv/bin/python3 ../docset/generate_docset.py list > /dev/null
# check that all Mermaid diagrams parse (needs Node.js) # check that all Mermaid diagrams parse (needs Node.js)
# This target is used in the CI (ci_test_documentation_mermaid). # This target is used in the CI (ci_test_documentation_mermaid).
@@ -132,10 +132,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
- [operator>>](../operator_gtgt.md) - deserialize from stream - [operator>>](../operator_gtgt.md) - deserialize from stream
- [`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) - opt in to rejecting a NUL byte in the input - [`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) - opt in to rejecting a NUL byte in the input
instead of treating it as end of input instead of treating it as end of input
- [`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md) - read a `std::istream` one character
at a time
- [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) - read a `FILE*` with the locking stdio
functions
## Version history ## Version history
@@ -147,10 +143,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0. - Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
- `JSON_STRICT_NUL_HANDLING` added in version 3.13.0 to optionally reject a NUL byte in the input instead of treating - `JSON_STRICT_NUL_HANDLING` added in version 3.13.0 to optionally reject a NUL byte in the input instead of treating
it as end of input; planned to become the default in version 4.0.0. it as end of input; planned to become the default in version 4.0.0.
- Parsing from an `std::istream` scans the characters in its stream buffer in bulk in version 3.13.0
([`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md)).
- Parsing from a `FILE*` locks the file once instead of once per character in version 3.13.0
([`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md)).
!!! warning "Deprecation" !!! warning "Deprecation"
+1 -1
View File
@@ -27,7 +27,7 @@ To store objects in C++, a type is defined by the template parameters explained
### Default type ### Default type
With the default values for `ArrayType` (`std::vector`) and `AllocatorType` (`std::allocator`), the default type for With the default values for `ArrayType` (`std::vector`) and `AllocatorType` (`std::allocator`), the default value for
`array_t` is: `array_t` is:
```cpp ```cpp
+1 -4
View File
@@ -233,7 +233,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
- documentation on [checked access](../../features/element_access/checked_access.md) - documentation on [checked access](../../features/element_access/checked_access.md)
- [`operator[]`](operator%5B%5D.md) for unchecked access by reference - [`operator[]`](operator%5B%5D.md) for unchecked access by reference
- [`value`](value.md) for access with default value - [`value`](value.md) for access with default value
- [basic_json_view::at](../basic_json_view/at.md) - the same access on a zero-copy view
## Version history ## Version history
@@ -242,6 +241,4 @@ Strong exception safety: if an exception occurs, the original value stays intact
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as 3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
already supported by [`operator[]`](operator[].md), [`value`](value.md), [`find`](find.md), and other lookup already supported by [`operator[]`](operator[].md), [`value`](value.md), [`find`](find.md), and other lookup
functions. functions.
4. Added in version 2.0.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of 4. Added in version 2.0.0.
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is not
a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
-1
View File
@@ -58,7 +58,6 @@ Constant.
## See also ## See also
- [front](front.md) to access the first element - [front](front.md) to access the first element
- [basic_json_view::back](../basic_json_view/back.md) - the same access on a zero-copy view
## Version history ## Version history
+1 -11
View File
@@ -68,14 +68,6 @@ basic_json(basic_json&& other) noexcept;
`std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to `string_t` `std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to `string_t`
and a `value_type` from which a `basic_json` value can be constructed. and a `value_type` from which a `basic_json` value can be constructed.
- **strings**: `string_t`, string literals, and all compatible string containers can be used. - **strings**: `string_t`, string literals, and all compatible string containers can be used.
!!! note "Rvalue containers are moved from"
If `val` is an rvalue of a compatible array-like or object-like container other than `array_t`/`object_t`
(e.g., `json j = std::move(vec);` or `json j(std::vector<std::string>{...});`), the elements are moved into
the JSON value instead of copied. Afterwards, the elements of the source container are in a valid but
unspecified state (**moved-from**). Keys of associative containers are `const` and therefore still copied.
Lvalues and `const` rvalues are copied, and the source is left unchanged.
- **numbers**: [`number_integer_t`](number_integer_t.md), [`number_unsigned_t`](number_unsigned_t.md), - **numbers**: [`number_integer_t`](number_integer_t.md), [`number_unsigned_t`](number_unsigned_t.md),
[`number_float_t`](number_float_t.md), and all convertible number types such as `int`, `size_t`, `int64_t`, `float` [`number_float_t`](number_float_t.md), and all convertible number types such as `int`, `size_t`, `int64_t`, `float`
or `double` can be used. or `double` can be used.
@@ -244,9 +236,7 @@ basic_json(basic_json&& other) noexcept;
2. No-throw guarantee: this constructor never throws exceptions. 2. No-throw guarantee: this constructor never throws exceptions.
3. Depends on the called constructor. For types directly supported by the library (i.e., all types for which no 3. Depends on the called constructor. For types directly supported by the library (i.e., all types for which no
`to_json()` function was provided), a strong guarantee holds: if an exception is thrown, there are no changes to any `to_json()` function was provided), a strong guarantee holds: if an exception is thrown, there are no changes to any
JSON value. **Exception:** when `val` is an rvalue array-like or object-like container, its elements are moved one JSON value.
by one; if an exception is thrown in the middle of the conversion (e.g., an allocation failure), the JSON value is
unchanged, but the source container may be left partially moved-from.
4. Depends on the called constructor. For types directly supported by the library (i.e., all types for which no 4. Depends on the called constructor. For types directly supported by the library (i.e., all types for which no
`to_json()` function was provided), a strong guarantee holds: if an exception is thrown, there are no changes to any `to_json()` function was provided), a strong guarantee holds: if an exception is thrown, there are no changes to any
JSON value. JSON value.
-2
View File
@@ -44,8 +44,6 @@ Constant.
- [rbegin](rbegin.md) returns a reverse iterator to the last element - [rbegin](rbegin.md) returns a reverse iterator to the last element
- [items](items.md) returns an iteration proxy to access keys and values during range-based for loops - [items](items.md) returns an iteration proxy to access keys and values during range-based for loops
- [Iterators](../../features/iterators.md) - the article on iterators - [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::begin](../basic_json_view/begin.md) - the same iteration on a zero-copy view (in document order,
not sorted by key)
## Version history ## Version history
+12 -1
View File
@@ -64,7 +64,18 @@ values of that type directly to a `basic_json` instance, and they will automatic
rather than arrays: rather than arrays:
```cpp ```cpp
using custom_json = nlohmann::ordered_json::with_binary_t<std::vector<std::byte>>; using custom_json = nlohmann::basic_json<
nlohmann::ordered_map, // ObjectType
std::vector, // ArrayType
std::string, // StringType
bool, // BooleanType
std::int64_t, // NumberIntegerType
std::uint64_t, // NumberUnsignedType
double, // NumberFloatType
std::allocator, // AllocatorType
nlohmann::adl_serializer,
std::vector<std::byte> // Custom BinaryType
>;
std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}}; std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}};
custom_json j = data; // Creates a binary value, not an array custom_json j = data; // Creates a binary value, not an array
+1 -1
View File
@@ -23,7 +23,7 @@ To store boolean values in C++, a type is defined by the template parameter `Bo
### Default type ### Default type
With the default values for `BooleanType` (`#!cpp bool`), the default type for `boolean_t` is `#!cpp bool`. With the default values for `BooleanType` (`#!cpp bool`), the default value for `boolean_t` is `#!cpp bool`.
### Storage ### Storage
@@ -42,7 +42,6 @@ Constant.
- [cend](cend.md) returns a const iterator to one past the last element - [cend](cend.md) returns a const iterator to one past the last element
- [crbegin](crbegin.md) returns a const reverse iterator to the last element - [crbegin](crbegin.md) returns a const reverse iterator to the last element
- [Iterators](../../features/iterators.md) - the article on iterators - [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::cbegin](../basic_json_view/cbegin.md) - the same iteration on a zero-copy view
## Version history ## Version history
-1
View File
@@ -42,7 +42,6 @@ Constant.
- [cbegin](cbegin.md) returns a const iterator to the first element - [cbegin](cbegin.md) returns a const iterator to the first element
- [crend](crend.md) returns a const reverse iterator to one before the first element - [crend](crend.md) returns a const reverse iterator to one before the first element
- [Iterators](../../features/iterators.md) - the article on iterators - [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::cend](../basic_json_view/cend.md) - the same iteration on a zero-copy view
## Version history ## Version history
@@ -10,10 +10,6 @@ bool contains(KeyType&& key) const;
// (3) // (3)
bool contains(const json_pointer& ptr) const; bool contains(const json_pointer& ptr) const;
// (4)
template<typename T>
bool contains(T) const = delete;
``` ```
1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the 1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the
@@ -21,9 +17,6 @@ bool contains(T) const = delete;
2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and 2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
`#!cpp typename object_comparator_t::is_transparent` denotes a type. `#!cpp typename object_comparator_t::is_transparent` denotes a type.
3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value. 3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value.
4. Deleted: this overload is only available if `T` is an integral type and is declared as deleted, so that a call with
an integer `key` (for example, `#!cpp j.contains(0)`) fails to compile. Otherwise, the integer literal `0` would convert to
a null `#!cpp const char*` and, from there, to the key type, causing undefined behavior at runtime.
## Template parameters ## Template parameters
@@ -46,7 +39,6 @@ bool contains(T) const = delete;
is not an object, `#!cpp false` is returned. is not an object, `#!cpp false` is returned.
2. See 1. 2. See 1.
3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. 3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise.
4. Deleted; a call with an integral argument does not compile.
## Exception safety ## Exception safety
@@ -57,7 +49,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
1. The function does not throw exceptions. 1. The function does not throw exceptions.
2. The function does not throw exceptions. 2. The function does not throw exceptions.
3. The function does not throw exceptions. 3. The function does not throw exceptions.
4. Deleted; a call with an integral argument does not compile.
## Complexity ## Complexity
@@ -136,7 +127,6 @@ Logarithmic in the size of the JSON object.
- [find](find.md) find a value in an object - [find](find.md) find a value in an object
- [count](count.md) returns the number of occurrences of a key - [count](count.md) returns the number of occurrences of a key
- [basic_json_view::contains](../basic_json_view/contains.md) - the same check on a zero-copy view
## Version history ## Version history
-8
View File
@@ -7,19 +7,12 @@ size_type count(const typename object_t::key_type& key) const;
// (2) // (2)
template<typename KeyType> template<typename KeyType>
size_type count(KeyType&& key) const; size_type count(KeyType&& key) const;
// (3)
template<typename T>
size_type count(T) const = delete;
``` ```
1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will 1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will
always be `0` (`key` was not found) or `1` (`key` was found). always be `0` (`key` was not found) or `1` (`key` was found).
2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and 2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
`#!cpp typename object_comparator_t::is_transparent` denotes a type. `#!cpp typename object_comparator_t::is_transparent` denotes a type.
3. Deleted: this overload is only available if `T` is an integral type and is declared as deleted, so that a call with
an integer `key` (for example, `#!cpp j.count(0)`) fails to compile. Otherwise, the integer literal `0` would convert to
a null `#!cpp const char*` and, from there, to the key type, causing undefined behavior at runtime.
## Template parameters ## Template parameters
@@ -87,7 +80,6 @@ Logarithmic in the size of the JSON object.
- [find](find.md) find a value in an object - [find](find.md) find a value in an object
- [contains](contains.md) checks whether a key exists - [contains](contains.md) checks whether a key exists
- [basic_json_view::count](../basic_json_view/count.md) - the same check on a zero-copy view
## Version history ## Version history
-1
View File
@@ -59,7 +59,6 @@ Currently, only `remove`, `add`, and `replace` operations are generated.
- [patch](patch.md) applies a JSON Patch - [patch](patch.md) applies a JSON Patch
- [patch_inplace](patch_inplace.md) applies a JSON Patch in place - [patch_inplace](patch_inplace.md) applies a JSON Patch in place
- [merge_patch](merge_patch.md) applies a JSON Merge Patch - [merge_patch](merge_patch.md) applies a JSON Merge Patch
- [merge_diff](merge_diff.md) creates a diff as a JSON Merge Patch
## Version history ## Version history
-7
View File
@@ -62,9 +62,6 @@ Linear.
## Notes ## Notes
Floating-point numbers are written with the fewest digits that read back as the same value (for `#!cpp double`; see
[number handling](../../features/types/number_handling.md#number-serialization)).
Binary values are serialized as an object containing two keys: Binary values are serialized as an object containing two keys:
- "bytes": an array of bytes as integers - "bytes": an array of bytes as integers
@@ -91,8 +88,6 @@ Binary values are serialized as an object containing two keys:
- [to_string](to_string.md) returns a string representation of a JSON value - [to_string](to_string.md) returns a string representation of a JSON value
- [operator<<](../operator_ltlt.md) serialize to stream - [operator<<](../operator_ltlt.md) serialize to stream
- [`basic_json_view::dump`](../basic_json_view/dump.md) the corresponding function of `basic_json_view`, serializing
directly from a flat index without building a `basic_json` value
- [Serialization](../../features/serialization.md) - the serialization article - [Serialization](../../features/serialization.md) - the serialization article
## Version history ## Version history
@@ -102,5 +97,3 @@ Binary values are serialized as an object containing two keys:
- Error handlers added in version 3.4.0. - Error handlers added in version 3.4.0.
- Serialization of binary values added in version 3.8.0. - Serialization of binary values added in version 3.8.0.
- Error handler `keep` added in version 3.13.0. - Error handler `keep` added in version 3.13.0.
- Doubles are written with the shortest digits (Żmij instead of Grisu2) since version 3.13.0; about 0.1% of doubles are
written differently, most of them with fewer digits.
-1
View File
@@ -64,7 +64,6 @@ itself is empty which is `#!cpp false` in the case of a string.
- [size](size.md) returns the number of elements - [size](size.md) returns the number of elements
- [clear](clear.md) clears the content and resets the value to the default value - [clear](clear.md) clears the content and resets the value to the default value
- [basic_json_view::empty](../basic_json_view/empty.md) - the same check on a zero-copy view
## Version history ## Version history
-1
View File
@@ -43,7 +43,6 @@ Constant.
- [cend](cend.md) returns a const iterator to one past the last element - [cend](cend.md) returns a const iterator to one past the last element
- [rend](rend.md) returns a reverse iterator to one before the first element - [rend](rend.md) returns a reverse iterator to one before the first element
- [Iterators](../../features/iterators.md) - the article on iterators - [Iterators](../../features/iterators.md) - the article on iterators
- [basic_json_view::end](../basic_json_view/end.md) - the same iteration on a zero-copy view
## Version history ## Version history
@@ -37,8 +37,8 @@ ignore
: ignore invalid UTF-8 sequences; all valid bytes are copied to the output unchanged, and invalid bytes are dropped : ignore invalid UTF-8 sequences; all valid bytes are copied to the output unchanged, and invalid bytes are dropped
keep keep
: keep invalid UTF-8 sequences unchanged; only meaningful for the binary formats mentioned above, since : keep invalid UTF-8 sequences unchanged; only meaningful for the binary formats mentioned above, since [`dump`]
[`dump`](dump.md) itself must produce text, and `keep` there writes the ill-formed bytes to the output as is, so the (dump.md) itself must produce text, and `keep` there writes the ill-formed bytes to the output as is, so the
result is then not valid UTF-8 (but still equals the input bytes exactly, including around any well-formed result is then not valid UTF-8 (but still equals the input bytes exactly, including around any well-formed
characters, which are still escaped as usual) characters, which are still escaped as usual)
-11
View File
@@ -10,21 +10,12 @@ template<typename KeyType>
iterator find(KeyType&& key); iterator find(KeyType&& key);
template<typename KeyType> template<typename KeyType>
const_iterator find(KeyType&& key) const; const_iterator find(KeyType&& key) const;
// (3)
template<typename T>
iterator find(T) = delete;
template<typename T>
const_iterator find(T) const = delete;
``` ```
1. Finds an element in a JSON object with a key equivalent to `key`. If the element is not found or the 1. Finds an element in a JSON object with a key equivalent to `key`. If the element is not found or the
JSON value is not an object, `end()` is returned. JSON value is not an object, `end()` is returned.
2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and 2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and
`#!cpp typename object_comparator_t::is_transparent` denotes a type. `#!cpp typename object_comparator_t::is_transparent` denotes a type.
3. Deleted: this overload is only available if `T` is an integral type and is declared as deleted, so that a call with
an integer `key` (for example, `#!cpp j.find(0)`) fails to compile. Otherwise, the integer literal `0` would convert to
a null `#!cpp const char*` and, from there, to the key type, causing undefined behavior at runtime.
## Template parameters ## Template parameters
@@ -93,8 +84,6 @@ Logarithmic in the size of the JSON object.
- [count](count.md) returns the number of occurrences of a key - [count](count.md) returns the number of occurrences of a key
- [contains](contains.md) checks whether a key exists - [contains](contains.md) checks whether a key exists
- [basic_json_view::find](../basic_json_view/find.md) - the same lookup on a zero-copy view (a duplicate key resolves
to the first member, whereas `parse()` keeps the last)
## Version history ## Version history
@@ -124,8 +124,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been
deprecated in version 3.13.0. In version 4.0.0, this overload deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`. `#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`.
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
+1 -2
View File
@@ -110,8 +110,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been
deprecated in version 3.13.0. In version 4.0.0, this overload deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`. `#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`.
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
+1 -2
View File
@@ -126,8 +126,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_bson` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_bson` with a pointer and a length as first two parameters, which has been
deprecated in version 3.8.0. In version 4.0.0, this overload deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_bson(ptr, len, ...);` with `#!cpp from_bson(ptr, ptr+len, ...);`. `#!cpp from_bson(ptr, len, ...);` with `#!cpp from_bson(ptr, ptr+len, ...);`.
- Overload (2) replaces calls to `from_bson` with a pair of iterators as their first parameter, which has been - Overload (2) replaces calls to `from_bson` with a pair of iterators as their first parameter, which has been
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
+1 -2
View File
@@ -135,8 +135,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_cbor` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_cbor` with a pointer and a length as first two parameters, which has been
deprecated in version 3.8.0. In version 4.0.0, this overload deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_cbor(ptr, len, ...);` with `#!cpp from_cbor(ptr, ptr+len, ...);`. `#!cpp from_cbor(ptr, len, ...);` with `#!cpp from_cbor(ptr, ptr+len, ...);`.
- Overload (2) replaces calls to `from_cbor` with a pair of iterators as their first parameter, which has been - Overload (2) replaces calls to `from_cbor` with a pair of iterators as their first parameter, which has been
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
@@ -127,8 +127,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_msgpack` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_msgpack` with a pointer and a length as first two parameters, which has been
deprecated in version 3.8.0. In version 4.0.0, this overload deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_msgpack(ptr, len, ...);` with `#!cpp from_msgpack(ptr, ptr+len, ...);`. `#!cpp from_msgpack(ptr, len, ...);` with `#!cpp from_msgpack(ptr, ptr+len, ...);`.
- Overload (2) replaces calls to `from_msgpack` with a pair of iterators as their first parameter, which has been - Overload (2) replaces calls to `from_msgpack` with a pair of iterators as their first parameter, which has been
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
@@ -125,8 +125,7 @@ Linear in the size of the input.
!!! warning "Deprecation" !!! warning "Deprecation"
- Overload (2) replaces calls to `from_ubjson` with a pointer and a length as first two parameters, which has been - Overload (2) replaces calls to `from_ubjson` with a pointer and a length as first two parameters, which has been
deprecated in version 3.8.0. In version 4.0.0, this overload deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
will be deleted (`= delete`) rather than removed. Please replace all calls like
`#!cpp from_ubjson(ptr, len, ...);` with `#!cpp from_ubjson(ptr, ptr+len, ...);`. `#!cpp from_ubjson(ptr, len, ...);` with `#!cpp from_ubjson(ptr, ptr+len, ...);`.
- Overload (2) replaces calls to `from_ubjson` with a pair of iterators as their first parameter, which has been - Overload (2) replaces calls to `from_ubjson` with a pair of iterators as their first parameter, which has been
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
-2
View File
@@ -51,8 +51,6 @@ Constant.
## See also ## See also
- [back](back.md) to access the last element - [back](back.md) to access the last element
- [basic_json_view::front](../basic_json_view/front.md) - the same access on a zero-copy view (document order, not
sorted; duplicate keys are visited)
## Version history ## Version history
-2
View File
@@ -183,8 +183,6 @@ overload (3).
- [get_ref](get_ref.md) get a reference to the stored value - [get_ref](get_ref.md) get a reference to the stored value
- [operator ValueType](operator_ValueType.md) get a value via implicit conversion - [operator ValueType](operator_ValueType.md) get a value via implicit conversion
- [Converting values](../../features/conversions.md) - the type conversions article - [Converting values](../../features/conversions.md) - the type conversions article
- [basic_json_view::get](../basic_json_view/get.md) - the same conversion on a zero-copy view (many types are
converted without ever building a `basic_json` value)
## Version history ## Version history
@@ -61,8 +61,6 @@ Constant.
## See also ## See also
- [get_ptr()](get_ptr.md) get a pointer value - [get_ptr()](get_ptr.md) get a pointer value
- [basic_json_view::get_string](../basic_json_view/get_string.md) - the closest counterpart on a zero-copy view: a
string without a copy, but as a view rather than a reference to a value that must already exist
## Version history ## Version history
@@ -72,7 +72,6 @@ Depends on the `json_serializer<ValueType>::from_json()` implementation.
- [get_ref](get_ref.md) get a reference to the stored value - [get_ref](get_ref.md) get a reference to the stored value
- [get_ptr](get_ptr.md) get a pointer to the stored value - [get_ptr](get_ptr.md) get a pointer to the stored value
- [Converting values](../../features/conversions.md) - the type conversions article - [Converting values](../../features/conversions.md) - the type conversions article
- [basic_json_view::get_to](../basic_json_view/get_to.md) - the same conversion on a zero-copy view
## Version history ## Version history
+1 -2
View File
@@ -85,7 +85,7 @@ The class satisfies the following concept requirements:
- [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): JSON values can be compared with - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): JSON values can be compared with
`==`, see [`operator==`](operator_eq.md). `==`, see [`operator==`](operator_eq.md).
- [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): JSON values can be compared with - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): JSON values can be compared with
`<`, see [`operator<`](operator_lt.md). `<`, see [`operator<`](operator_le.md).
- [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): Any JSON lvalue or rvalue of can be swapped with - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): Any JSON lvalue or rvalue of can be swapped with
any lvalue or rvalue of other compatible types, using unqualified function `swap`. any lvalue or rvalue of other compatible types, using unqualified function `swap`.
- [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): JSON values can be compared against - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): JSON values can be compared against
@@ -285,7 +285,6 @@ Access to the JSON value
### JSON Merge Patch functions ### JSON Merge Patch functions
- [**merge_patch**](merge_patch.md) - applies a JSON Merge Patch - [**merge_patch**](merge_patch.md) - applies a JSON Merge Patch
- [**merge_diff**](merge_diff.md) (_static_) - creates a diff as a JSON Merge Patch
## Static functions ## Static functions
@@ -40,7 +40,6 @@ Constant.
- [is_structured](is_structured.md) checks whether the JSON value is structured (array or object) - [is_structured](is_structured.md) checks whether the JSON value is structured (array or object)
- [type](type.md) returns the type of the JSON value - [type](type.md) returns the type of the JSON value
- [array_t](array_t.md) the type used to store JSON arrays - [array_t](array_t.md) the type used to store JSON arrays
- [basic_json_view::is_array](../basic_json_view/is_array.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -39,7 +39,6 @@ Constant.
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive - [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [binary_t](binary_t.md) the type used to store binary values - [binary_t](binary_t.md) the type used to store binary values
- [get_binary](get_binary.md) returns a reference to the stored binary value - [get_binary](get_binary.md) returns a reference to the stored binary value
- [basic_json_view::is_binary](../basic_json_view/is_binary.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -38,7 +38,6 @@ Constant.
- [boolean_t](boolean_t.md) the type used to store JSON booleans - [boolean_t](boolean_t.md) the type used to store JSON booleans
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive - [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [basic_json_view::is_boolean](../basic_json_view/is_boolean.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -85,11 +85,6 @@ with `allow_exceptions` set to `#!cpp false`: a parse error then yields a discar
--8<-- "examples/is_discarded__parse.output" --8<-- "examples/is_discarded__parse.output"
``` ```
## See also
- [basic_json_view::is_discarded](../basic_json_view/is_discarded.md) - the corresponding check on a zero-copy view,
which is `#!cpp true` if the view refers to no value
## Version history ## Version history
- Added in version 1.0.0. - Added in version 1.0.0.
@@ -40,7 +40,6 @@ Constant.
- [is_object](is_object.md) checks whether the JSON value is an object - [is_object](is_object.md) checks whether the JSON value is an object
- [type](type.md) returns the type of the JSON value - [type](type.md) returns the type of the JSON value
- [value_t](value_t.md) the enumeration of JSON types - [value_t](value_t.md) the enumeration of JSON types
- [basic_json_view::is_null](../basic_json_view/is_null.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -49,7 +49,6 @@ constexpr bool is_number() const noexcept
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number - [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number - [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number - [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number](../basic_json_view/is_number.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -40,7 +40,6 @@ Constant.
- [is_number()](is_number.md) check if the value is a number - [is_number()](is_number.md) check if the value is a number
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number - [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number - [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [basic_json_view::is_number_float](../basic_json_view/is_number_float.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -40,7 +40,6 @@ Constant.
- [is_number()](is_number.md) check if the value is a number - [is_number()](is_number.md) check if the value is a number
- [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number - [is_number_unsigned()](is_number_unsigned.md) check if the value is an unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number - [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number_integer](../basic_json_view/is_number_integer.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -7,9 +7,6 @@ constexpr bool is_number_unsigned() const noexcept;
This function returns `#!cpp true` if and only if the JSON value is an unsigned integer number. This excludes This function returns `#!cpp true` if and only if the JSON value is an unsigned integer number. This excludes
floating-point and signed integer values. floating-point and signed integer values.
If [`number_unsigned_t`](number_unsigned_t.md) is the same type as [`number_integer_t`](number_integer_t.md), every
integer is stored as `number_integer_t`, and this function always returns `#!cpp false`.
## Return value ## Return value
`#!cpp true` if type is an unsigned integer number, `#!cpp false` otherwise. `#!cpp true` if type is an unsigned integer number, `#!cpp false` otherwise.
@@ -43,7 +40,6 @@ Constant.
- [is_number()](is_number.md) check if the value is a number - [is_number()](is_number.md) check if the value is a number
- [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number - [is_number_integer()](is_number_integer.md) check if the value is an integer or unsigned integer number
- [is_number_float()](is_number_float.md) check if the value is a floating-point number - [is_number_float()](is_number_float.md) check if the value is a floating-point number
- [basic_json_view::is_number_unsigned](../basic_json_view/is_number_unsigned.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -40,7 +40,6 @@ Constant.
- [is_structured](is_structured.md) checks whether the JSON value is structured (array or object) - [is_structured](is_structured.md) checks whether the JSON value is structured (array or object)
- [type](type.md) returns the type of the JSON value - [type](type.md) returns the type of the JSON value
- [object_t](object_t.md) the type used to store JSON objects - [object_t](object_t.md) the type used to store JSON objects
- [basic_json_view::is_object](../basic_json_view/is_object.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -62,7 +62,6 @@ This library extends primitive types to binary types, because binary types are r
- [is_boolean()](is_boolean.md) returns whether the JSON value is a boolean - [is_boolean()](is_boolean.md) returns whether the JSON value is a boolean
- [is_number()](is_number.md) returns whether the JSON value is a number - [is_number()](is_number.md) returns whether the JSON value is a number
- [is_binary()](is_binary.md) returns whether the JSON value is a binary array - [is_binary()](is_binary.md) returns whether the JSON value is a binary array
- [basic_json_view::is_primitive](../basic_json_view/is_primitive.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -39,7 +39,6 @@ Constant.
- [is_primitive](is_primitive.md) checks whether the JSON value is primitive - [is_primitive](is_primitive.md) checks whether the JSON value is primitive
- [type](type.md) returns the type of the JSON value - [type](type.md) returns the type of the JSON value
- [string_t](string_t.md) the type used to store JSON strings - [string_t](string_t.md) the type used to store JSON strings
- [basic_json_view::is_string](../basic_json_view/is_string.md) - the same check on a zero-copy view
## Version history ## Version history
@@ -57,7 +57,6 @@ Note that though strings are containers in C++, they are treated as primitive va
- [is_primitive()](is_primitive.md) returns whether JSON value is primitive - [is_primitive()](is_primitive.md) returns whether JSON value is primitive
- [is_array()](is_array.md) returns whether the value is an array - [is_array()](is_array.md) returns whether the value is an array
- [is_object()](is_object.md) returns whether the value is an object - [is_object()](is_object.md) returns whether the value is an object
- [basic_json_view::is_structured](../basic_json_view/is_structured.md) - the same check on a zero-copy view
## Version history ## Version history
-2
View File
@@ -99,8 +99,6 @@ When iterating over an array, `key()` will return the index of the element as st
- [begin](begin.md) returns an iterator to the first element - [begin](begin.md) returns an iterator to the first element
- [end](end.md) returns an iterator to one past the last element - [end](end.md) returns an iterator to one past the last element
- [basic_json_view::items](../basic_json_view/items.md) - the same range on a zero-copy view (`#!cpp const auto`,
not `#!cpp const auto&`: items are produced on the fly; document order, not sorted; duplicate keys are visited)
## Version history ## Version history
@@ -62,5 +62,5 @@ same name. Hidden members remain accessible via [`as_base_class`](as_base_class.
## Version history ## Version history
- Added in version 3.11.3. - Added in version 3.12.0.
- Made a public member type in version 3.13.0; it was private before, so it could not be named outside the class. - Made a public member type in version 3.13.0; it was private before, so it could not be named outside the class.
@@ -1,79 +0,0 @@
# <small>nlohmann::basic_json::</small>merge_diff
```cpp
static basic_json merge_diff(const basic_json& source,
const basic_json& target);
```
Creates a [JSON Merge Patch](https://tools.ietf.org/html/rfc7396) so that value `source` can be changed into the value
`target` by calling the [`merge_patch`](merge_patch.md) function. The patch contains only what differs: changed and
added members with their new values, and removed members with the value `#!json null`. Nested objects are compared
member by member; any other value that differs, including an array, is replaced as a whole.
For two JSON values `source` and `target`, where `target` contains no object member whose value is `#!json null`, the
following code always yields `#!cpp true` (for [`ordered_json`](../ordered_json.md), see the notes below):
```cpp
basic_json patched = source;
patched.merge_patch(merge_diff(source, target));
patched == target;
```
## Parameters
`source` (in)
: JSON value to compare from
`target` (in)
: JSON value to compare against
## Return value
a JSON Merge Patch to convert the `source` to `target`
## Exception safety
Strong guarantee: `source` and `target` are never modified.
## Complexity
Linear in the total number of values (including nested ones) in `source` and `target`, times the cost of a key-based
object operation (looking up a key, or adding one to the patch): logarithmic for [`json`](../json.md), and linear for
[`ordered_json`](../ordered_json.md) (see [`ordered_map` complexity](../ordered_map.md#complexity)). For
`ordered_json`, diffing two objects with `n` and `m` members therefore takes O((n+m)²).
## Notes
- A merge patch uses `#!json null` to remove a member, so it cannot set a member to `#!json null`. As in RFC 7396, a
`#!json null` member of `target` is treated as absent: the patch removes the member from `source` instead of setting
it to `#!json null`. A member that is `#!json null` in both `source` and `target` is unchanged and left out of the
patch, so `source` keeps it.
- A merge patch cannot reorder object members, and [`merge_patch`](merge_patch.md) appends added members at the end.
For [`ordered_json`](../ordered_json.md), the patched value therefore has the same members as `target`, but not
necessarily in the same order, and may compare unequal to it. The patch lists changed and removed members in the
order of `source`, followed by added members in the order of `target`.
## Examples
??? example
The following code shows how a JSON Merge Patch is created as a diff for two JSON values.
```cpp
--8<-- "examples/merge_diff.cpp"
```
Output:
```json
--8<-- "examples/merge_diff.output"
```
## See also
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
- [merge_patch](merge_patch.md) applies a JSON Merge Patch
- [diff](diff.md) creates a diff as a JSON Patch
## Version history
- Added in version 3.13.0.
@@ -67,7 +67,6 @@ returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was
- [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
- [patch](patch.md) apply a JSON patch - [patch](patch.md) apply a JSON patch
- [merge_diff](merge_diff.md) creates a diff as a JSON Merge Patch
## Version history ## Version history
@@ -23,10 +23,9 @@ type to use.
## Template parameters ## Template parameters
`NumberFloatType` `NumberFloatType`
: the type to store floating-point numbers. The type must be `#!cpp float`, `#!cpp double`, or : the type to store floating-point numbers. Parsing and serialization are implemented in terms of
`#!cpp long double`. The parser converts `#!cpp float`, `#!cpp double`, and a `#!cpp long double` that is IEEE 754 `#!cpp std::strtof`/`#!cpp std::strtod`/`#!cpp std::strtold` and `#!cpp std::snprintf`, so the type must be
binary64 itself. It converts other `#!cpp long double` formats with `#!cpp std::from_chars` where available, or `#!cpp float`, `#!cpp double`, or `#!cpp long double`. The
with `#!cpp std::strtold` otherwise. Serialization falls back to `#!cpp std::snprintf`. The
[binary formats](../../features/binary_formats/index.md) additionally require `#!cpp float` or `#!cpp double`, [binary formats](../../features/binary_formats/index.md) additionally require `#!cpp float` or `#!cpp double`,
because they have no encoding for `#!cpp long double`. See because they have no encoding for `#!cpp long double`. See
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype). [Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
@@ -35,7 +34,7 @@ type to use.
### Default type ### Default type
With the default values for `NumberFloatType` (`double`), the default type for `number_float_t` is `#!cpp double`. With the default values for `NumberFloatType` (`double`), the default value for `number_float_t` is `#!cpp double`.
### Default behavior ### Default behavior
@@ -52,11 +51,9 @@ With the default values for `NumberFloatType` (`double`), the default type for `
> interoperability can be achieved by implementations that expect no more precision or range than these provide, in the > interoperability can be achieved by implementations that expect no more precision or range than these provide, in the
> sense that implementations will approximate JSON numbers within the expected precision. > sense that implementations will approximate JSON numbers within the expected precision.
This implementation does exactly follow this approach, as it uses double precision floating-point numbers by default. This implementation does exactly follow this approach, as it uses double precision floating-point numbers. Note values
Note that with the default `double`, numbers smaller than `-1.79769313486232e+308` or greater than smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally
`1.79769313486232e+308` are rejected during parsing with and be serialized to `null`.
[`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406). Non-finite values (NaN and infinity) can
only be stored by assigning them directly and are serialized to `null`.
During deserialization (from JSON text or any of the binary formats), a finite number that does not fit into During deserialization (from JSON text or any of the binary formats), a finite number that does not fit into
`number_float_t` is rejected with [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406), for `number_float_t` is rejected with [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406), for
@@ -31,7 +31,7 @@ to use.
### Default type ### Default type
With the default values for `NumberIntegerType` (`std::int64_t`), the default type for `number_integer_t` is With the default values for `NumberIntegerType` (`std::int64_t`), the default value for `number_integer_t` is
`#!cpp std::int64_t`. `#!cpp std::int64_t`.
### Default behavior ### Default behavior
@@ -25,15 +25,14 @@ the type to use.
`NumberUnsignedType` `NumberUnsignedType`
: the type to store unsigned integers. It must be an **unsigned integral** type (`#!cpp std::is_integral`) with a : the type to store unsigned integers. It must be an **unsigned integral** type (`#!cpp std::is_integral`) with a
`#!cpp std::numeric_limits` specialization, and it must be able to represent the absolute value of every `#!cpp std::numeric_limits` specialization, and it must be able to represent the absolute value of every
[`number_integer_t`](number_integer_t.md) value. Alternatively, it can be the same type as [`number_integer_t`](number_integer_t.md) value. See
[`number_integer_t`](number_integer_t.md); then every integer is stored as `number_integer_t`. See
[Template Parameter Requirements](../../features/types/template_parameters.md#numberintegertype-and-numberunsignedtype). [Template Parameter Requirements](../../features/types/template_parameters.md#numberintegertype-and-numberunsignedtype).
## Notes ## Notes
### Default type ### Default type
With the default values for `NumberUnsignedType` (`std::uint64_t`), the default type for `number_unsigned_t` is With the default values for `NumberUnsignedType` (`std::uint64_t`), the default value for `number_unsigned_t` is
`#!cpp std::uint64_t`. `#!cpp std::uint64_t`.
### Default behavior ### Default behavior
@@ -90,4 +89,3 @@ Integer number values are stored directly inside a `basic_json` type.
## Version history ## Version history
- Added in version 2.0.0. - Added in version 2.0.0.
- Can be the same type as `number_integer_t` since version 3.13.0.
+1 -1
View File
@@ -36,7 +36,7 @@ To store objects in C++, a type is defined by the template parameters described
### Default type ### Default type
With the default values for `ObjectType` (`std::map`), `StringType` (`std::string`), and `AllocatorType` With the default values for `ObjectType` (`std::map`), `StringType` (`std::string`), and `AllocatorType`
(`std::allocator`), the default type for `object_t` is: (`std::allocator`), the default value for `object_t` is:
```cpp ```cpp
// until C++14 // until C++14
+8 -10
View File
@@ -137,10 +137,13 @@ Strong exception safety: if an exception occurs, the original value stays intact
When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing When the JSON pointer traverses intermediate levels that don't exist at all yet (not just a missing
leaf), each missing level is created as an array or an object depending on whether the corresponding leaf), each missing level is created as an array or an object depending on whether the corresponding
pointer token parses as a non-negative integer: a numeric token creates an array, a non-numeric token pointer token is a valid array index: the token `0`, a sequence of digits that does not begin with `0`,
creates an object. For example, on an initially `#!json null` value, `/foo/0/0/0` creates nested arrays, or the token `-` creates an array, and every other token creates an object. For example, on an
while `/foo/one/one/one` creates nested objects. This is not specified by the JSON Pointer RFC; it is initially `#!json null` value, `/foo/0/0/0` creates nested arrays, while `/foo/one/one/one` creates
this library's own, intentional disambiguation rule. See also [JSON Pointer](../../features/json_pointer.md). nested objects. Tokens such as `01` or the empty token cannot be array indices (cf. RFC 6901, Sect. 4)
and therefore create objects, just as they would if the level already existed as an object. This is not
specified by the JSON Pointer RFC; it is this library's own, intentional disambiguation rule. See also
[JSON Pointer](../../features/json_pointer.md).
!!! warning "Deprecation" !!! warning "Deprecation"
@@ -275,9 +278,6 @@ Strong exception safety: if an exception occurs, the original value stays intact
- documentation on [runtime assertions](../../features/assertions.md) - documentation on [runtime assertions](../../features/assertions.md)
- see [`at`](at.md) for access by reference with range checking - see [`at`](at.md) for access by reference with range checking
- see [`value`](value.md) for access with default value - see [`value`](value.md) for access with default value
- [basic_json_view::operator[]](../basic_json_view/operator%5B%5D.md) - the same access on a zero-copy view (a duplicate
key resolves to the first member, whereas `parse()` keeps the last; a missing key gives a discarded view instead of
undefined behavior)
## Version history ## Version history
@@ -289,6 +289,4 @@ Strong exception safety: if an exception occurs, the original value stays intact
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as 3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
already supported by [`at`](at.md), [`value`](value.md), [`find`](find.md), and other lookup functions. already supported by [`at`](at.md), [`value`](value.md), [`find`](find.md), and other lookup functions.
4. Added in version 2.0.0. A missing array index in the const version is guarded by a runtime assertion since 4. Added in version 2.0.0. A missing array index in the const version is guarded by a runtime assertion since
version 3.13.0. Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of version 3.13.0.
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is not
a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
@@ -11,17 +11,18 @@ template<typename ScalarType>
bool operator==(ScalarType lhs, const const_reference rhs) noexcept(/* see below */); // (2) bool operator==(ScalarType lhs, const const_reference rhs) noexcept(/* see below */); // (2)
// since C++20 // since C++20
class basic_json {
bool operator==(const_reference rhs) const noexcept; // (1) bool operator==(const_reference rhs) const noexcept; // (1)
template<typename ScalarType> template<typename ScalarType>
bool operator==(ScalarType rhs) const noexcept(/* see below */); // (2) bool operator==(ScalarType rhs) const noexcept(/* see below */); // (2)
};
``` ```
1. Compares two JSON values for equality according to the following rules: 1. Compares two JSON values for equality according to the following rules:
- Two JSON values are equal if (1) neither value is discarded, and (2) they are of the same type and their stored - Two JSON values are equal if (1) neither value is discarded, and (2) they are of the same type and their stored
values are the same according to their respective `operator==`. values are the same according to their respective `operator==`.
- Integer and floating-point numbers are compared by their exact values, without converting the integer to - Integer and floating-point numbers are automatically converted before comparison.
floating-point. For instance, `9007199254740993` and `9007199254740992.0` are not equal.
2. Compares a JSON value and a scalar or a scalar and a JSON value for equality by converting the 2. Compares a JSON value and a scalar or a scalar and a JSON value for equality by converting the
scalar to a JSON value and comparing both JSON values according to 1. scalar to a JSON value and comparing both JSON values according to 1.
@@ -170,8 +171,6 @@ Linear.
- [operator!=](operator_ne.md) compare for inequality - [operator!=](operator_ne.md) compare for inequality
- [operator<=>](operator_spaceship.md) comparison: 3-way (C++20) - [operator<=>](operator_spaceship.md) comparison: 3-way (C++20)
- [basic_json_view::operator==](../basic_json_view/operator_eq.md) - the same comparison on a zero-copy view, without
building a `basic_json` value for it
## Version history ## Version history
@@ -15,8 +15,7 @@ bool operator<(ScalarType lhs, const const_reference rhs) noexcept(/* see below
following rules: following rules:
- If either operand is discarded, the comparison yields `#!cpp false`. - If either operand is discarded, the comparison yields `#!cpp false`.
- If both operands have the same type, the values are compared using their respective `operator<`. - If both operands have the same type, the values are compared using their respective `operator<`.
- Integer and floating-point numbers are compared by their exact values, without converting the integer to - Integer and floating-point numbers are automatically converted before comparison.
floating-point. For instance, `9007199254740992.0` is less than `9007199254740993`.
- In case `lhs` and `rhs` have different types, the values are ignored and the order of the types - In case `lhs` and `rhs` have different types, the values are ignored and the order of the types
is considered, which is: is considered, which is:
1. null 1. null
Loaded 100 of 529 files, more files were not shown because too many files have changed in this diff. Show more