Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
589c29d69b | ||
|
|
80fd9c0fb4 | ||
|
|
169f1fcb2d | ||
|
|
020a834128 | ||
|
|
7dcff6b8cd | ||
|
|
769c5cde57 | ||
|
|
993e37e7ec |
No files matched your search
@@ -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
@@ -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.
|
||||||
|
|
||||||
|
|||||||
+24
-19
@@ -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
|
||||||
@@ -108,9 +108,16 @@ The tests are located in [`tests/src/unit-*.cpp`](https://github.com/nlohmann/js
|
|||||||
are structured along the features of the library or the nature of the tests. Usually, it should be clear from the
|
are structured along the features of the library or the nature of the tests. Usually, it should be clear from the
|
||||||
context which existing file needs to be extended, and only very few cases require creating new test files.
|
context which existing file needs to be extended, and only very few cases require creating new test files.
|
||||||
|
|
||||||
When fixing a bug, edit `unit-regression3.cpp` and add a section referencing the fixed issue.
|
When fixing a bug, edit `unit-regression3.cpp` and add a section referencing the fixed issue. Tests that need C++17 or
|
||||||
`unit-regression2.cpp` holds the older tests; the two files exist because a single one grew large enough for the
|
C++20 go into `unit-regression3-cpp17.cpp` or `unit-regression3-cpp20.cpp` instead, so the large file is not rebuilt
|
||||||
MinGW linker to fail relocating it, so please keep adding to the smaller file rather than growing the larger one.
|
for every C++ standard. `unit-regression2.cpp` holds the older tests; the two files exist because a single one grew
|
||||||
|
large enough for the MinGW linker to fail relocating it, so please keep adding to the smaller file rather than growing
|
||||||
|
the larger one.
|
||||||
|
|
||||||
|
To keep compile times down, several test files are compiled together as one translation unit. This sets a few rules
|
||||||
|
for test files, such as giving file-scope helpers file-specific names. See the README in the
|
||||||
|
[`tests`](https://github.com/nlohmann/json/tree/develop/tests) folder for how the tests are built and what to keep in
|
||||||
|
mind when adding them.
|
||||||
|
|
||||||
#### Exceptions
|
#### Exceptions
|
||||||
|
|
||||||
@@ -149,17 +156,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 +186,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 +225,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 +243,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.
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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/.*"
|
||||||
|
|||||||
@@ -83,7 +83,8 @@ jobs:
|
|||||||
# byte for byte), so there is nothing to gain from checking out a
|
# byte for byte), so there is nothing to gain from checking out a
|
||||||
# separate copy, and doing so would make this step fail on a PR
|
# separate copy, and doing so would make this step fail on a PR
|
||||||
# that adds support for a new dispatch table until that PR itself
|
# that adds support for a new dispatch table until that PR itself
|
||||||
# merges to develop.
|
# 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"
|
||||||
@@ -116,6 +117,7 @@ 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 .
|
||||||
|
cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
|
||||||
|
|
||||||
# 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
|
||||||
@@ -136,13 +138,17 @@ 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
|
||||||
|
# Pass --version explicitly so this step also works with the tool
|
||||||
|
# copy from develop before this repository's own generate_natvis.py
|
||||||
|
# learns to derive the version itself: the older script requires
|
||||||
|
# --version, and the newer one accepts it as an explicit override.
|
||||||
|
ABI_MACROS=include/nlohmann/detail/abi_macros.hpp
|
||||||
|
VERSION_MAJOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MAJOR' $ABI_MACROS | grep -o '[0-9]\+')
|
||||||
|
VERSION_MINOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MINOR' $ABI_MACROS | grep -o '[0-9]\+')
|
||||||
|
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
|
# The template is what this check verifies the committed natvis
|
||||||
# file against, so take it from this PR rather than from the
|
# file against, so take it from this PR rather than from the
|
||||||
# develop checkout: generate_natvis.py loads the template from its
|
# develop checkout: generate_natvis.py loads the template from its
|
||||||
@@ -150,7 +156,7 @@ jobs:
|
|||||||
# template could never pass. Like the macro_builder step above,
|
# template could never pass. Like the macro_builder step above,
|
||||||
# this only renders PR content in a job without credentials.
|
# this only renders PR content in a job without credentials.
|
||||||
cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
|
cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
|
||||||
python3 $NATVIS_TOOL_DIR/generate_natvis.py $MAIN_DIR
|
python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
|
||||||
|
|
||||||
- name: Build patch and check for differences
|
- name: Build patch and check for differences
|
||||||
id: diff
|
id: diff
|
||||||
@@ -159,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
|
||||||
|
|||||||
@@ -96,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'
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
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@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
@@ -117,7 +117,6 @@ jobs:
|
|||||||
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:
|
||||||
@@ -280,7 +279,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Get latest CMake and ninja
|
- name: Get latest CMake and ninja
|
||||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
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
|
||||||
|
|||||||
@@ -187,7 +187,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:
|
||||||
@@ -217,10 +217,8 @@ jobs:
|
|||||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
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
-14
@@ -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,17 +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
|
|
||||||
@@ -81,7 +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",
|
|
||||||
],
|
],
|
||||||
includes = ["single_include"],
|
includes = ["single_include"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
|||||||
+1
-1
@@ -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
@@ -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()
|
||||||
|
|||||||
@@ -14,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.
|
||||||
@@ -24,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:
|
||||||
|
|
||||||
@@ -268,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.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
module(
|
module(
|
||||||
name = "nlohmann_json",
|
name = "nlohmann_json",
|
||||||
version = "3.12.0",
|
|
||||||
compatibility_level = 1,
|
compatibility_level = 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -41,18 +41,12 @@ all:
|
|||||||
@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"
|
@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"
|
||||||
|
|
||||||
@@ -114,18 +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)
|
||||||
|
|
||||||
NATVIS_VENV=tools/generate_natvis/venv
|
|
||||||
|
|
||||||
# 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 .
|
|
||||||
|
|
||||||
# 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; \
|
||||||
@@ -142,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) 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); 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) 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:
|
||||||
@@ -223,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
- [Pkg-config](#pkg-config)
|
- [Pkg-config](#pkg-config)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
- [Contact](#contact)
|
- [Contact](#contact)
|
||||||
- [Security](#security)
|
|
||||||
- [Thanks](#thanks)
|
- [Thanks](#thanks)
|
||||||
- [Used third-party tools](#used-third-party-tools)
|
- [Used third-party tools](#used-third-party-tools)
|
||||||
- [Notes](#notes)
|
- [Notes](#notes)
|
||||||
@@ -113,9 +112,9 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t
|
|||||||
|
|
||||||
## Quick reference
|
## Quick reference
|
||||||
|
|
||||||
- **Constructors**: [basic_json](https://json.nlohmann.me/api/basic_json/basic_json), [array](https://json.nlohmann.me/api/basic_json/array), [binary](https://json.nlohmann.me/api/basic_json/binary), [object](https://json.nlohmann.me/api/basic_json/object)
|
- **Constructors** [basic_json](https://json.nlohmann.me/api/basic_json/basic_json), [array](https://json.nlohmann.me/api/basic_json/array), [binary](https://json.nlohmann.me/api/basic_json/binary), [object](https://json.nlohmann.me/api/basic_json/object)
|
||||||
- **Object inspection**: [type](https://json.nlohmann.me/api/basic_json/type), [operator value_t](https://json.nlohmann.me/api/basic_json/operator_value_t), [type_name](https://json.nlohmann.me/api/basic_json/type_name), [is_primitive](https://json.nlohmann.me/api/basic_json/is_primitive), [is_structured](https://json.nlohmann.me/api/basic_json/is_structured), [is_null](https://json.nlohmann.me/api/basic_json/is_null), [is_boolean](https://json.nlohmann.me/api/basic_json/is_boolean), [is_number](https://json.nlohmann.me/api/basic_json/is_number), [is_number_integer](https://json.nlohmann.me/api/basic_json/is_number_integer), [is_number_unsigned](https://json.nlohmann.me/api/basic_json/is_number_unsigned), [is_number_float](https://json.nlohmann.me/api/basic_json/is_number_float), [is_object](https://json.nlohmann.me/api/basic_json/is_object), [is_array](https://json.nlohmann.me/api/basic_json/is_array), [is_string](https://json.nlohmann.me/api/basic_json/is_string), [is_binary](https://json.nlohmann.me/api/basic_json/is_binary), [is_discarded](https://json.nlohmann.me/api/basic_json/is_discarded)
|
- **Object inspection**: [type](https://json.nlohmann.me/api/basic_json/type), [operator value_t](https://json.nlohmann.me/api/basic_json/operator_value_t), [type_name](https://json.nlohmann.me/api/basic_json/type_name), [is_primitive](https://json.nlohmann.me/api/basic_json/is_primitive), [is_structured](https://json.nlohmann.me/api/basic_json/is_structured), [is_null](https://json.nlohmann.me/api/basic_json/is_null), [is_boolean](https://json.nlohmann.me/api/basic_json/is_boolean), [is_number](https://json.nlohmann.me/api/basic_json/is_number), [is_number_integer](https://json.nlohmann.me/api/basic_json/is_number_integer), [is_number_unsigned](https://json.nlohmann.me/api/basic_json/is_number_unsigned), [is_number_float](https://json.nlohmann.me/api/basic_json/is_number_float), [is_object](https://json.nlohmann.me/api/basic_json/is_object), [is_array](https://json.nlohmann.me/api/basic_json/is_array), [is_string](https://json.nlohmann.me/api/basic_json/is_string), [is_binary](https://json.nlohmann.me/api/basic_json/is_binary), [is_discarded](https://json.nlohmann.me/api/basic_json/is_discarded)
|
||||||
- **Value access**: [get](https://json.nlohmann.me/api/basic_json/get), [get_to](https://json.nlohmann.me/api/basic_json/get_to), [get_ptr](https://json.nlohmann.me/api/basic_json/get_ptr), [get_ref](https://json.nlohmann.me/api/basic_json/get_ref), [operator ValueType](https://json.nlohmann.me/api/basic_json/operator_ValueType), [get_binary](https://json.nlohmann.me/api/basic_json/get_binary)
|
- **Value access**; [get](https://json.nlohmann.me/api/basic_json/get), [get_to](https://json.nlohmann.me/api/basic_json/get_to), [get_ptr](https://json.nlohmann.me/api/basic_json/get_ptr), [get_ref](https://json.nlohmann.me/api/basic_json/get_ref), [operator ValueType](https://json.nlohmann.me/api/basic_json/operator_ValueType), [get_binary](https://json.nlohmann.me/api/basic_json/get_binary)
|
||||||
- **Element access**: [at](https://json.nlohmann.me/api/basic_json/at), [operator[]](https://json.nlohmann.me/api/basic_json/operator[]), [value](https://json.nlohmann.me/api/basic_json/value), [front](https://json.nlohmann.me/api/basic_json/front), [back](https://json.nlohmann.me/api/basic_json/back)
|
- **Element access**: [at](https://json.nlohmann.me/api/basic_json/at), [operator[]](https://json.nlohmann.me/api/basic_json/operator[]), [value](https://json.nlohmann.me/api/basic_json/value), [front](https://json.nlohmann.me/api/basic_json/front), [back](https://json.nlohmann.me/api/basic_json/back)
|
||||||
- **Lookup**: [find](https://json.nlohmann.me/api/basic_json/find), [count](https://json.nlohmann.me/api/basic_json/count), [contains](https://json.nlohmann.me/api/basic_json/contains)
|
- **Lookup**: [find](https://json.nlohmann.me/api/basic_json/find), [count](https://json.nlohmann.me/api/basic_json/count), [contains](https://json.nlohmann.me/api/basic_json/contains)
|
||||||
- **Iterators**: [begin](https://json.nlohmann.me/api/basic_json/begin), [cbegin](https://json.nlohmann.me/api/basic_json/cbegin), [end](https://json.nlohmann.me/api/basic_json/end), [cend](https://json.nlohmann.me/api/basic_json/cend), [rbegin](https://json.nlohmann.me/api/basic_json/rbegin), [rend](https://json.nlohmann.me/api/basic_json/rend), [crbegin](https://json.nlohmann.me/api/basic_json/crbegin), [crend](https://json.nlohmann.me/api/basic_json/crend), [items](https://json.nlohmann.me/api/basic_json/items)
|
- **Iterators**: [begin](https://json.nlohmann.me/api/basic_json/begin), [cbegin](https://json.nlohmann.me/api/basic_json/cbegin), [end](https://json.nlohmann.me/api/basic_json/end), [cend](https://json.nlohmann.me/api/basic_json/cend), [rbegin](https://json.nlohmann.me/api/basic_json/rbegin), [rend](https://json.nlohmann.me/api/basic_json/rend), [crbegin](https://json.nlohmann.me/api/basic_json/crbegin), [crend](https://json.nlohmann.me/api/basic_json/crend), [items](https://json.nlohmann.me/api/basic_json/items)
|
||||||
@@ -1185,7 +1184,7 @@ binary[1]; // 0xFE
|
|||||||
binary.set_subtype(0x10);
|
binary.set_subtype(0x10);
|
||||||
|
|
||||||
// serialize to MessagePack
|
// serialize to MessagePack
|
||||||
auto msgpack = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
|
auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
|
||||||
```
|
```
|
||||||
|
|
||||||
## Customers
|
## Customers
|
||||||
@@ -1221,7 +1220,17 @@ I would be happy to learn about other compilers/versions.
|
|||||||
Please note:
|
Please note:
|
||||||
|
|
||||||
- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler.
|
- GCC 4.8 has a bug [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824): multiline raw strings cannot be the arguments to macros. Don't use multiline raw strings directly in macros with this compiler.
|
||||||
- For GCC running on MinGW or Android, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod` or `strtof`) may occur. Note this is not an issue with the code, but rather with the compiler or C++ standard library itself: use a recent toolchain (for Android, a current [NDK](https://developer.android.com/ndk) with the LLVM C++ library `APP_STL := c++_shared`, and for MinGW, a distribution with a complete C++11 standard library). See [this discussion](https://github.com/nlohmann/json/issues/136) for MinGW and [this discussion](https://github.com/nlohmann/json/issues/219) for the old Android NDK using `APP_STL := gnustl_static`.
|
- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
APP_STL := c++_shared
|
||||||
|
NDK_TOOLCHAIN_VERSION := clang3.6
|
||||||
|
APP_CPPFLAGS += -frtti -fexceptions
|
||||||
|
```
|
||||||
|
|
||||||
|
The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10.
|
||||||
|
|
||||||
|
- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod` or `strtof`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](https://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
|
||||||
|
|
||||||
- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case.
|
- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case.
|
||||||
|
|
||||||
@@ -1387,7 +1396,7 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
|||||||
- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
||||||
- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||||
- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
||||||
- The class contains an adapted version of the Eisel-Lemire algorithm, its table of powers of five, and its digit comparison for long numbers from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
- The class contains an adapted version of the Eisel-Lemire algorithm and its table of powers of five from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
||||||
|
|
||||||
<img align="right" src="https://git.fsfe.org/reuse/reuse-ci/raw/branch/master/reuse-horizontal.png" alt="REUSE Software">
|
<img align="right" src="https://git.fsfe.org/reuse/reuse-ci/raw/branch/master/reuse-horizontal.png" alt="REUSE Software">
|
||||||
|
|
||||||
@@ -1428,416 +1437,436 @@ I deeply appreciate the help of the following people.
|
|||||||
12. [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual Studio.
|
12. [kepkin](https://github.com/kepkin) patiently pushed forward the support for Microsoft Visual Studio.
|
||||||
13. [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types.
|
13. [gregmarr](https://github.com/gregmarr) simplified the implementation of reverse iterators and helped with numerous hints and improvements. In particular, he pushed forward the implementation of user-defined types.
|
||||||
14. [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling.
|
14. [Caio Luppi](https://github.com/caiovlp) fixed a bug in the Unicode handling.
|
||||||
15. [dariomt](https://github.com/dariomt) fixed some typos in the examples and fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values.
|
15. [dariomt](https://github.com/dariomt) fixed some typos in the examples.
|
||||||
16. [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation.
|
16. [Daniel Frey](https://github.com/d-frey) cleaned up some pointers and implemented exception-safe memory allocation.
|
||||||
17. [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue.
|
17. [Colin Hirsch](https://github.com/ColinH) took care of a small namespace issue.
|
||||||
18. [Huu Nguyen](https://github.com/whoshuu) corrected a variable name in the documentation.
|
18. [Huu Nguyen](https://github.com/whoshuu) corrected a variable name in the documentation.
|
||||||
19. [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference.
|
19. [Silverweed](https://github.com/silverweed) overloaded `parse()` to accept an rvalue reference.
|
||||||
20. [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
20. [dariomt](https://github.com/dariomt) fixed a subtlety in MSVC type support and implemented the `get_ref()` function to get a reference to stored values.
|
||||||
21. [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
21. [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
||||||
22. [406345](https://github.com/406345) fixed two small warnings.
|
22. [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
||||||
23. [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
|
23. [406345](https://github.com/406345) fixed two small warnings.
|
||||||
24. [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
|
24. [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
|
||||||
25. [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers and implemented better roundtrip support for parsed numbers.
|
25. [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
|
||||||
26. [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file.
|
26. [twelsby](https://github.com/twelsby) fixed the array subscript operator, an issue that failed the MSVC build, and floating-point parsing/dumping. He further added support for unsigned integer numbers and implemented better roundtrip support for parsed numbers.
|
||||||
27. [msm-](https://github.com/msm-) added support for American Fuzzy Lop.
|
27. [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file.
|
||||||
28. [Annihil](https://github.com/Annihil) fixed an example in the README file.
|
28. [msm-](https://github.com/msm-) added support for American Fuzzy Lop.
|
||||||
29. [Themercee](https://github.com/Themercee) noted a wrong URL in the README file.
|
29. [Annihil](https://github.com/Annihil) fixed an example in the README file.
|
||||||
30. [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`.
|
30. [Themercee](https://github.com/Themercee) noted a wrong URL in the README file.
|
||||||
31. [abc100m](https://github.com/abc100m) analyzed the issues with GCC 4.8 and proposed a [partial solution](https://github.com/nlohmann/json/pull/212).
|
31. [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`.
|
||||||
32. [zewt](https://github.com/zewt) added useful notes to the README file about Android.
|
32. [abc100m](https://github.com/abc100m) analyzed the issues with GCC 4.8 and proposed a [partial solution](https://github.com/nlohmann/json/pull/212).
|
||||||
33. [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
|
33. [zewt](https://github.com/zewt) added useful notes to the README file about Android.
|
||||||
34. [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
|
34. [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
|
||||||
35. [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
|
35. [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
|
||||||
36. [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
36. [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
|
||||||
37. [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
37. [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
||||||
38. [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
38. [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
||||||
39. [Thomas Braun](https://github.com/t-b) fixed a warning in a test case and adjusted MSVC calls in the CI.
|
39. [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
||||||
40. [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types and split the single header file into smaller chunks.
|
40. [Thomas Braun](https://github.com/t-b) fixed a warning in a test case and adjusted MSVC calls in the CI.
|
||||||
41. [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
|
41. [Théo DELRIEU](https://github.com/theodelrieu) patiently and constructively oversaw the long way toward [iterator-range parsing](https://github.com/nlohmann/json/issues/290). He also implemented the magic behind the serialization/deserialization of user-defined types and split the single header file into smaller chunks.
|
||||||
42. [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
|
42. [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
|
||||||
43. [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
|
43. [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
|
||||||
44. [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
|
44. [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
|
||||||
45. [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
|
45. [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
|
||||||
46. [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
|
46. [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
|
||||||
47. [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
|
47. [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
|
||||||
48. [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
|
48. [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
|
||||||
49. [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning and supported the implementation of user-defined types.
|
49. [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
|
||||||
50. [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
|
50. [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
|
||||||
51. [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
|
51. [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
|
||||||
52. [Daniel599](https://github.com/Daniel599) helped to get Travis to execute the tests with Clang's sanitizers and allowed to use more algorithms with the `items()` function.
|
52. [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
|
||||||
53. [Jonathan Lee](https://github.com/vjon) fixed an example in the README file.
|
53. [Daniel599](https://github.com/Daniel599) helped to get Travis to execute the tests with Clang's sanitizers.
|
||||||
54. [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types.
|
54. [Jonathan Lee](https://github.com/vjon) fixed an example in the README file.
|
||||||
55. [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio.
|
55. [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types.
|
||||||
56. [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example.
|
56. [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio.
|
||||||
57. [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite.
|
57. [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types.
|
||||||
58. [ukhegg](https://github.com/ukhegg) proposed an improvement for the examples section.
|
58. [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example.
|
||||||
59. [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README.
|
59. [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite.
|
||||||
60. [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s.
|
60. [ukhegg](https://github.com/ukhegg) proposed an improvement for the examples section.
|
||||||
61. [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation.
|
61. [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README.
|
||||||
62. [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings.
|
62. [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s.
|
||||||
63. [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible.
|
63. [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation.
|
||||||
64. [ftillier](https://github.com/ftillier) fixed a compiler warning.
|
64. [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings.
|
||||||
65. [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped.
|
65. [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible.
|
||||||
66. [Fytch](https://github.com/Fytch) found a bug in the documentation.
|
66. [ftillier](https://github.com/ftillier) fixed a compiler warning.
|
||||||
67. [Jay Sistar](https://github.com/Type1J) implemented a Meson build description.
|
67. [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped.
|
||||||
68. [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation.
|
68. [Fytch](https://github.com/Fytch) found a bug in the documentation.
|
||||||
69. [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager.
|
69. [Jay Sistar](https://github.com/Type1J) implemented a Meson build description.
|
||||||
70. [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`.
|
70. [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation.
|
||||||
71. [Mike Tzou](https://github.com/Chocobo1) fixed some typos.
|
71. [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager.
|
||||||
72. [amrcode](https://github.com/amrcode) noted misleading documentation about comparison of floats.
|
72. [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`.
|
||||||
73. [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
|
73. [Mike Tzou](https://github.com/Chocobo1) fixed some typos.
|
||||||
74. [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
|
74. [amrcode](https://github.com/amrcode) noted misleading documentation about comparison of floats.
|
||||||
75. [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
|
75. [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
|
||||||
76. [Greg Hurrell](https://github.com/wincent) fixed a typo.
|
76. [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
|
||||||
77. [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
|
77. [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
|
||||||
78. [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
|
78. [Greg Hurrell](https://github.com/wincent) fixed a typo.
|
||||||
79. [Markus Werle](https://github.com/daixtrose) fixed a typo.
|
79. [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
|
||||||
80. [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
|
80. [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
|
||||||
81. [Alex](https://github.com/leha-bot) noted an error in a code sample.
|
81. [Markus Werle](https://github.com/daixtrose) fixed a typo.
|
||||||
82. [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped to fix them.
|
82. [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
|
||||||
83. [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams.
|
83. [Alex](https://github.com/leha-bot) noted an error in a code sample.
|
||||||
84. [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error, fixed the compilation with MSVC 2015 in debug mode and fixed a warning.
|
84. [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped to fix them.
|
||||||
85. [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings and avoided unnecessary string copies in `find()` and `count()`.
|
85. [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams.
|
||||||
86. [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file.
|
86. [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error.
|
||||||
87. [pvleuven](https://github.com/pvleuven) helped to fix a warning in ICC.
|
87. [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings.
|
||||||
88. [Pavel](https://github.com/crea7or) helped to fix some warnings in MSVC.
|
88. [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file.
|
||||||
89. [Mitja](https://github.com/Itja) fixed some typos.
|
89. [pvleuven](https://github.com/pvleuven) helped to fix a warning in ICC.
|
||||||
90. [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links.
|
90. [Pavel](https://github.com/crea7or) helped to fix some warnings in MSVC.
|
||||||
91. [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view and removed the dependency from `std::stringstream`.
|
91. [Jamie Seward](https://github.com/jseward) avoided unnecessary string copies in `find()` and `count()`.
|
||||||
92. [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings.
|
92. [Mitja](https://github.com/Itja) fixed some typos.
|
||||||
93. [Eren Okka](https://github.com/erengy) fixed some MSVC warnings.
|
93. [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links.
|
||||||
94. [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed.
|
94. [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view.
|
||||||
95. [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README.
|
95. [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings.
|
||||||
96. [zerodefect](https://github.com/zerodefect) fixed a compiler warning.
|
96. [Eren Okka](https://github.com/erengy) fixed some MSVC warnings.
|
||||||
97. [Kert](https://github.com/kaidokert) allowed to template the string type in the serialization and added the possibility to override the exceptional behavior.
|
97. [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed.
|
||||||
98. [mark-99](https://github.com/mark-99) helped fix an ICC error.
|
98. [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README.
|
||||||
99. [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file.
|
99. [zerodefect](https://github.com/zerodefect) fixed a compiler warning.
|
||||||
100. [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings.
|
100. [Kert](https://github.com/kaidokert) allowed to template the string type in the serialization and added the possibility to override the exceptional behavior.
|
||||||
101. [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
|
101. [mark-99](https://github.com/mark-99) helped fix an ICC error.
|
||||||
102. [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
|
102. [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file.
|
||||||
103. [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
|
103. [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings.
|
||||||
104. [agrianius](https://github.com/agrianius) allowed dumping JSON to an alternative string type and added code to use alternative string implementations.
|
104. [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
|
||||||
105. [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
|
105. [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
|
||||||
106. [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
|
106. [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
|
||||||
107. [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
|
107. [agrianius](https://github.com/agrianius) allowed dumping JSON to an alternative string type.
|
||||||
108. [James Upjohn](https://github.com/jupjohn) fixed a version number in the compilers section.
|
108. [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
|
||||||
109. [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration.
|
109. [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
|
||||||
110. [Jan Schöppach](https://github.com/dns13) fixed a typo.
|
110. [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
|
||||||
111. [martin-mfg](https://github.com/martin-mfg) fixed a typo.
|
111. [James Upjohn](https://github.com/jupjohn) fixed a version number in the compilers section.
|
||||||
112. [Julius Rakow](https://github.com/juliusrakow) fixed the Meson include directory and fixed the links to [cppreference.com](https://cppreference.com).
|
112. [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration.
|
||||||
113. [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
|
113. [Jan Schöppach](https://github.com/dns13) fixed a typo.
|
||||||
114. [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library and fixed an issue with a double macro definition.
|
114. [martin-mfg](https://github.com/martin-mfg) fixed a typo.
|
||||||
115. [thyu](https://github.com/thyu) fixed a compiler warning.
|
115. [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`.
|
||||||
116. [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2.
|
116. [agrianius](https://github.com/agrianius) added code to use alternative string implementations.
|
||||||
117. [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library.
|
117. [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function.
|
||||||
118. [Ben Berman](https://github.com/rivertam) made some error messages more understandable.
|
118. [Julius Rakow](https://github.com/juliusrakow) fixed the Meson include directory and fixed the links to [cppreference.com](https://cppreference.com).
|
||||||
119. [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler.
|
119. [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode.
|
||||||
120. [mandreyel](https://github.com/mandreyel) fixed a compilation problem.
|
120. [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
|
||||||
121. [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file.
|
121. [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library.
|
||||||
122. [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8.
|
122. [thyu](https://github.com/thyu) fixed a compiler warning.
|
||||||
123. [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory.
|
123. [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2.
|
||||||
124. [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning.
|
124. [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library.
|
||||||
125. [Dan Gendreau](https://github.com/dgendreau) implemented the `NLOHMANN_JSON_SERIALIZE_ENUM` macro to quickly define an enum/JSON mapping.
|
125. [Hyeon Kim](https://github.com/simnalamburt) fixed an issue with a double macro definition.
|
||||||
126. [efp](https://github.com/efp) added line and column information to parse errors.
|
126. [Ben Berman](https://github.com/rivertam) made some error messages more understandable.
|
||||||
127. [julian-becker](https://github.com/julian-becker) added BSON support.
|
127. [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler.
|
||||||
128. [Pratik Chowdhury](https://github.com/pratikpc) added support for structured bindings.
|
128. [mandreyel](https://github.com/mandreyel) fixed a compilation problem.
|
||||||
129. [David Avedissian](https://github.com/davedissian) added support for Clang 5.0.1 (PS4 version).
|
129. [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file.
|
||||||
130. [Jonathan Dumaresq](https://github.com/dumarjo) implemented an input adapter to read from `FILE*`.
|
130. [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8.
|
||||||
131. [kjpus](https://github.com/kjpus) fixed a link in the documentation.
|
131. [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory.
|
||||||
132. [Manvendra Singh](https://github.com/manu-chroma) fixed a typo in the documentation.
|
132. [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning.
|
||||||
133. [ziggurat29](https://github.com/ziggurat29) fixed an MSVC warning.
|
133. [Dan Gendreau](https://github.com/dgendreau) implemented the `NLOHMANN_JSON_SERIALIZE_ENUM` macro to quickly define an enum/JSON mapping.
|
||||||
134. [Sylvain Corlay](https://github.com/SylvainCorlay) added code to avoid an issue with MSVC.
|
134. [efp](https://github.com/efp) added line and column information to parse errors.
|
||||||
135. [mefyl](https://github.com/mefyl) fixed a bug when JSON was parsed from an input stream.
|
135. [julian-becker](https://github.com/julian-becker) added BSON support.
|
||||||
136. [Millian Poquet](https://github.com/mpoquet) allowed to install the library via Meson.
|
136. [Pratik Chowdhury](https://github.com/pratikpc) added support for structured bindings.
|
||||||
137. [Michael Behrns-Miller](https://github.com/moodboom) found an issue with a missing namespace.
|
137. [David Avedissian](https://github.com/davedissian) added support for Clang 5.0.1 (PS4 version).
|
||||||
138. [Nasztanovics Ferenc](https://github.com/naszta) fixed a compilation issue with libc 2.12.
|
138. [Jonathan Dumaresq](https://github.com/dumarjo) implemented an input adapter to read from `FILE*`.
|
||||||
139. [Andreas Schwab](https://github.com/andreas-schwab) fixed the endian conversion.
|
139. [kjpus](https://github.com/kjpus) fixed a link in the documentation.
|
||||||
140. [Mark-Dunning](https://github.com/Mark-Dunning) fixed a warning in MSVC.
|
140. [Manvendra Singh](https://github.com/manu-chroma) fixed a typo in the documentation.
|
||||||
141. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) added `operator/` for JSON Pointers and fixed a compilation issue with MSVC.
|
141. [ziggurat29](https://github.com/ziggurat29) fixed an MSVC warning.
|
||||||
142. [John-Mark](https://github.com/johnmarkwayve) noted a missing header.
|
142. [Sylvain Corlay](https://github.com/SylvainCorlay) added code to avoid an issue with MSVC.
|
||||||
143. [Vitaly Zaitsev](https://github.com/xvitaly) fixed compilation with GCC 9.0.
|
143. [mefyl](https://github.com/mefyl) fixed a bug when JSON was parsed from an input stream.
|
||||||
144. [Laurent Stacul](https://github.com/stac47) fixed compilation with GCC 9.0.
|
144. [Millian Poquet](https://github.com/mpoquet) allowed to install the library via Meson.
|
||||||
145. [Ivor Wanders](https://github.com/iwanders) helped to reduce the CMake requirement to version 3.1 and fixed the examples to catch exception by `const&`.
|
145. [Michael Behrns-Miller](https://github.com/moodboom) found an issue with a missing namespace.
|
||||||
146. [njlr](https://github.com/njlr) updated the Buckaroo instructions.
|
146. [Nasztanovics Ferenc](https://github.com/naszta) fixed a compilation issue with libc 2.12.
|
||||||
147. [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS.
|
147. [Andreas Schwab](https://github.com/andreas-schwab) fixed the endian conversion.
|
||||||
148. [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function.
|
148. [Mark-Dunning](https://github.com/Mark-Dunning) fixed a warning in MSVC.
|
||||||
149. [past-due](https://github.com/past-due) suppressed an unfixable warning.
|
149. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) added `operator/` for JSON Pointers.
|
||||||
150. [Elvis Oric](https://github.com/elvisoric) improved Meson support.
|
150. [John-Mark](https://github.com/johnmarkwayve) noted a missing header.
|
||||||
151. [Matěj Plch](https://github.com/Afforix) fixed an example in the README.
|
151. [Vitaly Zaitsev](https://github.com/xvitaly) fixed compilation with GCC 9.0.
|
||||||
152. [Mark Beckwith](https://github.com/wythe) fixed two typos.
|
152. [Laurent Stacul](https://github.com/stac47) fixed compilation with GCC 9.0.
|
||||||
153. [scinart](https://github.com/scinart) fixed a bug in the serializer.
|
153. [Ivor Wanders](https://github.com/iwanders) helped to reduce the CMake requirement to version 3.1.
|
||||||
154. [Patrick Boettcher](https://github.com/pboettch) implemented `push_back()` and `pop_back()` for JSON Pointers.
|
154. [njlr](https://github.com/njlr) updated the Buckaroo instructions.
|
||||||
155. [Bruno Oliveira](https://github.com/nicoddemus) added support for Conda.
|
155. [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS.
|
||||||
156. [Michele Caini](https://github.com/skypjack) fixed links in the README.
|
156. [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function.
|
||||||
157. [Hani](https://github.com/hnkb) documented how to install the library with NuGet.
|
157. [past-due](https://github.com/past-due) suppressed an unfixable warning.
|
||||||
158. [yann-morin-1998](https://github.com/yann-morin-1998) helped to reduce the CMake requirement to version 3.1.
|
158. [Elvis Oric](https://github.com/elvisoric) improved Meson support.
|
||||||
159. [Konstantin Podsvirov](https://github.com/podsvirov) maintains a package for the MSYS2 software distro and fixed the MSYS2 package documentation.
|
159. [Matěj Plch](https://github.com/Afforix) fixed an example in the README.
|
||||||
160. [remyabel](https://github.com/remyabel2) added GNUInstallDirs to the CMake files.
|
160. [Mark Beckwith](https://github.com/wythe) fixed a typo.
|
||||||
161. [Taylor Howard](https://github.com/taylorhoward92) fixed a unit test.
|
161. [scinart](https://github.com/scinart) fixed a bug in the serializer.
|
||||||
162. [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method.
|
162. [Patrick Boettcher](https://github.com/pboettch) implemented `push_back()` and `pop_back()` for JSON Pointers.
|
||||||
163. [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning.
|
163. [Bruno Oliveira](https://github.com/nicoddemus) added support for Conda.
|
||||||
164. [Viktor Kirilov](https://github.com/onqtam) switched the unit tests from [Catch](https://github.com/philsquared/Catch) to [doctest](https://github.com/doctest/doctest)
|
164. [Michele Caini](https://github.com/skypjack) fixed links in the README.
|
||||||
165. [Juncheng E](https://github.com/ejcjason) fixed a typo.
|
165. [Hani](https://github.com/hnkb) documented how to install the library with NuGet.
|
||||||
166. [tete17](https://github.com/tete17) fixed a bug in the `contains` function.
|
166. [Mark Beckwith](https://github.com/wythe) fixed a typo.
|
||||||
167. [Xav83](https://github.com/Xav83) fixed some cppcheck warnings.
|
167. [yann-morin-1998](https://github.com/yann-morin-1998) helped to reduce the CMake requirement to version 3.1.
|
||||||
168. [0xflotus](https://github.com/0xflotus) fixed some typos.
|
168. [Konstantin Podsvirov](https://github.com/podsvirov) maintains a package for the MSYS2 software distro.
|
||||||
169. [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`.
|
169. [remyabel](https://github.com/remyabel2) added GNUInstallDirs to the CMake files.
|
||||||
170. [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types.
|
170. [Taylor Howard](https://github.com/taylorhoward92) fixed a unit test.
|
||||||
171. [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly.
|
171. [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method.
|
||||||
172. [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos.
|
172. [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning.
|
||||||
173. [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`.
|
173. [Viktor Kirilov](https://github.com/onqtam) switched the unit tests from [Catch](https://github.com/philsquared/Catch) to [doctest](https://github.com/onqtam/doctest)
|
||||||
174. [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization.
|
174. [Juncheng E](https://github.com/ejcjason) fixed a typo.
|
||||||
175. [Yuriy Vountesmery](https://github.com/ua-code-dragon) noted a subtle bug in a preprocessor check.
|
175. [tete17](https://github.com/tete17) fixed a bug in the `contains` function.
|
||||||
176. [Chen](https://github.com/dota17) fixed numerous issues in the library.
|
176. [Xav83](https://github.com/Xav83) fixed some cppcheck warnings.
|
||||||
177. [Antony Kellermann](https://github.com/aokellermann) added a CI step for GCC 10.1.
|
177. [0xflotus](https://github.com/0xflotus) fixed some typos.
|
||||||
178. [Alex](https://github.com/gistrec) fixed an MSVC warning.
|
178. [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`.
|
||||||
179. [Rainer](https://github.com/rvjr) proposed an improvement in the floating-point serialization in CBOR.
|
179. [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types.
|
||||||
180. [Francois Chabot](https://github.com/FrancoisChabot) made performance improvements in the input adapters.
|
180. [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly.
|
||||||
181. [Arthur Sonzogni](https://github.com/ArthurSonzogni) documented how the library can be included via `FetchContent`.
|
181. [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos.
|
||||||
182. [Rimas Misevičius](https://github.com/rmisev) fixed an error message.
|
182. [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`.
|
||||||
183. [Alexander Myasnikov](https://github.com/alexandermyasnikov) fixed some examples and a link in the README.
|
183. [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization.
|
||||||
184. [Hubert Chathi](https://github.com/uhoreg) made CMake's version config file architecture-independent.
|
184. [Yuriy Vountesmery](https://github.com/ua-code-dragon) noted a subtle bug in a preprocessor check.
|
||||||
185. [OmnipotentEntity](https://github.com/OmnipotentEntity) implemented the binary values for CBOR, MessagePack, BSON, and UBJSON.
|
185. [Chen](https://github.com/dota17) fixed numerous issues in the library.
|
||||||
186. [ArtemSarmini](https://github.com/ArtemSarmini) fixed a compilation issue with GCC 10 and fixed a leak.
|
186. [Antony Kellermann](https://github.com/aokellermann) added a CI step for GCC 10.1.
|
||||||
187. [Evgenii Sopov](https://github.com/sea5kg) integrated the library to the wsjcpp package manager.
|
187. [Alex](https://github.com/gistrec) fixed an MSVC warning.
|
||||||
188. [Sergey Linev](https://github.com/linev) fixed a compiler warning.
|
188. [Rainer](https://github.com/rvjr) proposed an improvement in the floating-point serialization in CBOR.
|
||||||
189. [Miguel Magalhães](https://github.com/magamig) fixed the year in the copyright.
|
189. [Francois Chabot](https://github.com/FrancoisChabot) made performance improvements in the input adapters.
|
||||||
190. [Alexander “weej” Jones](https://github.com/alex-weej) fixed an example in the README.
|
190. [Arthur Sonzogni](https://github.com/ArthurSonzogni) documented how the library can be included via `FetchContent`.
|
||||||
191. [Antoine Cœur](https://github.com/Coeur) fixed some typos in the documentation.
|
191. [Rimas Misevičius](https://github.com/rmisev) fixed an error message.
|
||||||
192. [jothepro](https://github.com/jothepro) updated links to the Hunter package.
|
192. [Alexander Myasnikov](https://github.com/alexandermyasnikov) fixed some examples and a link in the README.
|
||||||
193. [Dave Lee](https://github.com/kastiglione) fixed a link in the README.
|
193. [Hubert Chathi](https://github.com/uhoreg) made CMake's version config file architecture-independent.
|
||||||
194. [Joël Lamotte](https://github.com/Klaim) added instruction for using Build2's package manager.
|
194. [OmnipotentEntity](https://github.com/OmnipotentEntity) implemented the binary values for CBOR, MessagePack, BSON, and UBJSON.
|
||||||
195. [Paul Jurczak](https://github.com/pauljurczak) fixed an example in the README.
|
195. [ArtemSarmini](https://github.com/ArtemSarmini) fixed a compilation issue with GCC 10 and fixed a leak.
|
||||||
196. [Carlos Gomes Martinho](https://github.com/gocarlos) updated the Conan package source.
|
196. [Evgenii Sopov](https://github.com/sea5kg) integrated the library to the wsjcpp package manager.
|
||||||
197. [Tridacnid](https://github.com/Tridacnid) improved the CMake tests.
|
197. [Sergey Linev](https://github.com/linev) fixed a compiler warning.
|
||||||
198. [Michael](https://github.com/MBalszun) fixed MSVC warnings.
|
198. [Miguel Magalhães](https://github.com/magamig) fixed the year in the copyright.
|
||||||
199. [Quentin Barbarat](https://github.com/quentin-dev) fixed an example in the documentation.
|
199. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) fixed a compilation issue with MSVC.
|
||||||
200. [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
200. [Alexander “weej” Jones](https://github.com/alex-weej) fixed an example in the README.
|
||||||
201. [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README and updated the links in the documentation to use HTTPS.
|
201. [Antoine Cœur](https://github.com/Coeur) fixed some typos in the documentation.
|
||||||
202. [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
202. [jothepro](https://github.com/jothepro) updated links to the Hunter package.
|
||||||
203. [AODQ](https://github.com/AODQ) fixed a compiler warning.
|
203. [Dave Lee](https://github.com/kastiglione) fixed a link in the README.
|
||||||
204. [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline.
|
204. [Joël Lamotte](https://github.com/Klaim) added instruction for using Build2's package manager.
|
||||||
205. [pfeatherstone](https://github.com/pfeatherstone) improved the upper bound of arguments of the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
205. [Paul Jurczak](https://github.com/pauljurczak) fixed an example in the README.
|
||||||
206. [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values.
|
206. [Sonu Lohani](https://github.com/sonulohani) fixed a warning.
|
||||||
207. [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation.
|
207. [Carlos Gomes Martinho](https://github.com/gocarlos) updated the Conan package source.
|
||||||
208. [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes.
|
208. [Konstantin Podsvirov](https://github.com/podsvirov) fixed the MSYS2 package documentation.
|
||||||
209. [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`.
|
209. [Tridacnid](https://github.com/Tridacnid) improved the CMake tests.
|
||||||
210. [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config.
|
210. [Michael](https://github.com/MBalszun) fixed MSVC warnings.
|
||||||
211. [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
211. [Quentin Barbarat](https://github.com/quentin-dev) fixed an example in the documentation.
|
||||||
212. [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
|
212. [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
||||||
213. [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
|
213. [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README.
|
||||||
214. [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer.
|
214. [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
||||||
215. Lars Wirzenius reviewed the README file.
|
215. [AODQ](https://github.com/AODQ) fixed a compiler warning.
|
||||||
216. [Jun Jie](https://github.com/ongjunjie) fixed a compiler path in the CMake scripts.
|
216. [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline.
|
||||||
217. [Ronak Buch](https://github.com/rbuch) fixed typos in the documentation.
|
217. [pfeatherstone](https://github.com/pfeatherstone) improved the upper bound of arguments of the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||||
218. [Alexander Karzhenkov](https://github.com/karzhenkov) fixed a move constructor and the Travis builds.
|
218. [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values.
|
||||||
219. [Leonardo Lima](https://github.com/leozz37) added CPM.Cmake support.
|
219. [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation.
|
||||||
220. [Joseph Blackman](https://github.com/jbzdarkid) fixed a warning.
|
220. [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes.
|
||||||
221. [Yaroslav](https://github.com/YarikTH) updated doctest and implemented unit tests.
|
221. [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`.
|
||||||
222. [Martin Stump](https://github.com/globberwops) fixed a bug in the CMake files.
|
222. [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config.
|
||||||
223. [Jaakko Moisio](https://github.com/jasujm) fixed a bug in the input adapters.
|
223. [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||||
224. [bl-ue](https://github.com/bl-ue) fixed some Markdown issues in the README file.
|
224. [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
|
||||||
225. [William A. Wieselquist](https://github.com/wawiesel) fixed an example from the README.
|
225. [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
|
||||||
226. [abbaswasim](https://github.com/abbaswasim) fixed an example from the README.
|
226. [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer.
|
||||||
227. [Remy Jette](https://github.com/remyjette) fixed a warning.
|
227. Lars Wirzenius reviewed the README file.
|
||||||
228. [Fraser](https://github.com/frasermarlow) fixed the documentation.
|
228. [Jun Jie](https://github.com/ongjunjie) fixed a compiler path in the CMake scripts.
|
||||||
229. [Ben Beasley](https://github.com/musicinmybrain) updated doctest.
|
229. [Ronak Buch](https://github.com/rbuch) fixed typos in the documentation.
|
||||||
230. [Doron Behar](https://github.com/doronbehar) fixed pkg-config.pc.
|
230. [Alexander Karzhenkov](https://github.com/karzhenkov) fixed a move constructor and the Travis builds.
|
||||||
231. [raduteo](https://github.com/raduteo) fixed a warning.
|
231. [Leonardo Lima](https://github.com/leozz37) added CPM.Cmake support.
|
||||||
232. [David Pfahler](https://github.com/theShmoo) added the possibility to compile the library without I/O support.
|
232. [Joseph Blackman](https://github.com/jbzdarkid) fixed a warning.
|
||||||
233. [Morten Fyhn Amundsen](https://github.com/mortenfyhn) fixed a typo.
|
233. [Yaroslav](https://github.com/YarikTH) updated doctest and implemented unit tests.
|
||||||
234. [jpl-mac](https://github.com/jpl-mac) allowed treating the library as a system header in CMake.
|
234. [Martin Stump](https://github.com/globberwops) fixed a bug in the CMake files.
|
||||||
235. [Jason Dsouza](https://github.com/jasmcaus) fixed the indentation of the CMake file.
|
235. [Jaakko Moisio](https://github.com/jasujm) fixed a bug in the input adapters.
|
||||||
236. [offa](https://github.com/offa) added a link to Conan Center to the documentation.
|
236. [bl-ue](https://github.com/bl-ue) fixed some Markdown issues in the README file.
|
||||||
237. [Rafail Giavrimis](https://github.com/grafail) fixed the Google Benchmark default branch.
|
237. [William A. Wieselquist](https://github.com/wawiesel) fixed an example from the README.
|
||||||
238. [Louis Dionne](https://github.com/ldionne) fixed a conversion operator.
|
238. [abbaswasim](https://github.com/abbaswasim) fixed an example from the README.
|
||||||
239. [justanotheranonymoususer](https://github.com/justanotheranonymoususer) made the examples in the README more consistent.
|
239. [Remy Jette](https://github.com/remyjette) fixed a warning.
|
||||||
240. [Finkman](https://github.com/Finkman) suppressed some `-Wfloat-equal` warnings and fixed the debug pretty-printer.
|
240. [Fraser](https://github.com/frasermarlow) fixed the documentation.
|
||||||
241. [Ferry Huberts](https://github.com/fhuberts) fixed `-Wswitch-enum` warnings and fixed a typo.
|
241. [Ben Beasley](https://github.com/musicinmybrain) updated doctest.
|
||||||
242. [Arseniy Terekhin](https://github.com/senyai) made the GDB pretty-printer robust against unset variable names.
|
242. [Doron Behar](https://github.com/doronbehar) fixed pkg-config.pc.
|
||||||
243. [Amir Masoud Abdol](https://github.com/amirmasoudabdol) updated the Homebrew command as nlohmann/json is now in homebrew-core.
|
243. [raduteo](https://github.com/raduteo) fixed a warning.
|
||||||
244. [Hallot](https://github.com/Hallot) fixed some `-Wextra-semi-stmt warnings`.
|
244. [David Pfahler](https://github.com/theShmoo) added the possibility to compile the library without I/O support.
|
||||||
245. [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS` and fixed a check for `std::filesystem`.
|
245. [Morten Fyhn Amundsen](https://github.com/mortenfyhn) fixed a typo.
|
||||||
246. [Bogdan Popescu](https://github.com/Kapeli) hosts the [docset](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for offline documentation viewers.
|
246. [jpl-mac](https://github.com/jpl-mac) allowed treating the library as a system header in CMake.
|
||||||
247. [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`.
|
247. [Jason Dsouza](https://github.com/jasmcaus) fixed the indentation of the CMake file.
|
||||||
248. [miikka75](https://github.com/miikka75) provided an important fix to compile C++17 code with Clang 9.
|
248. [offa](https://github.com/offa) added a link to Conan Center to the documentation.
|
||||||
249. [Maarten Becker](https://github.com/kernie) fixed a warning for shadowed variables.
|
249. [TotalCaesar659](https://github.com/TotalCaesar659) updated the links in the documentation to use HTTPS.
|
||||||
250. [Cristi Vîjdea](https://github.com/axnsan12) fixed typos in the `operator[]` documentation.
|
250. [Rafail Giavrimis](https://github.com/grafail) fixed the Google Benchmark default branch.
|
||||||
251. [Alex Beregszaszi](https://github.com/axic) fixed spelling mistakes in comments.
|
251. [Louis Dionne](https://github.com/ldionne) fixed a conversion operator.
|
||||||
252. [Dirk Stolle](https://github.com/striezel) fixed typos in the documentation.
|
252. [justanotheranonymoususer](https://github.com/justanotheranonymoususer) made the examples in the README more consistent.
|
||||||
253. [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation.
|
253. [Finkman](https://github.com/Finkman) suppressed some `-Wfloat-equal` warnings.
|
||||||
254. [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ.
|
254. [Ferry Huberts](https://github.com/fhuberts) fixed `-Wswitch-enum` warnings.
|
||||||
255. [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements.
|
255. [Arseniy Terekhin](https://github.com/senyai) made the GDB pretty-printer robust against unset variable names.
|
||||||
256. [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format.
|
256. [Amir Masoud Abdol](https://github.com/amirmasoudabdol) updated the Homebrew command as nlohmann/json is now in homebrew-core.
|
||||||
257. [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
|
257. [Hallot](https://github.com/Hallot) fixed some `-Wextra-semi-stmt warnings`.
|
||||||
258. [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines.
|
258. [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS`.
|
||||||
259. [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC.
|
259. [Bogdan Popescu](https://github.com/Kapeli) hosts the [docset](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for offline documentation viewers.
|
||||||
260. [Dimitris Apostolou](https://github.com/rex4539) fixed a typo.
|
260. [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`.
|
||||||
261. [Michael Nosthoff](https://github.com/heinemml) fixed a typo.
|
261. [miikka75](https://github.com/miikka75) provided an important fix to compile C++17 code with Clang 9.
|
||||||
262. [JungHoon Lee](https://github.com/jhnlee) fixed a typo.
|
262. [Maarten Becker](https://github.com/kernie) fixed a warning for shadowed variables.
|
||||||
263. [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file.
|
263. [Cristi Vîjdea](https://github.com/axnsan12) fixed typos in the `operator[]` documentation.
|
||||||
264. [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation.
|
264. [Alex Beregszaszi](https://github.com/axic) fixed spelling mistakes in comments.
|
||||||
265. [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`.
|
265. [Dirk Stolle](https://github.com/striezel) fixed typos in documentation.
|
||||||
266. [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo.
|
266. [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation.
|
||||||
267. [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error.
|
267. [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ.
|
||||||
268. [KsaNL](https://github.com/KsaNL) fixed a build error when including `<windows.h>`.
|
268. [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements.
|
||||||
269. [Andrea Pappacoda](https://github.com/Tachi107) moved `.pc` and `.cmake` files to `share` directory.
|
269. [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format.
|
||||||
270. [Wolf Vollprecht](https://github.com/wolfv) added the `patch_inplace` function.
|
270. [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
|
||||||
271. [Jake Zimmerman](https://github.com/jez) highlighted common usage patterns in the README file.
|
271. [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines.
|
||||||
272. [NN](https://github.com/NN---) added the Visual Studio output directory to `.gitignore`.
|
272. [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC.
|
||||||
273. [Romain Reignier](https://github.com/romainreignier) improved the performance of the vector output adapter.
|
273. [Giovanni Cerretani](https://github.com/gcerretani) fixed a check for `std::filesystem`.
|
||||||
274. [Mike](https://github.com/Mike-Leo-Smith) fixed the `std::iterator_traits`.
|
274. [Dimitris Apostolou](https://github.com/rex4539) fixed a typo.
|
||||||
275. [Richard Hozák](https://github.com/richardhozak) added macro `JSON_NO_ENUM` to disable default enum conversions.
|
275. [Ferry Huberts](https://github.com/fhuberts) fixed a typo.
|
||||||
276. [vakokako](https://github.com/vakokako) fixed tests when compiling with C++20.
|
276. [Michael Nosthoff](https://github.com/heinemml) fixed a typo.
|
||||||
277. [Alexander “weej” Jones](https://github.com/alexweej) fixed an example in the README.
|
277. [JungHoon Lee](https://github.com/jhnlee) fixed a typo.
|
||||||
278. [Eli Schwartz](https://github.com/eli-schwartz) added more files to the `include.zip` archive.
|
278. [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file.
|
||||||
279. [Kevin Lu](https://github.com/kevinlul) fixed a compilation issue when typedefs with certain names were present.
|
279. [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation.
|
||||||
280. [Trevor Hickey](https://github.com/luxe) improved the description of an example.
|
280. [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`.
|
||||||
281. [Jef LeCompte](https://github.com/jef) updated the year in the README file.
|
281. [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo.
|
||||||
282. [Alexandre Hamez](https://github.com/ahamez) fixed a warning.
|
282. [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error.
|
||||||
283. [Maninderpal Badhan](https://github.com/mbadhan) fixed a typo.
|
283. [KsaNL](https://github.com/KsaNL) fixed a build error when including `<windows.h>`.
|
||||||
284. [kevin--](https://github.com/kevin--) added a note to an example in the README file.
|
284. [Andrea Pappacoda](https://github.com/Tachi107) moved `.pc` and `.cmake` files to `share` directory.
|
||||||
285. [I](https://github.com/wx257osn2) fixed a typo.
|
285. [Wolf Vollprecht](https://github.com/wolfv) added the `patch_inplace` function.
|
||||||
286. [Gregorio Litenstein](https://github.com/Lord-Kamina) fixed the Clang detection.
|
286. [Jake Zimmerman](https://github.com/jez) highlighted common usage patterns in the README file.
|
||||||
287. [Andreas Smas](https://github.com/andoma) added a Doozer badge.
|
287. [NN](https://github.com/NN---) added the Visual Studio output directory to `.gitignore`.
|
||||||
288. [WanCW](https://github.com/wancw) fixed the string conversion with Clang.
|
288. [Romain Reignier](https://github.com/romainreignier) improved the performance of the vector output adapter.
|
||||||
289. [zhaohuaxishi](https://github.com/zhaohuaxishi) fixed a Doxygen error.
|
289. [Mike](https://github.com/Mike-Leo-Smith) fixed the `std::iterator_traits`.
|
||||||
290. [emvivre](https://github.com/emvivre) removed an invalid parameter from CMake.
|
290. [Richard Hozák](https://github.com/richardhozak) added macro `JSON_NO_ENUM` to disable default enum conversions.
|
||||||
291. [Tobias Hermann](https://github.com/Dobiasd) fixed a link in the README file.
|
291. [vakokako](https://github.com/vakokako) fixed tests when compiling with C++20.
|
||||||
292. [Michael](https://github.com/traits) fixed a warning.
|
292. [Alexander “weej” Jones](https://github.com/alexweej) fixed an example in the README.
|
||||||
293. [Ryan Mulder](https://github.com/ryanjmulder) added `ensure_ascii` to the `dump` function.
|
293. [Eli Schwartz](https://github.com/eli-schwartz) added more files to the `include.zip` archive.
|
||||||
294. [Muri Nicanor](https://github.com/murinicanor) fixed the `sed` discovery in the Makefile.
|
294. [Kevin Lu](https://github.com/kevinlul) fixed a compilation issue when typedefs with certain names were present.
|
||||||
295. [David Avedissian](https://github.com/dgavedissian) implemented SFINAE-friendly `iterator_traits`.
|
295. [Trevor Hickey](https://github.com/luxe) improved the description of an example.
|
||||||
296. [AQNOUCH Mohammed](https://github.com/aqnouch) fixed a typo in the README.
|
296. [Jef LeCompte](https://github.com/jef) updated the year in the README file.
|
||||||
297. [Gareth Sylvester-Bradley](https://github.com/garethsb) added `operator/=` and `operator/` to construct JSON pointers.
|
297. [Alexandre Hamez](https://github.com/ahamez) fixed a warning.
|
||||||
298. [Michael Macnair](https://github.com/mykter) added support for afl-fuzz testing.
|
298. [Maninderpal Badhan](https://github.com/mbadhan) fixed a typo.
|
||||||
299. [Berkus Decker](https://github.com/berkus) fixed a typo in the README.
|
299. [kevin--](https://github.com/kevin--) added a note to an example in the README file.
|
||||||
300. [Illia Polishchuk](https://github.com/ilqvya) improved the CMake testing.
|
300. [I](https://github.com/wx257osn2) fixed a typo.
|
||||||
301. [Ikko Ashimine](https://github.com/eltociear) fixed two typos.
|
301. [Gregorio Litenstein](https://github.com/Lord-Kamina) fixed the Clang detection.
|
||||||
302. [Raphael Grimm](https://github.com/barcode) added the possibility to define a custom base class.
|
302. [Andreas Smas](https://github.com/andoma) added a Doozer badge.
|
||||||
303. [tocic](https://github.com/tocic) fixed typos in the documentation.
|
303. [WanCW](https://github.com/wancw) fixed the string conversion with Clang.
|
||||||
304. [Vertexwahn](https://github.com/Vertexwahn) added Bazel build support.
|
304. [zhaohuaxishi](https://github.com/zhaohuaxishi) fixed a Doxygen error.
|
||||||
305. [DavidKorczynski](https://github.com/DavidKorczynski) added a CIFuzz CI GitHub action.
|
305. [emvivre](https://github.com/emvivre) removed an invalid parameter from CMake.
|
||||||
306. [Florian Segginger](https://github.com/floriansegginger) bumped the years in the README.
|
306. [Tobias Hermann](https://github.com/Dobiasd) fixed a link in the README file.
|
||||||
307. [haadfida](https://github.com/haadfida) cleaned up the badges of used services.
|
307. [Michael](https://github.com/traits) fixed a warning.
|
||||||
308. [Arsen Arsenović](https://github.com/ArsenArsen) fixed a build error.
|
308. [Ryan Mulder](https://github.com/ryanjmulder) added `ensure_ascii` to the `dump` function.
|
||||||
309. [theevilone45](https://github.com/theevilone45) fixed a typo in a CMake file.
|
309. [Muri Nicanor](https://github.com/murinicanor) fixed the `sed` discovery in the Makefile.
|
||||||
310. [Sergei Trofimovich](https://github.com/trofi) fixed the custom allocator support.
|
310. [David Avedissian](https://github.com/dgavedissian) implemented SFINAE-friendly `iterator_traits`.
|
||||||
311. [Joyce](https://github.com/joycebrum) fixed some security issues in the GitHub workflows.
|
311. [AQNOUCH Mohammed](https://github.com/aqnouch) fixed a typo in the README.
|
||||||
312. [Nicolas Jakob](https://github.com/njakob) add vcpkg version badge.
|
312. [Gareth Sylvester-Bradley](https://github.com/garethsb) added `operator/=` and `operator/` to construct JSON pointers.
|
||||||
313. [Tomerkm](https://github.com/Tomerkm) added tests.
|
313. [Michael Macnair](https://github.com/mykter) added support for afl-fuzz testing.
|
||||||
314. [No.](https://github.com/tusooa) fixed the use of `get<>` calls.
|
314. [Berkus Decker](https://github.com/berkus) fixed a typo in the README.
|
||||||
315. [taro](https://github.com/tarolling) fixed a typo in the `CODEOWNERS` file.
|
315. [Illia Polishchuk](https://github.com/ilqvya) improved the CMake testing.
|
||||||
316. [Felix Yan](https://github.com/felixonmars) fixed a typo in the README.
|
316. [Ikko Ashimine](https://github.com/eltociear) fixed a typo.
|
||||||
317. [HO-COOH](https://github.com/HO-COOH) fixed a parenthesis in the documentation.
|
317. [Raphael Grimm](https://github.com/barcode) added the possibility to define a custom base class.
|
||||||
318. [miny1233](https://github.com/miny1233) fixed a parenthesis in the documentation.
|
318. [tocic](https://github.com/tocic) fixed typos in the documentation.
|
||||||
319. [tomalakgeretkal](https://github.com/tomalakgeretkal) fixed a compilation error.
|
319. [Vertexwahn](https://github.com/Vertexwahn) added Bazel build support.
|
||||||
320. [alferov](https://github.com/ALF-ONE) fixed a compilation error and fixed a version in the documentation.
|
320. [Dirk Stolle](https://github.com/striezel) fixed typos in the documentation.
|
||||||
321. [Craig Scott](https://github.com/craigscott-crascit) fixed a deprecation warning in CMake.
|
321. [DavidKorczynski](https://github.com/DavidKorczynski) added a CIFuzz CI GitHub action.
|
||||||
322. [Vyacheslav Zhdanovskiy](https://github.com/ZeronSix) added macros for serialization-only types.
|
322. [Finkman](https://github.com/Finkman) fixed the debug pretty-printer.
|
||||||
323. [Mathieu Westphal](https://github.com/mwestphal) fixed typos.
|
323. [Florian Segginger](https://github.com/floriansegginger) bumped the years in the README.
|
||||||
324. [scribam](https://github.com/scribam) fixed the MinGW workflow.
|
324. [haadfida](https://github.com/haadfida) cleaned up the badges of used services.
|
||||||
325. [Aleksei Sapitskii](https://github.com/aleksproger) added support for Apple's Swift Package Manager.
|
325. [Arsen Arsenović](https://github.com/ArsenArsen) fixed a build error.
|
||||||
326. [Benjamin Buch](https://github.com/bebuch) fixed the installation path in CMake.
|
326. [theevilone45](https://github.com/theevilone45) fixed a typo in a CMake file.
|
||||||
327. [Colby Haskell](https://github.com/colbychaskell) clarified the parse error message in case a file cannot be opened.
|
327. [Sergei Trofimovich](https://github.com/trofi) fixed the custom allocator support.
|
||||||
328. [Juan Carlos Arevalo Baeza](https://github.com/TheJCAB) fixed the enum conversion.
|
328. [Joyce](https://github.com/joycebrum) fixed some security issues in the GitHub workflows.
|
||||||
329. [ss](https://github.com/serge-s) fixed the amalgamation call.
|
329. [Nicolas Jakob](https://github.com/njakob) add vcpkg version badge.
|
||||||
330. [AniketDhemare](https://github.com/AniketDhemare) fixed a version in the documentation.
|
330. [Tomerkm](https://github.com/Tomerkm) added tests.
|
||||||
331. [Philip Müller](https://github.com/philip-paul-mueller) fixed an example.
|
331. [No.](https://github.com/tusooa) fixed the use of `get<>` calls.
|
||||||
332. [Leila Shcheglova](https://github.com/LeilaShcheglova) fixed a warning in a test.
|
332. [taro](https://github.com/tarolling) fixed a typo in the `CODEOWNERS` file.
|
||||||
333. [Alex Prabhat Bara](https://github.com/alexprabhat99) fixed a function name in the documentation.
|
333. [Ikko Eltociear Ashimine](https://github.com/eltociear) fixed a typo.
|
||||||
334. [laterlaugh](https://github.com/laterlaugh) fixed some typos.
|
334. [Felix Yan](https://github.com/felixonmars) fixed a typo in the README.
|
||||||
335. [Yuanhao Jia](https://github.com/MrJia1997) fixed the GDB pretty printer.
|
335. [HO-COOH](https://github.com/HO-COOH) fixed a parenthesis in the documentation.
|
||||||
336. [Fallen_Breath](https://github.com/Fallen-Breath) fixed an example for JSON Pointer.
|
336. [Ivor Wanders](https://github.com/iwanders) fixed the examples to catch exception by `const&`.
|
||||||
337. [Nikhil Idiculla](https://github.com/tsnl) fixed some typos.
|
337. [miny1233](https://github.com/miny1233) fixed a parenthesis in the documentation.
|
||||||
338. [Griffin Myers](https://github.com/gmyers18) updated the Natvis file.
|
338. [tomalakgeretkal](https://github.com/tomalakgeretkal) fixed a compilation error.
|
||||||
339. [thetimr](https://github.com/thetimr) fixed a typo in the documentation.
|
339. [alferov](https://github.com/ALF-ONE) fixed a compilation error.
|
||||||
340. [Balazs Erseki](https://github.com/zerocukor287) fixed a URL in the contribution guidelines.
|
340. [Craig Scott](https://github.com/craigscott-crascit) fixed a deprecation warning in CMake.
|
||||||
341. [Niccolò Iardella](https://github.com/rotolof) added `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
341. [Vyacheslav Zhdanovskiy](https://github.com/ZeronSix) added macros for serialization-only types.
|
||||||
342. [Borislav Stanimirov](https://github.com/iboB) allowed overriding the CMake target name.
|
342. [Mathieu Westphal](https://github.com/mwestphal) fixed typos.
|
||||||
343. [Captain Crutches](https://github.com/captaincrutches) made `iterator_proxy_value` a `std::forward_iterator`.
|
343. [scribam](https://github.com/scribam) fixed the MinGW workflow.
|
||||||
344. [Fredrik Sandhei](https://github.com/fsandhei) added type conversion support for `std::optional`.
|
344. [Aleksei Sapitskii](https://github.com/aleksproger) added support for Apple's Swift Package Manager.
|
||||||
345. [jh96](https://github.com/jordan-hoang) added exceptions when `nullptr` is passed to `parse`.
|
345. [Benjamin Buch](https://github.com/bebuch) fixed the installation path in CMake.
|
||||||
346. [Stuart Gorman](https://github.com/StuartGorman) fixed number parsing when `EINTR` set in `errno`.
|
346. [Colby Haskell](https://github.com/colbychaskell) clarified the parse error message in case a file cannot be opened.
|
||||||
347. [Dylan Baker](https://github.com/dcbaker) generated a pkg-config file that follows the pkg-config conventions.
|
347. [Juan Carlos Arevalo Baeza](https://github.com/TheJCAB) fixed the enum conversion.
|
||||||
348. [Tianyi Chen](https://github.com/TianyiChen) optimized the binary `get_number` implementation.
|
348. [alferov](https://github.com/ALF-ONE) fixed a version in the documentation.
|
||||||
349. [peng-wang-cn](https://github.com/peng-wang-cn) added type conversion support for multidimensional arrays.
|
349. [ss](https://github.com/serge-s) fixed the amalgamation call.
|
||||||
350. [Einars Netlis-Galejs](https://github.com/EinarsNG) added `ONLY_SERIALIZE` for `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
350. [AniketDhemare](https://github.com/AniketDhemare) fixed a version in the documentation.
|
||||||
351. [Marcel](https://github.com/mering) removed `alwayslink=True` Bazel flag.
|
351. [Philip Müller](https://github.com/philip-paul-mueller) fixed an example.
|
||||||
352. [Harinath Nampally](https://github.com/hnampally) added diagnostic positions to exceptions.
|
352. [Leila Shcheglova](https://github.com/LeilaShcheglova) fixed a warning in a test.
|
||||||
353. [Nissim Armand Ben Danan](https://github.com/NissimBendanan) fixed `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` with an empty JSON instance.
|
353. [Alex Prabhat Bara](https://github.com/alexprabhat99) fixed a function name in the documentation.
|
||||||
354. [Michael Valladolid](https://github.com/codenut) added support for BSON uint64 serialization/deserialization.
|
354. [laterlaugh](https://github.com/laterlaugh) fixed some typos.
|
||||||
355. [Nikhil](https://github.com/nikhilreddydev) updated the documentation.
|
355. [Yuanhao Jia](https://github.com/MrJia1997) fixed the GDB pretty printer.
|
||||||
356. [Nebojša Cvetković](https://github.com/nebkat) added support for BJDATA optimized binary array type.
|
356. [Fallen_Breath](https://github.com/Fallen-Breath) fixed an example for JSON Pointer.
|
||||||
357. [Sushrut Shringarputale](https://github.com/sushshring) added support for diagnostic positions.
|
357. [Nikhil Idiculla](https://github.com/tsnl) fixed some typos.
|
||||||
358. [kimci86](https://github.com/kimci86) templated to `NLOHMANN_DEFINE_TYPE` macros to also support `ordered_json`.
|
358. [Griffin Myers](https://github.com/gmyers18) updated the Natvis file.
|
||||||
359. [Richard Topchii](https://github.com/richardtop) added support for VisionOS in the Swift Package Manager.
|
359. [thetimr](https://github.com/thetimr) fixed a typo in the documentation.
|
||||||
360. [Robert Chisholm](https://github.com/Robadob) fixed a typo.
|
360. [Balazs Erseki](https://github.com/zerocukor287) fixed a URL in the contribution guidelines.
|
||||||
361. [zjyhjqs](https://github.com/zjyhjqs) added CPack support.
|
361. [Niccolò Iardella](https://github.com/rotolof) added `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||||
362. [bitFiedler](https://github.com/bitFiedler) made GDB pretty printer work with Python 3.8.
|
362. [Borislav Stanimirov](https://github.com/iboB) allowed overriding the CMake target name.
|
||||||
363. [Gianfranco Costamagna](https://github.com/LocutusOfBorg) fixed a compiler warning.
|
363. [Captain Crutches](https://github.com/captaincrutches) made `iterator_proxy_value` a `std::forward_iterator`.
|
||||||
364. [risa2000](https://github.com/risa2000) made `std::filesystem::path` conversion to/from UTF-8 encoded string explicit.
|
364. [Fredrik Sandhei](https://github.com/fsandhei) added type conversion support for `std::optional`.
|
||||||
365. [AM](https://github.com/maqnouch) fixed typos in the README.
|
365. [jh96](https://github.com/jordan-hoang) added exceptions when `nullptr` is passed to `parse`.
|
||||||
366. [dmenendez-gruposantander](https://github.com/dmenendez-gruposantander) fixed typos in the comments of the examples.
|
366. [Stuart Gorman](https://github.com/StuartGorman) fixed number parsing when `EINTR` set in `errno`.
|
||||||
367. [Mihai Stan](https://github.com/mstan-xx) fixed comparisons against the literal `0`.
|
367. [Dylan Baker](https://github.com/dcbaker) generated a pkg-config file that follows the pkg-config conventions.
|
||||||
368. [Matt Gumbel](https://github.com/intelmatt) fixed some `-Weffc++` warnings.
|
368. [Tianyi Chen](https://github.com/TianyiChen) optimized the binary `get_number` implementation.
|
||||||
369. [vimpunk](https://github.com/vimpunk) moved a lambda out of an unevaluated context to support older compilers.
|
369. [peng-wang-cn](https://github.com/peng-wang-cn) added type conversion support for multidimensional arrays.
|
||||||
370. [Chris Harris](https://github.com/cjh1) fixed the compilation with GCC 4.8.
|
370. [Einars Netlis-Galejs](https://github.com/EinarsNG) added `ONLY_SERIALIZE` for `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||||
371. [Palmer Dabbelt](https://github.com/palmer-dabbelt) generated and installed a pkg-config file.
|
371. [Marcel](https://github.com/mering) removed `alwayslink=True` Bazel flag.
|
||||||
372. [Gus Pozuelo](https://github.com/ap-viavi) made `ordered_map` compatible with GCC 5.5, Clang 3.6, and Xcode 9.
|
372. [Harinath Nampally](https://github.com/hnampally) added diagnostic positions to exceptions.
|
||||||
373. [AK](https://github.com/Lioncky) fixed an MSVC build error caused by the `min`/`max` macros from `windows.h`.
|
373. [Nissim Armand Ben Danan](https://github.com/NissimBendanan) fixed `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` with an empty JSON instance.
|
||||||
374. [Sergiu Deitsch](https://github.com/sergiud) provided a fallback for missing `char8_t` support.
|
374. [Michael Valladolid](https://github.com/codenut) added support for BSON uint64 serialization/deserialization.
|
||||||
375. [Xiaochuan Ye](https://github.com/XueSongTap) fixed `from_msgpack` for `std::byte` input by specializing `std::char_traits`.
|
375. [Nikhil](https://github.com/nikhilreddydev) updated the documentation.
|
||||||
376. [Ville Vesilehto](https://github.com/thevilledev) fixed an overflow in the BJData size calculation and rejected overflowing negative integers in CBOR.
|
376. [Nebojša Cvetković](https://github.com/nebkat) added support for BJDATA optimized binary array type.
|
||||||
377. [NmPassTHFan](https://github.com/nmpassthf) replaced the deprecated `std::is_trivial` for C++26.
|
377. [Sushrut Shringarputale](https://github.com/sushshring) added support for diagnostic positions.
|
||||||
378. [Chris Ever](https://github.com/chirsz-ever) added the `ignore_trailing_commas` parser option.
|
378. [kimci86](https://github.com/kimci86) templated to `NLOHMANN_DEFINE_TYPE` macros to also support `ordered_json`.
|
||||||
379. [Kuan-Fu Wu](https://github.com/kfwu1999) fixed the example code for `json_pointer` initialization.
|
379. [Richard Topchii](https://github.com/richardtop) added support for VisionOS in the Swift Package Manager.
|
||||||
380. [David Kilzer](https://github.com/ddkilzer) added a missing header to the input adapters.
|
380. [Robert Chisholm](https://github.com/Robadob) fixed a typo.
|
||||||
381. [Miko](https://github.com/mikomikotaishi) added proper C++20 module support, simplified the module API, and fixed missing exports.
|
381. [zjyhjqs](https://github.com/zjyhjqs) added CPack support.
|
||||||
382. [hitgirl](https://github.com/hitgil) fixed the CMake configuration when cross-compiling.
|
382. [bitFiedler](https://github.com/bitFiedler) made GDB pretty printer work with Python 3.8.
|
||||||
383. [Devon Thomas](https://github.com/ThomaDevOSU) mentioned the Artistic Style formatting in the contribution guidelines.
|
383. [Gianfranco Costamagna](https://github.com/LocutusOfBorg) fixed a compiler warning.
|
||||||
384. [Erik Hu](https://github.com/Erikhu1) made Coveralls upload errors non-fatal in the CI.
|
384. [risa2000](https://github.com/risa2000) made `std::filesystem::path` conversion to/from UTF-8 encoded string explicit.
|
||||||
385. [co63oc](https://github.com/co63oc) fixed typos.
|
385. [AM](https://github.com/maqnouch) fixed typos in the README.
|
||||||
386. [DmitriBogdanov](https://github.com/DmitriBogdanov) fixed broken package manager links in the documentation.
|
386. [dmenendez-gruposantander](https://github.com/dmenendez-gruposantander) fixed typos in the comments of the examples.
|
||||||
387. [Bander](https://github.com/banderzhm) improved the MSVC compatibility of the C++ modules.
|
387. [Mihai Stan](https://github.com/mstan-xx) fixed comparisons against the literal `0`.
|
||||||
388. [Andy Choi](https://github.com/ccpong) removed an unnecessary `template` keyword before `get` in the README and the documentation.
|
388. [Matt Gumbel](https://github.com/intelmatt) fixed some `-Weffc++` warnings.
|
||||||
389. [SamareshSingh](https://github.com/ssam18) fixed single-element brace initialization to copy/move instead of wrapping in an array, fixed the `WITH_DEFAULT` macros for `ordered_map`, and handled moved events in `serve_header.py`.
|
389. [vimpunk](https://github.com/vimpunk) moved a lambda out of an unevaluated context to support older compilers.
|
||||||
390. [Aditya](https://github.com/Lumowhisp) improved the documentation of the documentation generation.
|
390. [Chris Harris](https://github.com/cjh1) fixed the compilation with GCC 4.8.
|
||||||
391. [cheese1](https://github.com/cheese1) clarified the README.
|
391. [Palmer Dabbelt](https://github.com/palmer-dabbelt) generated and installed a pkg-config file.
|
||||||
392. [KhloodElhossiny](https://github.com/khloodelhossiny) enabled `std::string_view` keys in `operator[]`.
|
392. [Gus Pozuelo](https://github.com/ap-viavi) made `ordered_map` compatible with GCC 5.5, Clang 3.6, and Xcode 9.
|
||||||
393. [Charles Cabergs](https://github.com/cacharle) fixed a `-Wtautological-constant-out-of-range-compare` warning.
|
393. [AK](https://github.com/Lioncky) fixed an MSVC build error caused by the `min`/`max` macros from `windows.h`.
|
||||||
394. [EALePain](https://github.com/EALePain) made the `std::tuple` conversion work with reference types such as `std::tie`.
|
394. [Sergiu Deitsch](https://github.com/sergiud) provided a fallback for missing `char8_t` support.
|
||||||
395. [koala_oishi](https://github.com/chibi-dogs) fixed grammatical wording in the README.
|
395. [Xiaochuan Ye](https://github.com/XueSongTap) fixed `from_msgpack` for `std::byte` input by specializing `std::char_traits`.
|
||||||
396. [riccardoori11](https://github.com/riccardoori11) fixed a typo in the documentation.
|
396. [Ville Vesilehto](https://github.com/thevilledev) fixed an overflow in the BJData size calculation and rejected overflowing negative integers in CBOR.
|
||||||
397. [Swastik Bose](https://github.com/VasuBhakt) fixed the parent pointers after `update()` with `JSON_DIAGNOSTICS` and fixed the Doxygen autolinking of requirements.
|
397. [NmPassTHFan](https://github.com/nmpassthf) replaced the deprecated `std::is_trivial` for C++26.
|
||||||
398. [trdesilva](https://github.com/trdesilva) added `front`, `pop_front`, and `push_front` to `json_pointer`.
|
398. [Chris Ever](https://github.com/chirsz-ever) added the `ignore_trailing_commas` parser option.
|
||||||
399. [Akhilesh Arora](https://github.com/akhilesharora) fixed an incomplete-type error with `ordered_json`.
|
399. [Kuan-Fu Wu](https://github.com/kfwu1999) fixed the example code for `json_pointer` initialization.
|
||||||
400. [Hariom Phulre](https://github.com/hariomphulre) fixed the C++20 modules compilation with GCC.
|
400. [David Kilzer](https://github.com/ddkilzer) added a missing header to the input adapters.
|
||||||
401. [Kirill Lokotkov](https://github.com/RUSLoker) fixed printing `long double` values.
|
401. [Miko](https://github.com/mikomikotaishi) added proper C++20 module support, simplified the module API, and fixed missing exports.
|
||||||
402. [George Sedov](https://github.com/radistmorse) added the `NLOHMANN_DEFINE_TYPE_*_WITH_NAMES` macros.
|
402. [hitgirl](https://github.com/hitgil) fixed the CMake configuration when cross-compiling.
|
||||||
403. [Caillin Nugent](https://github.com/nugentcaillin) added the `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` macro.
|
403. [Devon Thomas](https://github.com/ThomaDevOSU) mentioned the Artistic Style formatting in the contribution guidelines.
|
||||||
404. [Cosmin D.](https://github.com/drcosmin) fixed `std::filesystem::path` conversions and added an MSVC workaround for `std::unique_ptr`.
|
404. [Erik Hu](https://github.com/Erikhu1) made Coveralls upload errors non-fatal in the CI.
|
||||||
405. [Paul Dreik](https://github.com/pauldreik) fixed a test relying on implementation-specific behavior.
|
405. [co63oc](https://github.com/co63oc) fixed typos.
|
||||||
406. [Daniel Falk](https://github.com/daniel-falk) added missing copyright notices to the SBOM.
|
406. [DmitriBogdanov](https://github.com/DmitriBogdanov) fixed broken package manager links in the documentation.
|
||||||
407. [Federico Sfriso](https://github.com/federicosfriso05-dotcom) added support for constructing JSON values from C++20 range views.
|
407. [Bander](https://github.com/banderzhm) improved the MSVC compatibility of the C++ modules.
|
||||||
408. [Luke Banicevic](https://github.com/banaboi) fixed corrupt BSON output for lengths exceeding `INT32_MAX`, cleaned up the BSON writer, and improved the documentation.
|
408. [Andy Choi](https://github.com/ccpong) removed an unnecessary `template` keyword before `get` in the README and the documentation.
|
||||||
409. [Patrick Armstrong](https://github.com/Patrick10199) updated the CBOR references and the half-precision float assertions.
|
409. [SamareshSingh](https://github.com/ssam18) fixed single-element brace initialization to copy/move instead of wrapping in an array, fixed the `WITH_DEFAULT` macros for `ordered_map`, and handled moved events in `serve_header.py`.
|
||||||
410. [Yash Bavadiya](https://github.com/xevrion) added checks to all BSON reads.
|
410. [Aditya](https://github.com/Lumowhisp) improved the documentation of the documentation generation.
|
||||||
411. [hum4nBeing](https://github.com/hum4nBeing) fixed the overflow handling of high-precision numbers in UBJSON.
|
411. [cheese1](https://github.com/cheese1) clarified the README.
|
||||||
412. [tomatotomata](https://github.com/tomatotomata) added checks for reading CBOR tagged subtypes.
|
412. [KhloodElhossiny](https://github.com/khloodelhossiny) enabled `std::string_view` keys in `operator[]`.
|
||||||
413. [YingqiDuan](https://github.com/YingqiDuan) documented the BSON interoperability.
|
413. [Charles Cabergs](https://github.com/cacharle) fixed a `-Wtautological-constant-out-of-range-compare` warning.
|
||||||
414. [KBS](https://github.com/youdie006) documented the standards compliance and the strictness of `parse()` and `operator>>`.
|
414. [EALePain](https://github.com/EALePain) made the `std::tuple` conversion work with reference types such as `std::tie`.
|
||||||
415. [Petr Bělohlávek](https://github.com/petrbel) added Clang 21 and 22 to the CI.
|
415. [koala_oishi](https://github.com/chibi-dogs) fixed grammatical wording in the README.
|
||||||
416. [Dmitry Rantovov](https://github.com/darkdi) fixed the placement of a CBOR documentation block.
|
416. [riccardoori11](https://github.com/riccardoori11) fixed a typo in the documentation.
|
||||||
417. [ljcjclljc](https://github.com/ljcjclljc) fixed the comparison of large unsigned integers with signed integers.
|
417. [Swastik Bose](https://github.com/VasuBhakt) fixed the parent pointers after `update()` with `JSON_DIAGNOSTICS` and fixed the Doxygen autolinking of requirements.
|
||||||
418. [Sahil Kamate](https://github.com/sahilkamate03) fixed the handling of CBOR tags 0-5 and 21-23.
|
418. [trdesilva](https://github.com/trdesilva) added `front`, `pop_front`, and `push_front` to `json_pointer`.
|
||||||
419. [Krishnanand G](https://github.com/Krishnanand-G) made the UBJSON writer reject `use_type` without `use_size`.
|
419. [Akhilesh Arora](https://github.com/akhilesharora) fixed an incomplete-type error with `ordered_json`.
|
||||||
420. [whn](https://github.com/Whning0513) documented the lenient BSON input handling and corrected the complexity of `to_bson`.
|
420. [Hariom Phulre](https://github.com/hariomphulre) fixed the C++20 modules compilation with GCC.
|
||||||
421. [elix3r](https://github.com/22elix3r) fixed `update()` with `merge_objects` when merging a primitive into an object.
|
421. [Kirill Lokotkov](https://github.com/RUSLoker) fixed printing `long double` values.
|
||||||
422. [Avionic Harshit](https://github.com/avionicharshit-byte) made `diff()` linear when an array shrinks.
|
422. [George Sedov](https://github.com/radistmorse) added the `NLOHMANN_DEFINE_TYPE_*_WITH_NAMES` macros.
|
||||||
423. [Qatadaha Bin Matloob](https://github.com/qatcod) fixed comparisons between integers and floats and fixed unparsable BJData output.
|
423. [Caillin Nugent](https://github.com/nugentcaillin) added the `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` macro.
|
||||||
424. [Wu Shuwen](https://github.com/dajiaohuang) removed an unused include.
|
424. [Cosmin D.](https://github.com/drcosmin) fixed `std::filesystem::path` conversions and added an MSVC workaround for `std::unique_ptr`.
|
||||||
|
425. [Paul Dreik](https://github.com/pauldreik) fixed a test relying on implementation-specific behavior.
|
||||||
|
426. [Daniel Falk](https://github.com/daniel-falk) added missing copyright notices to the SBOM.
|
||||||
|
427. [Federico Sfriso](https://github.com/federicosfriso05-dotcom) added support for constructing JSON values from C++20 range views.
|
||||||
|
428. [Luke Banicevic](https://github.com/banaboi) fixed corrupt BSON output for lengths exceeding `INT32_MAX`, cleaned up the BSON writer, and improved the documentation.
|
||||||
|
429. [Patrick Armstrong](https://github.com/Patrick10199) updated the CBOR references and the half-precision float assertions.
|
||||||
|
430. [Yash Bavadiya](https://github.com/xevrion) added checks to all BSON reads.
|
||||||
|
431. [hum4nBeing](https://github.com/hum4nBeing) fixed the overflow handling of high-precision numbers in UBJSON.
|
||||||
|
432. [tomatotomata](https://github.com/tomatotomata) added checks for reading CBOR tagged subtypes.
|
||||||
|
433. [YingqiDuan](https://github.com/YingqiDuan) documented the BSON interoperability.
|
||||||
|
434. [KBS](https://github.com/youdie006) documented the standards compliance and the strictness of `parse()` and `operator>>`.
|
||||||
|
435. [Petr Bělohlávek](https://github.com/petrbel) added Clang 21 and 22 to the CI.
|
||||||
|
436. [Dmitry Rantovov](https://github.com/darkdi) fixed the placement of a CBOR documentation block.
|
||||||
|
437. [ljcjclljc](https://github.com/ljcjclljc) fixed the comparison of large unsigned integers with signed integers.
|
||||||
|
438. [Sahil Kamate](https://github.com/sahilkamate03) fixed the handling of CBOR tags 0-5 and 21-23.
|
||||||
|
439. [Krishnanand G](https://github.com/Krishnanand-G) made the UBJSON writer reject `use_type` without `use_size`.
|
||||||
|
440. [whn](https://github.com/Whning0513) documented the lenient BSON input handling and corrected the complexity of `to_bson`.
|
||||||
|
441. [elix3r](https://github.com/22elix3r) fixed `update()` with `merge_objects` when merging a primitive into an object.
|
||||||
|
442. [Avionic Harshit](https://github.com/avionicharshit-byte) made `diff()` linear when an array shrinks.
|
||||||
|
443. [Qatadaha Bin Matloob](https://github.com/qatcod) fixed comparisons between integers and floats and fixed unparsable BJData output.
|
||||||
|
444. [Wu Shuwen](https://github.com/dajiaohuang) removed an unused include.
|
||||||
|
|
||||||
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
|
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
|
||||||
|
|
||||||
@@ -1850,28 +1879,21 @@ The library itself consists of a single header file licensed under the MIT licen
|
|||||||
- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
|
- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
|
||||||
- [**Artistic Style**](https://astyle.sourceforge.net) for automatic source code indentation
|
- [**Artistic Style**](https://astyle.sourceforge.net) for automatic source code indentation
|
||||||
- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers
|
- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers
|
||||||
- [**Clang-Tidy**](https://clang.llvm.org/extra/clang-tidy/) for static analysis and style checks
|
|
||||||
- [**CMake**](https://cmake.org) for build automation
|
- [**CMake**](https://cmake.org) for build automation
|
||||||
- [**Codacy**](https://www.codacy.com) for further [code analysis](https://app.codacy.com/gh/nlohmann/json/dashboard)
|
- [**Codacy**](https://www.codacy.com) for further [code analysis](https://app.codacy.com/gh/nlohmann/json/dashboard)
|
||||||
- [**CodeQL**](https://codeql.github.com) for code scanning
|
|
||||||
- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
|
- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
|
||||||
- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json)
|
- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json)
|
||||||
- [**cppcheck**](https://cppcheck.sourceforge.io) for static analysis
|
- [**cppcheck**](https://cppcheck.sourceforge.io) for static analysis
|
||||||
- [**cpplint**](https://github.com/cpplint/cpplint) for style checks
|
- [**doctest**](https://github.com/onqtam/doctest) for the unit tests
|
||||||
- [**doctest**](https://github.com/doctest/doctest) for the unit tests
|
- [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md)
|
||||||
- [**Flawfinder**](https://dwheeler.com/flawfinder/) for static analysis
|
|
||||||
- [**GitHub Changelog Generator**](https://github.com/github-changelog-generator/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md)
|
|
||||||
- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks
|
- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks
|
||||||
- [**Hedley**](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros
|
- [**Hedley**](https://nemequ.github.io/hedley/) to avoid re-inventing several compiler-agnostic feature macros
|
||||||
- [**include-what-you-use**](https://include-what-you-use.org) to check the included headers
|
|
||||||
- [**Infer**](https://fbinfer.com) for static analysis
|
|
||||||
- [**lcov**](https://github.com/linux-test-project/lcov) to process coverage information and create an HTML view
|
- [**lcov**](https://github.com/linux-test-project/lcov) to process coverage information and create an HTML view
|
||||||
- [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz
|
- [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz
|
||||||
- [**Material for MkDocs**](https://squidfunk.github.io/mkdocs-material/) for the style of the documentation site
|
- [**Material for MkDocs**](https://squidfunk.github.io/mkdocs-material/) for the style of the documentation site
|
||||||
- [**MkDocs**](https://www.mkdocs.org) for the documentation site
|
- [**MkDocs**](https://www.mkdocs.org) for the documentation site
|
||||||
- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json))
|
- [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json))
|
||||||
- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments.
|
- [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments.
|
||||||
- [**Semgrep**](https://semgrep.dev) for static analysis
|
|
||||||
- [**Valgrind**](https://valgrind.org) to check for correct memory management
|
- [**Valgrind**](https://valgrind.org) to check for correct memory management
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
@@ -1965,10 +1987,10 @@ If the testdata is not found, several test suites will fail like this:
|
|||||||
|
|
||||||
```
|
```
|
||||||
===============================================================================
|
===============================================================================
|
||||||
json/tests/src/make_test_data_available.hpp:26:
|
json/tests/src/make_test_data_available.hpp:21:
|
||||||
TEST CASE: check test suite is downloaded
|
TEST CASE: check test suite is downloaded
|
||||||
|
|
||||||
json/tests/src/make_test_data_available.hpp:28: FATAL ERROR: REQUIRE( utils::check_testsuite_downloaded() ) is NOT correct!
|
json/tests/src/make_test_data_available.hpp:23: FATAL ERROR: REQUIRE( utils::check_testsuite_downloaded() ) is NOT correct!
|
||||||
values: REQUIRE( false )
|
values: REQUIRE( false )
|
||||||
logged: Test data not found in 'json/cmake-build-debug/json_test_data'.
|
logged: Test data not found in 'json/cmake-build-debug/json_test_data'.
|
||||||
Please execute target 'download_test_data' before running this test suite.
|
Please execute target 'download_test_data' before running this test suite.
|
||||||
@@ -1979,10 +2001,10 @@ json/tests/src/make_test_data_available.hpp:28: FATAL ERROR: REQUIRE( utils::che
|
|||||||
|
|
||||||
In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
|
In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
|
||||||
|
|
||||||
Some tests require network access to execute properly. They are labeled as `git_required`. Please execute `ctest -LE git_required` to skip these tests. See [issue #4851](https://github.com/nlohmann/json/issues/4851) for more information.
|
Some tests are requiring network to be properly execute. They are labeled as `git_required`. Please execute `ctest -LE git_required` to skip these tests. See [issue #4851](https://github.com/nlohmann/json/issues/4851) for more information.
|
||||||
|
|
||||||
Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. Furthermore, assertions must be switched off to ensure reproducible builds (see [discussion 4494](https://github.com/nlohmann/json/discussions/4494)).
|
Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. Furthermore, assertions must be switched off to ensure reproducible builds (see [discussion 4494](https://github.com/nlohmann/json/discussions/4494)).
|
||||||
|
|
||||||
Note you need to call `ctest -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information.
|
Note you need to call `cmake -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information.
|
||||||
|
|
||||||
As Intel compilers use unsafe floating point optimization by default, the unit tests may fail. Use flag [`/fp:precise`](https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/fp-model-fp.html) then.
|
As Intel compilers use unsafe floating point optimization by default, the unit tests may fail. Use flag [`/fp:precise`](https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/fp-model-fp.html) then.
|
||||||
+2
-8
@@ -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
-36
@@ -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)
|
||||||
@@ -364,7 +367,7 @@ add_custom_target(ci_test_coverage
|
|||||||
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} --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
|
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 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
|
||||||
@@ -420,7 +423,7 @@ 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 venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp ${include_dir}/json_literals.hpp
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.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
|
||||||
@@ -431,8 +434,6 @@ add_custom_target(ci_test_amalgamation
|
|||||||
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~ ${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"
|
||||||
)
|
)
|
||||||
@@ -610,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}")
|
||||||
@@ -625,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()
|
||||||
@@ -730,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})
|
||||||
@@ -787,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}"
|
||||||
@@ -808,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"
|
||||||
@@ -830,12 +823,10 @@ add_custom_target(ci_cuda_example
|
|||||||
|
|
||||||
add_custom_target(ci_module_cpp20
|
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -880,11 +871,11 @@ add_custom_target(ci_icpx
|
|||||||
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
# The following tests are excluded as they trigger known nvc++ 25.5 defects (not
|
||||||
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
# library bugs); see https://github.com/nlohmann/json for tracking. Only the
|
||||||
# affected language-standard variants are excluded so coverage is otherwise kept:
|
# affected language-standard variants are excluded so coverage is otherwise kept:
|
||||||
# - test-comparison_cpp20, test-comparison_legacy_cpp20
|
# - test-comparison-cpp20_cpp20, test-comparison_legacy-cpp20_cpp20
|
||||||
# miscompiles cross-type/<=> comparison (e.g. `-17 <= null`)
|
# miscompiles cross-type/<=> comparison (e.g. `-17 <= null`)
|
||||||
# - test-constructor1_cpp11
|
# - test-constructor1_cpp11
|
||||||
# std::initializer_list lifetime bug -> SIGSEGV
|
# std::initializer_list lifetime bug -> SIGSEGV
|
||||||
# - test-deserialization_cpp20
|
# - test-deserialization-cpp20_cpp20
|
||||||
# mangles the UTF-8 u8"" string literal in the char8_t (C++20) section
|
# mangles the UTF-8 u8"" string literal in the char8_t (C++20) section
|
||||||
add_custom_target(ci_nvhpc
|
add_custom_target(ci_nvhpc
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
@@ -896,7 +887,7 @@ add_custom_target(ci_nvhpc
|
|||||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
||||||
# the pipes are escaped so the surrounding shell passes them to ctest verbatim
|
# the pipes are escaped so the surrounding shell passes them to ctest verbatim
|
||||||
# instead of treating them as shell pipe operators
|
# instead of treating them as shell pipe operators
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_nvhpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-comparison_cpp20\\|test-comparison_legacy_cpp20\\|test-constructor1_cpp11\\|test-deserialization_cpp20" --output-on-failure
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_nvhpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-comparison-cpp20_cpp20\\|test-comparison_legacy-cpp20_cpp20\\|test-constructor1_cpp11\\|test-deserialization-cpp20_cpp20" --output-on-failure
|
||||||
COMMENT "Compile and test with NVIDIA HPC SDK (nvc++)"
|
COMMENT "Compile and test with NVIDIA HPC SDK (nvc++)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +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",
|
|
||||||
],
|
],
|
||||||
includes = ["single_include"],
|
includes = ["single_include"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
|||||||
+366
-39
@@ -109,6 +109,55 @@ function(_json_test_apply_test_properties test_target properties_target)
|
|||||||
endif()
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# for internal use by _json_test_add_test() and _json_test_add_unity_batch():
|
||||||
|
# registers the CTest test <test_name>_cpp<cxx_standard> (plus its Valgrind
|
||||||
|
# variant), which runs the executable target <test_target> with the arguments
|
||||||
|
# in ARGN, and applies the test properties of the test- and standard-specific
|
||||||
|
# interface targets
|
||||||
|
function(_json_test_register_test test_name test_target cxx_standard)
|
||||||
|
set(ctest_name ${test_name}_cpp${cxx_standard})
|
||||||
|
|
||||||
|
if (JSON_FastTests)
|
||||||
|
add_test(NAME ${ctest_name}
|
||||||
|
COMMAND ${test_target} ${DOCTEST_TEST_FILTER} ${ARGN}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
add_test(NAME ${ctest_name}
|
||||||
|
COMMAND ${test_target} ${DOCTEST_TEST_FILTER} ${ARGN} --no-skip
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
set_tests_properties(${ctest_name} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
|
||||||
|
|
||||||
|
# apply standard-specific test properties
|
||||||
|
if(TARGET _json_test_interface__cpp_${cxx_standard})
|
||||||
|
_json_test_apply_test_properties(${ctest_name} _json_test_interface__cpp_${cxx_standard})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# apply test-specific test properties
|
||||||
|
if(TARGET _json_test_interface_${test_name})
|
||||||
|
_json_test_apply_test_properties(${ctest_name} _json_test_interface_${test_name})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# apply test- and standard-specific test properties
|
||||||
|
if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
|
||||||
|
_json_test_apply_test_properties(${ctest_name}
|
||||||
|
_json_test_interface_${test_name}_cpp_${cxx_standard}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(JSON_Valgrind)
|
||||||
|
add_test(NAME ${ctest_name}_valgrind
|
||||||
|
COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER} ${ARGN}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
set_tests_properties(${ctest_name}_valgrind PROPERTIES
|
||||||
|
LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# for internal use by json_test_add_test_for()
|
# for internal use by json_test_add_test_for()
|
||||||
function(_json_test_add_test test_name file main cxx_standard)
|
function(_json_test_add_test test_name file main cxx_standard)
|
||||||
set(test_target ${test_name}_cpp${cxx_standard})
|
set(test_target ${test_name}_cpp${cxx_standard})
|
||||||
@@ -143,45 +192,7 @@ function(_json_test_add_test test_name file main cxx_standard)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (JSON_FastTests)
|
_json_test_register_test(${test_name} ${test_target} ${cxx_standard})
|
||||||
add_test(NAME ${test_target}
|
|
||||||
COMMAND ${test_target} ${DOCTEST_TEST_FILTER}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_test(NAME ${test_target}
|
|
||||||
COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
|
|
||||||
|
|
||||||
# apply standard-specific test properties
|
|
||||||
if(TARGET _json_test_interface__cpp_${cxx_standard})
|
|
||||||
_json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# apply test-specific test properties
|
|
||||||
if(TARGET _json_test_interface_${test_name})
|
|
||||||
_json_test_apply_test_properties(${test_target} _json_test_interface_${test_name})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# apply test- and standard-specific test properties
|
|
||||||
if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
|
|
||||||
_json_test_apply_test_properties(${test_target}
|
|
||||||
_json_test_interface_${test_name}_cpp_${cxx_standard}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(JSON_Valgrind)
|
|
||||||
add_test(NAME ${test_target}_valgrind
|
|
||||||
COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
set_tests_properties(${test_target}_valgrind PROPERTIES
|
|
||||||
LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
@@ -200,6 +211,14 @@ endfunction()
|
|||||||
# Use NAME <name> to override the filename-derived test name.
|
# Use NAME <name> to override the filename-derived test name.
|
||||||
# Use FORCE to create the test regardless of the file containing
|
# Use FORCE to create the test regardless of the file containing
|
||||||
# JSON_HAS_CPP_<version_number>.
|
# JSON_HAS_CPP_<version_number>.
|
||||||
|
#
|
||||||
|
# Tests that depend on the C++ standard (e.g., because they use the macros
|
||||||
|
# JSON_HAS_FILESYSTEM, JSON_HAS_RANGES, or JSON_HAS_THREE_WAY_COMPARISON)
|
||||||
|
# should not make the whole of a large unit-foo.cpp be rebuilt for every
|
||||||
|
# standard. Put them into a separate file unit-foo-cpp<NN>.cpp (see, e.g.,
|
||||||
|
# unit-items-cpp17.cpp) which wraps its content in #ifdef JSON_HAS_CPP_<NN>.
|
||||||
|
# Then, unit-foo.cpp itself contains no JSON_HAS_CPP_<NN> and is only built for
|
||||||
|
# C++11.
|
||||||
# Test targets are linked against <main>.
|
# Test targets are linked against <main>.
|
||||||
# CXX_STANDARDS defaults to "11".
|
# CXX_STANDARDS defaults to "11".
|
||||||
#############################################################################
|
#############################################################################
|
||||||
@@ -243,6 +262,314 @@ function(json_test_add_test_for file)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# for internal use by json_test_add_unity_tests(): sets <result> to whether the
|
||||||
|
# (absolute) <file> is built for <cxx_standard>; same rule as in
|
||||||
|
# json_test_add_test_for(): C++11 always, others only if the file contains
|
||||||
|
# JSON_HAS_CPP_<cxx_standard> or <force> is set
|
||||||
|
function(_json_test_unity_applies file cxx_standard force result)
|
||||||
|
set(${result} TRUE PARENT_SCOPE)
|
||||||
|
if(NOT ("${cxx_standard}" STREQUAL 11 OR force))
|
||||||
|
file(READ ${file} file_content)
|
||||||
|
string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found)
|
||||||
|
if(${has_cpp_found} EQUAL -1)
|
||||||
|
set(${result} FALSE PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# for internal use by json_test_add_unity_tests(): creates the executable
|
||||||
|
# test-unity-<batch_name>_cpp<cxx_standard> from the (absolute) source files
|
||||||
|
# in ARGN, which are #include-d by a generated source file, and registers one
|
||||||
|
# CTest test per source file that runs only the test cases of that file; if
|
||||||
|
# <private> is true, the generated file defines JSON_TESTS_PRIVATE first
|
||||||
|
function(_json_test_add_unity_batch batch_name cxx_standard main private)
|
||||||
|
set(batch_target test-unity-${batch_name}_cpp${cxx_standard})
|
||||||
|
set(batch_source ${PROJECT_BINARY_DIR}/tests/unity/${batch_target}.cpp)
|
||||||
|
|
||||||
|
set(batch_content "// generated by cmake/test.cmake; do not edit\n")
|
||||||
|
if(private)
|
||||||
|
string(APPEND batch_content "// at least one file of this batch needs access to private members of the library\n")
|
||||||
|
string(APPEND batch_content "#define JSON_TESTS_PRIVATE\n")
|
||||||
|
# the files define the macro again; mark this definition as used, as
|
||||||
|
# -Wunused-macros reports an unused definition when it is redefined
|
||||||
|
string(APPEND batch_content "#ifdef JSON_TESTS_PRIVATE\n#endif\n")
|
||||||
|
endif()
|
||||||
|
foreach(file ${ARGN})
|
||||||
|
string(APPEND batch_content "#include \"${file}\" // NOLINT(bugprone-suspicious-include)\n")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# only touch the generated file if it changed to keep incremental builds incremental
|
||||||
|
set(old_content "")
|
||||||
|
if(EXISTS ${batch_source})
|
||||||
|
file(READ ${batch_source} old_content)
|
||||||
|
endif()
|
||||||
|
if(NOT "${old_content}" STREQUAL "${batch_content}")
|
||||||
|
file(WRITE ${batch_source} "${batch_content}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(${batch_target} ${batch_source})
|
||||||
|
target_link_libraries(${batch_target} PRIVATE ${main})
|
||||||
|
set_target_properties(${batch_target} PROPERTIES
|
||||||
|
CXX_STANDARD ${cxx_standard}
|
||||||
|
CXX_STANDARD_REQUIRED ON
|
||||||
|
)
|
||||||
|
if(TARGET _json_test_interface__cpp_${cxx_standard})
|
||||||
|
target_link_libraries(${batch_target} PRIVATE _json_test_interface__cpp_${cxx_standard})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# rebuild the batch when one of its files changes, and show the files in IDEs;
|
||||||
|
# files that are also built standalone (VARIANT_FILES) are left out, as
|
||||||
|
# HEADER_FILE_ONLY is a per-file property and would also affect those targets
|
||||||
|
set_source_files_properties(${batch_source} PROPERTIES OBJECT_DEPENDS "${ARGN}")
|
||||||
|
foreach(file ${ARGN})
|
||||||
|
if(NOT file IN_LIST _json_test_unity_variant_files)
|
||||||
|
set_source_files_properties(${file} PROPERTIES HEADER_FILE_ONLY ON)
|
||||||
|
target_sources(${batch_target} PRIVATE ${file})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(file ${ARGN})
|
||||||
|
get_filename_component(file_basename ${file} NAME_WE)
|
||||||
|
string(REGEX REPLACE "unit-(.+)" "test-\\1" test_name ${file_basename})
|
||||||
|
|
||||||
|
# run only the test cases defined in this file (and in the shared
|
||||||
|
# make_test_data_available.hpp if the file uses it)
|
||||||
|
file(READ ${file} file_content)
|
||||||
|
set(source_filter "--source-file=*${file_basename}.cpp")
|
||||||
|
string(FIND "${file_content}" make_test_data_available.hpp uses_test_data)
|
||||||
|
if(NOT ${uses_test_data} EQUAL -1)
|
||||||
|
string(APPEND source_filter ",*make_test_data_available.hpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_json_test_register_test(${test_name} ${batch_target} ${cxx_standard} "${source_filter}")
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# json_test_add_unity_tests(
|
||||||
|
# FILES <files>...
|
||||||
|
# MAIN <main>
|
||||||
|
# [CXX_STANDARDS <version_number>...] [FORCE]
|
||||||
|
# [BATCH_SIZE <size>]
|
||||||
|
# [GROUPS <group>...]
|
||||||
|
# [VARIANT_FILES <files>...])
|
||||||
|
#
|
||||||
|
# Like calling json_test_add_test_for(<file> MAIN <main> ...) for each of the
|
||||||
|
# <files>, but compiles several files together to speed up the build: for each
|
||||||
|
# C++ standard, the files are split into batches of <size> files (default: 8)
|
||||||
|
# and each batch is built as a single executable
|
||||||
|
#
|
||||||
|
# test-unity-<pool><index>_cpp<version_number>
|
||||||
|
#
|
||||||
|
# whose generated source file #include-s the files of the batch (so they share
|
||||||
|
# the template instantiations of the library). The tests are still named
|
||||||
|
# test-foo_cpp<version_number>, one per file, but run the batch executable with
|
||||||
|
# a doctest filter that selects the test cases of that file only.
|
||||||
|
#
|
||||||
|
# Files are only batched with files that agree on the macros defined before
|
||||||
|
# the library is included: files that define at most JSON_TESTS_PRIVATE (or
|
||||||
|
# macros derived from global compile definitions) form the pools "plain" and
|
||||||
|
# "private". All other files are added with json_test_add_test_for() as usual,
|
||||||
|
# as are files with test-specific build settings (see
|
||||||
|
# json_test_set_test_options()) and the files listed in the explicit
|
||||||
|
# exclusion list below.
|
||||||
|
# Each <group> names a list variable json_test_unity_group_<group> of test file
|
||||||
|
# stems (file names without "unit-" and ".cpp"). The batchable files of a group
|
||||||
|
# are compiled together (regardless of BATCH_SIZE) as one executable
|
||||||
|
#
|
||||||
|
# test-unity-<group>_cpp<version_number>
|
||||||
|
#
|
||||||
|
# so that related tests, which instantiate the same templates, share one
|
||||||
|
# translation unit. A group may mix the pools "plain" and "private"; if any of
|
||||||
|
# its files needs JSON_TESTS_PRIVATE, the whole group is built with it. Files
|
||||||
|
# that cannot be batched stay standalone even if they are listed in a group.
|
||||||
|
# Files in no group are batched by BATCH_SIZE as described above.
|
||||||
|
# <files> in VARIANT_FILES are also built standalone with other settings, so
|
||||||
|
# they are not marked as header-only sources of the batch.
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
function(json_test_add_unity_tests)
|
||||||
|
cmake_parse_arguments(args "FORCE" "MAIN;BATCH_SIZE" "FILES;CXX_STANDARDS;VARIANT_FILES;GROUPS" ${ARGN})
|
||||||
|
|
||||||
|
if("${args_MAIN}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR "Required argument MAIN <main> missing.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${args_BATCH_SIZE}" STREQUAL "")
|
||||||
|
set(args_BATCH_SIZE 8)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${args_CXX_STANDARDS}" STREQUAL "")
|
||||||
|
set(args_CXX_STANDARDS 11)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(args_FORCE)
|
||||||
|
set(force FORCE)
|
||||||
|
else()
|
||||||
|
set(force "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_json_test_unity_variant_files "")
|
||||||
|
foreach(file ${args_VARIANT_FILES})
|
||||||
|
get_filename_component(file ${file} ABSOLUTE)
|
||||||
|
list(APPEND _json_test_unity_variant_files ${file})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# files that must not be merged into a batch: unit-32bit.cpp is only built
|
||||||
|
# for 32bit targets, and unit-no-macro-leak.cpp checks that including the
|
||||||
|
# library defines no unprefixed macro, which any other file would disturb
|
||||||
|
set(standalone_files unit-32bit.cpp unit-no-macro-leak.cpp)
|
||||||
|
|
||||||
|
set(harmless_macros "^(DOCTEST_.*|SKIP_TESTS_FOR_.*|JSON_TEST_DEPRECATED_FUNCTIONS_DELETED|JSON_TEST_STRICT_NUL_HANDLING_ENABLED|JSON_TEST_STRINGIZE)$")
|
||||||
|
|
||||||
|
# classify the files
|
||||||
|
set(plain_files "")
|
||||||
|
set(private_files "")
|
||||||
|
set(standalone_abs_files "")
|
||||||
|
foreach(file ${args_FILES})
|
||||||
|
get_filename_component(file_name ${file} NAME)
|
||||||
|
get_filename_component(file_basename ${file} NAME_WE)
|
||||||
|
string(REGEX REPLACE "unit-(.+)" "test-\\1" test_name ${file_basename})
|
||||||
|
|
||||||
|
set(batchable TRUE)
|
||||||
|
if(file_name IN_LIST standalone_files)
|
||||||
|
set(batchable FALSE)
|
||||||
|
endif()
|
||||||
|
if(TARGET _json_test_interface_${test_name})
|
||||||
|
set(batchable FALSE)
|
||||||
|
endif()
|
||||||
|
foreach(cxx_standard ${args_CXX_STANDARDS})
|
||||||
|
if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
|
||||||
|
set(batchable FALSE)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# files that suppress GCC's -Wnoexcept around their include of the
|
||||||
|
# library: the suppression has no effect once another file of the
|
||||||
|
# batch included the library first
|
||||||
|
if(batchable)
|
||||||
|
file(READ ${file} file_content)
|
||||||
|
string(FIND "${file_content}" "SUPPRESS_WARNING(\"-Wnoexcept\")" suppresses_noexcept)
|
||||||
|
if(NOT ${suppresses_noexcept} EQUAL -1)
|
||||||
|
set(batchable FALSE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(pool plain)
|
||||||
|
if(batchable)
|
||||||
|
# collect the macros (un)defined before the library is included
|
||||||
|
file(READ ${file} file_content)
|
||||||
|
string(FIND "${file_content}" "#include <nlohmann/" include_position)
|
||||||
|
if(NOT ${include_position} EQUAL -1)
|
||||||
|
string(SUBSTRING "${file_content}" 0 ${include_position} file_content)
|
||||||
|
endif()
|
||||||
|
string(REGEX MATCHALL "(^|\n)[ \t]*#[ \t]*(define|undef)[ \t]+[A-Za-z_0-9]+" directives "${file_content}")
|
||||||
|
foreach(directive ${directives})
|
||||||
|
string(REGEX REPLACE "^.*[ \t]([A-Za-z_0-9]+)$" "\\1" macro "${directive}")
|
||||||
|
if(macro MATCHES "${harmless_macros}")
|
||||||
|
continue()
|
||||||
|
elseif("${macro}" STREQUAL JSON_TESTS_PRIVATE)
|
||||||
|
set(pool private)
|
||||||
|
else()
|
||||||
|
set(batchable FALSE)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(file_abs ${file} ABSOLUTE)
|
||||||
|
if(NOT batchable)
|
||||||
|
list(APPEND standalone_abs_files ${file_abs})
|
||||||
|
json_test_add_test_for(${file} MAIN ${args_MAIN} CXX_STANDARDS ${args_CXX_STANDARDS} ${force})
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
get_filename_component(file ${file} ABSOLUTE)
|
||||||
|
list(APPEND ${pool}_files ${file})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# resolve the explicit groups: group_<name>_files are the (absolute) files
|
||||||
|
# of the group, group_<name>_private tells whether one of them is private
|
||||||
|
set(grouped_files "")
|
||||||
|
foreach(group ${args_GROUPS})
|
||||||
|
if(NOT DEFINED json_test_unity_group_${group})
|
||||||
|
message(FATAL_ERROR "Unity test group '${group}' is not defined (json_test_unity_group_${group}).")
|
||||||
|
endif()
|
||||||
|
set(group_${group}_files "")
|
||||||
|
set(group_${group}_private FALSE)
|
||||||
|
foreach(stem ${json_test_unity_group_${group}})
|
||||||
|
# check against the source directory, because FILES may be filtered (JSON_TestShard)
|
||||||
|
get_filename_component(file ${CMAKE_CURRENT_SOURCE_DIR}/src/unit-${stem}.cpp ABSOLUTE)
|
||||||
|
if(NOT EXISTS ${file})
|
||||||
|
message(FATAL_ERROR "Unity test group '${group}' lists '${stem}', but ${file} does not exist.")
|
||||||
|
endif()
|
||||||
|
if(file IN_LIST grouped_files)
|
||||||
|
message(FATAL_ERROR "Unity test file unit-${stem}.cpp is listed in more than one group (second: '${group}').")
|
||||||
|
endif()
|
||||||
|
list(APPEND grouped_files ${file})
|
||||||
|
|
||||||
|
if(file IN_LIST standalone_abs_files)
|
||||||
|
message(STATUS "Unity test group '${group}': unit-${stem}.cpp cannot be batched and stays standalone")
|
||||||
|
elseif(file IN_LIST plain_files)
|
||||||
|
list(APPEND group_${group}_files ${file})
|
||||||
|
list(REMOVE_ITEM plain_files ${file})
|
||||||
|
elseif(file IN_LIST private_files)
|
||||||
|
list(APPEND group_${group}_files ${file})
|
||||||
|
list(REMOVE_ITEM private_files ${file})
|
||||||
|
set(group_${group}_private TRUE)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(cxx_standard ${args_CXX_STANDARDS})
|
||||||
|
if(NOT compiler_supports_cpp_${cxx_standard})
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# explicit groups: one batch per group
|
||||||
|
foreach(group ${args_GROUPS})
|
||||||
|
set(batch_files "")
|
||||||
|
foreach(file ${group_${group}_files})
|
||||||
|
_json_test_unity_applies(${file} ${cxx_standard} "${force}" applies)
|
||||||
|
if(applies)
|
||||||
|
list(APPEND batch_files ${file})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if(batch_files)
|
||||||
|
_json_test_add_unity_batch(${group} ${cxx_standard} ${args_MAIN} ${group_${group}_private} ${batch_files})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# remaining files: batches of BATCH_SIZE files per pool
|
||||||
|
foreach(pool plain private)
|
||||||
|
set(is_private FALSE)
|
||||||
|
if(pool STREQUAL private)
|
||||||
|
set(is_private TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(batch_files "")
|
||||||
|
set(batch_count 0)
|
||||||
|
set(batch_index 0)
|
||||||
|
foreach(file ${${pool}_files})
|
||||||
|
_json_test_unity_applies(${file} ${cxx_standard} "${force}" applies)
|
||||||
|
if(NOT applies)
|
||||||
|
continue()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND batch_files ${file})
|
||||||
|
math(EXPR batch_count "${batch_count} + 1")
|
||||||
|
if(batch_count EQUAL args_BATCH_SIZE)
|
||||||
|
_json_test_add_unity_batch(${pool}${batch_index} ${cxx_standard} ${args_MAIN} ${is_private} ${batch_files})
|
||||||
|
set(batch_files "")
|
||||||
|
set(batch_count 0)
|
||||||
|
math(EXPR batch_index "${batch_index} + 1")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
if(batch_files)
|
||||||
|
_json_test_add_unity_batch(${pool}${batch_index} ${cxx_standard} ${args_MAIN} ${is_private} ${batch_files})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# json_test_should_build_32bit_test(
|
# json_test_should_build_32bit_test(
|
||||||
# <build_32bit_var> <build_32bit_only_var> <input>)
|
# <build_32bit_var> <build_32bit_only_var> <input>)
|
||||||
|
|||||||
+2
-2
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
@@ -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())
|
|
||||||
@@ -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).
|
||||||
|
|||||||
@@ -241,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.
|
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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`:
|
|
||||||
```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).
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ To store objects in C++, a type is defined by the template parameters described
|
|||||||
|
|
||||||
`StringType`
|
`StringType`
|
||||||
: the type of the keys or names (e.g., `std::string`). The comparison function `std::less<StringType>` is used to
|
: the type of the keys or names (e.g., `std::string`). The comparison function `std::less<StringType>` is used to
|
||||||
order elements inside the container.
|
order elements inside the container. `object_t::key_type` must be implicitly convertible to `string_t` (required by the
|
||||||
|
binary formats).
|
||||||
|
|
||||||
`AllocatorType`
|
`AllocatorType`
|
||||||
: the allocator to use for objects (e.g., `std::allocator`)
|
: the allocator to use for objects (e.g., `std::allocator`)
|
||||||
|
|||||||
@@ -286,6 +286,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,10 +11,12 @@ 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
|
||||||
bool operator==(const_reference rhs) const noexcept; // (1)
|
class basic_json {
|
||||||
|
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:
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// since C++20
|
// since C++20
|
||||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1)
|
class basic_json {
|
||||||
|
std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1)
|
||||||
|
|
||||||
template<typename ScalarType>
|
template<typename ScalarType>
|
||||||
std::partial_ordering operator<=>(const ScalarType rhs) const noexcept(/* see below */); // (2)
|
std::partial_ordering operator<=>(const ScalarType rhs) const noexcept(/* see below */); // (2)
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
1. 3-way compares two JSON values producing a result of type `std::partial_ordering` according to the following rules:
|
1. 3-way compares two JSON values producing a result of type `std::partial_ordering` according to the following rules:
|
||||||
|
|||||||
@@ -112,6 +112,3 @@ is thrown. In any case, the original value is not changed: the patch is applied
|
|||||||
location has a non-object/non-array parent in version 3.13.0.
|
location has a non-object/non-array parent in version 3.13.0.
|
||||||
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
||||||
prefix of its "path" location instead of silently producing a corrupted result in version 3.13.0.
|
prefix of its "path" location instead of silently producing a corrupted result in version 3.13.0.
|
||||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
|
|
||||||
[`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.
|
|
||||||
@@ -110,6 +110,3 @@ function throws an exception.
|
|||||||
location has a non-object/non-array parent in version 3.13.0.
|
location has a non-object/non-array parent in version 3.13.0.
|
||||||
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
- Added [`out_of_range.414`](../../home/exceptions.md#jsonexceptionout_of_range414) and rejected a "move" operation whose "from" location is a proper
|
||||||
prefix of its "path" location instead of silently producing a corrupted result in version 3.13.0.
|
prefix of its "path" location instead of silently producing a corrupted result in version 3.13.0.
|
||||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
|
|
||||||
[`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.
|
|
||||||
@@ -41,8 +41,6 @@ With (2), the bytes written before the exception remain in the output adapter.
|
|||||||
above 9223372036854775807, which BON8 cannot represent
|
above 9223372036854775807, which BON8 cannot represent
|
||||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if `j` contains a string that is not
|
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if `j` contains a string that is not
|
||||||
valid UTF-8
|
valid UTF-8
|
||||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is
|
|
||||||
discarded; example: `"cannot serialize discarded value to BON8"`
|
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,8 @@ The function can throw the following exceptions:
|
|||||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a key is not a
|
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in a key is not a
|
||||||
number; example: `"array index 'one' is not a number"`
|
number; example: `"array index 'one' is not a number"`
|
||||||
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a level becomes an array
|
- Throws [`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) if a level becomes an array
|
||||||
(because one of its keys is `0`) and another key at that level begins with a digit but is not a valid array index
|
(because one of its keys is `0`) and another key at that level cannot be an array index; example:
|
||||||
(such as `1a`), or is `-`; example:
|
`"unresolved reference token 'x'"`
|
||||||
`"unresolved reference token '-'"`
|
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
@@ -81,6 +80,3 @@ Apart from these two cases, for a JSON value `j`, the following is always true:
|
|||||||
|
|
||||||
- Added in version 2.0.0.
|
- Added in version 2.0.0.
|
||||||
- Made the array/object decision independent of the object's iteration order in version 3.13.0.
|
- Made the array/object decision independent of the object's iteration order in version 3.13.0.
|
||||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
|
|
||||||
[`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.
|
|
||||||
@@ -119,14 +119,6 @@ changes to any JSON value.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
!!! warning "`null` members are not missing"
|
|
||||||
|
|
||||||
The default value is used only if the key (or JSON Pointer) does not exist. A member that exists but is
|
|
||||||
`#!json null` is converted like any other value, so `#!cpp j.value("k", 0)` throws a
|
|
||||||
[`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `"k"` is `#!json null`. See
|
|
||||||
[Access with default value](../../features/element_access/default_value.md)
|
|
||||||
for alternatives.
|
|
||||||
|
|
||||||
!!! warning "Return type"
|
!!! warning "Return type"
|
||||||
|
|
||||||
The value function is a template, and the return type of the function is determined by the type of the provided
|
The value function is a template, and the return type of the function is determined by the type of the provided
|
||||||
@@ -235,6 +227,4 @@ changes to any JSON value.
|
|||||||
[`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), and other lookup functions.
|
[`operator[]`](operator[].md), [`at`](at.md), [`find`](find.md), and other lookup functions.
|
||||||
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
||||||
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
||||||
`default_value`, as documented). Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109)
|
`default_value`, as documented).
|
||||||
instead of returning `default_value` 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.
|
|
||||||
@@ -18,11 +18,13 @@ bool operator==(
|
|||||||
const json_pointer<RefStringTypeRhs>& rhs); // (2)
|
const json_pointer<RefStringTypeRhs>& rhs); // (2)
|
||||||
|
|
||||||
// since C++20
|
// since C++20
|
||||||
template<typename RefStringTypeRhs>
|
class json_pointer {
|
||||||
bool operator==(
|
template<typename RefStringTypeRhs>
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // (1)
|
bool operator==(
|
||||||
|
const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // (1)
|
||||||
|
|
||||||
bool operator==(const string_t& rhs) const; // (2)
|
bool operator==(const string_t& rhs) const; // (2)
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Compares two JSON pointers for equality by comparing their reference tokens.
|
1. Compares two JSON pointers for equality by comparing their reference tokens.
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// since C++20
|
// since C++20
|
||||||
template<typename RefStringTypeRhs>
|
class json_pointer {
|
||||||
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // *NOPAD*
|
template<typename RefStringTypeRhs>
|
||||||
|
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // *NOPAD*
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
3-way compares two JSON pointers by lexicographically comparing their sequences of reference tokens: corresponding
|
3-way compares two JSON pointers by lexicographically comparing their sequences of reference tokens: corresponding
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ header. See also the [macro overview page](../../features/macros.md).
|
|||||||
|
|
||||||
- [**JSON_HAS_CPP_11**<br>**JSON_HAS_CPP_14**<br>**JSON_HAS_CPP_17**<br>**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard
|
- [**JSON_HAS_CPP_11**<br>**JSON_HAS_CPP_14**<br>**JSON_HAS_CPP_17**<br>**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard
|
||||||
- [**JSON_HAS_FILESYSTEM**<br>**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support
|
- [**JSON_HAS_FILESYSTEM**<br>**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support
|
||||||
- [**JSON_HAS_RANGE_VIEW_CONVERSION**](json_has_range_view_conversion.md) - control construction from `std::ranges` views
|
|
||||||
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
||||||
- [**JSON_HAS_STATIC_RTTI**](json_has_static_rtti.md) - control RTTI (run time type information) support
|
- [**JSON_HAS_STATIC_RTTI**](json_has_static_rtti.md) - control RTTI (run time type information) support
|
||||||
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
||||||
|
|||||||
@@ -49,6 +49,6 @@ The default value is detected based on preprocessor macros such as `#!cpp __cplu
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.10.0.
|
- Added in version 3.10.5.
|
||||||
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
||||||
- Added `JSON_HAS_CPP_26` in version 3.13.0.
|
- Added `JSON_HAS_CPP_26` in version 3.13.0.
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# JSON_HAS_RANGE_VIEW_CONVERSION
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#define JSON_HAS_RANGE_VIEW_CONVERSION /* value */
|
|
||||||
```
|
|
||||||
|
|
||||||
This macro indicates whether a JSON array can be constructed directly from a C++20 range view (`std::ranges::view`),
|
|
||||||
such as the result of `std::views::filter` or `std::views::transform`. Possible values are `1` when supported or `0`
|
|
||||||
when unsupported.
|
|
||||||
|
|
||||||
## Default definition
|
|
||||||
|
|
||||||
The default value is `1` if [`JSON_HAS_RANGES`](json_has_ranges.md) is `1` and the compiler is not MinGW (that is,
|
|
||||||
`#!cpp __MINGW32__` is not defined), and `0` otherwise.
|
|
||||||
|
|
||||||
When the macro is not defined, the library will define it to its default value.
|
|
||||||
|
|
||||||
!!! info "Known compiler/stdlib exclusions"
|
|
||||||
|
|
||||||
- **MinGW** -- disabled, because its `std::ranges` support is incomplete ([issue #4916](https://github.com/nlohmann/json/issues/4916)).
|
|
||||||
- All toolchains for which [`JSON_HAS_RANGES`](json_has_ranges.md#default-definition) is disabled.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
??? example
|
|
||||||
|
|
||||||
The code below forces the library to disable the conversion from range views:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#define JSON_HAS_RANGE_VIEW_CONVERSION 0
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
## See also
|
|
||||||
|
|
||||||
- [JSON_HAS_RANGES](json_has_ranges.md) - control `std::ranges` support
|
|
||||||
- [Constructing from a C++20 range view](../../features/conversions.md#putting-values-in) - usage of the feature
|
|
||||||
|
|
||||||
## Version history
|
|
||||||
|
|
||||||
- Added in version 3.13.0.
|
|
||||||
@@ -20,7 +20,7 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
- **GCC 11.1.0** — disabled (the shipped `<ranges>` header has a syntax error; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
- **GCC 11.1.0** — disabled (the shipped `<ranges>` header has a syntax error; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||||
- **libstdc++ < 11** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
- **libstdc++ < 11** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||||
- **Clang < 16 with libstdc++** — disabled (incomplete ranges support; [issue #5161](https://github.com/nlohmann/json/issues/5161))
|
- **Clang < 16 with libstdc++** — disabled (incomplete ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||||
- **libc++ < 160000** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
- **libc++ < 160000** — disabled (incomplete C++20 ranges support; [issue #4440](https://github.com/nlohmann/json/issues/4440))
|
||||||
- **nvcc (CUDA) 12.0.x and 12.1.x** — disabled (the `enable_borrowed_range` variable-template syntax triggers a parse error
|
- **nvcc (CUDA) 12.0.x and 12.1.x** — disabled (the `enable_borrowed_range` variable-template syntax triggers a parse error
|
||||||
under these two toolkit versions; fixed in CUDA 12.2; [issue #3907](https://github.com/nlohmann/json/issues/3907))
|
under these two toolkit versions; fixed in CUDA 12.2; [issue #3907](https://github.com/nlohmann/json/issues/3907))
|
||||||
@@ -44,12 +44,9 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
- [JSON_HAS_CPP_11 / JSON_HAS_CPP_14 / JSON_HAS_CPP_17 / JSON_HAS_CPP_20 / JSON_HAS_CPP_23 /
|
- [JSON_HAS_CPP_11 / JSON_HAS_CPP_14 / JSON_HAS_CPP_17 / JSON_HAS_CPP_20 / JSON_HAS_CPP_23 /
|
||||||
JSON_HAS_CPP_26](json_has_cpp_11.md) - set supported C++ standard
|
JSON_HAS_CPP_26](json_has_cpp_11.md) - set supported C++ standard
|
||||||
- [JSON_HAS_RANGE_VIEW_CONVERSION](json_has_range_view_conversion.md) - control construction from `std::ranges` views
|
|
||||||
- [JSON_HAS_STD_FORMAT](json_has_std_format.md) - a similar feature-detection macro, for `std::format`/`std::formatter`
|
- [JSON_HAS_STD_FORMAT](json_has_std_format.md) - a similar feature-detection macro, for `std::format`/`std::formatter`
|
||||||
support
|
support
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.11.0.
|
- Added in version 3.11.0.
|
||||||
- Added the exclusions for libstdc++ < 11, Clang < 16 with libstdc++, libc++ < 16, and nvcc (CUDA) 12.0.x and 12.1.x in
|
|
||||||
version 3.13.0. Before, only GCC 11.1.0 was excluded.
|
|
||||||
@@ -20,10 +20,7 @@ The macro does not affect:
|
|||||||
- The binary readers ([`from_cbor`](../basic_json/from_cbor.md), [`from_msgpack`](../basic_json/from_msgpack.md),
|
- The binary readers ([`from_cbor`](../basic_json/from_cbor.md), [`from_msgpack`](../basic_json/from_msgpack.md),
|
||||||
[`from_ubjson`](../basic_json/from_ubjson.md), [`from_bjdata`](../basic_json/from_bjdata.md),
|
[`from_ubjson`](../basic_json/from_ubjson.md), [`from_bjdata`](../basic_json/from_bjdata.md),
|
||||||
[`from_bson`](../basic_json/from_bson.md)): none of these formats requires a decoder to reject ill-formed UTF-8, so
|
[`from_bson`](../basic_json/from_bson.md)): none of these formats requires a decoder to reject ill-formed UTF-8, so
|
||||||
by default they return the bytes unchanged (`error_handler_t::keep`), independent of this macro. Pass an
|
they always return the bytes unchanged.
|
||||||
`error_handler` argument explicitly to validate or sanitize the strings they read.
|
|
||||||
- [`from_bon8`](../basic_json/from_bon8.md): BON8 always validates, because the UTF-8 lead bytes mark where a string
|
|
||||||
ends.
|
|
||||||
|
|
||||||
## Default definition
|
## Default definition
|
||||||
|
|
||||||
|
|||||||
@@ -190,5 +190,3 @@ void to_json(BasicJsonType& j, const B& b) {
|
|||||||
4. Added in version 3.12.0.
|
4. Added in version 3.12.0.
|
||||||
5. Added in version 3.12.0.
|
5. Added in version 3.12.0.
|
||||||
6. Added in version 3.12.0.
|
6. Added in version 3.12.0.
|
||||||
|
|
||||||
All six macros were changed to allow an empty member list in version 3.13.0.
|
|
||||||
@@ -186,6 +186,3 @@ See the examples below for the concrete generated code.
|
|||||||
1. Added in version 3.9.0.
|
1. Added in version 3.9.0.
|
||||||
2. Added in version 3.11.0.
|
2. Added in version 3.11.0.
|
||||||
3. Added in version 3.11.3.
|
3. Added in version 3.11.3.
|
||||||
|
|
||||||
All three macros were changed to work with any `basic_json` specialization (not only `nlohmann::json`) in version 3.12.0,
|
|
||||||
and to allow an empty member list in version 3.13.0.
|
|
||||||
@@ -185,6 +185,3 @@ See the examples below for the concrete generated code.
|
|||||||
1. Added in version 3.9.0.
|
1. Added in version 3.9.0.
|
||||||
2. Added in version 3.11.0.
|
2. Added in version 3.11.0.
|
||||||
3. Added in version 3.11.3.
|
3. Added in version 3.11.3.
|
||||||
|
|
||||||
All three macros were changed to work with any `basic_json` specialization (not only `nlohmann::json`) in version 3.12.0,
|
|
||||||
and to allow an empty member list in version 3.13.0.
|
|
||||||
@@ -38,6 +38,4 @@ the library.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.11.0. Changed inline namespace name in version 3.11.2. Added the ABI tag `_dp` in
|
- Added in version 3.11.0. Changed inline namespace name in version 3.11.2.
|
||||||
version 3.12.0, and the ABI tags `_bics`, `_psp`, `_snul`, `_sbu8`, and `_ekmo` in version 3.13.0; see
|
|
||||||
[`nlohmann` Namespace](../../features/namespace.md#structure).
|
|
||||||
@@ -14,7 +14,7 @@ These macros can be used to open and close the `nlohmann` namespace. See
|
|||||||
## Default definition
|
## Default definition
|
||||||
|
|
||||||
The default definitions open and close the `nlohmann` namespace. The precise definition of
|
The default definitions open and close the `nlohmann` namespace. The precise definition of
|
||||||
`NLOHMANN_JSON_NAMESPACE_BEGIN` varies as described [here](../../features/namespace.md#structure).
|
[`NLOHMANN_JSON_NAMESPACE_BEGIN`] varies as described [here](../../features/namespace.md#structure).
|
||||||
|
|
||||||
1. Default definition of `NLOHMANN_JSON_NAMESPACE_BEGIN`:
|
1. Default definition of `NLOHMANN_JSON_NAMESPACE_BEGIN`:
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ The library parses, stores, and serializes JSON values in memory. It does not op
|
|||||||
files (it only reads from streams or `std::FILE*` handles that the caller has already opened), does not read environment
|
files (it only reads from streams or `std::FILE*` handles that the caller has already opened), does not read environment
|
||||||
variables, and does not implement cryptography or handle credentials.
|
variables, and does not implement cryptography or handle credentials.
|
||||||
|
|
||||||
The primary threat is therefore **untrusted input**: JSON text or binary data (BJData, BON8, BSON, CBOR, MessagePack, UBJSON)
|
The primary threat is therefore **untrusted input**: JSON text or binary data (BJData, BSON, CBOR, MessagePack, UBJSON)
|
||||||
that an attacker controls, passed to [`parse`](../api/basic_json/parse.md), [`accept`](../api/basic_json/accept.md),
|
that an attacker controls, passed to [`parse`](../api/basic_json/parse.md), [`accept`](../api/basic_json/accept.md),
|
||||||
[`sax_parse`](../api/basic_json/sax_parse.md), or one of the `from_*` functions such as
|
[`sax_parse`](../api/basic_json/sax_parse.md), or one of the `from_*` functions such as
|
||||||
[`from_cbor`](../api/basic_json/from_cbor.md). Such input may try to
|
[`from_cbor`](../api/basic_json/from_cbor.md). Such input may try to
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ violations will result in a failed build.
|
|||||||
|
|
||||||
Note: C++20 modules support may hit compiler-specific issues not covered by the general compiler matrix below. See [Modules](../features/modules.md#known-issues) for known issues and workarounds.
|
Note: C++20 modules support may hit compiler-specific issues not covered by the general compiler matrix below. See [Modules](../features/modules.md#known-issues) for known issues and workarounds.
|
||||||
|
|
||||||
Note: Some modern features (like C++20 ranges or filesystem support) may be disabled on specific broken or incomplete toolchains even when standard feature-test macros indicate support. See [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md), [`JSON_HAS_RANGE_VIEW_CONVERSION`](../api/macros/json_has_range_view_conversion.md), and [`JSON_HAS_FILESYSTEM`](../api/macros/json_has_filesystem.md) for details on known exclusions.
|
Note: Some modern features (like C++20 ranges or filesystem support) may be disabled on specific broken or incomplete toolchains even when standard feature-test macros indicate support. See [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md) and [`JSON_HAS_FILESYSTEM`](../api/macros/json_has_filesystem.md) for details on known exclusions.
|
||||||
|
|
||||||
- [x] The library is compiled with 50+ different C++ compilers with different operating systems and platforms,
|
- [x] The library is compiled with 50+ different C++ compilers with different operating systems and platforms,
|
||||||
including the oldest versions known to compile the library.
|
including the oldest versions known to compile the library.
|
||||||
@@ -107,7 +107,7 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
- [x] The library is compiled with all C++ language revisions (C++11, C++14, C++17, C++20, C++23, and C++26) to detect
|
- [x] The library is compiled with all C++ language revisions (C++11, C++14, C++17, C++20, C++23, and C++26) to detect
|
||||||
and fix language deprecations early.
|
and fix language deprecations early.
|
||||||
- [x] The library is checked for compiler warnings:
|
- [x] The library is checked for compiler warnings:
|
||||||
- On Clang, `-Weverything` is used with 7 exceptions.
|
- On Clang, `-Weverything` is used with 8 exceptions.
|
||||||
|
|
||||||
??? abstract "Clang warnings"
|
??? abstract "Clang warnings"
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
using namespace nlohmann::literals;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
// the source document
|
|
||||||
json source = R"(
|
|
||||||
{
|
|
||||||
"title": "Goodbye!",
|
|
||||||
"author": {
|
|
||||||
"givenName": "John",
|
|
||||||
"familyName": "Doe"
|
|
||||||
},
|
|
||||||
"tags": [
|
|
||||||
"example",
|
|
||||||
"sample"
|
|
||||||
],
|
|
||||||
"content": "This will be unchanged"
|
|
||||||
}
|
|
||||||
)"_json;
|
|
||||||
|
|
||||||
// the target document
|
|
||||||
json target = R"(
|
|
||||||
{
|
|
||||||
"title": "Hello!",
|
|
||||||
"author": {
|
|
||||||
"givenName": "John"
|
|
||||||
},
|
|
||||||
"tags": [
|
|
||||||
"example"
|
|
||||||
],
|
|
||||||
"content": "This will be unchanged",
|
|
||||||
"phoneNumber": "+01-123-456-7890"
|
|
||||||
}
|
|
||||||
)"_json;
|
|
||||||
|
|
||||||
// create the patch
|
|
||||||
json patch = json::merge_diff(source, target);
|
|
||||||
|
|
||||||
// roundtrip
|
|
||||||
json patched_source = source;
|
|
||||||
patched_source.merge_patch(patch);
|
|
||||||
|
|
||||||
// output patch and roundtrip result
|
|
||||||
std::cout << std::setw(4) << patch << "\n\n"
|
|
||||||
<< std::setw(4) << patched_source << std::endl;
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"author": {
|
|
||||||
"familyName": null
|
|
||||||
},
|
|
||||||
"phoneNumber": "+01-123-456-7890",
|
|
||||||
"tags": [
|
|
||||||
"example"
|
|
||||||
],
|
|
||||||
"title": "Hello!"
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"author": {
|
|
||||||
"givenName": "John"
|
|
||||||
},
|
|
||||||
"content": "This will be unchanged",
|
|
||||||
"phoneNumber": "+01-123-456-7890",
|
|
||||||
"tags": [
|
|
||||||
"example"
|
|
||||||
],
|
|
||||||
"title": "Hello!"
|
|
||||||
}
|
|
||||||
@@ -347,13 +347,6 @@ struct adl_serializer<boost::optional<T>> {
|
|||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tip "`std::optional` needs no serializer"
|
|
||||||
|
|
||||||
Since version 3.12.0, `std::optional<T>` is supported out of the box when compiling with C++17
|
|
||||||
(`std::nullopt` is converted to and from `null`). Do not write an `adl_serializer` for it; this pattern is only
|
|
||||||
needed for types such as `boost::optional` or for custom semantics. See [Conversions](conversions.md) and
|
|
||||||
[Omitting a field when serializing `std::optional`](conversions.md#omitting-a-field-when-serializing-stdoptional).
|
|
||||||
|
|
||||||
!!! note "ABI compatibility"
|
!!! note "ABI compatibility"
|
||||||
|
|
||||||
Use [`NLOHMANN_JSON_NAMESPACE_BEGIN`](../api/macros/nlohmann_json_namespace_begin.md) and `NLOHMANN_JSON_NAMESPACE_END`
|
Use [`NLOHMANN_JSON_NAMESPACE_BEGIN`](../api/macros/nlohmann_json_namespace_begin.md) and `NLOHMANN_JSON_NAMESPACE_END`
|
||||||
|
|||||||
@@ -217,8 +217,7 @@ json j = numbers; // [1,2,3]
|
|||||||
```
|
```
|
||||||
|
|
||||||
This requires [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md) to be enabled and is unavailable on MinGW due
|
This requires [`JSON_HAS_RANGES`](../api/macros/json_has_ranges.md) to be enabled and is unavailable on MinGW due
|
||||||
to incomplete C++20 ranges support there; see
|
to incomplete C++20 ranges support there.
|
||||||
[`JSON_HAS_RANGE_VIEW_CONVERSION`](../api/macros/json_has_range_view_conversion.md).
|
|
||||||
|
|
||||||
## Your own types
|
## Your own types
|
||||||
|
|
||||||
|
|||||||
@@ -30,47 +30,6 @@ you want to access and a default value in case there is no value stored with tha
|
|||||||
| `#!cpp j.value("append", false)` | `#!json true` |
|
| `#!cpp j.value("append", false)` | `#!json true` |
|
||||||
| `#!cpp j.value("logLevel", "verbose")` | `#!json "verbose"` |
|
| `#!cpp j.value("logLevel", "verbose")` | `#!json "verbose"` |
|
||||||
|
|
||||||
## Nested values
|
|
||||||
|
|
||||||
To read a value deep inside a document, pass a [JSON Pointer](../json_pointer.md) instead of a key. The default value is
|
|
||||||
returned if the value at the pointer does not exist, including the case that an intermediate key is missing. There is
|
|
||||||
no need to check each level with [`contains`](../../api/basic_json/contains.md) first.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
json j = {{"server", {{"port", 8080}}}, {"list", {10, 20}}};
|
|
||||||
|
|
||||||
int port = j.value("/server/port"_json_pointer, 80); // 8080
|
|
||||||
int timeout = j.value("/server/limits/timeout"_json_pointer, 30); // 30 (missing intermediate key)
|
|
||||||
int second = j.value("/list/1"_json_pointer, 0); // 20 (numeric tokens index arrays)
|
|
||||||
int third = j.value("/list/5"_json_pointer, 0); // 0 (index out of range)
|
|
||||||
|
|
||||||
bool has_port = j.contains("/server/port"_json_pointer); // true
|
|
||||||
bool has_host = j.contains("/server/host/name"_json_pointer); // false
|
|
||||||
```
|
|
||||||
|
|
||||||
If the path is only available as a dotted string such as `#!cpp "server.port"`, do not build the pointer by
|
|
||||||
concatenating `#!cpp "/"` and the parts: keys containing `/` or `~` would be misinterpreted. Append each part as a
|
|
||||||
reference token with [`operator/=`](../../api/json_pointer/operator_slasheq.md) instead. It escapes the token for you.
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
json::json_pointer to_pointer(const std::string& dotted)
|
|
||||||
{
|
|
||||||
json::json_pointer ptr;
|
|
||||||
std::istringstream in(dotted);
|
|
||||||
for (std::string token; std::getline(in, token, '.');)
|
|
||||||
{
|
|
||||||
ptr /= token;
|
|
||||||
}
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int port = j.value(to_pointer("server.port"), 80); // 8080
|
|
||||||
int first = j.value(to_pointer("list.0"), 0); // 10
|
|
||||||
```
|
|
||||||
|
|
||||||
The key `#!cpp "a/b"` yields the pointer `#!cpp "/a~1b"`; the dot-splitting itself is up to the caller, so keys
|
|
||||||
containing `.` need a different separator.
|
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
!!! failure "Exceptions"
|
!!! failure "Exceptions"
|
||||||
@@ -78,31 +37,6 @@ containing `.` need a different separator.
|
|||||||
- With string keys, `value` can only be used with objects. For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.
|
- With string keys, `value` can only be used with objects. For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.
|
||||||
- With JSON Pointers, `value` can be used with both objects and arrays. For other types (null, boolean, number, string), a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.
|
- With JSON Pointers, `value` can be used with both objects and arrays. For other types (null, boolean, number, string), a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.
|
||||||
|
|
||||||
!!! warning "`null` and mistyped members are not missing"
|
|
||||||
|
|
||||||
`value` returns the default value only if the key is **absent**. If the member exists, it is converted to the type
|
|
||||||
of the default value, even if it is `#!json null`. For `#!json {"k": null}`, the call `#!cpp j.value("k", 0)` throws
|
|
||||||
a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error302), and so does a member of another
|
|
||||||
type such as a string where a number is expected. The same holds for JSON Pointers.
|
|
||||||
|
|
||||||
To treat `#!json null` like a missing value, check for it explicitly:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
int n = (j.contains("k") && !j["k"].is_null()) ? j["k"].get<int>() : 0;
|
|
||||||
```
|
|
||||||
|
|
||||||
With C++17, [`get<std::optional<T>>()`](../../api/basic_json/get.md) maps `#!json null` to an empty optional. As
|
|
||||||
[`at`](../../api/basic_json/at.md) throws [`out_of_range`](../../home/exceptions.md#jsonexceptionout_of_range403)
|
|
||||||
for an absent key, use [`find`](../../api/basic_json/find.md) to cover both cases:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
std::optional<int> n; // empty if "k" is absent or null
|
|
||||||
if (const auto it = j.find("k"); it != j.end())
|
|
||||||
{
|
|
||||||
n = it->get<std::optional<int>>(); // still throws for a non-number such as "text"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! warning "Return type"
|
!!! warning "Return type"
|
||||||
|
|
||||||
The value function is a template, and the return type of the function is determined by the type of the provided
|
The value function is a template, and the return type of the function is determined by the type of the provided
|
||||||
@@ -129,6 +63,3 @@ containing `.` need a different separator.
|
|||||||
|
|
||||||
- [`value`](../../api/basic_json/value.md) for access with default value
|
- [`value`](../../api/basic_json/value.md) for access with default value
|
||||||
- documentation on [checked access](checked_access.md)
|
- documentation on [checked access](checked_access.md)
|
||||||
- documentation on [JSON Pointer](../json_pointer.md)
|
|
||||||
- [`contains`](../../api/basic_json/contains.md) to check whether a key or JSON Pointer exists
|
|
||||||
- [`json_pointer::operator/=`](../../api/json_pointer/operator_slasheq.md) to build a pointer token by token
|
|
||||||
@@ -77,10 +77,6 @@ auto val2 = j.at(json::json_pointer("/nested/three/1")); // false
|
|||||||
auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0
|
auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0
|
||||||
```
|
```
|
||||||
|
|
||||||
To read a value with a fallback, use [`value`](../api/basic_json/value.md) with a JSON Pointer; to test for existence,
|
|
||||||
use [`contains`](../api/basic_json/contains.md). Neither needs intermediate checks, see
|
|
||||||
[Nested values](element_access/default_value.md#nested-values).
|
|
||||||
|
|
||||||
!!! note "Creating intermediate levels that don't exist"
|
!!! note "Creating intermediate levels that don't exist"
|
||||||
|
|
||||||
See the [`operator[]` notes](../api/basic_json/operator%5B%5D.md#return-value) for how array vs. object is
|
See the [`operator[]` notes](../api/basic_json/operator%5B%5D.md#return-value) for how array vs. object is
|
||||||
@@ -130,8 +126,6 @@ auto j_original = j_flat.unflatten();
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- Class [`json_pointer`](../api/json_pointer/index.md)
|
- Class [`json_pointer`](../api/json_pointer/index.md)
|
||||||
- Functions [`value`](../api/basic_json/value.md), [`contains`](../api/basic_json/contains.md), and
|
|
||||||
[`at`](../api/basic_json/at.md) accept JSON Pointers; see [Nested values](element_access/default_value.md#nested-values)
|
|
||||||
- Function [`flatten`](../api/basic_json/flatten.md)
|
- Function [`flatten`](../api/basic_json/flatten.md)
|
||||||
- Function [`unflatten`](../api/basic_json/unflatten.md)
|
- Function [`unflatten`](../api/basic_json/unflatten.md)
|
||||||
- [JSON Patch](json_patch.md) - paths inside a patch are JSON Pointers
|
- [JSON Patch](json_patch.md) - paths inside a patch are JSON Pointers
|
||||||
|
|||||||
@@ -82,45 +82,6 @@ To override the built-in check, define `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERI
|
|||||||
|
|
||||||
See [full documentation of `JSON_HAS_FILESYSTEM` and `JSON_HAS_EXPERIMENTAL_FILESYSTEM`](../api/macros/json_has_filesystem.md).
|
See [full documentation of `JSON_HAS_FILESYSTEM` and `JSON_HAS_EXPERIMENTAL_FILESYSTEM`](../api/macros/json_has_filesystem.md).
|
||||||
|
|
||||||
## `JSON_HAS_RANGES`
|
|
||||||
|
|
||||||
The library uses `std::ranges` (and concepts) where available, for example, to parse from C++20 ranges and to
|
|
||||||
construct JSON arrays from range views. The library detects whether the standard library supports ranges and
|
|
||||||
disables the support on toolchains with an incomplete implementation. To override the built-in check, define
|
|
||||||
`JSON_HAS_RANGES` to `1` or `0`.
|
|
||||||
|
|
||||||
See [full documentation of `JSON_HAS_RANGES`](../api/macros/json_has_ranges.md).
|
|
||||||
|
|
||||||
## `JSON_HAS_RANGE_VIEW_CONVERSION`
|
|
||||||
|
|
||||||
When `JSON_HAS_RANGES` is enabled (and the compiler is not MinGW), a JSON array can be constructed directly from a C++20
|
|
||||||
range view such as `std::views::filter(...)`. To override the built-in check, define `JSON_HAS_RANGE_VIEW_CONVERSION` to
|
|
||||||
`1` or `0`.
|
|
||||||
|
|
||||||
See [full documentation of `JSON_HAS_RANGE_VIEW_CONVERSION`](../api/macros/json_has_range_view_conversion.md).
|
|
||||||
|
|
||||||
## `JSON_HAS_STATIC_RTTI`
|
|
||||||
|
|
||||||
The library detects whether the compiler supports run time type information (RTTI), which it needs, for instance, to
|
|
||||||
exclude `std::any` from the candidate types of the implicit conversion on C++17. To override the built-in check, define
|
|
||||||
`JSON_HAS_STATIC_RTTI` to `1` or `0`.
|
|
||||||
|
|
||||||
See [full documentation of `JSON_HAS_STATIC_RTTI`](../api/macros/json_has_static_rtti.md).
|
|
||||||
|
|
||||||
## `JSON_HAS_STD_FORMAT`
|
|
||||||
|
|
||||||
When compiling with C++20 and a standard library that provides `<format>`, the library provides a `std::formatter`
|
|
||||||
specialization for JSON values. To override the built-in check, define `JSON_HAS_STD_FORMAT` to `1` or `0`.
|
|
||||||
|
|
||||||
See [full documentation of `JSON_HAS_STD_FORMAT`](../api/macros/json_has_std_format.md).
|
|
||||||
|
|
||||||
## `JSON_HAS_THREE_WAY_COMPARISON`
|
|
||||||
|
|
||||||
When the compiler and standard library support 3-way comparison (the spaceship operator `<=>`), the library provides it
|
|
||||||
for JSON values. To override the built-in check, define `JSON_HAS_THREE_WAY_COMPARISON` to `1` or `0`.
|
|
||||||
|
|
||||||
See [full documentation of `JSON_HAS_THREE_WAY_COMPARISON`](../api/macros/json_has_three_way_comparison.md).
|
|
||||||
|
|
||||||
## `JSON_NOEXCEPTION`
|
## `JSON_NOEXCEPTION`
|
||||||
|
|
||||||
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
|
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
|
||||||
|
|||||||
@@ -9,16 +9,6 @@ syntax that closely mimics the document being modified. Unlike [JSON Patch](json
|
|||||||
express every kind of change (e.g., it cannot reorder array elements or remove a specific array element), but it is
|
express every kind of change (e.g., it cannot reorder array elements or remove a specific array element), but it is
|
||||||
easier to read and write for object-shaped documents.
|
easier to read and write for object-shaped documents.
|
||||||
|
|
||||||
The function [`merge_diff`](../api/basic_json/merge_diff.md) creates a merge patch that changes one JSON value into
|
|
||||||
another.
|
|
||||||
|
|
||||||
!!! tip "Not a general deep merge"
|
|
||||||
|
|
||||||
A merge patch is not a general deep merge: a `#!json null` value in the patch deletes the key from the target.
|
|
||||||
To merge two objects recursively (e.g., defaults and user settings), use
|
|
||||||
[`update`](../api/basic_json/update.md) with `merge_objects` set to `#!cpp true`; see
|
|
||||||
[Merging objects](modifying_values.md#merging-objects).
|
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
The following code shows how a JSON Merge Patch is applied to a JSON document.
|
The following code shows how a JSON Merge Patch is applied to a JSON document.
|
||||||
@@ -38,5 +28,3 @@ another.
|
|||||||
- [JSON Patch and Diff](json_patch.md) - a more expressive alternative that describes a sequence of operations
|
- [JSON Patch and Diff](json_patch.md) - a more expressive alternative that describes a sequence of operations
|
||||||
- [JSON Pointer](json_pointer.md) - the addressing scheme used by JSON Patch
|
- [JSON Pointer](json_pointer.md) - the addressing scheme used by JSON Patch
|
||||||
- Function [`merge_patch`](../api/basic_json/merge_patch.md)
|
- Function [`merge_patch`](../api/basic_json/merge_patch.md)
|
||||||
- Function [`merge_diff`](../api/basic_json/merge_diff.md)
|
|
||||||
- Function [`update`](../api/basic_json/update.md) - merge objects, optionally recursively
|
|
||||||
@@ -35,12 +35,8 @@ the insertion happened — useful for "add if absent" semantics.
|
|||||||
|
|
||||||
## Merging objects
|
## Merging objects
|
||||||
|
|
||||||
To merge one object into another, [`update`](../api/basic_json/update.md) copies all members from another object
|
To merge one object into another, [`update`](../api/basic_json/update.md) copies all members from another object,
|
||||||
(similar to Python's `dict.update`). This is the idiomatic way to combine two objects. It has two modes:
|
overwriting existing keys (similar to Python's `dict.update`). This is the idiomatic way to combine two objects.
|
||||||
|
|
||||||
- By default, the merge is shallow: existing keys are overwritten, even if both values are objects.
|
|
||||||
- With `merge_objects = #!cpp true`, keys whose values are objects in both JSON values are merged recursively.
|
|
||||||
Everything else is overwritten. In particular, arrays are replaced, not concatenated.
|
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
@@ -54,22 +50,9 @@ To merge one object into another, [`update`](../api/basic_json/update.md) copies
|
|||||||
--8<-- "examples/update.output"
|
--8<-- "examples/update.output"
|
||||||
```
|
```
|
||||||
|
|
||||||
A common use of the recursive mode is combining defaults with user settings. Nested defaults that the user did not set
|
For a recursive merge that follows [RFC 7386](https://tools.ietf.org/html/rfc7386), see
|
||||||
are kept:
|
[JSON Merge Patch](merge_patch.md). To apply a sequence of well-defined edit operations, see
|
||||||
|
[JSON Patch](json_patch.md).
|
||||||
```cpp
|
|
||||||
json defaults = {{"log", {{"level", "info"}, {"file", "app.log"}}}, {"retries", 3}};
|
|
||||||
json user_settings = {{"log", {{"level", "debug"}}}};
|
|
||||||
|
|
||||||
json config = defaults;
|
|
||||||
config.update(user_settings, true);
|
|
||||||
// {"log":{"file":"app.log","level":"debug"},"retries":3}
|
|
||||||
```
|
|
||||||
|
|
||||||
[JSON Merge Patch](merge_patch.md) ([RFC 7386](https://tools.ietf.org/html/rfc7386)) also merges objects recursively,
|
|
||||||
but it is a different tool: a `#!json null` in the patch means "remove this key". It is meant for applying merge patch
|
|
||||||
documents (e.g., received via HTTP PATCH). To merge configuration-like objects, use `#!cpp update(..., true)`. To apply
|
|
||||||
a sequence of well-defined edit operations, see [JSON Patch](json_patch.md).
|
|
||||||
|
|
||||||
## Removing elements
|
## Removing elements
|
||||||
|
|
||||||
@@ -89,7 +72,6 @@ a.erase(1); // [1,3,4] (erase by index)
|
|||||||
|
|
||||||
- [`push_back`](../api/basic_json/push_back.md) / [`emplace_back`](../api/basic_json/emplace_back.md) - append to an array
|
- [`push_back`](../api/basic_json/push_back.md) / [`emplace_back`](../api/basic_json/emplace_back.md) - append to an array
|
||||||
- [`emplace`](../api/basic_json/emplace.md) - insert into an object if the key is absent
|
- [`emplace`](../api/basic_json/emplace.md) - insert into an object if the key is absent
|
||||||
- [`update`](../api/basic_json/update.md) - merge objects (shallow, or recursive with `merge_objects`)
|
- [`update`](../api/basic_json/update.md) - merge objects
|
||||||
- [`merge_patch`](../api/basic_json/merge_patch.md) - apply an RFC 7386 merge patch
|
|
||||||
- [`erase`](../api/basic_json/erase.md) / [`clear`](../api/basic_json/clear.md) - remove elements
|
- [`erase`](../api/basic_json/erase.md) / [`clear`](../api/basic_json/clear.md) - remove elements
|
||||||
- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) - structured modifications
|
- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) - structured modifications
|
||||||
@@ -101,9 +101,3 @@ follows:
|
|||||||
|
|
||||||
- Introduced inline namespace (`json_v3_11_0[_abi-tag]*`) in version 3.11.0.
|
- Introduced inline namespace (`json_v3_11_0[_abi-tag]*`) in version 3.11.0.
|
||||||
- Changed structure of inline namespace in version 3.11.2.
|
- Changed structure of inline namespace in version 3.11.2.
|
||||||
- Added ABI tag `_dp` ([`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md)) in version 3.12.0.
|
|
||||||
- Added ABI tags `_bics` ([`JSON_BRACE_INIT_COPY_SEMANTICS`](../api/macros/json_brace_init_copy_semantics.md)), `_psp`
|
|
||||||
([`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md)), `_snul`
|
|
||||||
([`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md)), `_sbu8`
|
|
||||||
([`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md)), and `_ekmo`
|
|
||||||
([`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md)) in version 3.13.0.
|
|
||||||
@@ -82,13 +82,12 @@ flowchart TD
|
|||||||
|
|
||||||
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
||||||
- The number types can be changed, see [Template number types](#template-number-types).
|
- The number types can be changed, see [Template number types](#template-number-types).
|
||||||
- The library converts integers and floating-point numbers itself, independent of the locale. Floating-point
|
- Integers are converted by the library's own digit parser. Floating-point numbers are converted with
|
||||||
numbers are correctly rounded (to nearest, ties to even). Only a `#!c long double` that is not IEEE 754 binary64
|
[`std::from_chars`](https://en.cppreference.com/w/cpp/utility/from_chars) if the library is compiled with C++17
|
||||||
(e.g., the 80-bit x87 format) is converted with `#!cpp std::from_chars` where available, or else with
|
and the standard library supports it, then with an exact fast path for `#!c double` values with few significant
|
||||||
[`std::strtold`](https://en.cppreference.com/w/cpp/string/byte/strtof). For that call, the library temporarily
|
digits, and otherwise with the locale-aware
|
||||||
replaces the `.` with the decimal point of the current locale (which may be longer than one byte, e.g., in
|
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof) (`std::strtof`/`std::strtold` for the
|
||||||
`fa_IR.UTF-8`), so the result does not depend on the locale either. Changing the locale in another thread during
|
other floating-point types). Before version 3.13.0, the conversion was realized by
|
||||||
parsing is undefined behavior of the C library, though. Before version 3.13.0, the conversion was realized by
|
|
||||||
[`std::strtoull`](https://en.cppreference.com/w/cpp/string/byte/strtoul),
|
[`std::strtoull`](https://en.cppreference.com/w/cpp/string/byte/strtoul),
|
||||||
[`std::strtoll`](https://en.cppreference.com/w/cpp/string/byte/strtol), and `std::strtod`, respectively.
|
[`std::strtoll`](https://en.cppreference.com/w/cpp/string/byte/strtol), and `std::strtod`, respectively.
|
||||||
|
|
||||||
@@ -101,10 +100,10 @@ flowchart TD
|
|||||||
### Number limits
|
### Number limits
|
||||||
|
|
||||||
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
||||||
- Numbers exceeding the limits of `#!c double` (i.e., numbers whose rounded value is not satisfying
|
- Numbers exceeding the limits of `#!c double` (i.e., numbers that after conversion via
|
||||||
|
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof) are not satisfying
|
||||||
[`std::isfinite`](https://en.cppreference.com/w/cpp/numeric/math/isfinite) such as `#!c 1E400`) will throw exception
|
[`std::isfinite`](https://en.cppreference.com/w/cpp/numeric/math/isfinite) such as `#!c 1E400`) will throw exception
|
||||||
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing. Numbers too
|
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing.
|
||||||
small for `#!c double` (such as `#!c 1E-400`) become zero, with the sign of the number.
|
|
||||||
- Floating-point numbers are rounded to the next number representable as `double`. For instance
|
- Floating-point numbers are rounded to the next number representable as `double`. For instance
|
||||||
`#!c 3.141592653589793238462643383279` is stored as [`0x400921fb54442d18`](https://float.exposed/0x400921fb54442d18).
|
`#!c 3.141592653589793238462643383279` is stored as [`0x400921fb54442d18`](https://float.exposed/0x400921fb54442d18).
|
||||||
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ Requirements are split into two groups:
|
|||||||
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
||||||
the library. Four violations are not caught at compile time at all:
|
the library. Four violations are not caught at compile time at all:
|
||||||
|
|
||||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers
|
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and can silently misparse
|
||||||
stored as a `#!cpp long double` that is not IEEE 754 binary64 (e.g., the 80-bit x87 format), because the lexer
|
floating-point numbers, because the lexer may hand the buffer to `#!cpp std::strtod`, which reads up to the
|
||||||
hands the buffer to `#!cpp std::strtold`.
|
terminating null character.
|
||||||
- A stateful [`AllocatorType`](#allocatortype) compiles and silently ignores its state: allocation, deallocation,
|
- A stateful [`AllocatorType`](#allocatortype) compiles and silently ignores its state: allocation, deallocation,
|
||||||
and [`get_allocator()`](../../api/basic_json/get_allocator.md) each use a different default-constructed instance.
|
and [`get_allocator()`](../../api/basic_json/get_allocator.md) each use a different default-constructed instance.
|
||||||
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
||||||
@@ -353,21 +353,16 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
|||||||
### Always required
|
### Always required
|
||||||
|
|
||||||
- A member type `value_type` that is one byte wide and `char`-compatible. The library stores and processes UTF-8
|
- A member type `value_type` that is one byte wide and `char`-compatible. The library stores and processes UTF-8
|
||||||
encoded `char` data and passes `data()` to functions that take a `#!cpp const char*`, such as `#!cpp std::strtold`
|
encoded `char` data and passes `data()` to functions that take a `#!cpp const char*`, such as `#!cpp std::strtod`.
|
||||||
(only used to parse a `#!cpp long double` that is not IEEE 754 binary64, see
|
|
||||||
[`NumberFloatType`](#numberfloattype)).
|
|
||||||
`#!cpp std::wstring`, `#!cpp std::u16string`, and `#!cpp std::u32string` are **not** valid choices; see the FAQ on
|
`#!cpp std::wstring`, `#!cpp std::u16string`, and `#!cpp std::u32string` are **not** valid choices; see the FAQ on
|
||||||
[wide string handling](../../home/faq.md#wide-string-handling).
|
[wide string handling](../../home/faq.md#wide-string-handling).
|
||||||
- Constructors: default, copy, move, from `#!cpp const char*` (which must not be `#!cpp explicit`), from
|
- Constructors: default, copy, move, from `#!cpp const char*` (which must not be `#!cpp explicit`), from
|
||||||
`#!cpp (const char*, size_type)`, and from `#!cpp (size_type, char)`; and copy or move assignment.
|
`#!cpp (const char*, size_type)`, and from `#!cpp (size_type, char)`; and copy or move assignment.
|
||||||
- Member functions `size()`, `clear()`, `resize(n, c)`, `data()`, `push_back(char)`, and `operator[]`
|
- Member functions `size()`, `clear()`, `resize(n, c)`, `data()`, `push_back(char)`, and `operator[]`
|
||||||
(const and non-const, returning references). `c_str()` and `back()` are **not** required.
|
(const and non-const, returning references). `c_str()` and `back()` are **not** required.
|
||||||
- `data()` must return a pointer to a contiguous, **null-terminated** buffer. `#!cpp float`, `#!cpp double`, and a
|
- `data()` must return a pointer to a contiguous, **null-terminated** buffer -- the parser may hand it to
|
||||||
`#!cpp long double` that is IEEE 754 binary64 are converted by the library itself and do not depend on this. For any
|
`#!cpp std::strtod`, which reads up to the null character. A type whose `data()` is not null-terminated does not
|
||||||
other `NumberFloatType` (a `#!cpp long double` of another format), the parser falls back to `#!cpp std::strtold` when
|
fail to compile; it can silently misparse floating-point numbers.
|
||||||
`#!cpp std::from_chars` is not available or declines the token, and `std::strtold` reads up to the null character. A type whose `data()`
|
|
||||||
is not null-terminated does not fail to compile; with such a `NumberFloatType` it can silently misparse
|
|
||||||
floating-point numbers.
|
|
||||||
- `append(const char*, size_type)`, used by [`dump`](../../api/basic_json/dump.md), and `append(const StringType&)`,
|
- `append(const char*, size_type)`, used by [`dump`](../../api/basic_json/dump.md), and `append(const StringType&)`,
|
||||||
used by the CBOR reader for indefinite-length strings. The library's internal string concatenation additionally has
|
used by the CBOR reader for indefinite-length strings. The library's internal string concatenation additionally has
|
||||||
to append a `#!cpp char` and a `#!cpp const char*`; for each it selects between `append(arg)`, `#!cpp operator+=`,
|
to append a `#!cpp char` and a `#!cpp const char*`; for each it selects between `append(arg)`, `#!cpp operator+=`,
|
||||||
@@ -546,10 +541,9 @@ therefore silently changes parse results rather than raising an error. See
|
|||||||
|
|
||||||
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
||||||
|
|
||||||
- The [parser](../parsing/index.md) converts number literals to `#!cpp float`, `#!cpp double`, and a
|
- The [parser](../parsing/index.md) converts number literals with `#!cpp std::from_chars` or, as a fallback, with
|
||||||
`#!cpp long double` that is IEEE 754 binary64 itself; other `#!cpp long double` formats are converted with
|
`#!cpp std::strtof`, `#!cpp std::strtod`, or `#!cpp std::strtold`; the library provides overloads for exactly these
|
||||||
`#!cpp std::from_chars` where available, or with `#!cpp std::strtold`. The library provides overloads for exactly
|
three types.
|
||||||
these three types.
|
|
||||||
- [`dump`](../../api/basic_json/dump.md) falls back to `#!cpp std::snprintf` with the `%g` and `%Lg` conversion
|
- [`dump`](../../api/basic_json/dump.md) falls back to `#!cpp std::snprintf` with the `%g` and `%Lg` conversion
|
||||||
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
|
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
|
||||||
(`#!cpp float` is promoted to `#!cpp double`).
|
(`#!cpp float` is promoted to `#!cpp double`).
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ flowchart LR
|
|||||||
|
|
||||||
- **JSON text** is read by an [input adapter](#input-adapters), tokenized by the lexer, and turned into SAX events by
|
- **JSON text** is read by an [input adapter](#input-adapters), tokenized by the lexer, and turned into SAX events by
|
||||||
the parser.
|
the parser.
|
||||||
- **Binary formats** (BJData, BON8, BSON, CBOR, MessagePack, UBJSON) are read by an input adapter and turned into the same SAX
|
- **Binary formats** (BJData, BSON, CBOR, MessagePack, UBJSON) are read by an input adapter and turned into the same SAX
|
||||||
events by the `binary_reader`.
|
events by the `binary_reader`.
|
||||||
- A [SAX consumer](#sax-interface) receives the events. The one used by [`parse`](../api/basic_json/parse.md) builds a
|
- A [SAX consumer](#sax-interface) receives the events. The one used by [`parse`](../api/basic_json/parse.md) builds a
|
||||||
`basic_json` value tree.
|
`basic_json` value tree.
|
||||||
@@ -185,11 +185,9 @@ The lexer detects two optional extensions at compile time. Only `iterator_input_
|
|||||||
random-access input of single-byte characters:
|
random-access input of single-byte characters:
|
||||||
|
|
||||||
- `supports_seek`, `get_consumed_count()`, and `copy_consumed_range()` let the lexer reconstruct already consumed input
|
- `supports_seek`, `get_consumed_count()`, and `copy_consumed_range()` let the lexer reconstruct already consumed input
|
||||||
for error messages instead of copying every character it reads. With `get_read_count()` and
|
for error messages instead of copying every character it reads.
|
||||||
`count_consumed_lines()`, the lexer also derives the read position from the adapter and counts lines only when an
|
|
||||||
error needs them, instead of counting characters and lines on every read.
|
|
||||||
- `supports_bulk_scan`, `bulk_data()`, `bulk_remaining()`, and `bulk_skip()` let the lexer scan strings directly in
|
- `supports_bulk_scan`, `bulk_data()`, `bulk_remaining()`, and `bulk_skip()` let the lexer scan strings directly in
|
||||||
contiguous memory, several bytes at a time, and skip the spaces that indent a line in 8-byte steps.
|
contiguous memory, several bytes at a time.
|
||||||
|
|
||||||
The function `input_adapter` picks the right adapter for the argument passed to `parse`, `accept`, `sax_parse`, or the
|
The function `input_adapter` picks the right adapter for the argument passed to `parse`, `accept`, `sax_parse`, or the
|
||||||
`from_*` functions:
|
`from_*` functions:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ There are myriads of [JSON](https://json.org) libraries out there, and each may
|
|||||||
|
|
||||||
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
||||||
|
|
||||||
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/tests/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [OpenSSF Best Practices](https://www.bestpractices.dev/projects/289).
|
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/tests/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [OpenSSF Best Practices](https://www.bestpractices.dev/projects/289).
|
||||||
|
|
||||||
Other aspects were not so important to us:
|
Other aspects were not so important to us:
|
||||||
|
|
||||||
@@ -14,4 +14,4 @@ Other aspects were not so important to us:
|
|||||||
|
|
||||||
- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set.
|
- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set.
|
||||||
|
|
||||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#please-dont) for more information.
|
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
|
||||||
@@ -104,7 +104,7 @@ See [documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) for
|
|||||||
## Parse errors
|
## Parse errors
|
||||||
|
|
||||||
The library throws this exception when a parse error occurs. Parse errors
|
The library throws this exception when a parse error occurs. Parse errors
|
||||||
can occur during the deserialization of JSON text or of one of the binary formats (BJData, BON8, BSON, CBOR, MessagePack, UBJSON), as well
|
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
|
||||||
as when using JSON Patch.
|
as when using JSON Patch.
|
||||||
|
|
||||||
Exceptions have ids 1xx.
|
Exceptions have ids 1xx.
|
||||||
@@ -190,7 +190,7 @@ This error indicates a syntax error while deserializing a JSON text. The error m
|
|||||||
!!! tip
|
!!! tip
|
||||||
|
|
||||||
- Make sure the input is correctly read. Try to write the input to standard output to check if, for instance, the input file was successfully opened.
|
- Make sure the input is correctly read. Try to write the input to standard output to check if, for instance, the input file was successfully opened.
|
||||||
- Paste the input to a JSON validator like <https://jsonlint.com> or a tool like [jq](https://jqlang.github.io/jq/).
|
- Paste the input to a JSON validator like <http://jsonlint.com> or a tool like [jq](https://stedolan.github.io/jq/).
|
||||||
|
|
||||||
### json.exception.parse_error.102
|
### json.exception.parse_error.102
|
||||||
|
|
||||||
@@ -278,9 +278,7 @@ In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
|
|||||||
|
|
||||||
### json.exception.parse_error.109
|
### json.exception.parse_error.109
|
||||||
|
|
||||||
A JSON Pointer array index must be a number. This exception is thrown for an array index that does not begin with a
|
A JSON Pointer array index must be a number.
|
||||||
digit, except for `-` and the empty reference token, which throw [`out_of_range.404`](#jsonexceptionout_of_range404)
|
|
||||||
where they cannot be resolved.
|
|
||||||
|
|
||||||
!!! failure "Example messages"
|
!!! failure "Example messages"
|
||||||
|
|
||||||
@@ -291,11 +289,6 @@ where they cannot be resolved.
|
|||||||
[json.exception.parse_error.109] parse error: array index '+1' is not a number
|
[json.exception.parse_error.109] parse error: array index '+1' is not a number
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! note
|
|
||||||
|
|
||||||
Before version 3.13.0, a one-character array index that is not a digit (e.g., `x`) threw
|
|
||||||
[`out_of_range.404`](#jsonexceptionout_of_range404) instead.
|
|
||||||
|
|
||||||
### json.exception.parse_error.110
|
### json.exception.parse_error.110
|
||||||
|
|
||||||
When parsing a [binary format](../features/binary_formats/index.md), the byte vector ends before the complete value has
|
When parsing a [binary format](../features/binary_formats/index.md), the byte vector ends before the complete value has
|
||||||
@@ -817,7 +810,7 @@ does not list an enumerator and it is therefore converted like the first listed
|
|||||||
A discarded value (one created by [`parse()`](../api/basic_json/parse.md) with a callback that returns `false` for the
|
A discarded value (one created by [`parse()`](../api/basic_json/parse.md) with a callback that returns `false` for the
|
||||||
value, or by default-constructing a [`basic_json`](../api/basic_json/index.md) with
|
value, or by default-constructing a [`basic_json`](../api/basic_json/index.md) with
|
||||||
[`value_t::discarded`](../api/basic_json/value_t.md)) was passed to a binary serialization function, either directly or
|
[`value_t::discarded`](../api/basic_json/value_t.md)) was passed to a binary serialization function, either directly or
|
||||||
nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, BSON, or BON8.
|
nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, or BSON.
|
||||||
|
|
||||||
!!! failure "Example message"
|
!!! failure "Example message"
|
||||||
|
|
||||||
@@ -878,8 +871,7 @@ The provided key was not found in the JSON object.
|
|||||||
|
|
||||||
### json.exception.out_of_range.404
|
### json.exception.out_of_range.404
|
||||||
|
|
||||||
A reference token in a JSON Pointer could not be resolved, for instance an array index that begins with a digit but
|
A reference token in a JSON Pointer could not be resolved.
|
||||||
contains other characters (e.g., `1a`), or `-` where it cannot be used.
|
|
||||||
|
|
||||||
!!! failure "Example message"
|
!!! failure "Example message"
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ The class contains a slightly modified version of the Grisu2 algorithm from Flor
|
|||||||
|
|
||||||
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||||
|
|
||||||
The class contains an adapted version of the Eisel-Lemire algorithm, its table of powers of five, and its digit comparison for long numbers from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
The class contains an adapted version of the Eisel-Lemire algorithm and its table of powers of five from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
||||||
@@ -26,7 +26,7 @@ Fixes bugs found in 3.11.3 and adds several features. All changes are backward-c
|
|||||||
[BJData](../features/binary_formats/bjdata.md) draft 3 and unsigned 64-bit integers for
|
[BJData](../features/binary_formats/bjdata.md) draft 3 and unsigned 64-bit integers for
|
||||||
[BSON](../features/binary_formats/bson.md).
|
[BSON](../features/binary_formats/bson.md).
|
||||||
- Adds multidimensional C-array conversion and UTF-8 encoded `std::filesystem::path` conversions, and
|
- Adds multidimensional C-array conversion and UTF-8 encoded `std::filesystem::path` conversions, and
|
||||||
raises the minimum [CMake](../integration/cmake.md) version to 3.5 and supports CMake 4.0.
|
lowers the minimum [CMake](../integration/cmake.md) version to allow CMake 4.0.
|
||||||
|
|
||||||
[Full release notes](https://github.com/nlohmann/json/releases/tag/v3.12.0).
|
[Full release notes](https://github.com/nlohmann/json/releases/tag/v3.12.0).
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,17 @@ Build the unit tests against the [simdutf](https://github.com/simdutf/simdutf) U
|
|||||||
its version is set by the cache variable `JSON_SIMDUTF_VERSION`. This option is `OFF` by default. Depends on
|
its version is set by the cache variable `JSON_SIMDUTF_VERSION`. This option is `OFF` by default. Depends on
|
||||||
`JSON_BuildTests`.
|
`JSON_BuildTests`.
|
||||||
|
|
||||||
|
### `JSON_TestUnityBuild`
|
||||||
|
|
||||||
|
Build the unit tests in batches of several test files per executable to speed up compilation: the files of a batch are
|
||||||
|
compiled as one translation unit, so the template instantiations of the library are shared. Every test file still gets
|
||||||
|
its own CTest test (e.g., `test-foo_cpp11`), which runs only the test cases of that file from the shared executable.
|
||||||
|
This option is `ON` by default (and `OFF` with MinGW). Set it to `OFF` to get one executable per test file, e.g., when
|
||||||
|
debugging a single file. The number of files per executable is set by the cache variable `JSON_TestUnityBatchSize`
|
||||||
|
(default: `8`). Related test files (e.g., all binary formats) are grouped explicitly in `tests/CMakeLists.txt`; each
|
||||||
|
group is compiled as one executable per C++ standard regardless of the batch size, and only the remaining files are
|
||||||
|
batched by size. Depends on `JSON_BuildTests`.
|
||||||
|
|
||||||
### `JSON_Valgrind`
|
### `JSON_Valgrind`
|
||||||
|
|
||||||
Execute the test suite with [Valgrind](https://valgrind.org). This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
Execute the test suite with [Valgrind](https://valgrind.org). This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.15)
|
|||||||
|
|
||||||
include("cmake/HunterGate.cmake")
|
include("cmake/HunterGate.cmake")
|
||||||
HunterGate(
|
HunterGate(
|
||||||
URL "https://github.com/cpp-pm/hunter/archive/v0.26.12.tar.gz"
|
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
|
||||||
SHA1 "6498c5d0dec25d7fffb2b0574ebaf265179b894d"
|
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
|
||||||
)
|
)
|
||||||
|
|
||||||
project(json_example)
|
project(json_example)
|
||||||
|
|||||||
@@ -2,30 +2,12 @@
|
|||||||
|
|
||||||
# Creates a `<path>.md` sibling of each HTML output (for example,
|
# Creates a `<path>.md` sibling of each HTML output (for example,
|
||||||
# `features/comments/` becomes `features/comments.md`) so agents and tools can
|
# `features/comments/` becomes `features/comments.md`) so agents and tools can
|
||||||
# fetch the raw Markdown directly instead of parsing rendered HTML. The
|
# fetch the raw Markdown directly instead of parsing rendered HTML.
|
||||||
# `--8<-- "path"` lines of pymdownx.snippets are expanded with the extension's
|
|
||||||
# own preprocessor and the settings from mkdocs.yml, so the copies contain the
|
|
||||||
# included example code and files instead of the include directives.
|
|
||||||
|
|
||||||
import io
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import markdown
|
|
||||||
from pymdownx.snippets import SnippetMissingError
|
|
||||||
|
|
||||||
_pages = []
|
_pages = []
|
||||||
_snippets = None
|
|
||||||
|
|
||||||
|
|
||||||
def on_config(config):
|
|
||||||
global _snippets
|
|
||||||
md = markdown.Markdown(
|
|
||||||
extensions=["pymdownx.snippets"],
|
|
||||||
extension_configs={"pymdownx.snippets": config["mdx_configs"].get("pymdownx.snippets", {})},
|
|
||||||
)
|
|
||||||
_snippets = md.preprocessors["snippet"]
|
|
||||||
_snippets.auto_append = [] # the glossary is only needed to render abbreviations
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
def on_files(files, config):
|
def on_files(files, config):
|
||||||
@@ -40,11 +22,4 @@ def on_post_build(config):
|
|||||||
url = file.url.rstrip("/")
|
url = file.url.rstrip("/")
|
||||||
target = os.path.join(site_dir, (url or "index") + ".md")
|
target = os.path.join(site_dir, (url or "index") + ".md")
|
||||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||||
with io.open(file.abs_src_path, encoding="utf-8", newline="") as source:
|
shutil.copyfile(file.abs_src_path, target)
|
||||||
text = source.read()
|
|
||||||
try:
|
|
||||||
text = "\n".join(_snippets.run(text.split("\n")))
|
|
||||||
except (SnippetMissingError, OSError):
|
|
||||||
pass # keep the include directives; the regular build reports the missing file
|
|
||||||
with io.open(target, "w", encoding="utf-8", newline="") as copy:
|
|
||||||
copy.write(text)
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary -->
|
<!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary -->
|
||||||
|
|
||||||
*[ADL]: Argument-dependent lookup
|
*[ADL]: Argument-dependent lookup
|
||||||
*[API]: Application Programming Interface
|
*[API]: Application Programming Interfaces
|
||||||
*[ASCII]: American Standard Code for Information Interchange
|
*[ASCII]: American Standard Code for Information Interchange
|
||||||
*[BDFL]: Benevolent Dictator for Life
|
*[BDFL]: Benevolent Dictator for Life
|
||||||
*[BJData]: Binary JData
|
*[BJData]: Binary JData
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ nav:
|
|||||||
- 'json_serializer': api/basic_json/json_serializer.md
|
- 'json_serializer': api/basic_json/json_serializer.md
|
||||||
- 'max_size': api/basic_json/max_size.md
|
- 'max_size': api/basic_json/max_size.md
|
||||||
- 'meta': api/basic_json/meta.md
|
- 'meta': api/basic_json/meta.md
|
||||||
- 'merge_diff': api/basic_json/merge_diff.md
|
|
||||||
- 'merge_patch': api/basic_json/merge_patch.md
|
- 'merge_patch': api/basic_json/merge_patch.md
|
||||||
- 'number_float_t': api/basic_json/number_float_t.md
|
- 'number_float_t': api/basic_json/number_float_t.md
|
||||||
- 'number_integer_t': api/basic_json/number_integer_t.md
|
- 'number_integer_t': api/basic_json/number_integer_t.md
|
||||||
@@ -300,7 +299,6 @@ nav:
|
|||||||
- 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION': api/macros/json_disable_tuple_reference_conversion.md
|
- 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION': api/macros/json_disable_tuple_reference_conversion.md
|
||||||
- 'JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20, JSON_HAS_CPP_23, JSON_HAS_CPP_26': api/macros/json_has_cpp_11.md
|
- 'JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20, JSON_HAS_CPP_23, JSON_HAS_CPP_26': api/macros/json_has_cpp_11.md
|
||||||
- 'JSON_HAS_EXPERIMENTAL_FILESYSTEM, JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md
|
- 'JSON_HAS_EXPERIMENTAL_FILESYSTEM, JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md
|
||||||
- 'JSON_HAS_RANGE_VIEW_CONVERSION': api/macros/json_has_range_view_conversion.md
|
|
||||||
- 'JSON_HAS_RANGES': api/macros/json_has_ranges.md
|
- 'JSON_HAS_RANGES': api/macros/json_has_ranges.md
|
||||||
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
||||||
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
||||||
|
|||||||
@@ -288,6 +288,36 @@ def check_header_links() -> None:
|
|||||||
f'link to "{match.group(0)}" does not point to a documentation page')
|
f'link to "{match.group(0)}" does not point to a documentation page')
|
||||||
|
|
||||||
|
|
||||||
|
def check_docset() -> None:
|
||||||
|
"""Every API page and every macro has an entry in the docset index; no entry points to a missing page."""
|
||||||
|
entry_re = re.compile(r"VALUES \('((?:[^']|'')*)', '(\w+)', '([^']*)'\);")
|
||||||
|
names_by_path = {}
|
||||||
|
with open("../../docset/docSet.sql", encoding="utf-8") as sql:
|
||||||
|
for name, _, path in entry_re.findall(sql.read()):
|
||||||
|
names_by_path.setdefault(path, set()).add(name.replace("''", "'"))
|
||||||
|
|
||||||
|
def to_path(page):
|
||||||
|
if os.path.basename(page) == "index.md":
|
||||||
|
return page[:-len("index.md")] + "index.html"
|
||||||
|
return page[:-len(".md")] + "/index.html"
|
||||||
|
|
||||||
|
pages = sorted(glob.glob("**/*.md", recursive=True))
|
||||||
|
for path in sorted(set(names_by_path) - {to_path(p) for p in pages}):
|
||||||
|
report("docset/stale_entry", "../../docset/docSet.sql", f'entry "{path}" has no documentation page')
|
||||||
|
for page in (p for p in pages if p.startswith("api/")):
|
||||||
|
names = names_by_path.get(to_path(page))
|
||||||
|
if not names:
|
||||||
|
report("docset/missing_entry", page, "page has no entry in docs/docset/docSet.sql")
|
||||||
|
elif page.startswith("api/macros/") and os.path.basename(page) != "index.md":
|
||||||
|
with open(page, encoding="utf-8") as content:
|
||||||
|
text = content.read()
|
||||||
|
match = re.search(r"^# (.+)$", text, re.MULTILINE) or re.search(r"<h1>(.*?)</h1>", text, re.DOTALL)
|
||||||
|
title = re.sub(r"<[^>]+>|\s+", " ", match.group(1))
|
||||||
|
for macro in filter(None, (x.strip() for x in re.split(r"[,/]", title))):
|
||||||
|
if macro not in names:
|
||||||
|
report("docset/missing_macro", page, f'macro "{macro}" has no entry in docs/docset/docSet.sql')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print(120 * "-")
|
print(120 * "-")
|
||||||
check_structure()
|
check_structure()
|
||||||
@@ -297,6 +327,7 @@ if __name__ == "__main__":
|
|||||||
check_heading_levels()
|
check_heading_levels()
|
||||||
check_image_alt_text()
|
check_image_alt_text()
|
||||||
check_header_links()
|
check_header_links()
|
||||||
|
check_docset()
|
||||||
print(120 * "-")
|
print(120 * "-")
|
||||||
|
|
||||||
if warnings > 0:
|
if warnings > 0:
|
||||||
|
|||||||
@@ -9,9 +9,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint64_t
|
#include <cstdint> // uint64_t
|
||||||
#include <cstring> // memcpy
|
#if !defined(__SIZEOF_INT128__) && defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) && (!defined(__SIZEOF_INT128__) || (!defined(__GNUC__) && !defined(__clang__)))
|
#include <intrin0.h> // __umulh, _umul128
|
||||||
#include <intrin0.h> // __umulh, _umul128, _BitScanForward64, _BitScanReverse64
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -29,10 +28,6 @@ inline int count_leading_zeros(std::uint64_t x) noexcept
|
|||||||
{
|
{
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
return __builtin_clzll(x);
|
return __builtin_clzll(x);
|
||||||
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
|
||||||
unsigned long index = 0; // NOLINT(runtime/int): the type _BitScan*64 takes
|
|
||||||
_BitScanReverse64(&index, x);
|
|
||||||
return 63 - static_cast<int>(index);
|
|
||||||
#else
|
#else
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (int shift = 32; shift != 0; shift >>= 1)
|
for (int shift = 32; shift != 0; shift >>= 1)
|
||||||
@@ -47,29 +42,6 @@ inline int count_leading_zeros(std::uint64_t x) noexcept
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// number of trailing zero bits of x (x != 0)
|
|
||||||
inline int count_trailing_zeros(std::uint64_t x) noexcept
|
|
||||||
{
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
|
||||||
return __builtin_ctzll(x);
|
|
||||||
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
|
||||||
unsigned long index = 0; // NOLINT(runtime/int): the type _BitScan*64 takes
|
|
||||||
_BitScanForward64(&index, x);
|
|
||||||
return static_cast<int>(index);
|
|
||||||
#else
|
|
||||||
int n = 0;
|
|
||||||
for (int shift = 32; shift != 0; shift >>= 1)
|
|
||||||
{
|
|
||||||
if ((x << (64 - shift)) == 0)
|
|
||||||
{
|
|
||||||
n += shift;
|
|
||||||
x >>= shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the 128-bit product of two 64-bit numbers
|
/// the 128-bit product of two 64-bit numbers
|
||||||
struct uint128_parts
|
struct uint128_parts
|
||||||
{
|
{
|
||||||
@@ -103,26 +75,15 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// eight bytes as a little-endian word (a single load on little-endian targets)
|
/// eight bytes as a little-endian word (compilers fold this into one load on
|
||||||
inline std::uint64_t read_eight_bytes(const unsigned char* b) noexcept
|
/// little-endian targets)
|
||||||
|
inline std::uint64_t read_eight_bytes(const char* p) noexcept
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) || defined(__x86_64__) || defined(__i386__) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
const auto* b = reinterpret_cast<const unsigned char*>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
// the byte order already matches (all MSVC targets are little-endian)
|
|
||||||
std::uint64_t result = 0;
|
|
||||||
std::memcpy(&result, b, sizeof(result));
|
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
return static_cast<std::uint64_t>(b[0]) | (static_cast<std::uint64_t>(b[1]) << 8u)
|
return static_cast<std::uint64_t>(b[0]) | (static_cast<std::uint64_t>(b[1]) << 8u)
|
||||||
| (static_cast<std::uint64_t>(b[2]) << 16u) | (static_cast<std::uint64_t>(b[3]) << 24u)
|
| (static_cast<std::uint64_t>(b[2]) << 16u) | (static_cast<std::uint64_t>(b[3]) << 24u)
|
||||||
| (static_cast<std::uint64_t>(b[4]) << 32u) | (static_cast<std::uint64_t>(b[5]) << 40u)
|
| (static_cast<std::uint64_t>(b[4]) << 32u) | (static_cast<std::uint64_t>(b[5]) << 40u)
|
||||||
| (static_cast<std::uint64_t>(b[6]) << 48u) | (static_cast<std::uint64_t>(b[7]) << 56u);
|
| (static_cast<std::uint64_t>(b[6]) << 48u) | (static_cast<std::uint64_t>(b[7]) << 56u);
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// eight bytes as a little-endian word
|
|
||||||
inline std::uint64_t read_eight_bytes(const char* p) noexcept
|
|
||||||
{
|
|
||||||
return read_eight_bytes(reinterpret_cast<const unsigned char*>(p)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("null", j);
|
JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
n = nullptr;
|
n = nullptr;
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
throw_type_must_be("number", j);
|
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t&
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("boolean", j);
|
JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t&
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ inline void from_json(const BasicJsonType& j, StringType& s)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
@@ -183,7 +183,7 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
l.clear();
|
l.clear();
|
||||||
std::transform(j.rbegin(), j.rend(),
|
std::transform(j.rbegin(), j.rend(),
|
||||||
@@ -200,7 +200,7 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
l.resize(j.size());
|
l.resize(j.size());
|
||||||
std::transform(j.begin(), j.end(), std::begin(l),
|
std::transform(j.begin(), j.end(), std::begin(l),
|
||||||
@@ -305,7 +305,7 @@ void())
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
from_json_array_impl(j, arr, priority_tag<3> {});
|
from_json_array_impl(j, arr, priority_tag<3> {});
|
||||||
@@ -324,7 +324,7 @@ auto from_json(const BasicJsonType& j, identity_tag<std::array<T, N>> tag)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_inplace_array_impl(j, tag, make_index_sequence<N> {});
|
return from_json_inplace_array_impl(j, tag, make_index_sequence<N> {});
|
||||||
@@ -335,7 +335,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("binary", j);
|
JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||||
@@ -356,7 +356,7 @@ inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw_type_must_be("binary or array", j);
|
JSON_THROW(type_error::create(302, concat("type must be binary or array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("object", j);
|
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstructibleObjectType ret;
|
ConstructibleObjectType ret;
|
||||||
@@ -432,7 +432,7 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
|||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
throw_type_must_be("number", j);
|
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,7 +504,7 @@ auto from_json(const BasicJsonType& j, TupleRelated&& t)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_tuple_impl(j, std::forward<TupleRelated>(t), priority_tag<3> {});
|
return from_json_tuple_impl(j, std::forward<TupleRelated>(t), priority_tag<3> {});
|
||||||
@@ -517,14 +517,14 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", j);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
m.clear();
|
m.clear();
|
||||||
for (const auto& p : j)
|
for (const auto& p : j)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("array", p);
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||||
}
|
}
|
||||||
m.emplace(p.at(0).template get<typename MapType::key_type>(), p.at(1).template get<typename MapType::mapped_type>());
|
m.emplace(p.at(0).template get<typename MapType::key_type>(), p.at(1).template get<typename MapType::mapped_type>());
|
||||||
}
|
}
|
||||||
@@ -591,7 +591,7 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", j);
|
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
// Checking for C++20 standard or later can be insufficient in case the
|
// Checking for C++20 standard or later can be insufficient in case the
|
||||||
|
|||||||
@@ -414,13 +414,13 @@ inline void to_json(BasicJsonType& j, const EnumKeyedMap& map)
|
|||||||
BasicJsonType key = p.first;
|
BasicJsonType key = p.first;
|
||||||
if (JSON_HEDLEY_UNLIKELY(!key.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!key.is_string()))
|
||||||
{
|
{
|
||||||
throw_type_must_be("string", key);
|
JSON_THROW(type_error::create(302, concat("type must be string, but is ", key.type_name()), &key));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& key_string = *key.template get_ptr<typename BasicJsonType::string_t*>();
|
auto& key_string = *key.template get_ptr<typename BasicJsonType::string_t*>();
|
||||||
if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second))
|
if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(exception_id::enum_key_duplicate, concat("duplicate object key '", key_string, "'"), &key));
|
JSON_THROW(type_error::create(318, concat("duplicate object key '", key_string, "'"), &key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
external_constructor<value_t::object>::construct(j, std::move(obj));
|
external_constructor<value_t::object>::construct(j, std::move(obj));
|
||||||
|
|||||||
@@ -45,84 +45,6 @@ namespace detail
|
|||||||
// exceptions //
|
// exceptions //
|
||||||
////////////////
|
////////////////
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief the ids of the exceptions thrown by the library
|
|
||||||
@note The values are part of the public API: they are the `id` member of the
|
|
||||||
exceptions and appear in their `what()` messages.
|
|
||||||
@sa https://json.nlohmann.me/home/exceptions/
|
|
||||||
*/
|
|
||||||
enum class exception_id : int
|
|
||||||
{
|
|
||||||
// parse_error
|
|
||||||
syntax_error = 101, ///< unexpected token or invalid literal while parsing JSON
|
|
||||||
patch_not_an_array = 104, ///< a JSON Patch document is not an array of objects
|
|
||||||
patch_invalid_operation = 105, ///< a JSON Patch operation is malformed
|
|
||||||
pointer_index_leading_zero = 106, ///< a JSON Pointer array index has a leading zero
|
|
||||||
pointer_missing_slash = 107, ///< a JSON Pointer does not start with '/'
|
|
||||||
pointer_invalid_escape = 108, ///< a JSON Pointer contains an escape other than ~0 and ~1
|
|
||||||
pointer_index_not_a_number = 109, ///< a JSON Pointer array index is not a number
|
|
||||||
unexpected_end_of_input = 110, ///< a binary input ends early, or has bytes left at its end
|
|
||||||
unexpected_byte = 112, ///< a binary input contains an unexpected byte or invalid length
|
|
||||||
invalid_string_or_size = 113, ///< a binary input contains an invalid string or size specification
|
|
||||||
bson_unsupported_type = 114, ///< a BSON record type is not supported
|
|
||||||
invalid_high_precision_number = 115, ///< a UBJSON/BJData high-precision number cannot be parsed
|
|
||||||
// invalid_iterator
|
|
||||||
iterators_incompatible = 201, ///< the iterators of a range belong to different values
|
|
||||||
iterator_from_other_value = 202, ///< an iterator does not belong to the value it is used with
|
|
||||||
iterator_range_from_other_value = 203, ///< an iterator range does not belong to the value it is used with
|
|
||||||
iterator_range_out_of_range = 204, ///< an iterator range of a primitive value is not [begin, end)
|
|
||||||
iterator_out_of_range = 205, ///< an iterator of a primitive value is not begin()
|
|
||||||
iterator_range_of_null = 206, ///< an iterator range belongs to a null value
|
|
||||||
iterator_key_not_object = 207, ///< key() is called on an iterator of a non-object
|
|
||||||
iterator_subscript_on_object = 208, ///< operator[] is called on an iterator of an object
|
|
||||||
iterator_arithmetic_on_object = 209, ///< an offset operator is used on an iterator of an object
|
|
||||||
insert_range_incompatible = 210, ///< the iterators of an inserted range belong to different values
|
|
||||||
insert_range_into_itself = 211, ///< an inserted range belongs to the value it is inserted into
|
|
||||||
iterators_compare_different_values = 212, ///< iterators of different values are compared
|
|
||||||
iterator_order_on_object = 213, ///< iterators of an object are compared by order
|
|
||||||
iterator_value_unavailable = 214, ///< an iterator does not refer to a value
|
|
||||||
// type_error
|
|
||||||
object_from_non_pairs = 301, ///< an object is created from an initializer list that is not a list of pairs
|
|
||||||
type_mismatch = 302, ///< a value has the wrong type for a conversion
|
|
||||||
incompatible_reference_type = 303, ///< get_ref() is called with a reference type that does not match the value
|
|
||||||
at_wrong_type = 304, ///< at() is called on a value of the wrong type
|
|
||||||
subscript_wrong_type = 305, ///< operator[] is called on a value of the wrong type
|
|
||||||
value_wrong_type = 306, ///< value() is called on a value of the wrong type
|
|
||||||
erase_wrong_type = 307, ///< erase() is called on a value of the wrong type
|
|
||||||
push_back_wrong_type = 308, ///< push_back() or operator+= is called on a value of the wrong type
|
|
||||||
insert_wrong_type = 309, ///< insert() is called on a value of the wrong type
|
|
||||||
swap_wrong_type = 310, ///< swap() is called on a value of the wrong type
|
|
||||||
emplace_wrong_type = 311, ///< emplace() or emplace_back() is called on a value of the wrong type
|
|
||||||
update_wrong_type = 312, ///< update() is called on a value of the wrong type
|
|
||||||
unflatten_invalid_value = 313, ///< unflatten() finds conflicting paths
|
|
||||||
unflatten_not_object = 314, ///< unflatten() is called on a non-object
|
|
||||||
unflatten_value_not_primitive = 315, ///< unflatten() is called on an object with non-primitive values
|
|
||||||
invalid_utf8 = 316, ///< dump() finds a string that is not valid UTF-8
|
|
||||||
type_not_serializable = 317, ///< a value cannot be serialized to the requested binary format
|
|
||||||
enum_key_duplicate = 318, ///< an enum-keyed map has two keys that serialize to the same string
|
|
||||||
discarded_value_used = 321, ///< a discarded value is used
|
|
||||||
// out_of_range
|
|
||||||
array_index_out_of_range = 401, ///< an array index is out of range
|
|
||||||
pointer_past_the_end_index = 402, ///< a JSON Pointer uses the array index '-'
|
|
||||||
key_not_found = 403, ///< an object key is not found
|
|
||||||
pointer_unresolved = 404, ///< a JSON Pointer reference token cannot be resolved
|
|
||||||
patch_on_root = 405, ///< the root of a value has no parent, e.g. for a JSON Patch 'remove' or 'add' at the root
|
|
||||||
number_overflow = 406, ///< a number cannot be stored without overflowing to NaN or INF
|
|
||||||
integer_too_large = 407, ///< an integer cannot be represented in the binary format
|
|
||||||
container_too_large = 408, ///< the size of a container in a binary input exceeds the maximal capacity
|
|
||||||
bson_key_with_null = 409, ///< a BSON key contains U+0000
|
|
||||||
value_out_of_range = 410, ///< an enum value is undefined, or a JSON Pointer array index exceeds size_type
|
|
||||||
patch_add_parent_not_container = 411, ///< the parent of a JSON Patch 'add' target is not a container
|
|
||||||
length_too_large = 412, ///< a length does not fit into the length field of a binary format
|
|
||||||
patch_remove_parent_not_container = 413, ///< the parent of a JSON Patch 'remove' target is not a container
|
|
||||||
patch_move_into_child = 414, ///< a JSON Patch 'move' moves a value into one of its children
|
|
||||||
subtype_out_of_range = 415, ///< a binary subtype does not fit into one byte
|
|
||||||
// other_error
|
|
||||||
internal_error = 500, ///< unreachable code was reached
|
|
||||||
patch_test_failed = 501, ///< a JSON Patch 'test' operation failed
|
|
||||||
size_marker_required = 502 ///< UBJSON/BJData output with type markers requires size markers
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief general exception of the @ref basic_json class
|
/// @brief general exception of the @ref basic_json class
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/exception/
|
/// @sa https://json.nlohmann.me/api/basic_json/exception/
|
||||||
class exception : public std::exception
|
class exception : public std::exception
|
||||||
@@ -273,18 +195,6 @@ class parse_error : public exception
|
|||||||
return {id_, byte_, w.c_str()};
|
return {id_, byte_, w.c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static parse_error create(exception_id id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), pos, what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static parse_error create(exception_id id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), byte_, what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief byte index of the parse error
|
@brief byte index of the parse error
|
||||||
|
|
||||||
@@ -319,12 +229,6 @@ class invalid_iterator : public exception
|
|||||||
return {id_, w.c_str()};
|
return {id_, w.c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static invalid_iterator create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
invalid_iterator(int id_, const char* what_arg)
|
invalid_iterator(int id_, const char* what_arg)
|
||||||
@@ -343,12 +247,6 @@ class type_error : public exception
|
|||||||
return {id_, w.c_str()};
|
return {id_, w.c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static type_error create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||||
@@ -366,12 +264,6 @@ class out_of_range : public exception
|
|||||||
return {id_, w.c_str()};
|
return {id_, w.c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static out_of_range create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||||
@@ -389,12 +281,6 @@ class other_error : public exception
|
|||||||
return {id_, w.c_str()};
|
return {id_, w.c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
|
||||||
static other_error create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
|
||||||
{
|
|
||||||
return create(static_cast<int>(id_), what_arg, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||||
@@ -421,36 +307,6 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
(void)exception;
|
(void)exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief throws because @a j does not have the type a conversion expects
|
|
||||||
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
|
||||||
@param[in] j the value with the wrong type
|
|
||||||
@throw type_error.302 always
|
|
||||||
*/
|
|
||||||
template<typename BasicJsonType>
|
|
||||||
JSON_HEDLEY_NO_RETURN inline void throw_type_must_be(const char* expected, const BasicJsonType& j)
|
|
||||||
{
|
|
||||||
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
|
||||||
static_cast<void>(j);
|
|
||||||
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), &j));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief throws because an operation is not supported for the type of @a j
|
|
||||||
@param[in] id_ the id of the type_error exception (at_wrong_type..update_wrong_type)
|
|
||||||
@param[in] operation the operation, e.g. "erase()"
|
|
||||||
@param[in] j the value the operation was called on
|
|
||||||
@throw type_error always
|
|
||||||
*/
|
|
||||||
template<typename BasicJsonType>
|
|
||||||
JSON_HEDLEY_NO_RETURN inline void throw_cannot_use_with(const exception_id id_, const char* operation, const BasicJsonType& j)
|
|
||||||
{
|
|
||||||
static_cast<void>(id_); // unused when JSON_NOEXCEPTION is defined
|
|
||||||
static_cast<void>(operation);
|
|
||||||
static_cast<void>(j);
|
|
||||||
JSON_THROW(type_error::create(id_, concat("cannot use ", operation, " with ", j.type_name()), &j));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <cmath> // ldexp
|
#include <cmath> // ldexp
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t, uintmax_t
|
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t, uintmax_t
|
||||||
|
#include <cstdio> // snprintf
|
||||||
#include <cstring> // memcpy
|
#include <cstring> // memcpy
|
||||||
#include <iterator> // back_inserter
|
#include <iterator> // back_inserter
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
@@ -195,7 +196,8 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_end_of_input, concat("expected end of input; last byte: 0x", get_token_string()), "value");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
|
||||||
|
exception_message(concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +319,8 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -509,7 +512,9 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("string length must be at least 1, is ", std::to_string(len)), "string");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
||||||
@@ -519,7 +524,10 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(get() != 0x00))
|
if (JSON_HEDLEY_UNLIKELY(get() != 0x00))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, "BSON string is not null-terminated", "string");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message("BSON string is not null-terminated",
|
||||||
|
"string"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return check_string_utf8(result, "string");
|
return check_string_utf8(result, "string");
|
||||||
@@ -539,7 +547,9 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// All BSON binary values have a subtype
|
// All BSON binary values have a subtype
|
||||||
@@ -629,9 +639,11 @@ class binary_reader
|
|||||||
|
|
||||||
default: // anything else is not supported (yet)
|
default: // anything else is not supported (yet)
|
||||||
{
|
{
|
||||||
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
std::array<char, 3> cr{{}};
|
||||||
|
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
const std::string cr_str{cr.data()};
|
||||||
return sax->parse_error(element_type_parse_position, cr_str,
|
return sax->parse_error(element_type_parse_position, cr_str,
|
||||||
parse_error::create(exception_id::bson_unsupported_type, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -955,7 +967,9 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (tag_handler == cbor_tag_handler_t::error)
|
if (tag_handler == cbor_tag_handler_t::error)
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid byte", "value");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore and store: the tag value is already in the head, so
|
// ignore and store: the tag value is already in the head, so
|
||||||
@@ -975,7 +989,9 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
case cbor_tag_handler_t::error:
|
case cbor_tag_handler_t::error:
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid byte", "value");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
case cbor_tag_handler_t::ignore:
|
case cbor_tag_handler_t::ignore:
|
||||||
@@ -1049,7 +1065,9 @@ class binary_reader
|
|||||||
|
|
||||||
default: // anything else (0xFF is handled inside the other types)
|
default: // anything else (0xFF is handled inside the other types)
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid byte", "value");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1062,7 +1080,10 @@ class binary_reader
|
|||||||
*/
|
*/
|
||||||
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
bool cbor_indefinite_string_error(const char* type_name, const char* context)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("indefinite-length ", type_name, " is not allowed inside indefinite-length ", type_name, "; last byte: 0x", get_token_string()), context);
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("indefinite-length ", type_name,
|
||||||
|
" is not allowed inside indefinite-length ", type_name, "; last byte: 0x", last_token), context), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1139,7 +1160,9 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x60-0x7B)", inside_indefinite ? "" : " or indefinite string type (0x7F)", "; last byte: 0x", get_token_string()), "string");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("expected length specification (0x60-0x7B)", inside_indefinite ? "" : " or indefinite string type (0x7F)", "; last byte: 0x", last_token), "string"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,7 +1292,9 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1350,7 +1375,9 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0x40-0x5B)", inside_indefinite ? "" : " or indefinite binary array type (0x5F)", "; last byte: 0x", get_token_string()), "binary");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("expected length specification (0x40-0x5B)", inside_indefinite ? "" : " or indefinite binary array type (0x5F)", "; last byte: 0x", last_token), "binary"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1496,7 +1523,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(len) || len == detail::unknown_size()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||||
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
||||||
}
|
}
|
||||||
result = conditional_static_cast<std::size_t>(len);
|
result = conditional_static_cast<std::size_t>(len);
|
||||||
@@ -1984,7 +2011,9 @@ class binary_reader
|
|||||||
|
|
||||||
default: // anything else
|
default: // anything else
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid byte", "value");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("invalid byte: 0x", last_token), "value"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2065,7 +2094,9 @@ class binary_reader
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", get_token_string()), "string");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2157,7 +2188,9 @@ class binary_reader
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("only string keys are supported, but found ", found, "; last byte: 0x", get_token_string()), "object key");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -2466,7 +2499,8 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, "string length must not be negative", "string");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
|
||||||
|
exception_message("string length must not be negative", "string"), nullptr));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2566,7 +2600,18 @@ class binary_reader
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return length_type_error("", "string");
|
auto last_token = get_token_string();
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
if (input_format != input_format_t::bjdata)
|
||||||
|
{
|
||||||
|
message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
|
||||||
|
}
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "string"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -2651,11 +2696,12 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(number < 0))
|
if (JSON_HEDLEY_UNLIKELY(number < 0))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, "count in an optimized container must be positive", "size");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
|
||||||
|
exception_message("count in an optimized container must be positive", "size"), nullptr));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
if (JSON_HEDLEY_UNLIKELY(!value_in_range_of<std::size_t>(number)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
exception_message("integer value overflow", "size"), nullptr));
|
||||||
}
|
}
|
||||||
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
|
||||||
@@ -2753,7 +2799,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (!value_in_range_of<std::size_t>(number))
|
if (!value_in_range_of<std::size_t>(number))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||||
exception_message("integer value overflow", "size"), nullptr));
|
exception_message("integer value overflow", "size"), nullptr));
|
||||||
}
|
}
|
||||||
result = detail::conditional_static_cast<std::size_t>(number);
|
result = detail::conditional_static_cast<std::size_t>(number);
|
||||||
@@ -2768,7 +2814,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
|
if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, "ndarray dimensional vector is not allowed", "size");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message("ndarray dimensional vector is not allowed", "size"), nullptr));
|
||||||
}
|
}
|
||||||
std::vector<size_t> dim;
|
std::vector<size_t> dim;
|
||||||
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
|
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
|
||||||
@@ -2804,7 +2850,9 @@ class binary_reader
|
|||||||
const char* type_name = bjd_type_name(ndarray_dtype);
|
const char* type_name = bjd_type_name(ndarray_dtype);
|
||||||
if (JSON_HEDLEY_UNLIKELY(type_name == nullptr))
|
if (JSON_HEDLEY_UNLIKELY(type_name == nullptr))
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid byte", "type");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message("invalid byte: 0x" + last_token, "type"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
string_t type_key = "_ArrayType_";
|
string_t type_key = "_ArrayType_";
|
||||||
@@ -2832,7 +2880,7 @@ class binary_reader
|
|||||||
// or SIZE_MAX.
|
// or SIZE_MAX.
|
||||||
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
if (JSON_HEDLEY_UNLIKELY(result > (std::numeric_limits<std::size_t>::max)() / i))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||||
}
|
}
|
||||||
result *= i;
|
result *= i;
|
||||||
// the pre-check above already rules out result becoming 0
|
// the pre-check above already rules out result becoming 0
|
||||||
@@ -2841,7 +2889,7 @@ class binary_reader
|
|||||||
// unknown-size container (see get_ubjson_size_type())
|
// unknown-size container (see get_ubjson_size_type())
|
||||||
if (result == npos)
|
if (result == npos)
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
||||||
{
|
{
|
||||||
@@ -2858,7 +2906,18 @@ class binary_reader
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return length_type_error(" after '#'", "size");
|
auto last_token = get_token_string();
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
if (input_format != input_format_t::bjdata)
|
||||||
|
{
|
||||||
|
message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
|
||||||
|
}
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(message, "size"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -2891,7 +2950,9 @@ class binary_reader
|
|||||||
if (input_format == input_format_t::bjdata
|
if (input_format == input_format_t::bjdata
|
||||||
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
||||||
@@ -2906,7 +2967,9 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat("expected '#' after type information; last byte: 0x", get_token_string()), "size");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
||||||
@@ -2925,7 +2988,8 @@ class binary_reader
|
|||||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
|
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
|
||||||
if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray)
|
if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, "ndarray requires both type and size", "size");
|
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||||
|
exception_message("ndarray requires both type and size", "size"), nullptr));
|
||||||
}
|
}
|
||||||
return is_error;
|
return is_error;
|
||||||
}
|
}
|
||||||
@@ -3057,7 +3121,9 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", get_token_string()), "char");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message(concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
|
||||||
}
|
}
|
||||||
string_t s(1, static_cast<typename string_t::value_type>(current));
|
string_t s(1, static_cast<typename string_t::value_type>(current));
|
||||||
return sax->string(s);
|
return sax->string(s);
|
||||||
@@ -3078,7 +3144,8 @@ class binary_reader
|
|||||||
default: // anything else
|
default: // anything else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return unexpected_byte("invalid byte", "value");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message("invalid byte: 0x" + last_token, "value"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -3141,7 +3208,7 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
if (JSON_HEDLEY_UNLIKELY((size_and_type.second == 'Z' || size_and_type.second == 'T' || size_and_type.second == 'F')
|
||||||
&& size_and_type.first > max_valueless_container_size))
|
&& size_and_type.first > max_valueless_container_size))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||||
exception_message("excessive array size", "size"), nullptr));
|
exception_message("excessive array size", "size"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3177,7 +3244,9 @@ class binary_reader
|
|||||||
// do not accept ND-array size in objects in BJData
|
// do not accept ND-array size in objects in BJData
|
||||||
if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
|
if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::unexpected_byte, "BJData object does not support ND-array size in optimized format", "object");
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message("BJData object does not support ND-array size in optimized format", "object"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size_and_type.first != npos)
|
if (size_and_type.first != npos)
|
||||||
@@ -3214,7 +3283,7 @@ class binary_reader
|
|||||||
// the lexer would stop at a NUL and accept the digits before it
|
// the lexer would stop at a NUL and accept the digits before it
|
||||||
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, "00", parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
return sax->parse_error(chars_read, "00", parse_error::create(115, chars_read,
|
||||||
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr));
|
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr));
|
||||||
}
|
}
|
||||||
number_vector.push_back(static_cast<char>(current));
|
number_vector.push_back(static_cast<char>(current));
|
||||||
@@ -3231,7 +3300,7 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
|
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3249,7 +3318,7 @@ class binary_reader
|
|||||||
return sax->parse_error(
|
return sax->parse_error(
|
||||||
chars_read,
|
chars_read,
|
||||||
number_string,
|
number_string,
|
||||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", number_string, '\''), nullptr));
|
out_of_range::create(406, concat("number overflow parsing '", number_string, '\''), nullptr));
|
||||||
}
|
}
|
||||||
// number_string is a std::string, while the SAX interface takes a
|
// number_string is a std::string, while the SAX interface takes a
|
||||||
// string_t; convert explicitly, as the two are only implicitly
|
// string_t; convert explicitly, as the two are only implicitly
|
||||||
@@ -3271,7 +3340,7 @@ class binary_reader
|
|||||||
case token_type::end_of_input:
|
case token_type::end_of_input:
|
||||||
case token_type::literal_or_value:
|
case token_type::literal_or_value:
|
||||||
default:
|
default:
|
||||||
return sax->parse_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3330,6 +3399,20 @@ class binary_reader
|
|||||||
return 0x80 <= c && c <= 0xBF;
|
return 0x80 <= c && c <= 0xBF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief report a parse error at the last read byte
|
||||||
|
|
||||||
|
@param[in] detail a detailed error message
|
||||||
|
@param[in] context further context information
|
||||||
|
@return false
|
||||||
|
*/
|
||||||
|
bool bon8_error(const std::string& detail, const char* context)
|
||||||
|
{
|
||||||
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||||
|
exception_message(concat(detail, ": 0x", last_token), context), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief read a BON8 value and everything nested inside it
|
@brief read a BON8 value and everything nested inside it
|
||||||
|
|
||||||
@@ -3545,7 +3628,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 0xFE: end of container where a value is expected
|
// 0xFE: end of container where a value is expected
|
||||||
return unexpected_byte("invalid byte", "value");
|
return bon8_error("invalid byte", "value");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -3672,7 +3755,7 @@ class binary_reader
|
|||||||
current = byte;
|
current = byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
return unexpected_byte("expected a string; last byte", "key");
|
return bon8_error("expected a string; last byte", "key");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -3795,7 +3878,7 @@ class binary_reader
|
|||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!valid_second))
|
if (JSON_HEDLEY_UNLIKELY(!valid_second))
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
return bon8_error("invalid UTF-8 byte", "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push_back(static_cast<typename string_t::value_type>(byte));
|
result.push_back(static_cast<typename string_t::value_type>(byte));
|
||||||
@@ -3809,7 +3892,7 @@ class binary_reader
|
|||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current)))
|
if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current)))
|
||||||
{
|
{
|
||||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
return bon8_error("invalid UTF-8 byte", "string");
|
||||||
}
|
}
|
||||||
result.push_back(static_cast<typename string_t::value_type>(current));
|
result.push_back(static_cast<typename string_t::value_type>(current));
|
||||||
}
|
}
|
||||||
@@ -3854,7 +3937,7 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
// in case of failure, advance position by 1 to report the failing location
|
// in case of failure, advance position by 1 to report the failing location
|
||||||
++chars_read;
|
++chars_read;
|
||||||
sax->parse_error(chars_read, "<end of file>", parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -4008,7 +4091,7 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, get_token_string(),
|
return sax->parse_error(chars_read, get_token_string(),
|
||||||
out_of_range::create(exception_id::number_overflow, exception_message("number overflow", "value"), nullptr));
|
out_of_range::create(406, exception_message("number overflow", "value"), nullptr));
|
||||||
}
|
}
|
||||||
return sax->number_float(result, "");
|
return sax->number_float(result, "");
|
||||||
}
|
}
|
||||||
@@ -4128,7 +4211,9 @@ class binary_reader
|
|||||||
|
|
||||||
if (error_handler == error_handler_t::strict)
|
if (error_handler == error_handler_t::strict)
|
||||||
{
|
{
|
||||||
return last_byte_error(exception_id::invalid_string_or_size, "invalid string: ill-formed UTF-8 byte", context);
|
auto last_token = get_token_string();
|
||||||
|
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||||
|
exception_message("invalid string: ill-formed UTF-8 byte", context), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
result = sanitize_utf8(result, error_handler);
|
result = sanitize_utf8(result, error_handler);
|
||||||
@@ -4224,53 +4309,19 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
return sax->parse_error(chars_read, "<end of file>",
|
return sax->parse_error(chars_read, "<end of file>",
|
||||||
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reports a parse error at the last read byte
|
|
||||||
@param[in] id_ the id of the parse_error exception
|
|
||||||
@param[in] detail a detailed error message
|
|
||||||
@param[in] context further context information
|
|
||||||
@return the result of the SAX parser's parse_error()
|
|
||||||
*/
|
|
||||||
bool last_byte_error(const exception_id id_, const std::string& detail, const std::string& context) const
|
|
||||||
{
|
|
||||||
return sax->parse_error(chars_read, get_token_string(), parse_error::create(id_, chars_read, exception_message(detail, context), nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reports the last read byte as unexpected (parse_error.112)
|
|
||||||
@param[in] detail what is wrong with the byte, e.g. "invalid byte"
|
|
||||||
@param[in] context further context information
|
|
||||||
@return the result of the SAX parser's parse_error()
|
|
||||||
*/
|
|
||||||
bool unexpected_byte(const char* detail, const std::string& context) const
|
|
||||||
{
|
|
||||||
return last_byte_error(exception_id::unexpected_byte, concat(detail, ": 0x", get_token_string()), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reports that the last read byte is not a UBJSON/BJData length type (parse_error.113)
|
|
||||||
@param[in] position where the length type was expected, e.g. " after '#'"
|
|
||||||
@param[in] context further context information
|
|
||||||
@return the result of the SAX parser's parse_error()
|
|
||||||
*/
|
|
||||||
bool length_type_error(const char* position, const char* context) const
|
|
||||||
{
|
|
||||||
const char* types = input_format == input_format_t::bjdata ? "U, i, u, I, m, l, M, L" : "U, i, I, l, L";
|
|
||||||
return last_byte_error(exception_id::invalid_string_or_size,
|
|
||||||
concat("expected length type specification (", types, ")", position, "; last byte: 0x", get_token_string()), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@return a string representation of the last read byte
|
@return a string representation of the last read byte
|
||||||
*/
|
*/
|
||||||
std::string get_token_string() const
|
std::string get_token_string() const
|
||||||
{
|
{
|
||||||
return hex_byte(static_cast<std::uint8_t>(current));
|
std::array<char, 3> cr{{}};
|
||||||
|
static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
return std::string{cr.data()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // count, find, min
|
#include <algorithm> // min
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // uint32_t
|
#include <cstdint> // uint32_t
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next, reverse_iterator
|
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
||||||
#include <streambuf> // streambuf
|
#include <streambuf> // streambuf
|
||||||
#include <string> // string, char_traits
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
||||||
@@ -297,7 +297,6 @@ class iterator_input_adapter
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
++eof_reads;
|
|
||||||
return char_traits<char_type>::eof();
|
return char_traits<char_type>::eof();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,26 +306,6 @@ class iterator_input_adapter
|
|||||||
return static_cast<std::size_t>(std::distance(begin, current));
|
return static_cast<std::size_t>(std::distance(begin, current));
|
||||||
}
|
}
|
||||||
|
|
||||||
// number of get_character() calls so far, including those that returned
|
|
||||||
// EOF; the lexer derives its position from it (see lexer::lazy_position)
|
|
||||||
std::size_t get_read_count() const
|
|
||||||
{
|
|
||||||
return get_consumed_count() + eof_reads;
|
|
||||||
}
|
|
||||||
|
|
||||||
// number of newlines in the consumed range [0, last_index); @a line_start
|
|
||||||
// is set to the index after the last of them (0 if there is none); only
|
|
||||||
// valid when supports_seek
|
|
||||||
std::size_t count_consumed_lines(std::size_t last_index, std::size_t& line_start) const
|
|
||||||
{
|
|
||||||
const auto to = std::next(begin, static_cast<typename std::iterator_traits<IteratorType>::difference_type>(last_index));
|
|
||||||
const auto newline = char_traits<char_type>::to_char_type('\n');
|
|
||||||
using reverse_it = std::reverse_iterator<IteratorType>;
|
|
||||||
const auto last_newline = std::find(reverse_it(to), reverse_it(begin), newline);
|
|
||||||
line_start = static_cast<std::size_t>(std::distance(begin, last_newline.base()));
|
|
||||||
return static_cast<std::size_t>(std::count(begin, last_newline.base(), newline));
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the already-consumed characters in the half-open range
|
// append the already-consumed characters in the half-open range
|
||||||
// [first_index, last_index) to @a out; only valid when supports_seek
|
// [first_index, last_index) to @a out; only valid when supports_seek
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
@@ -443,8 +422,6 @@ class iterator_input_adapter
|
|||||||
IteratorType begin;
|
IteratorType begin;
|
||||||
IteratorType current;
|
IteratorType current;
|
||||||
SentinelType end;
|
SentinelType end;
|
||||||
/// number of get_character() calls that returned EOF
|
|
||||||
std::size_t eof_reads = 0;
|
|
||||||
|
|
||||||
template<typename BaseInputAdapter, size_t T>
|
template<typename BaseInputAdapter, size_t T>
|
||||||
friend struct wide_string_input_helper;
|
friend struct wide_string_input_helper;
|
||||||
@@ -604,7 +581,7 @@ class wide_string_input_adapter
|
|||||||
template<class T>
|
template<class T>
|
||||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(exception_id::unexpected_byte, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -816,7 +793,7 @@ inline file_input_adapter input_adapter(std::FILE* file)
|
|||||||
{
|
{
|
||||||
if (file == nullptr)
|
if (file == nullptr)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||||
}
|
}
|
||||||
return file_input_adapter(file);
|
return file_input_adapter(file);
|
||||||
}
|
}
|
||||||
@@ -825,7 +802,7 @@ inline input_stream_adapter input_adapter(std::istream& stream)
|
|||||||
{
|
{
|
||||||
if (stream.rdbuf() == nullptr)
|
if (stream.rdbuf() == nullptr)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||||
}
|
}
|
||||||
return input_stream_adapter(stream);
|
return input_stream_adapter(stream);
|
||||||
}
|
}
|
||||||
@@ -850,7 +827,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
|
|||||||
{
|
{
|
||||||
if (b == nullptr)
|
if (b == nullptr)
|
||||||
{
|
{
|
||||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||||
}
|
}
|
||||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||||
const auto* ptr = reinterpret_cast<const char*>(b);
|
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||||
|
|||||||
@@ -176,27 +176,6 @@ template<typename ArrayType>
|
|||||||
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief reports an object or array whose announced size exceeds max_size()
|
|
||||||
|
|
||||||
Shared by json_sax_dom_parser and json_sax_dom_callback_parser.
|
|
||||||
|
|
||||||
@param[in] sax the SAX parser to report the error to
|
|
||||||
@param[in] len the number of elements announced by the input, or unknown_size()
|
|
||||||
@param[in] kind "object" or "array"
|
|
||||||
@param[in] ref the object or array that was just created
|
|
||||||
@return whether parsing should continue (false after reporting out_of_range.408)
|
|
||||||
*/
|
|
||||||
template<typename SAX, typename BasicJsonType>
|
|
||||||
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
|
||||||
{
|
|
||||||
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
/*!
|
/*!
|
||||||
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
||||||
@@ -206,35 +185,6 @@ befriends this struct, as the position members are private.
|
|||||||
*/
|
*/
|
||||||
struct diagnostic_positions
|
struct diagnostic_positions
|
||||||
{
|
{
|
||||||
/*!
|
|
||||||
@param[in,out] v the object or array whose opening brace or bracket was just read
|
|
||||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
|
||||||
*/
|
|
||||||
template<typename BasicJsonType, typename LexerType>
|
|
||||||
static void set_container_start(BasicJsonType& v, LexerType* lexer)
|
|
||||||
{
|
|
||||||
if (lexer)
|
|
||||||
{
|
|
||||||
// Lexer has read the first character of the container, so
|
|
||||||
// subtract 1 from the position to get the correct start position.
|
|
||||||
v.start_position = lexer->get_chars_read_total() - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@param[in,out] v the object or array whose closing brace or bracket was just read
|
|
||||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
|
||||||
*/
|
|
||||||
template<typename BasicJsonType, typename LexerType>
|
|
||||||
static void set_container_end(BasicJsonType& v, LexerType* lexer)
|
|
||||||
{
|
|
||||||
if (lexer)
|
|
||||||
{
|
|
||||||
// Lexer's position is past the closing brace or bracket, so set that as the end position.
|
|
||||||
v.end_position = lexer->get_chars_read_total();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@param[in,out] v the value that was just parsed
|
@param[in,out] v the value that was just parsed
|
||||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||||
@@ -247,7 +197,7 @@ struct diagnostic_positions
|
|||||||
// Lexer has read past the current field value, so set the end position to the current position.
|
// Lexer has read past the current field value, so set the end position to the current position.
|
||||||
// The start position will be set below based on the length of the string representation
|
// The start position will be set below based on the length of the string representation
|
||||||
// of the value.
|
// of the value.
|
||||||
v.end_position = lexer->get_chars_read_total();
|
v.end_position = lexer->get_position();
|
||||||
|
|
||||||
switch (v.type())
|
switch (v.type())
|
||||||
{
|
{
|
||||||
@@ -399,11 +349,22 @@ class json_sax_dom_parser
|
|||||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
|
// Manually set the start position of the object here.
|
||||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer has read the first character of the object, so
|
||||||
|
// subtract 1 from the position to get the correct start position.
|
||||||
|
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return check_container_size(*this, len, "object", ref_stack.back());
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||||
|
{
|
||||||
|
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool key(string_t& val)
|
bool key(string_t& val)
|
||||||
@@ -422,7 +383,11 @@ class json_sax_dom_parser
|
|||||||
JSON_ASSERT(ref_stack.back()->is_object());
|
JSON_ASSERT(ref_stack.back()->is_object());
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer's position is past the closing brace, so set that as the end position.
|
||||||
|
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref_stack.back()->set_parents();
|
ref_stack.back()->set_parents();
|
||||||
@@ -435,13 +400,17 @@ class json_sax_dom_parser
|
|||||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
|
// Manually set the start position of the array here.
|
||||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
return false;
|
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len != detail::unknown_size())
|
if (len != detail::unknown_size())
|
||||||
@@ -458,7 +427,11 @@ class json_sax_dom_parser
|
|||||||
JSON_ASSERT(ref_stack.back()->is_array());
|
JSON_ASSERT(ref_stack.back()->is_array());
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||||
|
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref_stack.back()->set_parents();
|
ref_stack.back()->set_parents();
|
||||||
@@ -638,11 +611,21 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
|
// Manually set the start position of the object here.
|
||||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer has read the first character of the object, so
|
||||||
|
// subtract 1 from the position to get the correct start position.
|
||||||
|
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return check_container_size(*this, len, "object", ref_stack.back());
|
// check object limit
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||||
|
{
|
||||||
|
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -712,7 +695,11 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer's position is past the closing brace, so set that as the end position.
|
||||||
|
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref_stack.back()->set_parents();
|
ref_stack.back()->set_parents();
|
||||||
@@ -723,7 +710,13 @@ class json_sax_dom_callback_parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const string_t object_key = pop_container();
|
JSON_ASSERT(!ref_stack.empty());
|
||||||
|
JSON_ASSERT(!keep_stack.empty());
|
||||||
|
JSON_ASSERT(!container_key_stack.empty());
|
||||||
|
ref_stack.pop_back();
|
||||||
|
keep_stack.pop_back();
|
||||||
|
const string_t object_key = std::move(container_key_stack.back());
|
||||||
|
container_key_stack.pop_back();
|
||||||
|
|
||||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||||
{
|
{
|
||||||
@@ -749,13 +742,20 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
|
// Manually set the start position of the array here.
|
||||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer has read the first character of the array, so
|
||||||
|
// subtract 1 from the position to get the correct start position.
|
||||||
|
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
// check array limit
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
return false;
|
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len != detail::unknown_size())
|
if (len != detail::unknown_size())
|
||||||
@@ -779,7 +779,11 @@ class json_sax_dom_callback_parser
|
|||||||
{
|
{
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
if (m_lexer_ref)
|
||||||
|
{
|
||||||
|
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||||
|
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ref_stack.back()->set_parents();
|
ref_stack.back()->set_parents();
|
||||||
@@ -805,7 +809,13 @@ class json_sax_dom_callback_parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const string_t object_key = pop_container();
|
JSON_ASSERT(!ref_stack.empty());
|
||||||
|
JSON_ASSERT(!keep_stack.empty());
|
||||||
|
JSON_ASSERT(!container_key_stack.empty());
|
||||||
|
ref_stack.pop_back();
|
||||||
|
keep_stack.pop_back();
|
||||||
|
const string_t object_key = std::move(container_key_stack.back());
|
||||||
|
container_key_stack.pop_back();
|
||||||
|
|
||||||
// remove discarded value
|
// remove discarded value
|
||||||
if (!ref_stack.empty() && ref_stack.back())
|
if (!ref_stack.empty() && ref_stack.back())
|
||||||
@@ -892,23 +902,6 @@ class json_sax_dom_callback_parser
|
|||||||
return string_t{};
|
return string_t{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief leave the object or array that end_object()/end_array() just closed
|
|
||||||
@return the key the container is stored under in its parent (see
|
|
||||||
container_key_stack)
|
|
||||||
*/
|
|
||||||
string_t pop_container()
|
|
||||||
{
|
|
||||||
JSON_ASSERT(!ref_stack.empty());
|
|
||||||
JSON_ASSERT(!keep_stack.empty());
|
|
||||||
JSON_ASSERT(!container_key_stack.empty());
|
|
||||||
ref_stack.pop_back();
|
|
||||||
keep_stack.pop_back();
|
|
||||||
string_t object_key = std::move(container_key_stack.back());
|
|
||||||
container_key_stack.pop_back();
|
|
||||||
return object_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief remove the discarded value the callback rejected from its parent,
|
@brief remove the discarded value the callback rejected from its parent,
|
||||||
unless it is a duplicate key's slot with a stashed previous value, in
|
unless it is a duplicate key's slot with a stashed previous value, in
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/bit_ops.hpp>
|
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/number_parse.hpp>
|
#include <nlohmann/detail/input/number_parse.hpp>
|
||||||
#include <nlohmann/detail/input/position_t.hpp>
|
#include <nlohmann/detail/input/position_t.hpp>
|
||||||
@@ -187,15 +186,6 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
static constexpr bool lazy_token_string =
|
static constexpr bool lazy_token_string =
|
||||||
input_adapter_supports_seek<InputAdapterType>(is_detected<detect_supports_seek, InputAdapterType> {});
|
input_adapter_supports_seek<InputAdapterType>(is_detected<detect_supports_seek, InputAdapterType> {});
|
||||||
|
|
||||||
/// whether the read position is derived from the input adapter on demand
|
|
||||||
/// instead of being counted on every scanned character. Seekable adapters
|
|
||||||
/// know how much input they consumed and can revisit it, so
|
|
||||||
/// chars_read_total is the adapter's read count (minus a pending unget),
|
|
||||||
/// and line and column are recomputed from the consumed input only when
|
|
||||||
/// get_position() is called (errors). Counting per character kept two
|
|
||||||
/// increments and a newline check in the hot path of every get().
|
|
||||||
static constexpr bool lazy_position = lazy_token_string;
|
|
||||||
|
|
||||||
/// whether a simulated unget can be passed on to the input adapter, which
|
/// whether a simulated unget can be passed on to the input adapter, which
|
||||||
/// then leaves the character in the input; see
|
/// then leaves the character in the input; see
|
||||||
/// input_adapter_supports_lookahead
|
/// input_adapter_supports_lookahead
|
||||||
@@ -205,9 +195,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
/// whether string scanning may bulk-consume runs of ordinary characters
|
/// whether string scanning may bulk-consume runs of ordinary characters
|
||||||
/// directly from a contiguous input buffer (SWAR fast path). This requires
|
/// directly from a contiguous input buffer (SWAR fast path). This requires
|
||||||
/// the token to be reconstructible lazily (lazy_token_string), so bypassing
|
/// the token to be reconstructible lazily (lazy_token_string), so bypassing
|
||||||
/// the per-character capture in get() cannot lose error diagnostics. It
|
/// the per-character capture in get() cannot lose error diagnostics.
|
||||||
/// also implies lazy_position, so the bulk paths need not advance the
|
|
||||||
/// position counters.
|
|
||||||
static constexpr bool bulk_scan =
|
static constexpr bool bulk_scan =
|
||||||
lazy_token_string
|
lazy_token_string
|
||||||
&& input_adapter_supports_bulk_scan<InputAdapterType>(is_detected<detect_supports_bulk_scan, InputAdapterType> {});
|
&& input_adapter_supports_bulk_scan<InputAdapterType>(is_detected<detect_supports_bulk_scan, InputAdapterType> {});
|
||||||
@@ -233,41 +221,6 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
// scan functions
|
// scan functions
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
/// contiguous input: try to decode the 4 hex digits following `\\u`
|
|
||||||
/// directly from the input buffer via hex_codepoint(), instead of 4 calls
|
|
||||||
/// to get(). On success, advances the adapter exactly as those 4 get()
|
|
||||||
/// calls would (bulk_scan implies lazy_position, so there are no position
|
|
||||||
/// counters to advance) and leaves @a current holding the last of
|
|
||||||
/// the 4 digits, just as the last such get() would; the codepoint is
|
|
||||||
/// written to @a out. Makes no state change and returns false for a
|
|
||||||
/// pending unget, fewer than 4 remaining bytes, or any of the 4 bytes not
|
|
||||||
/// being a hex digit, so the caller falls back unchanged to the
|
|
||||||
/// per-character loop, which then reports the same diagnostic (stopping
|
|
||||||
/// at the first invalid digit) as before this optimization.
|
|
||||||
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
|
||||||
{
|
|
||||||
if (next_unget || ia.bulk_remaining() < 4)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const char_type* const raw = ia.bulk_data();
|
|
||||||
const int codepoint = hex_codepoint(reinterpret_cast<const unsigned char*>(raw));
|
|
||||||
if (codepoint < 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ia.bulk_skip(4);
|
|
||||||
current = char_traits<char_type>::to_int_type(raw[3]);
|
|
||||||
out = codepoint;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// streaming input: no bulk fast path
|
|
||||||
bool get_codepoint_bulk(std::false_type /*bulk*/, int& /*out*/) const noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get codepoint from 4 hex characters following `\\u`
|
@brief get codepoint from 4 hex characters following `\\u`
|
||||||
|
|
||||||
@@ -287,14 +240,6 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
{
|
{
|
||||||
// this function only makes sense after reading `\u`
|
// this function only makes sense after reading `\u`
|
||||||
JSON_ASSERT(current == 'u');
|
JSON_ASSERT(current == 'u');
|
||||||
|
|
||||||
// contiguous input: decode all 4 hex digits directly from the buffer
|
|
||||||
int fast_codepoint = 0;
|
|
||||||
if (get_codepoint_bulk(std::integral_constant<bool, bulk_scan> {}, fast_codepoint))
|
|
||||||
{
|
|
||||||
return fast_codepoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
int codepoint = 0;
|
int codepoint = 0;
|
||||||
|
|
||||||
const auto factors = { 12u, 8u, 4u, 0u };
|
const auto factors = { 12u, 8u, 4u, 0u };
|
||||||
@@ -386,6 +331,10 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
}
|
}
|
||||||
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), pos);
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), pos);
|
||||||
ia.bulk_skip(pos);
|
ia.bulk_skip(pos);
|
||||||
|
// the run contains no newline (all bytes < 0x20 are treated as special),
|
||||||
|
// so only the flat character counters advance
|
||||||
|
position.chars_read_total += pos;
|
||||||
|
position.chars_read_current_line += pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// streaming input: no bulk fast path
|
/// streaming input: no bulk fast path
|
||||||
@@ -1095,11 +1044,9 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
token_type::parse_error otherwise
|
token_type::parse_error otherwise
|
||||||
|
|
||||||
@note The scanner is independent of the current locale: token_buffer
|
@note The scanner is independent of the current locale: token_buffer
|
||||||
always holds `.`. The conversion of float and double does not use
|
always holds `.`. Only the std::strtod fallback of convert_number()
|
||||||
the locale either. Only the std::strtold fallback of
|
depends on the locale, and it looks up the decimal point right
|
||||||
convert_number() for long double formats other than binary64
|
before converting (see detail::convert_float_locale_aware()).
|
||||||
depends on it, and it looks up the decimal point right before
|
|
||||||
converting (see detail::convert_float_locale_aware()).
|
|
||||||
*/
|
*/
|
||||||
token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
|
token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
|
||||||
{
|
{
|
||||||
@@ -1112,7 +1059,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
|
|
||||||
// offset just past the last mantissa byte in token_buffer (i.e. the
|
// offset just past the last mantissa byte in token_buffer (i.e. the
|
||||||
// index of 'e'/'E', or the whole token when there is no exponent).
|
// index of 'e'/'E', or the whole token when there is no exponent).
|
||||||
// convert_number() uses it to split the token; npos means
|
// convert_number() uses it to count significant digits; npos means
|
||||||
// "not seen an exponent yet" and is resolved at scan_number_done
|
// "not seen an exponent yet" and is resolved at scan_number_done
|
||||||
std::size_t mantissa_end = std::string::npos;
|
std::size_t mantissa_end = std::string::npos;
|
||||||
|
|
||||||
@@ -1442,8 +1389,8 @@ scan_number_done:
|
|||||||
@param[in] mantissa_end offset just past the last mantissa byte in
|
@param[in] mantissa_end offset just past the last mantissa byte in
|
||||||
token_buffer (the index of 'e'/'E', or
|
token_buffer (the index of 'e'/'E', or
|
||||||
token_buffer.size() when there is no exponent);
|
token_buffer.size() when there is no exponent);
|
||||||
with decimal_point_position, it locates the parts
|
used to skip Clinger's fast path when it cannot
|
||||||
of a float token without scanning it again
|
possibly succeed - see detail::mantissa_fits_clinger()
|
||||||
*/
|
*/
|
||||||
token_type convert_number(token_type number_type, std::size_t mantissa_end)
|
token_type convert_number(token_type number_type, std::size_t mantissa_end)
|
||||||
{
|
{
|
||||||
@@ -1497,11 +1444,10 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this code is reached if we parse a floating-point number or if an
|
// this code is reached if we parse a floating-point number or if an
|
||||||
// integer conversion above overflowed. float and double (and long
|
// integer conversion above overflowed. Prefer std::from_chars
|
||||||
// double where it is binary64) are converted by the library itself,
|
// (Eisel-Lemire, locale-independent, correctly rounded) when available;
|
||||||
// correctly rounded and independent of the locale; other long double
|
// otherwise the exact Clinger fast path (double only); otherwise the
|
||||||
// formats use std::from_chars when available, otherwise the
|
// locale-aware strtof/strtod/strtold.
|
||||||
// locale-aware strtold.
|
|
||||||
if (convert_float_fast(num_begin, num_end, decimal_point_position, mantissa_end, value_float))
|
if (convert_float_fast(num_begin, num_end, decimal_point_position, mantissa_end, value_float))
|
||||||
{
|
{
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
@@ -1621,6 +1567,8 @@ scan_number_done:
|
|||||||
if (JSON_HEDLEY_LIKELY(integer_result != token_type::uninitialized))
|
if (JSON_HEDLEY_LIKELY(integer_result != token_type::uninitialized))
|
||||||
{
|
{
|
||||||
ia.bulk_skip(len - 1);
|
ia.bulk_skip(len - 1);
|
||||||
|
position.chars_read_total += (len - 1);
|
||||||
|
position.chars_read_current_line += (len - 1);
|
||||||
return integer_result;
|
return integer_result;
|
||||||
}
|
}
|
||||||
// The value does not fit an integer, so this token converts as a
|
// The value does not fit an integer, so this token converts as a
|
||||||
@@ -1637,6 +1585,8 @@ scan_number_done:
|
|||||||
decimal_point_position = dot_index;
|
decimal_point_position = dot_index;
|
||||||
|
|
||||||
ia.bulk_skip(len - 1);
|
ia.bulk_skip(len - 1);
|
||||||
|
position.chars_read_total += (len - 1);
|
||||||
|
position.chars_read_current_line += (len - 1);
|
||||||
|
|
||||||
return convert_number(number_type, mantissa_end);
|
return convert_number(number_type, mantissa_end);
|
||||||
}
|
}
|
||||||
@@ -1687,7 +1637,7 @@ scan_number_done:
|
|||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
// the first character of the token has already been read, hence the -1
|
// the first character of the token has already been read, hence the -1
|
||||||
token_start_position = get_chars_read_total() - 1;
|
token_start_position = position.chars_read_total - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
note_token_start(std::integral_constant<bool, lazy_token_string> {});
|
note_token_start(std::integral_constant<bool, lazy_token_string> {});
|
||||||
@@ -1740,15 +1690,6 @@ scan_number_done:
|
|||||||
/// per-character position counters (line-count-on-'\n' bookkeeping is
|
/// per-character position counters (line-count-on-'\n' bookkeeping is
|
||||||
/// handled afterwards, in track_after_read(), once `current` is known)
|
/// handled afterwards, in track_after_read(), once `current` is known)
|
||||||
void advance_position() noexcept
|
void advance_position() noexcept
|
||||||
{
|
|
||||||
advance_position_impl(std::integral_constant<bool, lazy_position> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// seekable adapter: the position is derived from the adapter on demand
|
|
||||||
void advance_position_impl(std::true_type /*lazy*/) const noexcept {}
|
|
||||||
|
|
||||||
/// streaming adapter: count the character
|
|
||||||
void advance_position_impl(std::false_type /*lazy*/) noexcept
|
|
||||||
{
|
{
|
||||||
++position.chars_read_total;
|
++position.chars_read_total;
|
||||||
++position.chars_read_current_line;
|
++position.chars_read_current_line;
|
||||||
@@ -1762,16 +1703,7 @@ scan_number_done:
|
|||||||
// seekable adapters reconstruct the token lazily on error (see
|
// seekable adapters reconstruct the token lazily on error (see
|
||||||
// get_token_string), so the eager per-character copy is skipped
|
// get_token_string), so the eager per-character copy is skipped
|
||||||
capture_char(std::integral_constant<bool, lazy_token_string> {});
|
capture_char(std::integral_constant<bool, lazy_token_string> {});
|
||||||
track_newline(std::integral_constant<bool, lazy_position> {});
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// seekable adapter: lines are counted on demand in get_position()
|
|
||||||
void track_newline(std::true_type /*lazy*/) const noexcept {}
|
|
||||||
|
|
||||||
/// streaming adapter: start a new line after reading a newline
|
|
||||||
void track_newline(std::false_type /*lazy*/) noexcept
|
|
||||||
{
|
|
||||||
if (current == '\n')
|
if (current == '\n')
|
||||||
{
|
{
|
||||||
++position.lines_read;
|
++position.lines_read;
|
||||||
@@ -1780,6 +1712,8 @@ scan_number_done:
|
|||||||
chars_read_before_newline = position.chars_read_current_line;
|
chars_read_before_newline = position.chars_read_current_line;
|
||||||
position.chars_read_current_line = 0;
|
position.chars_read_current_line = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1823,22 +1757,12 @@ scan_number_done:
|
|||||||
We implement unget by setting variable next_unget to true. The input is not
|
We implement unget by setting variable next_unget to true. The input is not
|
||||||
changed - we just simulate ungetting by modifying chars_read_total,
|
changed - we just simulate ungetting by modifying chars_read_total,
|
||||||
chars_read_current_line, and token_string. The next call to get() will
|
chars_read_current_line, and token_string. The next call to get() will
|
||||||
behave as if the unget character is read again. With lazy_position, the
|
behave as if the unget character is read again.
|
||||||
pending next_unget is all get_chars_read_total() needs.
|
|
||||||
*/
|
*/
|
||||||
void unget()
|
void unget()
|
||||||
{
|
{
|
||||||
next_unget = true;
|
next_unget = true;
|
||||||
unget_position(std::integral_constant<bool, lazy_position> {});
|
|
||||||
uncapture_char(std::integral_constant<bool, lazy_token_string> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// seekable adapter: get_chars_read_total() accounts for next_unget
|
|
||||||
void unget_position(std::true_type /*lazy*/) const noexcept {}
|
|
||||||
|
|
||||||
/// streaming adapter: step the counters back over the ungotten character
|
|
||||||
void unget_position(std::false_type /*lazy*/) noexcept
|
|
||||||
{
|
|
||||||
--position.chars_read_total;
|
--position.chars_read_total;
|
||||||
|
|
||||||
// in case we "unget" a newline, we have to also decrement the lines_read
|
// in case we "unget" a newline, we have to also decrement the lines_read
|
||||||
@@ -1861,6 +1785,8 @@ scan_number_done:
|
|||||||
{
|
{
|
||||||
--position.chars_read_current_line;
|
--position.chars_read_current_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uncapture_char(std::integral_constant<bool, lazy_token_string> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// adapter without lookahead: nothing to do (see release_lookahead)
|
/// adapter without lookahead: nothing to do (see release_lookahead)
|
||||||
@@ -1931,21 +1857,10 @@ scan_number_done:
|
|||||||
// diagnostics
|
// diagnostics
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief return the number of characters read so far
|
|
||||||
|
|
||||||
Unlike get_position(), this is O(1) for all adapters, so it may be called
|
|
||||||
for every value (JSON_DIAGNOSTIC_POSITIONS).
|
|
||||||
*/
|
|
||||||
std::size_t get_chars_read_total() const noexcept
|
|
||||||
{
|
|
||||||
return get_chars_read_total_impl(std::integral_constant<bool, lazy_position> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// return position of last read token
|
/// return position of last read token
|
||||||
position_t get_position() const
|
constexpr position_t get_position() const noexcept
|
||||||
{
|
{
|
||||||
return get_position_impl(std::integral_constant<bool, lazy_position> {});
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1982,43 +1897,6 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
|
||||||
/// seekable adapter: every get() either read from the adapter (including
|
|
||||||
/// reads at EOF, which get() counts as characters as well) or replayed an
|
|
||||||
/// ungotten character, so the count is the adapter's read count minus a
|
|
||||||
/// still pending unget
|
|
||||||
std::size_t get_chars_read_total_impl(std::true_type /*lazy*/) const noexcept
|
|
||||||
{
|
|
||||||
return ia.get_read_count() - (next_unget ? 1u : 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// streaming adapter: the counter is maintained by get() and unget()
|
|
||||||
std::size_t get_chars_read_total_impl(std::false_type /*lazy*/) const noexcept
|
|
||||||
{
|
|
||||||
return position.chars_read_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// seekable adapter: count the lines in the consumed input; O(input read
|
|
||||||
/// so far), but only called on errors
|
|
||||||
position_t get_position_impl(std::true_type /*lazy*/) const
|
|
||||||
{
|
|
||||||
position_t result;
|
|
||||||
result.chars_read_total = get_chars_read_total();
|
|
||||||
// reads at EOF count as characters but are not part of the input
|
|
||||||
const std::size_t consumed = (std::min)(result.chars_read_total, ia.get_consumed_count());
|
|
||||||
std::size_t line_start = 0;
|
|
||||||
result.lines_read = ia.count_consumed_lines(consumed, line_start);
|
|
||||||
result.chars_read_current_line = result.chars_read_total - line_start;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// streaming adapter: the position is maintained by get() and unget()
|
|
||||||
position_t get_position_impl(std::false_type /*lazy*/) const noexcept
|
|
||||||
{
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// seekable adapter: rebuild the last read token from the input on demand
|
/// seekable adapter: rebuild the last read token from the input on demand
|
||||||
const std::vector<char_type>& collect_token_chars(std::vector<char_type>& out, std::true_type /*lazy*/) const
|
const std::vector<char_type>& collect_token_chars(std::vector<char_type>& out, std::true_type /*lazy*/) const
|
||||||
{
|
{
|
||||||
@@ -2126,57 +2004,15 @@ scan_number_done:
|
|||||||
// into one that reloads the pointer from memory every character
|
// into one that reloads the pointer from memory every character
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (current == '\n')
|
|
||||||
{
|
|
||||||
skip_indentation(std::integral_constant<bool, bulk_scan> {});
|
|
||||||
}
|
|
||||||
get_ignoring_pending_unget();
|
get_ignoring_pending_unget();
|
||||||
}
|
}
|
||||||
while (current_is_whitespace());
|
while (current_is_whitespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief contiguous input: skip the space indentation that follows a newline
|
|
||||||
8 bytes at a time
|
|
||||||
|
|
||||||
Pretty-printed JSON indents every line with a run of spaces, which the loop
|
|
||||||
in skip_whitespace() would otherwise read one character at a time. The
|
|
||||||
spaces are skipped 8 bytes at a time; the last 7 bytes of the input and any
|
|
||||||
other whitespace are left to that loop. Skipping bypasses get(), which is
|
|
||||||
fine because bulk_scan implies lazy_position: the position is derived from
|
|
||||||
the adapter, not counted per character.
|
|
||||||
*/
|
|
||||||
void skip_indentation(std::true_type /*bulk*/)
|
|
||||||
{
|
|
||||||
JSON_ASSERT(!next_unget);
|
|
||||||
const std::size_t remaining = ia.bulk_remaining();
|
|
||||||
if (remaining < 8)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const char* const data = reinterpret_cast<const char*>(ia.bulk_data());
|
|
||||||
std::size_t pos = 0;
|
|
||||||
for (; pos + 8 <= remaining; pos += 8)
|
|
||||||
{
|
|
||||||
// little-endian, so the first byte is the lowest
|
|
||||||
const std::uint64_t non_space = read_eight_bytes(data + pos) ^ 0x2020202020202020ull;
|
|
||||||
if (non_space != 0)
|
|
||||||
{
|
|
||||||
// skip the spaces before the first other byte of this word
|
|
||||||
pos += static_cast<std::size_t>(count_trailing_zeros(non_space)) / 8;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ia.bulk_skip(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// streaming input: no bulk fast path
|
|
||||||
void skip_indentation(std::false_type /*bulk*/) const noexcept {}
|
|
||||||
|
|
||||||
token_type scan()
|
token_type scan()
|
||||||
{
|
{
|
||||||
// initially, skip the BOM
|
// initially, skip the BOM
|
||||||
if (get_chars_read_total() == 0 && !skip_bom())
|
if (position.chars_read_total == 0 && !skip_bom())
|
||||||
{
|
{
|
||||||
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
|
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
@@ -2203,7 +2039,7 @@ scan_number_done:
|
|||||||
token_type scan_expecting(token_type expected_type)
|
token_type scan_expecting(token_type expected_type)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(expected_type == token_type::name_separator || expected_type == token_type::value_separator);
|
JSON_ASSERT(expected_type == token_type::name_separator || expected_type == token_type::value_separator);
|
||||||
JSON_ASSERT(get_chars_read_total() > 0);
|
JSON_ASSERT(position.chars_read_total > 0);
|
||||||
const char_int_type expected_char = static_cast<unsigned char>((expected_type == token_type::name_separator) ? ':' : ',');
|
const char_int_type expected_char = static_cast<unsigned char>((expected_type == token_type::name_separator) ? ':' : ',');
|
||||||
skip_whitespace();
|
skip_whitespace();
|
||||||
if (JSON_HEDLEY_LIKELY(current == expected_char))
|
if (JSON_HEDLEY_LIKELY(current == expected_char))
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 182 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user