mirror of
https://github.com/nlohmann/json.git
synced 2026-10-12 10:13:13 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8418ff85b6 |
@@ -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.
|
||||||
|
|
||||||
|
|||||||
+14
-16
@@ -98,7 +98,7 @@ $ ctest --test-dir build -j 10
|
|||||||
The test suite should report:
|
The test suite should report:
|
||||||
|
|
||||||
```
|
```
|
||||||
100% tests passed, 0 tests failed out of <number of tests>
|
100% tests passed, 0 tests failed out of 98
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Add tests
|
#### Add tests
|
||||||
@@ -149,17 +149,14 @@ make build -C docs/mkdocs # strict build: fails on broken links, anchor
|
|||||||
make check_mermaid -C docs/mkdocs # checks the Mermaid diagrams (requires Node.js)
|
make check_mermaid -C docs/mkdocs # checks the Mermaid diagrams (requires Node.js)
|
||||||
```
|
```
|
||||||
|
|
||||||
The search index of the docset is generated from [`mkdocs.yml`](https://github.com/nlohmann/json/blob/develop/docs/mkdocs/mkdocs.yml)
|
A new API page also needs an entry in [`docs/docset/docSet.sql`](https://github.com/nlohmann/json/blob/develop/docs/docset/docSet.sql),
|
||||||
and each page's title (H1) and declaration by
|
the search index of the docset; `make build` reports missing entries.
|
||||||
[`docs/docset/generate_docset.py`](https://github.com/nlohmann/json/blob/develop/docs/docset/generate_docset.py);
|
|
||||||
`make build` reports API pages that cannot be classified.
|
|
||||||
|
|
||||||
### Amalgamate the source code
|
### Amalgamate the source code
|
||||||
|
|
||||||
The single-header files
|
The single-header files
|
||||||
[`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp),
|
[`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) and
|
||||||
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp), and
|
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
||||||
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
|
|
||||||
are **generated** from the source files in the
|
are **generated** from the source files in the
|
||||||
[`include/nlohmann` directory](https://github.com/nlohmann/json/tree/develop/include/nlohmann). **Do not** edit the
|
[`include/nlohmann` directory](https://github.com/nlohmann/json/tree/develop/include/nlohmann). **Do not** edit the
|
||||||
files directly; instead, modify the include/nlohmann sources and regenerate the files by executing:
|
files directly; instead, modify the include/nlohmann sources and regenerate the files by executing:
|
||||||
@@ -182,7 +179,7 @@ The amalgamation check in CI fails if any of these generated files is out of dat
|
|||||||
|
|
||||||
## Recommended documentation
|
## Recommended documentation
|
||||||
|
|
||||||
- The library’s [README file](https://github.com/nlohmann/json/blob/develop/README.md) is an excellent starting point to
|
- The library’s [README file](https://github.com/nlohmann/json/blob/master/README.md) is an excellent starting point to
|
||||||
understand its functionality.
|
understand its functionality.
|
||||||
- The [documentation page](https://json.nlohmann.me) is the reference documentation of the library.
|
- The [documentation page](https://json.nlohmann.me) is the reference documentation of the library.
|
||||||
- [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) is the reference for the JavaScript Object Notation (JSON)
|
- [RFC 8259](https://datatracker.ietf.org/doc/html/rfc8259) is the reference for the JavaScript Object Notation (JSON)
|
||||||
@@ -221,9 +218,9 @@ feature macros then allows users to test their code against the library in the n
|
|||||||
### Break C++11 language conformance
|
### Break C++11 language conformance
|
||||||
|
|
||||||
This library is designed to work with C++11 and later. This means that any
|
This library is designed to work with C++11 and later. This means that any
|
||||||
[supported C++11 compiler](https://github.com/nlohmann/json/blob/develop/README.md#supported-compilers) should compile
|
[supported C++11 compiler](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers) should compile
|
||||||
the library without problems. Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual
|
the library without problems. Some compilers like GCC 4.7 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual
|
||||||
C++ 2013 and earlier are known not to work due to missing or incomplete C++11 support.
|
Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support.
|
||||||
|
|
||||||
Please do not add features that do not work with the mentioned supported compilers. Please guard features from C++14 and
|
Please do not add features that do not work with the mentioned supported compilers. Please guard features from C++14 and
|
||||||
later against the respective [`JSON_HAS_CPP_14`](https://json.nlohmann.me/api/macros/json_has_cpp_11/) macros.
|
later against the respective [`JSON_HAS_CPP_14`](https://json.nlohmann.me/api/macros/json_has_cpp_11/) macros.
|
||||||
@@ -239,11 +236,12 @@ extension.
|
|||||||
The following areas really need contribution and are always welcomed:
|
The following areas really need contribution and are always welcomed:
|
||||||
|
|
||||||
- Extending the **continuous integration** toward more exotic compilers such as Android NDK, Intel's Compiler, or the
|
- Extending the **continuous integration** toward more exotic compilers such as Android NDK, Intel's Compiler, or the
|
||||||
bleeding-edge versions of Clang.
|
bleeding-edge versions Clang.
|
||||||
- Improving the efficiency of the **JSON parser**. The current parser is a hand-written iterative parser that keeps an
|
- Improving the efficiency of the **JSON parser**. The current parser is implemented as a naive recursive descent parser
|
||||||
explicit stack instead of recursing, with hand-coded string handling. Speeding up the lexer or the value construction
|
with hand-coded string handling. More sophisticated approaches like LALR parsers would be really appreciated. That
|
||||||
would be appreciated. Parser generators like Bison or ANTLR do not play nice with single-header files -- I really
|
said, parser generators like Bison or ANTLR do not play nice with single-header files -- I really would like to keep
|
||||||
would like to keep the parser inside the `json.hpp` header.
|
the parser inside the `json.hpp` header, and I am not aware of approaches similar to [`re2c`](http://re2c.org) for
|
||||||
|
parsing.
|
||||||
- Extending and updating existing **benchmarks** to include (the most recent version of) this library. Though efficiency
|
- Extending and updating existing **benchmarks** to include (the most recent version of) this library. Though efficiency
|
||||||
is not everything, speed and memory consumption are very important characteristics for C++ developers, so having
|
is not everything, speed and memory consumption are very important characteristics for C++ developers, so having
|
||||||
proper comparisons would be interesting.
|
proper comparisons would be interesting.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -166,13 +166,6 @@ jobs:
|
|||||||
# link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash
|
# link, but the binaries clang 11.0.1 and clang 18.1.8 then produce crash
|
||||||
# before doctest prints its first line - 39 of 102 tests on clang 18.
|
# before doctest prints its first line - 39 of 102 tests on clang 18.
|
||||||
# Keep the objects small by splitting the test files instead.
|
# Keep the objects small by splitting the test files instead.
|
||||||
# Objects with more than 65535 sections fail to link with "relocation
|
|
||||||
# truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata'": the MinGW
|
|
||||||
# linker stores the section an associative COMDAT section belongs to in
|
|
||||||
# 16 bits (x_associated in binutils' include/coff/internal.h), so it
|
|
||||||
# discards the jump tables of inline functions together with the wrong
|
|
||||||
# function. Each basic_json specialization a test file instantiates adds
|
|
||||||
# many sections, so test a second one in a file of its own.
|
|
||||||
- name: Run CMake
|
- name: Run CMake
|
||||||
run: cmake -S . -B build ^
|
run: cmake -S . -B build ^
|
||||||
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
|
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
|
||||||
@@ -187,7 +180,7 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: cd build ; ctest -j 10 -C Debug --output-on-failure
|
run: cd build ; ctest -j 10 -C Debug --output-on-failure
|
||||||
|
|
||||||
clang-cl:
|
clang-cl-12:
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -217,10 +210,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
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ cc_library(
|
|||||||
"include/nlohmann/detail/conversions/from_json.hpp",
|
"include/nlohmann/detail/conversions/from_json.hpp",
|
||||||
"include/nlohmann/detail/conversions/to_chars.hpp",
|
"include/nlohmann/detail/conversions/to_chars.hpp",
|
||||||
"include/nlohmann/detail/conversions/to_json.hpp",
|
"include/nlohmann/detail/conversions/to_json.hpp",
|
||||||
"include/nlohmann/detail/conversions/zmij.hpp",
|
|
||||||
"include/nlohmann/detail/exceptions.hpp",
|
"include/nlohmann/detail/exceptions.hpp",
|
||||||
"include/nlohmann/detail/hash.hpp",
|
"include/nlohmann/detail/hash.hpp",
|
||||||
"include/nlohmann/detail/input/binary_reader.hpp",
|
"include/nlohmann/detail/input/binary_reader.hpp",
|
||||||
@@ -82,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.
|
||||||
|
|
||||||
@@ -1385,10 +1394,9 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
|||||||
|
|
||||||
- The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
|
- The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
|
||||||
- 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 port of the shortest double-to-decimal conversion of [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich, including the conversion of the digits to text by Xiang JunBo and the SIMD instruction sequence of Dougall Johnson, which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2025 [Victor Zverovich](https://github.com/vitaut)
|
|
||||||
- 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">
|
||||||
|
|
||||||
@@ -1429,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.
|
||||||
|
|
||||||
@@ -1851,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
|
||||||
@@ -1966,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.
|
||||||
@@ -1980,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"
|
|
||||||
|
|||||||
+17
-14
@@ -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"
|
||||||
)
|
)
|
||||||
@@ -718,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})
|
||||||
@@ -775,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}"
|
||||||
@@ -796,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"
|
||||||
@@ -818,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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|||||||
@@ -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"],
|
||||||
|
|||||||
+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.
|
|
||||||
|
|||||||
@@ -64,7 +64,18 @@ values of that type directly to a `basic_json` instance, and they will automatic
|
|||||||
rather than arrays:
|
rather than arrays:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
using custom_json = nlohmann::ordered_json::with_binary_t<std::vector<std::byte>>;
|
using custom_json = nlohmann::basic_json<
|
||||||
|
nlohmann::ordered_map, // ObjectType
|
||||||
|
std::vector, // ArrayType
|
||||||
|
std::string, // StringType
|
||||||
|
bool, // BooleanType
|
||||||
|
std::int64_t, // NumberIntegerType
|
||||||
|
std::uint64_t, // NumberUnsignedType
|
||||||
|
double, // NumberFloatType
|
||||||
|
std::allocator, // AllocatorType
|
||||||
|
nlohmann::adl_serializer,
|
||||||
|
std::vector<std::byte> // Custom BinaryType
|
||||||
|
>;
|
||||||
|
|
||||||
std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}};
|
std::vector<std::byte> data{std::byte{1}, std::byte{2}, std::byte{3}};
|
||||||
custom_json j = data; // Creates a binary value, not an array
|
custom_json j = data; // Creates a binary value, not an array
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,6 @@ Linear.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
Floating-point numbers are written with the fewest digits that read back as the same value (for `#!cpp double`; see
|
|
||||||
[number handling](../../features/types/number_handling.md#number-serialization)).
|
|
||||||
|
|
||||||
Binary values are serialized as an object containing two keys:
|
Binary values are serialized as an object containing two keys:
|
||||||
|
|
||||||
- "bytes": an array of bytes as integers
|
- "bytes": an array of bytes as integers
|
||||||
@@ -100,5 +97,3 @@ Binary values are serialized as an object containing two keys:
|
|||||||
- Error handlers added in version 3.4.0.
|
- Error handlers added in version 3.4.0.
|
||||||
- Serialization of binary values added in version 3.8.0.
|
- Serialization of binary values added in version 3.8.0.
|
||||||
- Error handler `keep` added in version 3.13.0.
|
- Error handler `keep` added in version 3.13.0.
|
||||||
- Doubles are written with the shortest digits (Żmij instead of Grisu2) since version 3.13.0; about 0.1% of doubles are
|
|
||||||
written differently, most of them with fewer digits.
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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.
|
|
||||||
|
|||||||
@@ -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.
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ By default, implicit conversions are enabled.
|
|||||||
`JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`:
|
`JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
using wjson = nlohmann::json::with_string_t<std::wstring>;
|
using wjson = nlohmann::basic_json<std::map, std::vector, std::wstring>;
|
||||||
|
|
||||||
void load(const nlohmann::json& j);
|
void load(const nlohmann::json& j);
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,19 @@ class base_class_with_hidden_members
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using json = nlohmann::json::with_base_class_t<base_class_with_hidden_members>;
|
using json = nlohmann::basic_json <
|
||||||
|
std::map,
|
||||||
|
std::vector,
|
||||||
|
std::string,
|
||||||
|
bool,
|
||||||
|
std::int64_t,
|
||||||
|
std::uint64_t,
|
||||||
|
double,
|
||||||
|
std::allocator,
|
||||||
|
nlohmann::adl_serializer,
|
||||||
|
std::vector<std::uint8_t>,
|
||||||
|
base_class_with_hidden_members
|
||||||
|
>;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,9 +19,25 @@ int main()
|
|||||||
<< j.contains("/array/1"_json_pointer) << '\n'
|
<< j.contains("/array/1"_json_pointer) << '\n'
|
||||||
<< j.contains("/array/-"_json_pointer) << '\n'
|
<< j.contains("/array/-"_json_pointer) << '\n'
|
||||||
<< j.contains("/array/4"_json_pointer) << '\n'
|
<< j.contains("/array/4"_json_pointer) << '\n'
|
||||||
<< j.contains("/baz"_json_pointer) << '\n'
|
<< j.contains("/baz"_json_pointer) << std::endl;
|
||||||
// an array index with a leading '0' is not found
|
|
||||||
<< j.contains("/array/01"_json_pointer) << '\n'
|
try
|
||||||
// an array index that is not a number is not found
|
{
|
||||||
<< j.contains("/array/one"_json_pointer) << std::endl;
|
// try to use an array index with leading '0'
|
||||||
|
j.contains("/array/01"_json_pointer);
|
||||||
|
}
|
||||||
|
catch (const json::parse_error& e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// try to use an array index that is not a number
|
||||||
|
j.contains("/array/one"_json_pointer);
|
||||||
|
}
|
||||||
|
catch (const json::parse_error& e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,3 @@ true
|
|||||||
false
|
false
|
||||||
false
|
false
|
||||||
false
|
false
|
||||||
false
|
|
||||||
false
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "custom_array_type.hpp"
|
#include "custom_array_type.hpp"
|
||||||
|
|
||||||
using custom_json = nlohmann::json::with_array_t<custom_array_type>;
|
using custom_json = nlohmann::basic_json<std::map, custom_array_type>;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "custom_binary_type.hpp"
|
#include "custom_binary_type.hpp"
|
||||||
|
|
||||||
using custom_json = nlohmann::json::with_binary_t<custom_binary_type>;
|
using custom_json = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||||
|
std::int64_t, std::uint64_t, double, std::allocator,
|
||||||
|
nlohmann::adl_serializer, custom_binary_type>;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "custom_object_type.hpp"
|
#include "custom_object_type.hpp"
|
||||||
|
|
||||||
using custom_json = nlohmann::json::with_object_t<custom_object_type>;
|
using custom_json = nlohmann::basic_json<custom_object_type, std::vector>;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "custom_string_type.hpp"
|
#include "custom_string_type.hpp"
|
||||||
|
|
||||||
using custom_json = nlohmann::json::with_string_t<custom_string_type>;
|
using custom_json = nlohmann::basic_json<std::map, std::vector, custom_string_type>;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ int main()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// parsing input with a syntax error
|
// parsing input with a syntax error
|
||||||
json j = json::parse("[1,2,3,]");
|
json::parse("[1,2,3,]");
|
||||||
}
|
}
|
||||||
catch (const json::parse_error& e)
|
catch (const json::parse_error& e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,13 +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.
|
||||||
|
|
||||||
!!! 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.
|
||||||
@@ -35,4 +28,3 @@ easier to read and write for object-shaped documents.
|
|||||||
- [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 [`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;`.
|
||||||
@@ -134,10 +133,9 @@ That is, `-0` is stored as a signed integer, but the serialization does not repr
|
|||||||
### Number serialization
|
### Number serialization
|
||||||
|
|
||||||
- Integer numbers are serialized as is; that is, no scientific notation is used.
|
- Integer numbers are serialized as is; that is, no scientific notation is used.
|
||||||
- Floating-point numbers are serialized with the fewest digits that read back as the same value (the closest such
|
- Floating-point numbers are serialized as specified by the `#!c %g` printf modifier with
|
||||||
digits if there are several), in the layout of the `#!c %g` printf modifier: `#!c 1.5`, `#!c 100.0`, `#!c 1e+100`.
|
[`std::numeric_limits<double>::max_digits10`](https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10)
|
||||||
Doubles are converted with the algorithm of [Żmij](https://github.com/vitaut/zmij), floats with Grisu2, which
|
significant digits. The rationale is to use the shortest representation while still allowing round-tripping.
|
||||||
can write more digits than necessary.
|
|
||||||
|
|
||||||
!!! hint "Notes regarding precision of floating-point numbers"
|
!!! hint "Notes regarding precision of floating-point numbers"
|
||||||
|
|
||||||
@@ -353,8 +351,9 @@ The number types can be changed with template parameters.
|
|||||||
|
|
||||||
A `basic_json` type that uses `#!c long double` as floating-point type.
|
A `basic_json` type that uses `#!c long double` as floating-point type.
|
||||||
|
|
||||||
```cpp hl_lines="1"
|
```cpp hl_lines="2"
|
||||||
using json_ld = nlohmann::json::with_float_t<long double>;
|
using json_ld = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||||
|
std::int64_t, std::uint64_t, long double>;
|
||||||
```
|
```
|
||||||
|
|
||||||
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse
|
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ these requirements so they do not have to be discovered by trial and error. Each
|
|||||||
that are known to work for that parameter and the ones that do not, checked against Boost 1.83, Abseil 20250127.0,
|
that are known to work for that parameter and the ones that do not, checked against Boost 1.83, Abseil 20250127.0,
|
||||||
Folly, EASTL 3.21, `ankerl::unordered_dense`, `phmap`, `gtl`, `robin_hood`, `tsl::ordered_map`, and Qt 6.
|
Folly, EASTL 3.21, `ankerl::unordered_dense`, `phmap`, `gtl`, `robin_hood`, `tsl::ordered_map`, and Qt 6.
|
||||||
|
|
||||||
To change a single template parameter and keep the others, use the member alias templates
|
|
||||||
[`with_*_t`](../../api/basic_json/with_t.md); for instance, `nlohmann::json::with_float_t<long double>` is `json` with
|
|
||||||
`#!cpp long double` as [`number_float_t`](../../api/basic_json/number_float_t.md).
|
|
||||||
|
|
||||||
## How to read this page
|
## How to read this page
|
||||||
|
|
||||||
Requirements are split into two groups:
|
Requirements are split into two groups:
|
||||||
@@ -30,9 +26,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
|
||||||
@@ -147,7 +143,7 @@ struct unordered_map_object
|
|||||||
using base_t::base_t;
|
using base_t::base_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
using unordered_json = nlohmann::json::with_object_t<unordered_map_object>;
|
using unordered_json = nlohmann::basic_json<unordered_map_object>;
|
||||||
```
|
```
|
||||||
|
|
||||||
Whether `#!cpp std::unordered_map` can be instantiated at all depends on the standard library: `object_t` is formed
|
Whether `#!cpp std::unordered_map` can be instantiated at all depends on the standard library: `object_t` is formed
|
||||||
@@ -180,7 +176,7 @@ struct flat_hash_object
|
|||||||
using base_t::base_t;
|
using base_t::base_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
using flat_hash_json = nlohmann::json::with_object_t<flat_hash_object>;
|
using flat_hash_json = nlohmann::basic_json<flat_hash_object>;
|
||||||
```
|
```
|
||||||
|
|
||||||
`absl::node_hash_map` keeps references to the mapped values valid across insertions; `absl::flat_hash_map` does not,
|
`absl::node_hash_map` keeps references to the mapped values valid across insertions; `absl::flat_hash_map` does not,
|
||||||
@@ -353,21 +349,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,18 +537,16 @@ 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`).
|
||||||
|
|
||||||
If `#!cpp std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary64 number, `dump` uses the algorithm of
|
If `#!cpp std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary32 or binary64 number, `dump` uses the
|
||||||
Żmij, which produces the shortest representation that round-trips. For IEEE 754 binary32 numbers, it uses Grisu2,
|
Grisu2 algorithm, which produces the shortest representation that round-trips. Otherwise the `snprintf` fallback with
|
||||||
which produces a short representation that round-trips. Otherwise the `snprintf` fallback with `max_digits10` digits is
|
`max_digits10` digits is used.
|
||||||
used.
|
|
||||||
|
|
||||||
### Required for the binary formats
|
### Required for the binary formats
|
||||||
|
|
||||||
@@ -569,7 +558,7 @@ binary32 or binary64 field and have no encoding for `#!cpp long double`.
|
|||||||
|
|
||||||
| Type | Support |
|
| Type | Support |
|
||||||
|--------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
|--------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
||||||
| `#!cpp double` (default) | full; shortest round-trip output through Żmij |
|
| `#!cpp double` (default) | full; short round-trip output through Grisu2 |
|
||||||
| `#!cpp float` | full; short round-trip output through Grisu2 |
|
| `#!cpp float` | full; short round-trip output through Grisu2 |
|
||||||
| `#!cpp long double` | `dump` and `parse` only; the binary format writers do not compile, as they only handle IEEE 754 binary32 and binary64 |
|
| `#!cpp long double` | `dump` and `parse` only; the binary format writers do not compile, as they only handle IEEE 754 binary32 and binary64 |
|
||||||
| any other type | not usable |
|
| any other type | not usable |
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed und
|
|||||||
|
|
||||||
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 port of the shortest double-to-decimal conversion of [Żmij](https://github.com/vitaut/zmij) by Victor Zverovich, including the conversion of the digits to text by Xiang JunBo and the SIMD instruction sequence of Dougall Johnson, which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2025 [Victor Zverovich](https://github.com/vitaut)
|
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ function to use instead.
|
|||||||
=== "Deprecated"
|
=== "Deprecated"
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
using my_json = nlohmann::json::with_string_t<my_string_type>;
|
using my_json = nlohmann::basic_json<std::map, std::vector, my_string_type>;
|
||||||
nlohmann::json_pointer<my_json> ptr("/foo/bar/1");
|
nlohmann::json_pointer<my_json> ptr("/foo/bar/1");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -299,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,16 +9,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint64_t
|
#include <cstdint> // uint64_t
|
||||||
#include <cstring> // memcpy
|
|
||||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) && (!defined(__SIZEOF_INT128__) || (!defined(__GNUC__) && !defined(__clang__)))
|
|
||||||
#include <intrin0.h> // __umulh, _umul128, _BitScanForward64, _BitScanReverse64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp> // JSON_HEDLEY_ALWAYS_INLINE, NLOHMANN_JSON_NAMESPACE_BEGIN
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
// Portable bit-level helpers for the number and string scanners. They use
|
// Portable bit-level helpers for the number and string scanners. They use
|
||||||
// compiler builtins or platform-specific intrinsics where available and plain
|
// compiler builtins where available and plain C++ otherwise, so they need no
|
||||||
// C++ otherwise, so they work regardless of byte order.
|
// platform headers and work regardless of byte order.
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -29,10 +25,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 +39,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
|
||||||
{
|
{
|
||||||
@@ -83,12 +52,6 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
|||||||
__extension__ using uint128 = unsigned __int128;
|
__extension__ using uint128 = unsigned __int128;
|
||||||
const uint128 r = static_cast<uint128>(a) * b;
|
const uint128 r = static_cast<uint128>(a) * b;
|
||||||
return {static_cast<std::uint64_t>(r), static_cast<std::uint64_t>(r >> 64u)};
|
return {static_cast<std::uint64_t>(r), static_cast<std::uint64_t>(r >> 64u)};
|
||||||
#elif defined(_MSC_VER) && defined(_M_X64)
|
|
||||||
std::uint64_t high = 0;
|
|
||||||
const std::uint64_t low = _umul128(a, b, &high);
|
|
||||||
return {low, high};
|
|
||||||
#elif defined(_MSC_VER) && defined(_M_ARM64)
|
|
||||||
return {a * b, __umulh(a, b)};
|
|
||||||
#else
|
#else
|
||||||
const std::uint64_t a_lo = a & 0xFFFFFFFFu;
|
const std::uint64_t a_lo = a & 0xFFFFFFFFu;
|
||||||
const std::uint64_t a_hi = a >> 32u;
|
const std::uint64_t a_hi = a >> 32u;
|
||||||
@@ -103,27 +66,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
|
/// eight bytes as a little-endian word (compilers fold this into one load on
|
||||||
/// targets; always inlined, as GCC otherwise calls it in the number loops)
|
/// little-endian targets)
|
||||||
JSON_HEDLEY_ALWAYS_INLINE std::uint64_t read_eight_bytes(const unsigned char* b) noexcept
|
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
|
|
||||||
JSON_HEDLEY_ALWAYS_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
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
//
|
//
|
||||||
// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
|
// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
|
||||||
// SPDX-FileCopyrightText: 2025 Victor Zverovich <https://github.com/vitaut/zmij>
|
|
||||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
@@ -12,32 +11,11 @@
|
|||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cmath> // signbit, isfinite
|
#include <cmath> // signbit, isfinite
|
||||||
#include <cstddef> // size_t
|
|
||||||
#include <cstdint> // intN_t, uintN_t
|
#include <cstdint> // intN_t, uintN_t
|
||||||
#include <cstring> // memcpy, memmove
|
#include <cstring> // memcpy, memmove
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <type_traits> // conditional
|
#include <type_traits> // conditional
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <cstdlib> // _byteswap_uint64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// SSE2 (every x86-64 CPU) and NEON (every 64-bit Arm CPU) convert the 16
|
|
||||||
// digits of a double at once
|
|
||||||
#if defined(__x86_64__) || (defined(_M_X64) && !defined(_M_ARM64EC))
|
|
||||||
#include <emmintrin.h>
|
|
||||||
#define JSON_DTOA_SSE2 1
|
|
||||||
#define JSON_DTOA_NEON 0
|
|
||||||
#elif (defined(__aarch64__) || defined(_M_ARM64)) && !defined(_M_ARM64EC) && !defined(__ARM_BIG_ENDIAN)
|
|
||||||
#include <arm_neon.h>
|
|
||||||
#define JSON_DTOA_SSE2 0
|
|
||||||
#define JSON_DTOA_NEON 1
|
|
||||||
#else
|
|
||||||
#define JSON_DTOA_SSE2 0
|
|
||||||
#define JSON_DTOA_NEON 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <nlohmann/detail/conversions/zmij.hpp>
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
@@ -1069,381 +1047,6 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
|||||||
return append_exponent(buf, n - 1);
|
return append_exponent(buf, n - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// eight decimal digits (a value below 10^8) as bytes 0..9, the first digit
|
|
||||||
/// in the most significant byte: three steps that divide all lanes at once
|
|
||||||
/// by a multiplication (the conversion of Xiang JunBo, as in Zmij)
|
|
||||||
inline std::uint64_t eight_digit_bytes(std::uint64_t abcdefgh) noexcept
|
|
||||||
{
|
|
||||||
const std::uint64_t abcd_efgh = abcdefgh + (((std::uint64_t{1} << 32u) - 10000u) * ((abcdefgh * (((std::uint64_t{1} << 40u) / 10000u) + 1u)) >> 40u));
|
|
||||||
const std::uint64_t ab_cd_ef_gh = abcd_efgh + (((std::uint64_t{1} << 16u) - 100u) * (((abcd_efgh * (((std::uint64_t{1} << 19u) / 100u) + 1u)) >> 19u) & 0x7F0000007Fu));
|
|
||||||
return ab_cd_ef_gh + (((std::uint64_t{1} << 8u) - 10u) * (((ab_cd_ef_gh * (((std::uint64_t{1} << 10u) / 10u) + 1u)) >> 10u) & 0x000F000F000F000Fu));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// store the bytes of v, the most significant one first (one byte swap and
|
|
||||||
/// one store where the byte order is known: compilers do not reliably merge
|
|
||||||
/// the byte stores once this is inlined)
|
|
||||||
inline void store_msb_first(char* p, std::uint64_t v) noexcept
|
|
||||||
{
|
|
||||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
||||||
v = __builtin_bswap64(v);
|
|
||||||
std::memcpy(p, &v, sizeof(v));
|
|
||||||
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
||||||
std::memcpy(p, &v, sizeof(v));
|
|
||||||
#elif defined(_MSC_VER) // (little-endian on all its targets)
|
|
||||||
v = _byteswap_uint64(v);
|
|
||||||
std::memcpy(p, &v, sizeof(v));
|
|
||||||
#else
|
|
||||||
for (unsigned i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
p[i] = static_cast<char>(v >> (56u - (8u * i)));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief digits * 10^exp for a double, in the layout of format_buffer()
|
|
||||||
|
|
||||||
The layout is that of format_buffer() with min_exp -4 and max_exp 15 (the
|
|
||||||
digits10 of double). The digits are converted eight at a time and placed
|
|
||||||
with fixed-size moves instead of per-digit loops and moves of the buffer.
|
|
||||||
|
|
||||||
@param[in] digits the digits (not 0, at most 17 digits; trailing zeros allowed)
|
|
||||||
@param[in] exp the decimal exponent of the last digit
|
|
||||||
@return a pointer past the text; up to 41 bytes at @a first are written
|
|
||||||
(some beyond the returned end)
|
|
||||||
*/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
inline char* write_decimal(char* first, std::uint64_t digits, int exp) noexcept
|
|
||||||
{
|
|
||||||
JSON_ASSERT(digits != 0 && digits < 100000000000000000u);
|
|
||||||
const std::uint64_t upper = digits / 100000000u;
|
|
||||||
const std::uint64_t b0 = upper / 100000000u; // (one digit: it is its own byte)
|
|
||||||
const std::uint64_t b1 = eight_digit_bytes(upper % 100000000u);
|
|
||||||
const std::uint64_t b2 = eight_digit_bytes(digits % 100000000u);
|
|
||||||
// leading and trailing zero digits: zero bytes, counted without division
|
|
||||||
int leading = 16;
|
|
||||||
int zeros = 16;
|
|
||||||
if (b0 != 0)
|
|
||||||
{
|
|
||||||
leading = count_leading_zeros(b0) / 8;
|
|
||||||
}
|
|
||||||
else if (b1 != 0)
|
|
||||||
{
|
|
||||||
leading = 8 + (count_leading_zeros(b1) / 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
leading += count_leading_zeros(b2) / 8;
|
|
||||||
}
|
|
||||||
if (b2 != 0)
|
|
||||||
{
|
|
||||||
zeros = count_trailing_zeros(b2) / 8;
|
|
||||||
}
|
|
||||||
else if (b1 != 0)
|
|
||||||
{
|
|
||||||
zeros = 8 + (count_trailing_zeros(b1) / 8);
|
|
||||||
}
|
|
||||||
// (else: 16, b0 is the one digit that is not 0)
|
|
||||||
// the digits as text at text + leading, then '0's, so that fixed-size
|
|
||||||
// moves need not check how many digits there are
|
|
||||||
std::array<char, 64> text; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init): written before read
|
|
||||||
store_msb_first(text.data(), b0 + 0x3030303030303030u);
|
|
||||||
store_msb_first(text.data() + 8, b1 + 0x3030303030303030u);
|
|
||||||
store_msb_first(text.data() + 16, b2 + 0x3030303030303030u);
|
|
||||||
std::memset(text.data() + 24, '0', 40);
|
|
||||||
const int k = 24 - leading - zeros; // significant digits
|
|
||||||
const int n = k + exp + zeros; // position of the decimal point after the first digit
|
|
||||||
const char* const s0 = text.data() + leading;
|
|
||||||
|
|
||||||
if (-4 < n && n <= 15)
|
|
||||||
{
|
|
||||||
// "0.[000]digits" (n <= 0) is the digits after 1 - n leading '0's
|
|
||||||
// with the point after the first; "digits[000].0" (n >= k) and
|
|
||||||
// "dig.its" put the point after n characters
|
|
||||||
const int pad = n <= 0 ? 1 - n : 0;
|
|
||||||
const char* const s = s0 - pad;
|
|
||||||
const int len = k + pad;
|
|
||||||
const int point = n + pad;
|
|
||||||
std::memcpy(first, s, 16);
|
|
||||||
std::memcpy(first + point + 1, s + point, 24);
|
|
||||||
first[point] = '.';
|
|
||||||
return first + (point >= len ? point + 2 : len + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// d.igitse+XX, with at least two exponent digits (as append_exponent())
|
|
||||||
std::memcpy(first, s0, 16);
|
|
||||||
std::memcpy(first + 2, s0 + 1, 16);
|
|
||||||
first[1] = '.';
|
|
||||||
char* const end = first + (k == 1 ? 1 : k + 1);
|
|
||||||
const int e = n - 1;
|
|
||||||
const auto ea = e < 0 ? 0u - static_cast<unsigned>(e) : static_cast<unsigned>(e); // (unsigned: no signed overflow to assume)
|
|
||||||
const bool three = ea >= 100;
|
|
||||||
end[0] = 'e';
|
|
||||||
end[1] = e < 0 ? '-' : '+';
|
|
||||||
end[2] = static_cast<char>('0' + (three ? ea / 100 : (ea / 10) % 10));
|
|
||||||
end[3] = static_cast<char>('0' + (three ? (ea / 10) % 10 : ea % 10));
|
|
||||||
end[4] = static_cast<char>('0' + (ea % 10));
|
|
||||||
return end + (three ? 5 : 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief the shortest decimal of a positive double (Zmij), as write_decimal()
|
|
||||||
writes it
|
|
||||||
|
|
||||||
For a normal double, the shorter candidate has 15 or 16 digits: they are
|
|
||||||
converted at once (two halves of eight digits) and followed by the digit
|
|
||||||
after them, if there is one, without the multiplication and division by 10
|
|
||||||
that counting the digits of one number would take. The fixed layouts move
|
|
||||||
the digits after the point by one byte.
|
|
||||||
|
|
||||||
@return a pointer past the text; up to 41 bytes at @a first are written
|
|
||||||
(some beyond the returned end)
|
|
||||||
*/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
inline char* write_shortest(char* first, const zmij::shortest_decimal d) noexcept
|
|
||||||
{
|
|
||||||
const std::uint64_t sig = d.integral;
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(sig < 100000000000000u || sig >= 10000000000000000u))
|
|
||||||
{
|
|
||||||
// (subnormals)
|
|
||||||
return d.has_digit ? write_decimal(first, (sig * 10) + d.digit, d.exponent) : write_decimal(first, sig, d.exponent + 1);
|
|
||||||
}
|
|
||||||
const bool sixteen = sig >= 1000000000000000u; // (else 15 digits)
|
|
||||||
const int last = d.has_digit ? d.digit : 0;
|
|
||||||
const std::uint64_t upper = sig / 100000000u;
|
|
||||||
#if JSON_DTOA_SSE2
|
|
||||||
// NOLINTBEGIN(portability-simd-intrinsics)
|
|
||||||
// the two halves in the 64-bit lanes, each as abcd * 2^32 + efgh, then as
|
|
||||||
// bytes (as eight_digit_bytes(), one lane each)
|
|
||||||
const __m128i x = _mm_set_epi64x(static_cast<long long>(sig - (upper * 100000000u)), static_cast<long long>(upper)); // NOLINT(runtime/int)
|
|
||||||
const __m128i abcd = _mm_srli_epi64(_mm_mul_epu32(x, _mm_set1_epi64x(109951163)), 40); // 2^40 / 10000 + 1
|
|
||||||
const __m128i abcd_efgh = _mm_add_epi64(x, _mm_mul_epu32(abcd, _mm_set1_epi64x(4294957296))); // 2^32 - 10000
|
|
||||||
// 32-bit lanes in the order of the text: abcd, efgh of both halves
|
|
||||||
const __m128i fours = _mm_shuffle_epi32(abcd_efgh, _MM_SHUFFLE(2, 3, 0, 1));
|
|
||||||
const __m128i ab = _mm_srli_epi16(_mm_mulhi_epu16(fours, _mm_set1_epi32(5243)), 3);
|
|
||||||
const __m128i ab_cd = _mm_or_si128(_mm_slli_epi32(_mm_sub_epi16(fours, _mm_mullo_epi16(ab, _mm_set1_epi32(100))), 16), ab);
|
|
||||||
// 16-bit lanes ab (< 100) -> bytes a, b: 256 * ab - 2559 * (ab / 10)
|
|
||||||
const __m128i bytes = _mm_sub_epi16(_mm_slli_epi16(ab_cd, 8), _mm_mullo_epi16(_mm_set1_epi16(2559), _mm_mulhi_epu16(ab_cd, _mm_set1_epi16(6554))));
|
|
||||||
// the last digit that is not 0 (sig is not 0)
|
|
||||||
const auto nonzero = static_cast<std::uint64_t>(_mm_movemask_epi8(_mm_cmpgt_epi8(bytes, _mm_setzero_si128())));
|
|
||||||
const int digits = 63 - count_leading_zeros(nonzero) + (sixteen ? 1 : 0); // without trailing zeros
|
|
||||||
const __m128i chars = _mm_add_epi8(bytes, _mm_set1_epi8('0'));
|
|
||||||
// the 16 characters from the first digit
|
|
||||||
const __m128i s = sixteen ? chars : _mm_or_si128(_mm_srli_si128(chars, 1), _mm_slli_si128(_mm_cvtsi32_si128('0' + last), 15));
|
|
||||||
const char s16 = static_cast<char>(sixteen ? '0' + last : '0'); // the 17th
|
|
||||||
const auto store_16 = [&s](char* p) noexcept
|
|
||||||
{
|
|
||||||
std::memcpy(p, &s, 16);
|
|
||||||
};
|
|
||||||
const char first_digit = static_cast<char>(_mm_cvtsi128_si32(s));
|
|
||||||
// NOLINTEND(portability-simd-intrinsics)
|
|
||||||
#elif JSON_DTOA_NEON
|
|
||||||
// as with SSE2: the halves in 32-bit lanes, then abcd, efgh of both
|
|
||||||
const uint32x2_t halves = vcreate_u32(upper | ((sig - (upper * 100000000u)) << 32u));
|
|
||||||
const uint32x2_t abcd = vmovn_u64(vshrq_n_u64(vmull_n_u32(halves, static_cast<std::uint32_t>(((std::uint64_t{1} << 40u) / 10000u) + 1u)), 40));
|
|
||||||
const uint32x2_t efgh = vmls_n_u32(halves, abcd, 10000u);
|
|
||||||
const uint32x4_t fours = vcombine_u32(vzip1_u32(abcd, efgh), vzip2_u32(abcd, efgh));
|
|
||||||
const uint32x4_t ab = vshrq_n_u32(vmulq_n_u32(fours, 5243u), 19);
|
|
||||||
const uint16x8_t ab_cd = vreinterpretq_u16_u32(vorrq_u32(ab, vshlq_n_u32(vmlsq_n_u32(fours, ab, 100u), 16)));
|
|
||||||
const uint16x8_t tens = vshrq_n_u16(vmulq_n_u16(ab_cd, 103u), 10);
|
|
||||||
const uint8x16_t bytes = vreinterpretq_u8_u16(vorrq_u16(tens, vshlq_n_u16(vmlsq_n_u16(ab_cd, tens, 10u), 8)));
|
|
||||||
// the last digit that is not 0 (sig is not 0): a nibble per byte
|
|
||||||
const std::uint64_t nonzero = vget_lane_u64(vreinterpret_u64_u8(vshrn_n_u16(vreinterpretq_u16_u8(vtstq_u8(bytes, bytes)), 4)), 0);
|
|
||||||
const int digits = ((63 - count_leading_zeros(nonzero)) / 4) + (sixteen ? 1 : 0); // without trailing zeros
|
|
||||||
const uint8x16_t chars = vaddq_u8(bytes, vdupq_n_u8('0'));
|
|
||||||
// the 16 characters from the first digit
|
|
||||||
const uint8x16_t s = sixteen ? chars : vextq_u8(chars, vdupq_n_u8(static_cast<std::uint8_t>('0' + last)), 1);
|
|
||||||
const char s16 = static_cast<char>(sixteen ? '0' + last : '0'); // the 17th
|
|
||||||
const auto store_16 = [&s](char* p) noexcept
|
|
||||||
{
|
|
||||||
vst1q_u8(reinterpret_cast<std::uint8_t*>(p), s); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
|
||||||
};
|
|
||||||
const auto first_digit = static_cast<char>(vgetq_lane_u8(s, 0));
|
|
||||||
#else
|
|
||||||
const std::uint64_t hi = eight_digit_bytes(upper);
|
|
||||||
const std::uint64_t lo = eight_digit_bytes(sig - (upper * 100000000u));
|
|
||||||
// trailing zero digits: zero bytes (sig is not 0)
|
|
||||||
const int zeros = lo != 0 ? count_trailing_zeros(lo) / 8 : 8 + (count_trailing_zeros(hi) / 8);
|
|
||||||
const int digits = 15 - zeros + (sixteen ? 1 : 0); // without trailing zeros
|
|
||||||
// the 16 characters from the first digit
|
|
||||||
const std::uint64_t s_hi = (sixteen ? hi : (hi << 8u) | (lo >> 56u)) + 0x3030303030303030u;
|
|
||||||
const std::uint64_t s_lo = (sixteen ? lo : (lo << 8u) | static_cast<std::uint64_t>(last)) + 0x3030303030303030u;
|
|
||||||
const char s16 = static_cast<char>(sixteen ? '0' + last : '0'); // the 17th
|
|
||||||
const auto store_16 = [s_hi, s_lo](char* p) noexcept
|
|
||||||
{
|
|
||||||
store_msb_first(p, s_hi);
|
|
||||||
store_msb_first(p + 8, s_lo);
|
|
||||||
};
|
|
||||||
const auto first_digit = static_cast<char>(s_hi >> 56u);
|
|
||||||
#endif
|
|
||||||
const int len = d.has_digit ? 16 + (sixteen ? 1 : 0) : digits; // significant digits
|
|
||||||
const int n = 16 + (sixteen ? 1 : 0) + d.exponent; // digits before the point
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_LIKELY(n >= 1 && n <= 15))
|
|
||||||
{
|
|
||||||
// "dig.its" and "digits[000].0": the digits after the point move by
|
|
||||||
// one byte ('0's follow the digits)
|
|
||||||
#if JSON_DTOA_SSE2
|
|
||||||
// NOLINTBEGIN(portability-simd-intrinsics)
|
|
||||||
// (in the register: reading the digits back from memory right after
|
|
||||||
// storing them waits until the stores are done)
|
|
||||||
const __m128i at = _mm_set1_epi8(static_cast<char>(n));
|
|
||||||
const __m128i index = _mm_setr_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
|
||||||
const __m128i before = _mm_cmpgt_epi8(at, index);
|
|
||||||
const __m128i after = _mm_cmpgt_epi8(index, at);
|
|
||||||
const __m128i text = _mm_or_si128(_mm_or_si128(_mm_and_si128(s, before), _mm_and_si128(_mm_slli_si128(s, 1), after)),
|
|
||||||
_mm_andnot_si128(_mm_or_si128(before, after), _mm_set1_epi8('.')));
|
|
||||||
std::memcpy(first, &text, 16);
|
|
||||||
first[16] = static_cast<char>(_mm_extract_epi16(s, 7) >> 8);
|
|
||||||
first[17] = s16;
|
|
||||||
// NOLINTEND(portability-simd-intrinsics)
|
|
||||||
#elif JSON_DTOA_NEON
|
|
||||||
const uint8x16_t index = vcombine_u8(vcreate_u8(0x0706050403020100u), vcreate_u8(0x0F0E0D0C0B0A0908u));
|
|
||||||
const uint8x16_t at = vdupq_n_u8(static_cast<std::uint8_t>(n));
|
|
||||||
const uint8x16_t after_point = vbslq_u8(vcgtq_u8(index, at), vextq_u8(vdupq_n_u8(0), s, 15), vdupq_n_u8('.'));
|
|
||||||
vst1q_u8(reinterpret_cast<std::uint8_t*>(first), vbslq_u8(vcltq_u8(index, at), s, after_point)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
|
||||||
first[16] = static_cast<char>(vgetq_lane_u8(s, 15));
|
|
||||||
first[17] = s16;
|
|
||||||
#else
|
|
||||||
store_16(first);
|
|
||||||
first[16] = s16;
|
|
||||||
std::uint64_t after_point[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-pro-type-member-init,hicpp-member-init): written before read
|
|
||||||
std::memcpy(after_point, first + n, 16);
|
|
||||||
std::memcpy(first + n + 1, after_point, 16);
|
|
||||||
first[n] = '.';
|
|
||||||
#endif
|
|
||||||
return first + (n >= len ? n + 2 : len + 1);
|
|
||||||
}
|
|
||||||
if (n <= 0 && n > -4)
|
|
||||||
{
|
|
||||||
// "0.[000]digits"
|
|
||||||
std::memset(first, '0', 8);
|
|
||||||
first[1] = '.';
|
|
||||||
store_16(first + 2 - n);
|
|
||||||
first[18 - n] = s16;
|
|
||||||
return first + 2 - n + len;
|
|
||||||
}
|
|
||||||
// d.igitse+XX, with at least two exponent digits (as append_exponent())
|
|
||||||
store_16(first + 1);
|
|
||||||
first[17] = s16;
|
|
||||||
first[0] = first_digit;
|
|
||||||
first[1] = '.';
|
|
||||||
char* const end = first + (len == 1 ? 1 : len + 1);
|
|
||||||
const int e = n - 1;
|
|
||||||
const auto ea = e < 0 ? 0u - static_cast<unsigned>(e) : static_cast<unsigned>(e); // (unsigned: no signed overflow to assume)
|
|
||||||
const bool three = ea >= 100;
|
|
||||||
end[0] = 'e';
|
|
||||||
end[1] = e < 0 ? '-' : '+';
|
|
||||||
end[2] = static_cast<char>('0' + (three ? ea / 100 : (ea / 10) % 10));
|
|
||||||
end[3] = static_cast<char>('0' + (three ? (ea / 10) % 10 : ea % 10));
|
|
||||||
end[4] = static_cast<char>('0' + (ea % 10));
|
|
||||||
return end + (three ? 5 : 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief whether FloatType is an IEEE 754 binary64 type (a double, or a long double
|
|
||||||
that has the same format, as with MSVC and on Apple's Arm CPUs)
|
|
||||||
|
|
||||||
These are the types the conversion of Zmij (see zmij.hpp) is used for; all
|
|
||||||
others (binary32, or a format the library does not know) use Grisu2.
|
|
||||||
*/
|
|
||||||
template<typename FloatType>
|
|
||||||
constexpr bool has_binary64_format() noexcept
|
|
||||||
{
|
|
||||||
return std::numeric_limits<FloatType>::is_iec559
|
|
||||||
&& std::numeric_limits<FloatType>::digits == 53
|
|
||||||
&& std::numeric_limits<FloatType>::max_exponent == 1024
|
|
||||||
&& sizeof(FloatType) == sizeof(std::uint64_t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FloatType>
|
|
||||||
struct is_binary64 : std::integral_constant<bool, has_binary64_format<FloatType>()> {};
|
|
||||||
|
|
||||||
/// a positive finite float (other than binary64): Grisu2 and format_buffer()
|
|
||||||
template<typename FloatType>
|
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
char* write_positive_grisu2(char* first, const char* last, FloatType value)
|
|
||||||
{
|
|
||||||
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
|
||||||
static_cast<void>(last); // (only used in the assertion)
|
|
||||||
|
|
||||||
// Compute v = buffer * 10^decimal_exponent.
|
|
||||||
// The decimal digits are stored in the buffer, which needs to be interpreted
|
|
||||||
// as an unsigned decimal integer.
|
|
||||||
// len is the length of the buffer, i.e., the number of decimal digits.
|
|
||||||
int len = 0;
|
|
||||||
int decimal_exponent = 0;
|
|
||||||
grisu2(first, len, decimal_exponent, value);
|
|
||||||
|
|
||||||
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
|
|
||||||
|
|
||||||
// Format the buffer like printf("%.*g", prec, value)
|
|
||||||
constexpr int kMinExp = -4;
|
|
||||||
// Use digits10 here to increase compatibility with version 2.
|
|
||||||
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
|
|
||||||
|
|
||||||
JSON_ASSERT(last - first >= kMaxExp + 2);
|
|
||||||
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
|
||||||
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
|
||||||
|
|
||||||
return format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// a positive finite binary64 number: the shortest digits (Zmij), laid out by
|
|
||||||
/// write_shortest() (through a local buffer if [first, last) is shorter than
|
|
||||||
/// the 41 bytes it may write)
|
|
||||||
template<typename FloatType>
|
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
char* write_positive_zmij(char* first, const char* last, FloatType value)
|
|
||||||
{
|
|
||||||
static_assert(is_binary64<FloatType>::value,
|
|
||||||
"internal error: the conversion of Zmij needs IEEE 754 binary64 numbers");
|
|
||||||
std::uint64_t bits = 0;
|
|
||||||
std::memcpy(&bits, &value, sizeof(bits));
|
|
||||||
const zmij::shortest_decimal d = zmij::to_shortest(bits);
|
|
||||||
if (JSON_HEDLEY_LIKELY(last - first >= 41))
|
|
||||||
{
|
|
||||||
return write_shortest(first, d);
|
|
||||||
}
|
|
||||||
std::array<char, 64> buf; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init): written before read
|
|
||||||
const auto len = static_cast<std::size_t>(write_shortest(buf.data(), d) - buf.data());
|
|
||||||
JSON_ASSERT(last - first >= static_cast<std::ptrdiff_t>(len));
|
|
||||||
std::memcpy(first, buf.data(), len);
|
|
||||||
return first + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// a positive finite binary64 number: Zmij (as a long double has the format of
|
|
||||||
/// a double here, its bits are those of the double of the same value)
|
|
||||||
template<typename FloatType>
|
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
char* write_positive(char* first, const char* last, FloatType value, std::true_type /*is_binary64*/)
|
|
||||||
{
|
|
||||||
return write_positive_zmij(first, last, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// a positive finite float of any other format: Grisu2
|
|
||||||
template<typename FloatType>
|
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
char* write_positive(char* first, const char* last, FloatType value, std::false_type /*is_binary64*/)
|
|
||||||
{
|
|
||||||
return write_positive_grisu2(first, last, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// a positive finite float: Zmij for binary64 numbers, Grisu2 otherwise
|
|
||||||
template<typename FloatType>
|
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
char* write_positive(char* first, const char* last, FloatType value)
|
|
||||||
{
|
|
||||||
return write_positive(first, last, value, is_binary64<FloatType> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dtoa_impl
|
} // namespace dtoa_impl
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1461,6 +1064,7 @@ JSON_HEDLEY_NON_NULL(1, 2)
|
|||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
char* to_chars(char* first, const char* last, FloatType value)
|
char* to_chars(char* first, const char* last, FloatType value)
|
||||||
{
|
{
|
||||||
|
static_cast<void>(last); // maybe unused - fix warning
|
||||||
JSON_ASSERT(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
|
|
||||||
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
||||||
@@ -1486,7 +1090,28 @@ char* to_chars(char* first, const char* last, FloatType value)
|
|||||||
JSON_HEDLEY_DIAGNOSTIC_POP
|
JSON_HEDLEY_DIAGNOSTIC_POP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return dtoa_impl::write_positive(first, last, value);
|
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
|
||||||
|
// Compute v = buffer * 10^decimal_exponent.
|
||||||
|
// The decimal digits are stored in the buffer, which needs to be interpreted
|
||||||
|
// as an unsigned decimal integer.
|
||||||
|
// len is the length of the buffer, i.e., the number of decimal digits.
|
||||||
|
int len = 0;
|
||||||
|
int decimal_exponent = 0;
|
||||||
|
dtoa_impl::grisu2(first, len, decimal_exponent, value);
|
||||||
|
|
||||||
|
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
|
||||||
|
// Format the buffer like printf("%.*g", prec, value)
|
||||||
|
constexpr int kMinExp = -4;
|
||||||
|
// Use digits10 here to increase compatibility with version 2.
|
||||||
|
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
|
||||||
|
|
||||||
|
JSON_ASSERT(last - first >= kMaxExp + 2);
|
||||||
|
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
||||||
|
|
||||||
|
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -1,219 +0,0 @@
|
|||||||
// __ _____ _____ _____
|
|
||||||
// __| | __| | | | JSON for Modern C++
|
|
||||||
// | | |__ | | | | | | version 3.12.0
|
|
||||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|
||||||
//
|
|
||||||
// SPDX-FileCopyrightText: 2025 Victor Zverovich <https://github.com/vitaut/zmij>
|
|
||||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array> // array
|
|
||||||
#include <cstddef> // size_t
|
|
||||||
#include <cstdint> // uint32_t, uint64_t
|
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
|
||||||
#include <nlohmann/detail/bit_ops.hpp>
|
|
||||||
#include <nlohmann/detail/input/pow5_table.hpp>
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief the shortest decimal representation of a double
|
|
||||||
|
|
||||||
A C++11 port of the conversion of Zmij by Victor Zverovich
|
|
||||||
(https://github.com/vitaut/zmij, MIT license): the shortest decimal in the
|
|
||||||
rounding interval of a double, the closest one if there are several. Zmij
|
|
||||||
credits Xiang JunBo (producing the shorter candidate without a division) and
|
|
||||||
Dougall Johnson (the compressed powers of ten). The powers of ten are taken
|
|
||||||
from the table for number parsing (pow5_table.hpp) where it holds them, and
|
|
||||||
computed from the compressed tables of Zmij beyond it.
|
|
||||||
*/
|
|
||||||
namespace zmij
|
|
||||||
{
|
|
||||||
|
|
||||||
/// the compressed powers of ten of Zmij
|
|
||||||
inline const std::array<std::uint64_t, 28>& pow10_minor() noexcept
|
|
||||||
{
|
|
||||||
static const std::array<std::uint64_t, 28> table =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0x8000000000000000u, 0xa000000000000000u, 0xc800000000000000u, 0xfa00000000000000u, 0x9c40000000000000u,
|
|
||||||
0xc350000000000000u, 0xf424000000000000u, 0x9896800000000000u, 0xbebc200000000000u, 0xee6b280000000000u,
|
|
||||||
0x9502f90000000000u, 0xba43b74000000000u, 0xe8d4a51000000000u, 0x9184e72a00000000u, 0xb5e620f480000000u,
|
|
||||||
0xe35fa931a0000000u, 0x8e1bc9bf04000000u, 0xb1a2bc2ec5000000u, 0xde0b6b3a76400000u, 0x8ac7230489e80000u,
|
|
||||||
0xad78ebc5ac620000u, 0xd8d726b7177a8000u, 0x878678326eac9000u, 0xa968163f0a57b400u, 0xd3c21bcecceda100u,
|
|
||||||
0x84595161401484a0u, 0xa56fa5b99019a5c8u, 0xcecb8f27f4200f3au
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (high, low) pairs
|
|
||||||
inline const std::array<std::uint64_t, 50>& pow10_major() noexcept
|
|
||||||
{
|
|
||||||
static const std::array<std::uint64_t, 50> table =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0xaddcb9e83c6b1793u, 0xdf4abe242a1bbf3eu, 0xaf8e5410288e1b6fu, 0x07ecf0ae5ee44ddau, 0xb1442798f49ffb4au, 0x99cd11cfdf41779du,
|
|
||||||
0xb2fe3f0b8599ef07u, 0x861fa7e6dcb4aa15u, 0xb4bca50b065abe63u, 0x0fed077a756b53aau, 0xb67f6455292cbf08u, 0x1a3bc84c17b1d543u,
|
|
||||||
0xb84687c269ef3bfbu, 0x3d5d514f40eea742u, 0xba121a4650e4ddebu, 0x92f34d62616ce413u, 0xbbe226efb628afeau, 0x890489f70a55368cu,
|
|
||||||
0xbdb6b8e905cb600fu, 0x5400e987bbc1c921u, 0xbf8fdb78849a5f96u, 0xde98520472bdd034u, 0xc16d9a0095928a27u, 0x75b7053c0f178294u,
|
|
||||||
0xc350000000000000u, 0x0000000000000000u, 0xc5371912364ce305u, 0x6c28000000000000u, 0xc722f0ef9d80aad6u, 0x424d3ad2b7b97ef6u,
|
|
||||||
0xc913936dd571c84cu, 0x03bc3a19cd1e38eau, 0xcb090c8001ab551cu, 0x5cadf5bfd3072cc6u, 0xcd036837130890a1u, 0x36dba887c37a8c10u,
|
|
||||||
0xcf02b2c21207ef2eu, 0x94f967e45e03f4bcu, 0xd106f86e69d785c7u, 0xe13336d701beba52u, 0xd31045a8341ca07cu, 0x1ede48111209a051u,
|
|
||||||
0xd51ea6fa85785631u, 0x552a74227f3ea566u, 0xd732290fbacaf133u, 0xa97c177947ad4096u, 0xd94ad8b1c7380874u, 0x18375281ae7822bdu,
|
|
||||||
0xdb68c2ca82ed2a05u, 0xa67398db9f6820e1u
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// one bit per power: whether the computed value is one unit too large
|
|
||||||
inline const std::array<std::uint32_t, 21>& pow10_fixups() noexcept
|
|
||||||
{
|
|
||||||
static const std::array<std::uint32_t, 21> table =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
0x8d8fc810u, 0x06100293u, 0x19000000u, 0x00100000u, 0x00000908u, 0x00000000u, 0x04e00300u, 0x3807e0b2u, 0x3d83d793u, 0x0006f5ccu,
|
|
||||||
0x00000000u, 0xffff0000u, 0x8076337du, 0x4ff45ba0u, 0x09405033u, 0x034376d9u, 0x09000000u, 0x4e100501u, 0x076d14dcu, 0xf964f45eu,
|
|
||||||
0x0000003du
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the 128-bit significand of 10^k, rounded down, for k in [-307, 341]
|
|
||||||
/// (compute_pow10 of Zmij)
|
|
||||||
inline uint128_parts compute_pow10(int k) noexcept
|
|
||||||
{
|
|
||||||
const auto i = static_cast<unsigned>(k + 307);
|
|
||||||
const std::uint64_t m = pow10_minor()[(i + 24) % 28];
|
|
||||||
const std::size_t j = 2 * static_cast<std::size_t>((i + 24) / 28);
|
|
||||||
const std::uint64_t h_hi = pow10_major()[j];
|
|
||||||
const std::uint64_t h_lo = pow10_major()[j + 1];
|
|
||||||
const std::uint64_t h1 = full_multiplication(h_lo, m).high;
|
|
||||||
const std::uint64_t c0 = h_lo * m;
|
|
||||||
const std::uint64_t c1 = h1 + (h_hi * m);
|
|
||||||
const std::uint64_t c2 = (c1 < h1 ? 1u : 0u) + full_multiplication(h_hi, m).high;
|
|
||||||
uint128_parts r{};
|
|
||||||
if ((c2 >> 63u) != 0)
|
|
||||||
{
|
|
||||||
r.high = c2;
|
|
||||||
r.low = c1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
r.high = (c2 << 1u) | (c1 >> 63u);
|
|
||||||
r.low = (c1 << 1u) | (c0 >> 63u);
|
|
||||||
}
|
|
||||||
r.low -= (pow10_fixups()[i >> 5u] >> (i & 31u)) & 1u;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The 128-bit significand of 10^k, rounded down, for k in [-342, 341].
|
|
||||||
/// Up to 10^308, the table for number parsing holds the same significands
|
|
||||||
/// (those of 5^k), except for k in [-27, -1], where it holds them one unit
|
|
||||||
/// larger (as the Eisel-Lemire algorithm needs them).
|
|
||||||
inline uint128_parts pow10(int k) noexcept
|
|
||||||
{
|
|
||||||
if (k > pow5_128_largest_power)
|
|
||||||
{
|
|
||||||
return compute_pow10(k); // (only for the smallest doubles)
|
|
||||||
}
|
|
||||||
const auto i = 2 * static_cast<std::size_t>(k - pow5_128_smallest_power);
|
|
||||||
uint128_parts r{pow5_128()[i + 1], pow5_128()[i]};
|
|
||||||
const std::uint64_t adjust = static_cast<unsigned>(k + 27) < 27u ? 1u : 0u;
|
|
||||||
r.high -= r.low < adjust ? 1u : 0u;
|
|
||||||
r.low -= adjust;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (x_hi * 2^64 + x_lo) * y >> 64, as 128 bits
|
|
||||||
inline uint128_parts umul192_hi128(std::uint64_t x_hi, std::uint64_t x_lo, std::uint64_t y) noexcept
|
|
||||||
{
|
|
||||||
const uint128_parts p = full_multiplication(x_hi, y);
|
|
||||||
uint128_parts r{};
|
|
||||||
r.low = p.low + full_multiplication(x_lo, y).high;
|
|
||||||
r.high = p.high + (r.low < p.low ? 1u : 0u);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (x * y + c) >> 64
|
|
||||||
inline std::uint64_t umul128_add_hi64(std::uint64_t x, std::uint64_t y, std::uint64_t c) noexcept
|
|
||||||
{
|
|
||||||
const uint128_parts p = full_multiplication(x, y);
|
|
||||||
return p.high + (p.low + c < p.low ? 1u : 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the result of Zmij: the shorter candidate and, if that is outside the
|
|
||||||
/// rounding interval, the digit after it (16 bytes: returned in registers)
|
|
||||||
struct shortest_decimal
|
|
||||||
{
|
|
||||||
std::uint64_t integral; ///< the shorter candidate (15 or 16 digits for normal doubles)
|
|
||||||
int exponent; ///< the decimal exponent of the digit after it
|
|
||||||
unsigned char digit; ///< the digit after it (if has_digit)
|
|
||||||
bool has_digit; ///< whether the shortest decimal is integral * 10 + digit
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The shortest decimal in the rounding interval of a positive finite double
|
|
||||||
/// given by its bits, the closest one if there are several (to_decimal of
|
|
||||||
/// Zmij, which keeps the last digit apart: the 15 or 16 digits before it can be
|
|
||||||
/// converted without a multiplication by 10 first). Always inlined: GCC
|
|
||||||
/// otherwise calls it, and its result goes through memory.
|
|
||||||
JSON_HEDLEY_ALWAYS_INLINE shortest_decimal to_shortest(std::uint64_t bits) noexcept
|
|
||||||
{
|
|
||||||
constexpr int extra_shift = 9;
|
|
||||||
const auto raw_exp = static_cast<int>((bits >> 52u) & 0x7FFu);
|
|
||||||
std::uint64_t bin_sig = bits & ((std::uint64_t{1} << 52u) - 1);
|
|
||||||
// a power of two has a narrower interval below (except the smallest normal)
|
|
||||||
const bool regular = bin_sig != 0 || raw_exp <= 1;
|
|
||||||
const int bin_exp = (raw_exp == 0 ? 1 : raw_exp) - 1075;
|
|
||||||
if (raw_exp != 0)
|
|
||||||
{
|
|
||||||
bin_sig |= std::uint64_t{1} << 52u;
|
|
||||||
}
|
|
||||||
// floor(log10(2^bin_exp)), or floor(log10(3/4 * 2^bin_exp)) for the irregular case
|
|
||||||
const int dec_exp = ((bin_exp * 315653) - (regular ? 0 : 131072)) >> 20;
|
|
||||||
// scaled by 10^(-dec_exp - 1): the integral part is the shorter candidate
|
|
||||||
const int shift = bin_exp + ((-(dec_exp + 1) * 217707) >> 16) + 1 + extra_shift;
|
|
||||||
const uint128_parts p10 = pow10(-dec_exp - 1);
|
|
||||||
const uint128_parts p = umul192_hi128(p10.high, p10.low, bin_sig << static_cast<unsigned>(shift));
|
|
||||||
std::uint64_t integral = p.high >> static_cast<unsigned>(extra_shift);
|
|
||||||
const std::uint64_t fractional = (p.high << static_cast<unsigned>(64 - extra_shift)) | (p.low >> static_cast<unsigned>(extra_shift));
|
|
||||||
std::uint64_t digit = 0;
|
|
||||||
bool round_up = false;
|
|
||||||
bool round_down = false;
|
|
||||||
if (JSON_HEDLEY_LIKELY(regular))
|
|
||||||
{
|
|
||||||
const std::uint64_t half_ulp = (p10.high >> static_cast<unsigned>(extra_shift + 1 - shift)) + (1 - (bin_sig & 1u));
|
|
||||||
round_up = fractional + half_ulp < fractional;
|
|
||||||
round_down = half_ulp > fractional;
|
|
||||||
// the last digit of the longer candidate, rounded to nearest
|
|
||||||
digit = umul128_add_hi64(fractional, 10, (std::uint64_t{1} << 63u) + 6);
|
|
||||||
if (fractional == (std::uint64_t{1} << 62u))
|
|
||||||
{
|
|
||||||
digit = 2; // 2.5 rounds to 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const std::uint64_t half_ulp = p10.high >> static_cast<unsigned>(extra_shift + 1 - shift);
|
|
||||||
round_up = half_ulp > ~std::uint64_t{0} - fractional;
|
|
||||||
round_down = (half_ulp >> 1u) > fractional;
|
|
||||||
digit = umul128_add_hi64(fractional, 10, (std::uint64_t{1} << 63u) - 1);
|
|
||||||
const std::uint64_t lowest = umul128_add_hi64(fractional - (half_ulp >> 1u), 10, ~std::uint64_t{0});
|
|
||||||
digit = digit < lowest ? lowest : digit;
|
|
||||||
}
|
|
||||||
integral += round_up ? 1u : 0u;
|
|
||||||
// if the shorter candidate is outside the rounding interval: one digit more
|
|
||||||
return shortest_decimal{integral, dec_exp, static_cast<unsigned char>(digit), !round_up && !round_down};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace zmij
|
|
||||||
} // namespace detail
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
|
||||||
@@ -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()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@@ -581,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:
|
||||||
@@ -793,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);
|
||||||
}
|
}
|
||||||
@@ -802,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);
|
||||||
}
|
}
|
||||||
@@ -827,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_position() - 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_position();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -221,44 +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 and the position counters
|
|
||||||
/// exactly as those 4 get() calls would (a hex digit is never '\n', so
|
|
||||||
/// only the flat counters move) 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);
|
|
||||||
// a hex digit is never a newline, so only the flat counters advance
|
|
||||||
position.chars_read_total += 4;
|
|
||||||
position.chars_read_current_line += 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`
|
||||||
|
|
||||||
@@ -278,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 };
|
||||||
@@ -1090,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.
|
||||||
{
|
{
|
||||||
@@ -1107,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;
|
||||||
|
|
||||||
@@ -1437,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)
|
||||||
{
|
{
|
||||||
@@ -1492,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;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user