mirror of
https://github.com/nlohmann/json.git
synced 2026-10-11 17:07:15 +00:00
Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05e11ce350 | ||
|
|
087885f142 | ||
|
|
dc01cc02e2 | ||
|
|
007dfb0742 | ||
|
|
a44c80c6ce | ||
|
|
f6895fb84e | ||
|
|
247b03b2de | ||
|
|
56ff716d88 | ||
|
|
9bbd0dafb0 | ||
|
|
1c8437a724 | ||
|
|
934f6644d7 | ||
|
|
1795f59f10 | ||
|
|
2434cb6e72 | ||
|
|
e8b747e4bc | ||
|
|
c59ad95252 | ||
|
|
b38a2c9177 | ||
|
|
eb8899a29c | ||
|
|
11ef352511 | ||
|
|
74a03dec84 | ||
|
|
6197341a21 | ||
|
|
2cca04ae6f | ||
|
|
1649d9eda4 | ||
|
|
f8b47ff6f6 | ||
|
|
07ec1a4e31 | ||
|
|
74aefc3486 | ||
|
|
84ee12a67c | ||
|
|
2913e96433 | ||
|
|
44e8597701 | ||
|
|
374dfe4f0f | ||
|
|
d540750f21 | ||
|
|
69a0c1b82c | ||
|
|
d33068da73 | ||
|
|
d8dfc0d0f9 | ||
|
|
3d7f554927 | ||
|
|
a269794db7 |
No files matched your search
@@ -0,0 +1,3 @@
|
||||
# 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.
|
||||
# Since 2013, over 250 contributors have helped to improve the library.
|
||||
# Since 2013, over 400 contributors have helped to improve the library.
|
||||
# This CODEOWNERS file is only to make sure that @nlohmann is requested
|
||||
# for a code review in case of a pull request.
|
||||
|
||||
|
||||
+16
-14
@@ -98,7 +98,7 @@ $ ctest --test-dir build -j 10
|
||||
The test suite should report:
|
||||
|
||||
```
|
||||
100% tests passed, 0 tests failed out of 98
|
||||
100% tests passed, 0 tests failed out of <number of tests>
|
||||
```
|
||||
|
||||
#### Add tests
|
||||
@@ -149,14 +149,17 @@ 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)
|
||||
```
|
||||
|
||||
A new API page also needs an entry in [`docs/docset/docSet.sql`](https://github.com/nlohmann/json/blob/develop/docs/docset/docSet.sql),
|
||||
the search index of the docset; `make build` reports missing entries.
|
||||
The search index of the docset is generated from [`mkdocs.yml`](https://github.com/nlohmann/json/blob/develop/docs/mkdocs/mkdocs.yml)
|
||||
and each page's title (H1) and declaration by
|
||||
[`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
|
||||
|
||||
The single-header files
|
||||
[`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)
|
||||
[`single_include/nlohmann/json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp),
|
||||
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp), and
|
||||
[`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
|
||||
[`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:
|
||||
@@ -179,7 +182,7 @@ The amalgamation check in CI fails if any of these generated files is out of dat
|
||||
|
||||
## Recommended documentation
|
||||
|
||||
- The library’s [README file](https://github.com/nlohmann/json/blob/master/README.md) is an excellent starting point to
|
||||
- The library’s [README file](https://github.com/nlohmann/json/blob/develop/README.md) is an excellent starting point to
|
||||
understand its functionality.
|
||||
- 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)
|
||||
@@ -218,9 +221,9 @@ feature macros then allows users to test their code against the library in the n
|
||||
### Break C++11 language conformance
|
||||
|
||||
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/master/README.md#supported-compilers) should compile
|
||||
[supported C++11 compiler](https://github.com/nlohmann/json/blob/develop/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
|
||||
Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support.
|
||||
C++ 2013 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
|
||||
later against the respective [`JSON_HAS_CPP_14`](https://json.nlohmann.me/api/macros/json_has_cpp_11/) macros.
|
||||
@@ -236,12 +239,11 @@ extension.
|
||||
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
|
||||
bleeding-edge versions Clang.
|
||||
- Improving the efficiency of the **JSON parser**. The current parser is implemented as a naive recursive descent parser
|
||||
with hand-coded string handling. More sophisticated approaches like LALR parsers would be really appreciated. That
|
||||
said, parser generators like Bison or ANTLR do not play nice with single-header files -- I really would like to keep
|
||||
the parser inside the `json.hpp` header, and I am not aware of approaches similar to [`re2c`](http://re2c.org) for
|
||||
parsing.
|
||||
bleeding-edge versions of Clang.
|
||||
- Improving the efficiency of the **JSON parser**. The current parser is a hand-written iterative parser that keeps an
|
||||
explicit stack instead of recursing, with hand-coded string handling. Speeding up the lexer or the value construction
|
||||
would be appreciated. Parser generators like Bison or ANTLR do not play nice with single-header files -- I really
|
||||
would like to keep the parser inside the `json.hpp` header.
|
||||
- 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
|
||||
proper comparisons would be interesting.
|
||||
|
||||
@@ -52,7 +52,7 @@ body:
|
||||
If possible, provide a small and self-contained example that triggers
|
||||
the bug. Please understand that we cannot analyze and debug large code
|
||||
bases. Please do not paste screenshots here.
|
||||
render: Shell
|
||||
render: cpp
|
||||
- type: textarea
|
||||
id: output
|
||||
attributes:
|
||||
@@ -79,7 +79,7 @@ body:
|
||||
description: >
|
||||
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
|
||||
the commit hash. If you got the library from another source as the
|
||||
the commit hash. If you got the library from another source than the
|
||||
GitHub repository (e.g., via a package manager), please also state
|
||||
this.
|
||||
validations:
|
||||
|
||||
@@ -21,6 +21,17 @@ labels:
|
||||
files:
|
||||
- "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"
|
||||
files:
|
||||
- ".github/workflows/.*"
|
||||
|
||||
@@ -83,8 +83,7 @@ jobs:
|
||||
# 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
|
||||
# that adds support for a new dispatch table until that PR itself
|
||||
# merges to develop, the same way generate_natvis.py's --version
|
||||
# requirement briefly did.
|
||||
# merges to develop.
|
||||
TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX)
|
||||
c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder"
|
||||
"$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp"
|
||||
@@ -117,7 +116,6 @@ jobs:
|
||||
|
||||
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 .
|
||||
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/
|
||||
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
||||
@@ -138,17 +136,13 @@ jobs:
|
||||
${{ 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)
|
||||
|
||||
# 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
|
||||
run: |
|
||||
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
|
||||
# file against, so take it from this PR rather than from the
|
||||
# develop checkout: generate_natvis.py loads the template from its
|
||||
@@ -156,7 +150,7 @@ jobs:
|
||||
# template could never pass. Like the macro_builder step above,
|
||||
# this only renders PR content in a job without credentials.
|
||||
cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
|
||||
python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
|
||||
python3 $NATVIS_TOOL_DIR/generate_natvis.py $MAIN_DIR
|
||||
|
||||
- name: Build patch and check for differences
|
||||
id: diff
|
||||
@@ -165,7 +159,7 @@ jobs:
|
||||
mkdir -p ${{ github.workspace }}/patch
|
||||
git diff --patch --no-color > ${{ github.workspace }}/patch/amalgamation.patch
|
||||
if [ -s ${{ github.workspace }}/patch/amalgamation.patch ]; then
|
||||
echo "The source code has not been amalgamated/formatted correctly or BUILD.bazel is out of date. Diff:"
|
||||
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:"
|
||||
cat ${{ github.workspace }}/patch/amalgamation.patch
|
||||
echo "has_diff=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: '## 🔴 Amalgamation check failed! 🔴\nThe source code has not been amalgamated and/or formatted correctly, or `BUILD.bazel` is out of date.'
|
||||
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`).'
|
||||
+ (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:'
|
||||
+ '\n\n```shell\ngit apply amalgamation.patch\n```\n\n'
|
||||
|
||||
@@ -15,6 +15,7 @@ on:
|
||||
- .github/SECURITY.md
|
||||
- cmake/clang_flags.cmake
|
||||
- cmake/gcc_flags.cmake
|
||||
- include/nlohmann/detail/abi_macros.hpp
|
||||
- tests/fmt_formatter/project/main.cpp
|
||||
- tools/astyle/.astylerc
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
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]
|
||||
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]
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||
@@ -117,6 +117,7 @@ jobs:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Install Valgrind
|
||||
if: matrix.target == 'ci_test_valgrind'
|
||||
run: sudo apt-get update ; sudo apt-get install -y valgrind
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
@@ -279,7 +280,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||
- name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10
|
||||
- name: Disable filesystem support (std::filesystem is unusable) for clang 7 / 8 / 9 / 10
|
||||
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' }}
|
||||
- name: Run CMake
|
||||
|
||||
@@ -166,6 +166,13 @@ jobs:
|
||||
# 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.
|
||||
# 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
|
||||
run: cmake -S . -B build ^
|
||||
-DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" ^
|
||||
@@ -180,7 +187,7 @@ jobs:
|
||||
- name: Test
|
||||
run: cd build ; ctest -j 10 -C Debug --output-on-failure
|
||||
|
||||
clang-cl-12:
|
||||
clang-cl:
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -210,8 +217,10 @@ jobs:
|
||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||
with:
|
||||
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)
|
||||
run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_CI=ON -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
|
||||
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"
|
||||
- name: Build
|
||||
run: cmake --build build --config Debug --target ci_module_cpp20
|
||||
|
||||
+14
-1
@@ -27,7 +27,6 @@
|
||||
/docs/docset/JSON_for_Modern_C++.tgz
|
||||
/docs/docset/docSet.dsidx
|
||||
/docs/mkdocs/.cache/
|
||||
/docs/mkdocs/docs/__pycache__/
|
||||
/docs/mkdocs/hooks/__pycache__/
|
||||
/docs/mkdocs/scripts/mermaid/node_modules/
|
||||
/docs/mkdocs/site/
|
||||
@@ -47,3 +46,17 @@ nlohmann_json.spdx
|
||||
|
||||
# Bazel-related
|
||||
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,6 +25,7 @@ cc_library(
|
||||
"include/nlohmann/detail/conversions/from_json.hpp",
|
||||
"include/nlohmann/detail/conversions/to_chars.hpp",
|
||||
"include/nlohmann/detail/conversions/to_json.hpp",
|
||||
"include/nlohmann/detail/conversions/zmij.hpp",
|
||||
"include/nlohmann/detail/exceptions.hpp",
|
||||
"include/nlohmann/detail/hash.hpp",
|
||||
"include/nlohmann/detail/input/binary_reader.hpp",
|
||||
@@ -81,6 +82,7 @@ cc_library(
|
||||
hdrs = [
|
||||
"single_include/nlohmann/json.hpp",
|
||||
"single_include/nlohmann/json_fwd.hpp",
|
||||
"single_include/nlohmann/json_literals.hpp",
|
||||
],
|
||||
includes = ["single_include"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ authors:
|
||||
website: https://nlohmann.me
|
||||
title: "JSON for Modern C++"
|
||||
version: 3.12.0
|
||||
date-released: 2025-04-07
|
||||
date-released: 2025-04-11
|
||||
license: MIT
|
||||
repository-code: "https://github.com/nlohmann/json"
|
||||
url: https://json.nlohmann.me
|
||||
+1
-1
@@ -30,7 +30,7 @@ endif ()
|
||||
option(NLOHMANN_JSON_BUILD_MODULES "Build C++ modules support" OFF)
|
||||
|
||||
if(NLOHMANN_JSON_BUILD_MODULES)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.28)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.28)
|
||||
message(STATUS "Building nlohmann.json C++ module")
|
||||
add_subdirectory(src/modules)
|
||||
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:
|
||||
|
||||
- `ubuntu.yml`, `macos.yml`, `windows.yml` — build and run the test suite on Linux, macOS, and Windows.
|
||||
- `check_amalgamation.yml` — verify that the single-header amalgamation in `single_include` is up to date on pull requests.
|
||||
- `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.
|
||||
- `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.
|
||||
- `codeql-analysis.yml` — run [CodeQL](https://codeql.github.com) code scanning.
|
||||
@@ -24,7 +24,9 @@ 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.
|
||||
- `labeler.yml` — the "Pull Request Labeler" workflow (see `.github/labeler.yml`).
|
||||
- `stale.yml` — comment on and close stale issues and pull requests.
|
||||
- `publish_documentation.yml` — build and publish the documentation on every merge to the `develop` branch.
|
||||
- `publish_documentation.yml` — build and publish the documentation on pushes to the `develop` branch that touch the documentation sources (or the files it embeds).
|
||||
- `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:
|
||||
|
||||
@@ -266,8 +268,9 @@ meson setup builddir
|
||||
ninja -C builddir
|
||||
```
|
||||
|
||||
`meson_options.txt` defines the options, which mirror the CMake options that change the library's target (for example,
|
||||
`-DDiagnostics=true`). Meson requires this file next to `meson.build`, so it is also part of `include.zip`. `make check_build_options`
|
||||
`meson_options.txt` defines the options, which mirror the names of 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
|
||||
`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
|
||||
stay in sync with the CMake options.
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module(
|
||||
name = "nlohmann_json",
|
||||
version = "3.12.0",
|
||||
compatibility_level = 1,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check check_build_options
|
||||
.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
|
||||
|
||||
##########################################################################
|
||||
# configuration
|
||||
@@ -41,12 +41,18 @@ all:
|
||||
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
||||
@echo "ChangeLog.md - generate ChangeLog file"
|
||||
@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 "fuzzing - see tests/fuzzing.md for how to build and run the fuzzers"
|
||||
@echo "(fuzzers) - see tests/fuzzing.md, or run 'make -C tests fuzzers' to build the AFL fuzzers"
|
||||
@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 "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 "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_undef - rebuild hedley_undef.hpp from the JSON_HEDLEY_* #define names in hedley.hpp"
|
||||
|
||||
@@ -108,13 +114,18 @@ $(AMALGAMATED_FWD_FILE): $(SRCS)
|
||||
$(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp
|
||||
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
|
||||
# (the dependencies are installed into a virtual environment first)
|
||||
natvis:
|
||||
python3 tools/generate_natvis/generate_natvis.py .
|
||||
@test -d $(NATVIS_VENV) || python3 -mvenv $(NATVIS_VENV)
|
||||
@$(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
|
||||
# checked-in header; phony, because it never writes $(MACRO_SCOPE_HPP) itself
|
||||
macro_builder_check:
|
||||
macro_builder_check: install_astyle
|
||||
@set -e; \
|
||||
TMPDIR=$$(mktemp -d ./macro_builder_check.XXXXXX); \
|
||||
trap 'rm -rf "$$TMPDIR"' EXIT; \
|
||||
@@ -131,27 +142,27 @@ macro_builder_check:
|
||||
check_build_options:
|
||||
python3 tools/check_build_options/check_build_options.py .
|
||||
|
||||
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
|
||||
# check if the single headers have been amalgamated from the nlohmann sources and if BUILD.bazel and
|
||||
# nlohmann_json.natvis are up to date; all checks are run, and the checked-in files are always restored
|
||||
check-amalgamation:
|
||||
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
|
||||
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
|
||||
@mv $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~
|
||||
@$(MAKE) amalgamate
|
||||
@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)
|
||||
@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)
|
||||
@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)
|
||||
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
|
||||
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
|
||||
@mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE)
|
||||
@mv BUILD.bazel BUILD.bazel~
|
||||
@$(MAKE) BUILD.bazel
|
||||
@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)
|
||||
@mv BUILD.bazel~ BUILD.bazel
|
||||
@mv nlohmann_json.natvis nlohmann_json.natvis~
|
||||
@$(MAKE) natvis
|
||||
@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)
|
||||
@mv nlohmann_json.natvis~ nlohmann_json.natvis
|
||||
@$(MAKE) macro_builder_check
|
||||
@status=0; \
|
||||
banner() { printf '===================================================================\n %s\n===================================================================\n' "$$1"; }; \
|
||||
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel nlohmann_json.natvis; do \
|
||||
mv "$$FILE" "$$FILE~" || exit 1; \
|
||||
done; \
|
||||
$(MAKE) amalgamate || status=1; \
|
||||
$(MAKE) BUILD.bazel || status=1; \
|
||||
$(MAKE) natvis || status=1; \
|
||||
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE); do \
|
||||
diff "$$FILE" "$$FILE~" || { banner "$$FILE is out of date! Amalgamation required! Please read the contribution guidelines in file .github/CONTRIBUTING.md."; status=1; }; \
|
||||
done; \
|
||||
diff BUILD.bazel BUILD.bazel~ || { banner "BUILD.bazel is out of date! Please run 'make BUILD.bazel'."; status=1; }; \
|
||||
diff nlohmann_json.natvis nlohmann_json.natvis~ || { banner "nlohmann_json.natvis is out of date! Please run 'make natvis'."; status=1; }; \
|
||||
for FILE in $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel nlohmann_json.natvis; do \
|
||||
mv "$$FILE~" "$$FILE"; \
|
||||
done; \
|
||||
$(MAKE) macro_builder_check || status=1; \
|
||||
exit $$status
|
||||
|
||||
# generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild
|
||||
BUILD.bazel:
|
||||
@@ -212,8 +223,8 @@ release: include.zip json.tar.xz
|
||||
|
||||
# clean up
|
||||
clean:
|
||||
rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM
|
||||
rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
|
||||
rm -fr *.dSYM tests/*.dSYM tests/parse_*_fuzzer
|
||||
rm -fr cmake-build-benchmarks cmake-build-pvs-studio release_files
|
||||
$(MAKE) clean -Cdocs
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
- [Pkg-config](#pkg-config)
|
||||
- [License](#license)
|
||||
- [Contact](#contact)
|
||||
- [Security](#security)
|
||||
- [Thanks](#thanks)
|
||||
- [Used third-party tools](#used-third-party-tools)
|
||||
- [Notes](#notes)
|
||||
@@ -112,9 +113,9 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t
|
||||
|
||||
## 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)
|
||||
- **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)
|
||||
- **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)
|
||||
@@ -1184,7 +1185,7 @@ binary[1]; // 0xFE
|
||||
binary.set_subtype(0x10);
|
||||
|
||||
// serialize to MessagePack
|
||||
auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
|
||||
auto msgpack = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
|
||||
```
|
||||
|
||||
## Customers
|
||||
@@ -1220,17 +1221,7 @@ I would be happy to learn about other compilers/versions.
|
||||
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.
|
||||
- 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).
|
||||
- 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`.
|
||||
|
||||
- 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.
|
||||
|
||||
@@ -1394,9 +1385,10 @@ 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 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 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 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
|
||||
- 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
|
||||
|
||||
<img align="right" src="https://git.fsfe.org/reuse/reuse-ci/raw/branch/master/reuse-horizontal.png" alt="REUSE Software">
|
||||
|
||||
@@ -1437,436 +1429,416 @@ I deeply appreciate the help of the following people.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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. [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
||||
22. [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
||||
23. [406345](https://github.com/406345) fixed two small warnings.
|
||||
24. [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
|
||||
25. [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
|
||||
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. [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file.
|
||||
28. [msm-](https://github.com/msm-) added support for American Fuzzy Lop.
|
||||
29. [Annihil](https://github.com/Annihil) fixed an example in the README file.
|
||||
30. [Themercee](https://github.com/Themercee) noted a wrong URL in the README file.
|
||||
31. [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`.
|
||||
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. [zewt](https://github.com/zewt) added useful notes to the README file about Android.
|
||||
34. [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
|
||||
35. [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
|
||||
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. [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
||||
38. [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
||||
39. [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
||||
40. [Thomas Braun](https://github.com/t-b) fixed a warning in a test case and adjusted MSVC calls in the CI.
|
||||
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. [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
|
||||
43. [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
|
||||
44. [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
|
||||
45. [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
|
||||
46. [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
|
||||
47. [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
|
||||
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. [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
|
||||
50. [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
|
||||
51. [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
|
||||
52. [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
|
||||
53. [Daniel599](https://github.com/Daniel599) helped to get Travis to execute the tests with Clang's sanitizers.
|
||||
54. [Jonathan Lee](https://github.com/vjon) fixed an example in the README file.
|
||||
55. [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types.
|
||||
56. [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio.
|
||||
57. [Jared Grubb](https://github.com/jaredgrubb) supported the implementation of user-defined types.
|
||||
58. [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example.
|
||||
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. [ukhegg](https://github.com/ukhegg) proposed an improvement for the examples section.
|
||||
61. [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README.
|
||||
62. [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s.
|
||||
63. [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation.
|
||||
64. [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings.
|
||||
65. [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible.
|
||||
66. [ftillier](https://github.com/ftillier) fixed a compiler warning.
|
||||
67. [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped.
|
||||
68. [Fytch](https://github.com/Fytch) found a bug in the documentation.
|
||||
69. [Jay Sistar](https://github.com/Type1J) implemented a Meson build description.
|
||||
70. [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation.
|
||||
71. [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager.
|
||||
72. [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`.
|
||||
73. [Mike Tzou](https://github.com/Chocobo1) fixed some typos.
|
||||
74. [amrcode](https://github.com/amrcode) noted misleading documentation about comparison of floats.
|
||||
75. [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
|
||||
76. [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
|
||||
77. [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
|
||||
78. [Greg Hurrell](https://github.com/wincent) fixed a typo.
|
||||
79. [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
|
||||
80. [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
|
||||
81. [Markus Werle](https://github.com/daixtrose) fixed a typo.
|
||||
82. [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
|
||||
83. [Alex](https://github.com/leha-bot) noted an error in a code sample.
|
||||
84. [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped to fix them.
|
||||
85. [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams.
|
||||
86. [Sonu Lohani](https://github.com/sonulohani) fixed a small compilation error.
|
||||
87. [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings.
|
||||
88. [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file.
|
||||
89. [pvleuven](https://github.com/pvleuven) helped to fix a warning in ICC.
|
||||
90. [Pavel](https://github.com/crea7or) helped to fix some warnings in MSVC.
|
||||
91. [Jamie Seward](https://github.com/jseward) avoided unnecessary string copies in `find()` and `count()`.
|
||||
92. [Mitja](https://github.com/Itja) fixed some typos.
|
||||
93. [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links.
|
||||
94. [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view.
|
||||
95. [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings.
|
||||
96. [Eren Okka](https://github.com/erengy) fixed some MSVC warnings.
|
||||
97. [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed.
|
||||
98. [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README.
|
||||
99. [zerodefect](https://github.com/zerodefect) fixed a compiler warning.
|
||||
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. [mark-99](https://github.com/mark-99) helped fix an ICC error.
|
||||
102. [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file.
|
||||
103. [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings.
|
||||
104. [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
|
||||
105. [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
|
||||
106. [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
|
||||
107. [agrianius](https://github.com/agrianius) allowed dumping JSON to an alternative string type.
|
||||
108. [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
|
||||
109. [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
|
||||
110. [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
|
||||
111. [James Upjohn](https://github.com/jupjohn) fixed a version number in the compilers section.
|
||||
112. [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration.
|
||||
113. [Jan Schöppach](https://github.com/dns13) fixed a typo.
|
||||
114. [martin-mfg](https://github.com/martin-mfg) fixed a typo.
|
||||
115. [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`.
|
||||
116. [agrianius](https://github.com/agrianius) added code to use alternative string implementations.
|
||||
117. [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function.
|
||||
118. [Julius Rakow](https://github.com/juliusrakow) fixed the Meson include directory and fixed the links to [cppreference.com](https://cppreference.com).
|
||||
119. [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode.
|
||||
120. [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
|
||||
121. [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library.
|
||||
122. [thyu](https://github.com/thyu) fixed a compiler warning.
|
||||
123. [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2.
|
||||
124. [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library.
|
||||
125. [Hyeon Kim](https://github.com/simnalamburt) fixed an issue with a double macro definition.
|
||||
126. [Ben Berman](https://github.com/rivertam) made some error messages more understandable.
|
||||
127. [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler.
|
||||
128. [mandreyel](https://github.com/mandreyel) fixed a compilation problem.
|
||||
129. [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file.
|
||||
130. [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8.
|
||||
131. [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory.
|
||||
132. [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning.
|
||||
133. [Dan Gendreau](https://github.com/dgendreau) implemented the `NLOHMANN_JSON_SERIALIZE_ENUM` macro to quickly define an enum/JSON mapping.
|
||||
134. [efp](https://github.com/efp) added line and column information to parse errors.
|
||||
135. [julian-becker](https://github.com/julian-becker) added BSON support.
|
||||
136. [Pratik Chowdhury](https://github.com/pratikpc) added support for structured bindings.
|
||||
137. [David Avedissian](https://github.com/davedissian) added support for Clang 5.0.1 (PS4 version).
|
||||
138. [Jonathan Dumaresq](https://github.com/dumarjo) implemented an input adapter to read from `FILE*`.
|
||||
139. [kjpus](https://github.com/kjpus) fixed a link in the documentation.
|
||||
140. [Manvendra Singh](https://github.com/manu-chroma) fixed a typo in the documentation.
|
||||
141. [ziggurat29](https://github.com/ziggurat29) fixed an MSVC warning.
|
||||
142. [Sylvain Corlay](https://github.com/SylvainCorlay) added code to avoid an issue with MSVC.
|
||||
143. [mefyl](https://github.com/mefyl) fixed a bug when JSON was parsed from an input stream.
|
||||
144. [Millian Poquet](https://github.com/mpoquet) allowed to install the library via Meson.
|
||||
145. [Michael Behrns-Miller](https://github.com/moodboom) found an issue with a missing namespace.
|
||||
146. [Nasztanovics Ferenc](https://github.com/naszta) fixed a compilation issue with libc 2.12.
|
||||
147. [Andreas Schwab](https://github.com/andreas-schwab) fixed the endian conversion.
|
||||
148. [Mark-Dunning](https://github.com/Mark-Dunning) fixed a warning in MSVC.
|
||||
149. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) added `operator/` for JSON Pointers.
|
||||
150. [John-Mark](https://github.com/johnmarkwayve) noted a missing header.
|
||||
151. [Vitaly Zaitsev](https://github.com/xvitaly) fixed compilation with GCC 9.0.
|
||||
152. [Laurent Stacul](https://github.com/stac47) fixed compilation with GCC 9.0.
|
||||
153. [Ivor Wanders](https://github.com/iwanders) helped to reduce the CMake requirement to version 3.1.
|
||||
154. [njlr](https://github.com/njlr) updated the Buckaroo instructions.
|
||||
155. [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS.
|
||||
156. [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function.
|
||||
157. [past-due](https://github.com/past-due) suppressed an unfixable warning.
|
||||
158. [Elvis Oric](https://github.com/elvisoric) improved Meson support.
|
||||
159. [Matěj Plch](https://github.com/Afforix) fixed an example in the README.
|
||||
160. [Mark Beckwith](https://github.com/wythe) fixed a typo.
|
||||
161. [scinart](https://github.com/scinart) fixed a bug in the serializer.
|
||||
162. [Patrick Boettcher](https://github.com/pboettch) implemented `push_back()` and `pop_back()` for JSON Pointers.
|
||||
163. [Bruno Oliveira](https://github.com/nicoddemus) added support for Conda.
|
||||
164. [Michele Caini](https://github.com/skypjack) fixed links in the README.
|
||||
165. [Hani](https://github.com/hnkb) documented how to install the library with NuGet.
|
||||
166. [Mark Beckwith](https://github.com/wythe) fixed a typo.
|
||||
167. [yann-morin-1998](https://github.com/yann-morin-1998) helped to reduce the CMake requirement to version 3.1.
|
||||
168. [Konstantin Podsvirov](https://github.com/podsvirov) maintains a package for the MSYS2 software distro.
|
||||
169. [remyabel](https://github.com/remyabel2) added GNUInstallDirs to the CMake files.
|
||||
170. [Taylor Howard](https://github.com/taylorhoward92) fixed a unit test.
|
||||
171. [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method.
|
||||
172. [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning.
|
||||
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. [Juncheng E](https://github.com/ejcjason) fixed a typo.
|
||||
175. [tete17](https://github.com/tete17) fixed a bug in the `contains` function.
|
||||
176. [Xav83](https://github.com/Xav83) fixed some cppcheck warnings.
|
||||
177. [0xflotus](https://github.com/0xflotus) fixed some typos.
|
||||
178. [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`.
|
||||
179. [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types.
|
||||
180. [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly.
|
||||
181. [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos.
|
||||
182. [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`.
|
||||
183. [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization.
|
||||
184. [Yuriy Vountesmery](https://github.com/ua-code-dragon) noted a subtle bug in a preprocessor check.
|
||||
185. [Chen](https://github.com/dota17) fixed numerous issues in the library.
|
||||
186. [Antony Kellermann](https://github.com/aokellermann) added a CI step for GCC 10.1.
|
||||
187. [Alex](https://github.com/gistrec) fixed an MSVC warning.
|
||||
188. [Rainer](https://github.com/rvjr) proposed an improvement in the floating-point serialization in CBOR.
|
||||
189. [Francois Chabot](https://github.com/FrancoisChabot) made performance improvements in the input adapters.
|
||||
190. [Arthur Sonzogni](https://github.com/ArthurSonzogni) documented how the library can be included via `FetchContent`.
|
||||
191. [Rimas Misevičius](https://github.com/rmisev) fixed an error message.
|
||||
192. [Alexander Myasnikov](https://github.com/alexandermyasnikov) fixed some examples and a link in the README.
|
||||
193. [Hubert Chathi](https://github.com/uhoreg) made CMake's version config file architecture-independent.
|
||||
194. [OmnipotentEntity](https://github.com/OmnipotentEntity) implemented the binary values for CBOR, MessagePack, BSON, and UBJSON.
|
||||
195. [ArtemSarmini](https://github.com/ArtemSarmini) fixed a compilation issue with GCC 10 and fixed a leak.
|
||||
196. [Evgenii Sopov](https://github.com/sea5kg) integrated the library to the wsjcpp package manager.
|
||||
197. [Sergey Linev](https://github.com/linev) fixed a compiler warning.
|
||||
198. [Miguel Magalhães](https://github.com/magamig) fixed the year in the copyright.
|
||||
199. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) fixed a compilation issue with MSVC.
|
||||
200. [Alexander “weej” Jones](https://github.com/alex-weej) fixed an example in the README.
|
||||
201. [Antoine Cœur](https://github.com/Coeur) fixed some typos in the documentation.
|
||||
202. [jothepro](https://github.com/jothepro) updated links to the Hunter package.
|
||||
203. [Dave Lee](https://github.com/kastiglione) fixed a link in the README.
|
||||
204. [Joël Lamotte](https://github.com/Klaim) added instruction for using Build2's package manager.
|
||||
205. [Paul Jurczak](https://github.com/pauljurczak) fixed an example in the README.
|
||||
206. [Sonu Lohani](https://github.com/sonulohani) fixed a warning.
|
||||
207. [Carlos Gomes Martinho](https://github.com/gocarlos) updated the Conan package source.
|
||||
208. [Konstantin Podsvirov](https://github.com/podsvirov) fixed the MSYS2 package documentation.
|
||||
209. [Tridacnid](https://github.com/Tridacnid) improved the CMake tests.
|
||||
210. [Michael](https://github.com/MBalszun) fixed MSVC warnings.
|
||||
211. [Quentin Barbarat](https://github.com/quentin-dev) fixed an example in the documentation.
|
||||
212. [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
||||
213. [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README.
|
||||
214. [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
||||
215. [AODQ](https://github.com/AODQ) fixed a compiler warning.
|
||||
216. [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline.
|
||||
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. [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values.
|
||||
219. [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation.
|
||||
220. [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes.
|
||||
221. [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`.
|
||||
222. [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config.
|
||||
223. [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||
224. [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
|
||||
225. [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
|
||||
226. [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer.
|
||||
227. Lars Wirzenius reviewed the README file.
|
||||
228. [Jun Jie](https://github.com/ongjunjie) fixed a compiler path in the CMake scripts.
|
||||
229. [Ronak Buch](https://github.com/rbuch) fixed typos in the documentation.
|
||||
230. [Alexander Karzhenkov](https://github.com/karzhenkov) fixed a move constructor and the Travis builds.
|
||||
231. [Leonardo Lima](https://github.com/leozz37) added CPM.Cmake support.
|
||||
232. [Joseph Blackman](https://github.com/jbzdarkid) fixed a warning.
|
||||
233. [Yaroslav](https://github.com/YarikTH) updated doctest and implemented unit tests.
|
||||
234. [Martin Stump](https://github.com/globberwops) fixed a bug in the CMake files.
|
||||
235. [Jaakko Moisio](https://github.com/jasujm) fixed a bug in the input adapters.
|
||||
236. [bl-ue](https://github.com/bl-ue) fixed some Markdown issues in the README file.
|
||||
237. [William A. Wieselquist](https://github.com/wawiesel) fixed an example from the README.
|
||||
238. [abbaswasim](https://github.com/abbaswasim) fixed an example from the README.
|
||||
239. [Remy Jette](https://github.com/remyjette) fixed a warning.
|
||||
240. [Fraser](https://github.com/frasermarlow) fixed the documentation.
|
||||
241. [Ben Beasley](https://github.com/musicinmybrain) updated doctest.
|
||||
242. [Doron Behar](https://github.com/doronbehar) fixed pkg-config.pc.
|
||||
243. [raduteo](https://github.com/raduteo) fixed a warning.
|
||||
244. [David Pfahler](https://github.com/theShmoo) added the possibility to compile the library without I/O support.
|
||||
245. [Morten Fyhn Amundsen](https://github.com/mortenfyhn) fixed a typo.
|
||||
246. [jpl-mac](https://github.com/jpl-mac) allowed treating the library as a system header in CMake.
|
||||
247. [Jason Dsouza](https://github.com/jasmcaus) fixed the indentation of the CMake file.
|
||||
248. [offa](https://github.com/offa) added a link to Conan Center to the documentation.
|
||||
249. [TotalCaesar659](https://github.com/TotalCaesar659) updated the links in the documentation to use HTTPS.
|
||||
250. [Rafail Giavrimis](https://github.com/grafail) fixed the Google Benchmark default branch.
|
||||
251. [Louis Dionne](https://github.com/ldionne) fixed a conversion operator.
|
||||
252. [justanotheranonymoususer](https://github.com/justanotheranonymoususer) made the examples in the README more consistent.
|
||||
253. [Finkman](https://github.com/Finkman) suppressed some `-Wfloat-equal` warnings.
|
||||
254. [Ferry Huberts](https://github.com/fhuberts) fixed `-Wswitch-enum` warnings.
|
||||
255. [Arseniy Terekhin](https://github.com/senyai) made the GDB pretty-printer robust against unset variable names.
|
||||
256. [Amir Masoud Abdol](https://github.com/amirmasoudabdol) updated the Homebrew command as nlohmann/json is now in homebrew-core.
|
||||
257. [Hallot](https://github.com/Hallot) fixed some `-Wextra-semi-stmt warnings`.
|
||||
258. [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS`.
|
||||
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. [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`.
|
||||
261. [miikka75](https://github.com/miikka75) provided an important fix to compile C++17 code with Clang 9.
|
||||
262. [Maarten Becker](https://github.com/kernie) fixed a warning for shadowed variables.
|
||||
263. [Cristi Vîjdea](https://github.com/axnsan12) fixed typos in the `operator[]` documentation.
|
||||
264. [Alex Beregszaszi](https://github.com/axic) fixed spelling mistakes in comments.
|
||||
265. [Dirk Stolle](https://github.com/striezel) fixed typos in documentation.
|
||||
266. [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation.
|
||||
267. [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ.
|
||||
268. [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements.
|
||||
269. [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format.
|
||||
270. [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
|
||||
271. [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines.
|
||||
272. [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC.
|
||||
273. [Giovanni Cerretani](https://github.com/gcerretani) fixed a check for `std::filesystem`.
|
||||
274. [Dimitris Apostolou](https://github.com/rex4539) fixed a typo.
|
||||
275. [Ferry Huberts](https://github.com/fhuberts) fixed a typo.
|
||||
276. [Michael Nosthoff](https://github.com/heinemml) fixed a typo.
|
||||
277. [JungHoon Lee](https://github.com/jhnlee) fixed a typo.
|
||||
278. [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file.
|
||||
279. [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation.
|
||||
280. [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`.
|
||||
281. [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo.
|
||||
282. [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error.
|
||||
283. [KsaNL](https://github.com/KsaNL) fixed a build error when including `<windows.h>`.
|
||||
284. [Andrea Pappacoda](https://github.com/Tachi107) moved `.pc` and `.cmake` files to `share` directory.
|
||||
285. [Wolf Vollprecht](https://github.com/wolfv) added the `patch_inplace` function.
|
||||
286. [Jake Zimmerman](https://github.com/jez) highlighted common usage patterns in the README file.
|
||||
287. [NN](https://github.com/NN---) added the Visual Studio output directory to `.gitignore`.
|
||||
288. [Romain Reignier](https://github.com/romainreignier) improved the performance of the vector output adapter.
|
||||
289. [Mike](https://github.com/Mike-Leo-Smith) fixed the `std::iterator_traits`.
|
||||
290. [Richard Hozák](https://github.com/richardhozak) added macro `JSON_NO_ENUM` to disable default enum conversions.
|
||||
291. [vakokako](https://github.com/vakokako) fixed tests when compiling with C++20.
|
||||
292. [Alexander “weej” Jones](https://github.com/alexweej) fixed an example in the README.
|
||||
293. [Eli Schwartz](https://github.com/eli-schwartz) added more files to the `include.zip` archive.
|
||||
294. [Kevin Lu](https://github.com/kevinlul) fixed a compilation issue when typedefs with certain names were present.
|
||||
295. [Trevor Hickey](https://github.com/luxe) improved the description of an example.
|
||||
296. [Jef LeCompte](https://github.com/jef) updated the year in the README file.
|
||||
297. [Alexandre Hamez](https://github.com/ahamez) fixed a warning.
|
||||
298. [Maninderpal Badhan](https://github.com/mbadhan) fixed a typo.
|
||||
299. [kevin--](https://github.com/kevin--) added a note to an example in the README file.
|
||||
300. [I](https://github.com/wx257osn2) fixed a typo.
|
||||
301. [Gregorio Litenstein](https://github.com/Lord-Kamina) fixed the Clang detection.
|
||||
302. [Andreas Smas](https://github.com/andoma) added a Doozer badge.
|
||||
303. [WanCW](https://github.com/wancw) fixed the string conversion with Clang.
|
||||
304. [zhaohuaxishi](https://github.com/zhaohuaxishi) fixed a Doxygen error.
|
||||
305. [emvivre](https://github.com/emvivre) removed an invalid parameter from CMake.
|
||||
306. [Tobias Hermann](https://github.com/Dobiasd) fixed a link in the README file.
|
||||
307. [Michael](https://github.com/traits) fixed a warning.
|
||||
308. [Ryan Mulder](https://github.com/ryanjmulder) added `ensure_ascii` to the `dump` function.
|
||||
309. [Muri Nicanor](https://github.com/murinicanor) fixed the `sed` discovery in the Makefile.
|
||||
310. [David Avedissian](https://github.com/dgavedissian) implemented SFINAE-friendly `iterator_traits`.
|
||||
311. [AQNOUCH Mohammed](https://github.com/aqnouch) fixed a typo in the README.
|
||||
312. [Gareth Sylvester-Bradley](https://github.com/garethsb) added `operator/=` and `operator/` to construct JSON pointers.
|
||||
313. [Michael Macnair](https://github.com/mykter) added support for afl-fuzz testing.
|
||||
314. [Berkus Decker](https://github.com/berkus) fixed a typo in the README.
|
||||
315. [Illia Polishchuk](https://github.com/ilqvya) improved the CMake testing.
|
||||
316. [Ikko Ashimine](https://github.com/eltociear) fixed a typo.
|
||||
317. [Raphael Grimm](https://github.com/barcode) added the possibility to define a custom base class.
|
||||
318. [tocic](https://github.com/tocic) fixed typos in the documentation.
|
||||
319. [Vertexwahn](https://github.com/Vertexwahn) added Bazel build support.
|
||||
320. [Dirk Stolle](https://github.com/striezel) fixed typos in the documentation.
|
||||
321. [DavidKorczynski](https://github.com/DavidKorczynski) added a CIFuzz CI GitHub action.
|
||||
322. [Finkman](https://github.com/Finkman) fixed the debug pretty-printer.
|
||||
323. [Florian Segginger](https://github.com/floriansegginger) bumped the years in the README.
|
||||
324. [haadfida](https://github.com/haadfida) cleaned up the badges of used services.
|
||||
325. [Arsen Arsenović](https://github.com/ArsenArsen) fixed a build error.
|
||||
326. [theevilone45](https://github.com/theevilone45) fixed a typo in a CMake file.
|
||||
327. [Sergei Trofimovich](https://github.com/trofi) fixed the custom allocator support.
|
||||
328. [Joyce](https://github.com/joycebrum) fixed some security issues in the GitHub workflows.
|
||||
329. [Nicolas Jakob](https://github.com/njakob) add vcpkg version badge.
|
||||
330. [Tomerkm](https://github.com/Tomerkm) added tests.
|
||||
331. [No.](https://github.com/tusooa) fixed the use of `get<>` calls.
|
||||
332. [taro](https://github.com/tarolling) fixed a typo in the `CODEOWNERS` file.
|
||||
333. [Ikko Eltociear Ashimine](https://github.com/eltociear) fixed a typo.
|
||||
334. [Felix Yan](https://github.com/felixonmars) fixed a typo in the README.
|
||||
335. [HO-COOH](https://github.com/HO-COOH) fixed a parenthesis in the documentation.
|
||||
336. [Ivor Wanders](https://github.com/iwanders) fixed the examples to catch exception by `const&`.
|
||||
337. [miny1233](https://github.com/miny1233) fixed a parenthesis in the documentation.
|
||||
338. [tomalakgeretkal](https://github.com/tomalakgeretkal) fixed a compilation error.
|
||||
339. [alferov](https://github.com/ALF-ONE) fixed a compilation error.
|
||||
340. [Craig Scott](https://github.com/craigscott-crascit) fixed a deprecation warning in CMake.
|
||||
341. [Vyacheslav Zhdanovskiy](https://github.com/ZeronSix) added macros for serialization-only types.
|
||||
342. [Mathieu Westphal](https://github.com/mwestphal) fixed typos.
|
||||
343. [scribam](https://github.com/scribam) fixed the MinGW workflow.
|
||||
344. [Aleksei Sapitskii](https://github.com/aleksproger) added support for Apple's Swift Package Manager.
|
||||
345. [Benjamin Buch](https://github.com/bebuch) fixed the installation path in CMake.
|
||||
346. [Colby Haskell](https://github.com/colbychaskell) clarified the parse error message in case a file cannot be opened.
|
||||
347. [Juan Carlos Arevalo Baeza](https://github.com/TheJCAB) fixed the enum conversion.
|
||||
348. [alferov](https://github.com/ALF-ONE) fixed a version in the documentation.
|
||||
349. [ss](https://github.com/serge-s) fixed the amalgamation call.
|
||||
350. [AniketDhemare](https://github.com/AniketDhemare) fixed a version in the documentation.
|
||||
351. [Philip Müller](https://github.com/philip-paul-mueller) fixed an example.
|
||||
352. [Leila Shcheglova](https://github.com/LeilaShcheglova) fixed a warning in a test.
|
||||
353. [Alex Prabhat Bara](https://github.com/alexprabhat99) fixed a function name in the documentation.
|
||||
354. [laterlaugh](https://github.com/laterlaugh) fixed some typos.
|
||||
355. [Yuanhao Jia](https://github.com/MrJia1997) fixed the GDB pretty printer.
|
||||
356. [Fallen_Breath](https://github.com/Fallen-Breath) fixed an example for JSON Pointer.
|
||||
357. [Nikhil Idiculla](https://github.com/tsnl) fixed some typos.
|
||||
358. [Griffin Myers](https://github.com/gmyers18) updated the Natvis file.
|
||||
359. [thetimr](https://github.com/thetimr) fixed a typo in the documentation.
|
||||
360. [Balazs Erseki](https://github.com/zerocukor287) fixed a URL in the contribution guidelines.
|
||||
361. [Niccolò Iardella](https://github.com/rotolof) added `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||
362. [Borislav Stanimirov](https://github.com/iboB) allowed overriding the CMake target name.
|
||||
363. [Captain Crutches](https://github.com/captaincrutches) made `iterator_proxy_value` a `std::forward_iterator`.
|
||||
364. [Fredrik Sandhei](https://github.com/fsandhei) added type conversion support for `std::optional`.
|
||||
365. [jh96](https://github.com/jordan-hoang) added exceptions when `nullptr` is passed to `parse`.
|
||||
366. [Stuart Gorman](https://github.com/StuartGorman) fixed number parsing when `EINTR` set in `errno`.
|
||||
367. [Dylan Baker](https://github.com/dcbaker) generated a pkg-config file that follows the pkg-config conventions.
|
||||
368. [Tianyi Chen](https://github.com/TianyiChen) optimized the binary `get_number` implementation.
|
||||
369. [peng-wang-cn](https://github.com/peng-wang-cn) added type conversion support for multidimensional arrays.
|
||||
370. [Einars Netlis-Galejs](https://github.com/EinarsNG) added `ONLY_SERIALIZE` for `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||
371. [Marcel](https://github.com/mering) removed `alwayslink=True` Bazel flag.
|
||||
372. [Harinath Nampally](https://github.com/hnampally) added diagnostic positions to exceptions.
|
||||
373. [Nissim Armand Ben Danan](https://github.com/NissimBendanan) fixed `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` with an empty JSON instance.
|
||||
374. [Michael Valladolid](https://github.com/codenut) added support for BSON uint64 serialization/deserialization.
|
||||
375. [Nikhil](https://github.com/nikhilreddydev) updated the documentation.
|
||||
376. [Nebojša Cvetković](https://github.com/nebkat) added support for BJDATA optimized binary array type.
|
||||
377. [Sushrut Shringarputale](https://github.com/sushshring) added support for diagnostic positions.
|
||||
378. [kimci86](https://github.com/kimci86) templated to `NLOHMANN_DEFINE_TYPE` macros to also support `ordered_json`.
|
||||
379. [Richard Topchii](https://github.com/richardtop) added support for VisionOS in the Swift Package Manager.
|
||||
380. [Robert Chisholm](https://github.com/Robadob) fixed a typo.
|
||||
381. [zjyhjqs](https://github.com/zjyhjqs) added CPack support.
|
||||
382. [bitFiedler](https://github.com/bitFiedler) made GDB pretty printer work with Python 3.8.
|
||||
383. [Gianfranco Costamagna](https://github.com/LocutusOfBorg) fixed a compiler warning.
|
||||
384. [risa2000](https://github.com/risa2000) made `std::filesystem::path` conversion to/from UTF-8 encoded string explicit.
|
||||
385. [AM](https://github.com/maqnouch) fixed typos in the README.
|
||||
386. [dmenendez-gruposantander](https://github.com/dmenendez-gruposantander) fixed typos in the comments of the examples.
|
||||
387. [Mihai Stan](https://github.com/mstan-xx) fixed comparisons against the literal `0`.
|
||||
388. [Matt Gumbel](https://github.com/intelmatt) fixed some `-Weffc++` warnings.
|
||||
389. [vimpunk](https://github.com/vimpunk) moved a lambda out of an unevaluated context to support older compilers.
|
||||
390. [Chris Harris](https://github.com/cjh1) fixed the compilation with GCC 4.8.
|
||||
391. [Palmer Dabbelt](https://github.com/palmer-dabbelt) generated and installed a pkg-config file.
|
||||
392. [Gus Pozuelo](https://github.com/ap-viavi) made `ordered_map` compatible with GCC 5.5, Clang 3.6, and Xcode 9.
|
||||
393. [AK](https://github.com/Lioncky) fixed an MSVC build error caused by the `min`/`max` macros from `windows.h`.
|
||||
394. [Sergiu Deitsch](https://github.com/sergiud) provided a fallback for missing `char8_t` support.
|
||||
395. [Xiaochuan Ye](https://github.com/XueSongTap) fixed `from_msgpack` for `std::byte` input by specializing `std::char_traits`.
|
||||
396. [Ville Vesilehto](https://github.com/thevilledev) fixed an overflow in the BJData size calculation and rejected overflowing negative integers in CBOR.
|
||||
397. [NmPassTHFan](https://github.com/nmpassthf) replaced the deprecated `std::is_trivial` for C++26.
|
||||
398. [Chris Ever](https://github.com/chirsz-ever) added the `ignore_trailing_commas` parser option.
|
||||
399. [Kuan-Fu Wu](https://github.com/kfwu1999) fixed the example code for `json_pointer` initialization.
|
||||
400. [David Kilzer](https://github.com/ddkilzer) added a missing header to the input adapters.
|
||||
401. [Miko](https://github.com/mikomikotaishi) added proper C++20 module support, simplified the module API, and fixed missing exports.
|
||||
402. [hitgirl](https://github.com/hitgil) fixed the CMake configuration when cross-compiling.
|
||||
403. [Devon Thomas](https://github.com/ThomaDevOSU) mentioned the Artistic Style formatting in the contribution guidelines.
|
||||
404. [Erik Hu](https://github.com/Erikhu1) made Coveralls upload errors non-fatal in the CI.
|
||||
405. [co63oc](https://github.com/co63oc) fixed typos.
|
||||
406. [DmitriBogdanov](https://github.com/DmitriBogdanov) fixed broken package manager links in the documentation.
|
||||
407. [Bander](https://github.com/banderzhm) improved the MSVC compatibility of the C++ modules.
|
||||
408. [Andy Choi](https://github.com/ccpong) removed an unnecessary `template` keyword before `get` in the README and the documentation.
|
||||
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. [Aditya](https://github.com/Lumowhisp) improved the documentation of the documentation generation.
|
||||
411. [cheese1](https://github.com/cheese1) clarified the README.
|
||||
412. [KhloodElhossiny](https://github.com/khloodelhossiny) enabled `std::string_view` keys in `operator[]`.
|
||||
413. [Charles Cabergs](https://github.com/cacharle) fixed a `-Wtautological-constant-out-of-range-compare` warning.
|
||||
414. [EALePain](https://github.com/EALePain) made the `std::tuple` conversion work with reference types such as `std::tie`.
|
||||
415. [koala_oishi](https://github.com/chibi-dogs) fixed grammatical wording in the README.
|
||||
416. [riccardoori11](https://github.com/riccardoori11) fixed a typo in the documentation.
|
||||
417. [Swastik Bose](https://github.com/VasuBhakt) fixed the parent pointers after `update()` with `JSON_DIAGNOSTICS` and fixed the Doxygen autolinking of requirements.
|
||||
418. [trdesilva](https://github.com/trdesilva) added `front`, `pop_front`, and `push_front` to `json_pointer`.
|
||||
419. [Akhilesh Arora](https://github.com/akhilesharora) fixed an incomplete-type error with `ordered_json`.
|
||||
420. [Hariom Phulre](https://github.com/hariomphulre) fixed the C++20 modules compilation with GCC.
|
||||
421. [Kirill Lokotkov](https://github.com/RUSLoker) fixed printing `long double` values.
|
||||
422. [George Sedov](https://github.com/radistmorse) added the `NLOHMANN_DEFINE_TYPE_*_WITH_NAMES` macros.
|
||||
423. [Caillin Nugent](https://github.com/nugentcaillin) added the `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` macro.
|
||||
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.
|
||||
20. [ZahlGraf](https://github.com/ZahlGraf) added a workaround that allows compilation using Android NDK.
|
||||
21. [whackashoe](https://github.com/whackashoe) replaced a function that was marked as unsafe by Visual Studio.
|
||||
22. [406345](https://github.com/406345) fixed two small warnings.
|
||||
23. [Glen Fernandes](https://github.com/glenfe) noted a potential portability problem in the `has_mapped_type` function.
|
||||
24. [Corbin Hughes](https://github.com/nibroc) fixed some typos in the contribution guidelines.
|
||||
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.
|
||||
26. [Volker Diels-Grabsch](https://github.com/vog) fixed a link in the README file.
|
||||
27. [msm-](https://github.com/msm-) added support for American Fuzzy Lop.
|
||||
28. [Annihil](https://github.com/Annihil) fixed an example in the README file.
|
||||
29. [Themercee](https://github.com/Themercee) noted a wrong URL in the README file.
|
||||
30. [Lv Zheng](https://github.com/lv-zheng) fixed a namespace issue with `int64_t` and `uint64_t`.
|
||||
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).
|
||||
32. [zewt](https://github.com/zewt) added useful notes to the README file about Android.
|
||||
33. [Róbert Márki](https://github.com/robertmrk) added a fix to use move iterators and improved the integration via CMake.
|
||||
34. [Chris Kitching](https://github.com/ChrisKitching) cleaned up the CMake files.
|
||||
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).
|
||||
36. [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
||||
37. [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
||||
38. [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
||||
39. [Thomas Braun](https://github.com/t-b) fixed a warning in a test case and adjusted MSVC calls in the CI.
|
||||
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.
|
||||
41. [Stefan](https://github.com/5tefan) fixed a minor issue in the documentation.
|
||||
42. [Vasil Dimov](https://github.com/vasild) fixed the documentation regarding conversions from `std::multiset`.
|
||||
43. [ChristophJud](https://github.com/ChristophJud) overworked the CMake files to ease project inclusion.
|
||||
44. [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
|
||||
45. [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
|
||||
46. [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
|
||||
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.
|
||||
48. [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
|
||||
49. [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning and supported the implementation of user-defined types.
|
||||
50. [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
|
||||
51. [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
|
||||
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.
|
||||
53. [Jonathan Lee](https://github.com/vjon) fixed an example in the README file.
|
||||
54. [gnzlbg](https://github.com/gnzlbg) supported the implementation of user-defined types.
|
||||
55. [Alexej Harm](https://github.com/qis) helped to get the user-defined types working with Visual Studio.
|
||||
56. [EnricoBilla](https://github.com/EnricoBilla) noted a typo in an example.
|
||||
57. [Martin Hořeňovský](https://github.com/horenmar) found a way for a 2x speedup for the compilation time of the test suite.
|
||||
58. [ukhegg](https://github.com/ukhegg) proposed an improvement for the examples section.
|
||||
59. [rswanson-ihi](https://github.com/rswanson-ihi) noted a typo in the README.
|
||||
60. [Mihai Stan](https://github.com/stanmihai4) fixed a bug in the comparison with `nullptr`s.
|
||||
61. [Tushar Maheshwari](https://github.com/tusharpm) added [cotire](https://github.com/sakra/cotire) support to speed up the compilation.
|
||||
62. [TedLyngmo](https://github.com/TedLyngmo) noted a typo in the README, removed unnecessary bit arithmetic, and fixed some `-Weffc++` warnings.
|
||||
63. [Krzysztof Woś](https://github.com/krzysztofwos) made exceptions more visible.
|
||||
64. [ftillier](https://github.com/ftillier) fixed a compiler warning.
|
||||
65. [tinloaf](https://github.com/tinloaf) made sure all pushed warnings are properly popped.
|
||||
66. [Fytch](https://github.com/Fytch) found a bug in the documentation.
|
||||
67. [Jay Sistar](https://github.com/Type1J) implemented a Meson build description.
|
||||
68. [Henry Lee](https://github.com/HenryRLee) fixed a warning in ICC and improved the iterator implementation.
|
||||
69. [Vincent Thiery](https://github.com/vthiery) maintains a package for the Conan package manager.
|
||||
70. [Steffen](https://github.com/koemeet) fixed a potential issue with MSVC and `std::min`.
|
||||
71. [Mike Tzou](https://github.com/Chocobo1) fixed some typos.
|
||||
72. [amrcode](https://github.com/amrcode) noted misleading documentation about comparison of floats.
|
||||
73. [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
|
||||
74. [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
|
||||
75. [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
|
||||
76. [Greg Hurrell](https://github.com/wincent) fixed a typo.
|
||||
77. [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
|
||||
78. [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
|
||||
79. [Markus Werle](https://github.com/daixtrose) fixed a typo.
|
||||
80. [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
|
||||
81. [Alex](https://github.com/leha-bot) noted an error in a code sample.
|
||||
82. [Tom de Geus](https://github.com/tdegeus) reported some warnings with ICC and helped to fix them.
|
||||
83. [Perry Kundert](https://github.com/pjkundert) simplified reading from input streams.
|
||||
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.
|
||||
85. [Jamie Seward](https://github.com/jseward) fixed all MSVC warnings and avoided unnecessary string copies in `find()` and `count()`.
|
||||
86. [Nate Vargas](https://github.com/eld00d) added a Doxygen tag file.
|
||||
87. [pvleuven](https://github.com/pvleuven) helped to fix a warning in ICC.
|
||||
88. [Pavel](https://github.com/crea7or) helped to fix some warnings in MSVC.
|
||||
89. [Mitja](https://github.com/Itja) fixed some typos.
|
||||
90. [Jorrit Wronski](https://github.com/jowr) updated the Hunter package links.
|
||||
91. [Matthias Möller](https://github.com/TinyTinni) added a `.natvis` for the MSVC debug view and removed the dependency from `std::stringstream`.
|
||||
92. [bogemic](https://github.com/bogemic) fixed some C++17 deprecation warnings.
|
||||
93. [Eren Okka](https://github.com/erengy) fixed some MSVC warnings.
|
||||
94. [abolz](https://github.com/abolz) integrated the Grisu2 algorithm for proper floating-point formatting, allowing more roundtrip checks to succeed.
|
||||
95. [Vadim Evard](https://github.com/Pipeliner) fixed a Markdown issue in the README.
|
||||
96. [zerodefect](https://github.com/zerodefect) fixed a compiler warning.
|
||||
97. [Kert](https://github.com/kaidokert) allowed to template the string type in the serialization and added the possibility to override the exceptional behavior.
|
||||
98. [mark-99](https://github.com/mark-99) helped fix an ICC error.
|
||||
99. [Patrik Huber](https://github.com/patrikhuber) fixed links in the README file.
|
||||
100. [johnfb](https://github.com/johnfb) found a bug in the implementation of CBOR's indefinite length strings.
|
||||
101. [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
|
||||
102. [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
|
||||
103. [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
|
||||
104. [agrianius](https://github.com/agrianius) allowed dumping JSON to an alternative string type and added code to use alternative string implementations.
|
||||
105. [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
|
||||
106. [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
|
||||
107. [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
|
||||
108. [James Upjohn](https://github.com/jupjohn) fixed a version number in the compilers section.
|
||||
109. [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines and provided documentation for the CMake integration.
|
||||
110. [Jan Schöppach](https://github.com/dns13) fixed a typo.
|
||||
111. [martin-mfg](https://github.com/martin-mfg) fixed a typo.
|
||||
112. [Julius Rakow](https://github.com/juliusrakow) fixed the Meson include directory and fixed the links to [cppreference.com](https://cppreference.com).
|
||||
113. [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
|
||||
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.
|
||||
115. [thyu](https://github.com/thyu) fixed a compiler warning.
|
||||
116. [David Guthrie](https://github.com/LEgregius) fixed a subtle compilation error with Clang 3.4.2.
|
||||
117. [Dennis Fischer](https://github.com/dennisfischer) allowed to call `find_package` without installing the library.
|
||||
118. [Ben Berman](https://github.com/rivertam) made some error messages more understandable.
|
||||
119. [zakalibit](https://github.com/zakalibit) fixed a compilation problem with the Intel C++ compiler.
|
||||
120. [mandreyel](https://github.com/mandreyel) fixed a compilation problem.
|
||||
121. [Kostiantyn Ponomarenko](https://github.com/koponomarenko) added version and license information to the Meson build file.
|
||||
122. [Henry Schreiner](https://github.com/henryiii) added support for GCC 4.8.
|
||||
123. [knilch](https://github.com/knilch0r) made sure the test suite does not stall when run in the wrong directory.
|
||||
124. [Antonio Borondo](https://github.com/antonioborondo) fixed an MSVC 2017 warning.
|
||||
125. [Dan Gendreau](https://github.com/dgendreau) implemented the `NLOHMANN_JSON_SERIALIZE_ENUM` macro to quickly define an enum/JSON mapping.
|
||||
126. [efp](https://github.com/efp) added line and column information to parse errors.
|
||||
127. [julian-becker](https://github.com/julian-becker) added BSON support.
|
||||
128. [Pratik Chowdhury](https://github.com/pratikpc) added support for structured bindings.
|
||||
129. [David Avedissian](https://github.com/davedissian) added support for Clang 5.0.1 (PS4 version).
|
||||
130. [Jonathan Dumaresq](https://github.com/dumarjo) implemented an input adapter to read from `FILE*`.
|
||||
131. [kjpus](https://github.com/kjpus) fixed a link in the documentation.
|
||||
132. [Manvendra Singh](https://github.com/manu-chroma) fixed a typo in the documentation.
|
||||
133. [ziggurat29](https://github.com/ziggurat29) fixed an MSVC warning.
|
||||
134. [Sylvain Corlay](https://github.com/SylvainCorlay) added code to avoid an issue with MSVC.
|
||||
135. [mefyl](https://github.com/mefyl) fixed a bug when JSON was parsed from an input stream.
|
||||
136. [Millian Poquet](https://github.com/mpoquet) allowed to install the library via Meson.
|
||||
137. [Michael Behrns-Miller](https://github.com/moodboom) found an issue with a missing namespace.
|
||||
138. [Nasztanovics Ferenc](https://github.com/naszta) fixed a compilation issue with libc 2.12.
|
||||
139. [Andreas Schwab](https://github.com/andreas-schwab) fixed the endian conversion.
|
||||
140. [Mark-Dunning](https://github.com/Mark-Dunning) fixed a warning in MSVC.
|
||||
141. [Gareth Sylvester-Bradley](https://github.com/garethsb-sony) added `operator/` for JSON Pointers and fixed a compilation issue with MSVC.
|
||||
142. [John-Mark](https://github.com/johnmarkwayve) noted a missing header.
|
||||
143. [Vitaly Zaitsev](https://github.com/xvitaly) fixed compilation with GCC 9.0.
|
||||
144. [Laurent Stacul](https://github.com/stac47) fixed compilation with GCC 9.0.
|
||||
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&`.
|
||||
146. [njlr](https://github.com/njlr) updated the Buckaroo instructions.
|
||||
147. [Lion](https://github.com/lieff) fixed a compilation issue with GCC 7 on CentOS.
|
||||
148. [Isaac Nickaein](https://github.com/nickaein) improved the integer serialization performance and implemented the `contains()` function.
|
||||
149. [past-due](https://github.com/past-due) suppressed an unfixable warning.
|
||||
150. [Elvis Oric](https://github.com/elvisoric) improved Meson support.
|
||||
151. [Matěj Plch](https://github.com/Afforix) fixed an example in the README.
|
||||
152. [Mark Beckwith](https://github.com/wythe) fixed two typos.
|
||||
153. [scinart](https://github.com/scinart) fixed a bug in the serializer.
|
||||
154. [Patrick Boettcher](https://github.com/pboettch) implemented `push_back()` and `pop_back()` for JSON Pointers.
|
||||
155. [Bruno Oliveira](https://github.com/nicoddemus) added support for Conda.
|
||||
156. [Michele Caini](https://github.com/skypjack) fixed links in the README.
|
||||
157. [Hani](https://github.com/hnkb) documented how to install the library with NuGet.
|
||||
158. [yann-morin-1998](https://github.com/yann-morin-1998) helped to reduce the CMake requirement to version 3.1.
|
||||
159. [Konstantin Podsvirov](https://github.com/podsvirov) maintains a package for the MSYS2 software distro and fixed the MSYS2 package documentation.
|
||||
160. [remyabel](https://github.com/remyabel2) added GNUInstallDirs to the CMake files.
|
||||
161. [Taylor Howard](https://github.com/taylorhoward92) fixed a unit test.
|
||||
162. [Gabe Ron](https://github.com/Macr0Nerd) implemented the `to_string` method.
|
||||
163. [Watal M. Iwasaki](https://github.com/heavywatal) fixed a Clang warning.
|
||||
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)
|
||||
165. [Juncheng E](https://github.com/ejcjason) fixed a typo.
|
||||
166. [tete17](https://github.com/tete17) fixed a bug in the `contains` function.
|
||||
167. [Xav83](https://github.com/Xav83) fixed some cppcheck warnings.
|
||||
168. [0xflotus](https://github.com/0xflotus) fixed some typos.
|
||||
169. [Christian Deneke](https://github.com/chris0x44) added a const version of `json_pointer::back`.
|
||||
170. [Julien Hamaide](https://github.com/crazyjul) made the `items()` function work with custom string types.
|
||||
171. [Evan Nemerson](https://github.com/nemequ) updated fixed a bug in Hedley and updated this library accordingly.
|
||||
172. [Florian Pigorsch](https://github.com/flopp) fixed a lot of typos.
|
||||
173. [Camille Bégué](https://github.com/cbegue) fixed an issue in the conversion from `std::pair` and `std::tuple` to `json`.
|
||||
174. [Anthony VH](https://github.com/AnthonyVH) fixed a compile error in an enum deserialization.
|
||||
175. [Yuriy Vountesmery](https://github.com/ua-code-dragon) noted a subtle bug in a preprocessor check.
|
||||
176. [Chen](https://github.com/dota17) fixed numerous issues in the library.
|
||||
177. [Antony Kellermann](https://github.com/aokellermann) added a CI step for GCC 10.1.
|
||||
178. [Alex](https://github.com/gistrec) fixed an MSVC warning.
|
||||
179. [Rainer](https://github.com/rvjr) proposed an improvement in the floating-point serialization in CBOR.
|
||||
180. [Francois Chabot](https://github.com/FrancoisChabot) made performance improvements in the input adapters.
|
||||
181. [Arthur Sonzogni](https://github.com/ArthurSonzogni) documented how the library can be included via `FetchContent`.
|
||||
182. [Rimas Misevičius](https://github.com/rmisev) fixed an error message.
|
||||
183. [Alexander Myasnikov](https://github.com/alexandermyasnikov) fixed some examples and a link in the README.
|
||||
184. [Hubert Chathi](https://github.com/uhoreg) made CMake's version config file architecture-independent.
|
||||
185. [OmnipotentEntity](https://github.com/OmnipotentEntity) implemented the binary values for CBOR, MessagePack, BSON, and UBJSON.
|
||||
186. [ArtemSarmini](https://github.com/ArtemSarmini) fixed a compilation issue with GCC 10 and fixed a leak.
|
||||
187. [Evgenii Sopov](https://github.com/sea5kg) integrated the library to the wsjcpp package manager.
|
||||
188. [Sergey Linev](https://github.com/linev) fixed a compiler warning.
|
||||
189. [Miguel Magalhães](https://github.com/magamig) fixed the year in the copyright.
|
||||
190. [Alexander “weej” Jones](https://github.com/alex-weej) fixed an example in the README.
|
||||
191. [Antoine Cœur](https://github.com/Coeur) fixed some typos in the documentation.
|
||||
192. [jothepro](https://github.com/jothepro) updated links to the Hunter package.
|
||||
193. [Dave Lee](https://github.com/kastiglione) fixed a link in the README.
|
||||
194. [Joël Lamotte](https://github.com/Klaim) added instruction for using Build2's package manager.
|
||||
195. [Paul Jurczak](https://github.com/pauljurczak) fixed an example in the README.
|
||||
196. [Carlos Gomes Martinho](https://github.com/gocarlos) updated the Conan package source.
|
||||
197. [Tridacnid](https://github.com/Tridacnid) improved the CMake tests.
|
||||
198. [Michael](https://github.com/MBalszun) fixed MSVC warnings.
|
||||
199. [Quentin Barbarat](https://github.com/quentin-dev) fixed an example in the documentation.
|
||||
200. [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
||||
201. [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README and updated the links in the documentation to use HTTPS.
|
||||
202. [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
||||
203. [AODQ](https://github.com/AODQ) fixed a compiler warning.
|
||||
204. [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline.
|
||||
205. [pfeatherstone](https://github.com/pfeatherstone) improved the upper bound of arguments of the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||
206. [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values.
|
||||
207. [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation.
|
||||
208. [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes.
|
||||
209. [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`.
|
||||
210. [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config.
|
||||
211. [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||
212. [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
|
||||
213. [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
|
||||
214. [Hannes Domani](https://github.com/ssbssa) provided a GDB pretty printer.
|
||||
215. Lars Wirzenius reviewed the README file.
|
||||
216. [Jun Jie](https://github.com/ongjunjie) fixed a compiler path in the CMake scripts.
|
||||
217. [Ronak Buch](https://github.com/rbuch) fixed typos in the documentation.
|
||||
218. [Alexander Karzhenkov](https://github.com/karzhenkov) fixed a move constructor and the Travis builds.
|
||||
219. [Leonardo Lima](https://github.com/leozz37) added CPM.Cmake support.
|
||||
220. [Joseph Blackman](https://github.com/jbzdarkid) fixed a warning.
|
||||
221. [Yaroslav](https://github.com/YarikTH) updated doctest and implemented unit tests.
|
||||
222. [Martin Stump](https://github.com/globberwops) fixed a bug in the CMake files.
|
||||
223. [Jaakko Moisio](https://github.com/jasujm) fixed a bug in the input adapters.
|
||||
224. [bl-ue](https://github.com/bl-ue) fixed some Markdown issues in the README file.
|
||||
225. [William A. Wieselquist](https://github.com/wawiesel) fixed an example from the README.
|
||||
226. [abbaswasim](https://github.com/abbaswasim) fixed an example from the README.
|
||||
227. [Remy Jette](https://github.com/remyjette) fixed a warning.
|
||||
228. [Fraser](https://github.com/frasermarlow) fixed the documentation.
|
||||
229. [Ben Beasley](https://github.com/musicinmybrain) updated doctest.
|
||||
230. [Doron Behar](https://github.com/doronbehar) fixed pkg-config.pc.
|
||||
231. [raduteo](https://github.com/raduteo) fixed a warning.
|
||||
232. [David Pfahler](https://github.com/theShmoo) added the possibility to compile the library without I/O support.
|
||||
233. [Morten Fyhn Amundsen](https://github.com/mortenfyhn) fixed a typo.
|
||||
234. [jpl-mac](https://github.com/jpl-mac) allowed treating the library as a system header in CMake.
|
||||
235. [Jason Dsouza](https://github.com/jasmcaus) fixed the indentation of the CMake file.
|
||||
236. [offa](https://github.com/offa) added a link to Conan Center to the documentation.
|
||||
237. [Rafail Giavrimis](https://github.com/grafail) fixed the Google Benchmark default branch.
|
||||
238. [Louis Dionne](https://github.com/ldionne) fixed a conversion operator.
|
||||
239. [justanotheranonymoususer](https://github.com/justanotheranonymoususer) made the examples in the README more consistent.
|
||||
240. [Finkman](https://github.com/Finkman) suppressed some `-Wfloat-equal` warnings and fixed the debug pretty-printer.
|
||||
241. [Ferry Huberts](https://github.com/fhuberts) fixed `-Wswitch-enum` warnings and fixed a typo.
|
||||
242. [Arseniy Terekhin](https://github.com/senyai) made the GDB pretty-printer robust against unset variable names.
|
||||
243. [Amir Masoud Abdol](https://github.com/amirmasoudabdol) updated the Homebrew command as nlohmann/json is now in homebrew-core.
|
||||
244. [Hallot](https://github.com/Hallot) fixed some `-Wextra-semi-stmt warnings`.
|
||||
245. [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS` and fixed a check for `std::filesystem`.
|
||||
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.
|
||||
247. [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`.
|
||||
248. [miikka75](https://github.com/miikka75) provided an important fix to compile C++17 code with Clang 9.
|
||||
249. [Maarten Becker](https://github.com/kernie) fixed a warning for shadowed variables.
|
||||
250. [Cristi Vîjdea](https://github.com/axnsan12) fixed typos in the `operator[]` documentation.
|
||||
251. [Alex Beregszaszi](https://github.com/axic) fixed spelling mistakes in comments.
|
||||
252. [Dirk Stolle](https://github.com/striezel) fixed typos in the documentation.
|
||||
253. [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation.
|
||||
254. [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ.
|
||||
255. [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements.
|
||||
256. [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format.
|
||||
257. [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
|
||||
258. [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines.
|
||||
259. [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC.
|
||||
260. [Dimitris Apostolou](https://github.com/rex4539) fixed a typo.
|
||||
261. [Michael Nosthoff](https://github.com/heinemml) fixed a typo.
|
||||
262. [JungHoon Lee](https://github.com/jhnlee) fixed a typo.
|
||||
263. [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file.
|
||||
264. [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation.
|
||||
265. [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`.
|
||||
266. [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo.
|
||||
267. [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error.
|
||||
268. [KsaNL](https://github.com/KsaNL) fixed a build error when including `<windows.h>`.
|
||||
269. [Andrea Pappacoda](https://github.com/Tachi107) moved `.pc` and `.cmake` files to `share` directory.
|
||||
270. [Wolf Vollprecht](https://github.com/wolfv) added the `patch_inplace` function.
|
||||
271. [Jake Zimmerman](https://github.com/jez) highlighted common usage patterns in the README file.
|
||||
272. [NN](https://github.com/NN---) added the Visual Studio output directory to `.gitignore`.
|
||||
273. [Romain Reignier](https://github.com/romainreignier) improved the performance of the vector output adapter.
|
||||
274. [Mike](https://github.com/Mike-Leo-Smith) fixed the `std::iterator_traits`.
|
||||
275. [Richard Hozák](https://github.com/richardhozak) added macro `JSON_NO_ENUM` to disable default enum conversions.
|
||||
276. [vakokako](https://github.com/vakokako) fixed tests when compiling with C++20.
|
||||
277. [Alexander “weej” Jones](https://github.com/alexweej) fixed an example in the README.
|
||||
278. [Eli Schwartz](https://github.com/eli-schwartz) added more files to the `include.zip` archive.
|
||||
279. [Kevin Lu](https://github.com/kevinlul) fixed a compilation issue when typedefs with certain names were present.
|
||||
280. [Trevor Hickey](https://github.com/luxe) improved the description of an example.
|
||||
281. [Jef LeCompte](https://github.com/jef) updated the year in the README file.
|
||||
282. [Alexandre Hamez](https://github.com/ahamez) fixed a warning.
|
||||
283. [Maninderpal Badhan](https://github.com/mbadhan) fixed a typo.
|
||||
284. [kevin--](https://github.com/kevin--) added a note to an example in the README file.
|
||||
285. [I](https://github.com/wx257osn2) fixed a typo.
|
||||
286. [Gregorio Litenstein](https://github.com/Lord-Kamina) fixed the Clang detection.
|
||||
287. [Andreas Smas](https://github.com/andoma) added a Doozer badge.
|
||||
288. [WanCW](https://github.com/wancw) fixed the string conversion with Clang.
|
||||
289. [zhaohuaxishi](https://github.com/zhaohuaxishi) fixed a Doxygen error.
|
||||
290. [emvivre](https://github.com/emvivre) removed an invalid parameter from CMake.
|
||||
291. [Tobias Hermann](https://github.com/Dobiasd) fixed a link in the README file.
|
||||
292. [Michael](https://github.com/traits) fixed a warning.
|
||||
293. [Ryan Mulder](https://github.com/ryanjmulder) added `ensure_ascii` to the `dump` function.
|
||||
294. [Muri Nicanor](https://github.com/murinicanor) fixed the `sed` discovery in the Makefile.
|
||||
295. [David Avedissian](https://github.com/dgavedissian) implemented SFINAE-friendly `iterator_traits`.
|
||||
296. [AQNOUCH Mohammed](https://github.com/aqnouch) fixed a typo in the README.
|
||||
297. [Gareth Sylvester-Bradley](https://github.com/garethsb) added `operator/=` and `operator/` to construct JSON pointers.
|
||||
298. [Michael Macnair](https://github.com/mykter) added support for afl-fuzz testing.
|
||||
299. [Berkus Decker](https://github.com/berkus) fixed a typo in the README.
|
||||
300. [Illia Polishchuk](https://github.com/ilqvya) improved the CMake testing.
|
||||
301. [Ikko Ashimine](https://github.com/eltociear) fixed two typos.
|
||||
302. [Raphael Grimm](https://github.com/barcode) added the possibility to define a custom base class.
|
||||
303. [tocic](https://github.com/tocic) fixed typos in the documentation.
|
||||
304. [Vertexwahn](https://github.com/Vertexwahn) added Bazel build support.
|
||||
305. [DavidKorczynski](https://github.com/DavidKorczynski) added a CIFuzz CI GitHub action.
|
||||
306. [Florian Segginger](https://github.com/floriansegginger) bumped the years in the README.
|
||||
307. [haadfida](https://github.com/haadfida) cleaned up the badges of used services.
|
||||
308. [Arsen Arsenović](https://github.com/ArsenArsen) fixed a build error.
|
||||
309. [theevilone45](https://github.com/theevilone45) fixed a typo in a CMake file.
|
||||
310. [Sergei Trofimovich](https://github.com/trofi) fixed the custom allocator support.
|
||||
311. [Joyce](https://github.com/joycebrum) fixed some security issues in the GitHub workflows.
|
||||
312. [Nicolas Jakob](https://github.com/njakob) add vcpkg version badge.
|
||||
313. [Tomerkm](https://github.com/Tomerkm) added tests.
|
||||
314. [No.](https://github.com/tusooa) fixed the use of `get<>` calls.
|
||||
315. [taro](https://github.com/tarolling) fixed a typo in the `CODEOWNERS` file.
|
||||
316. [Felix Yan](https://github.com/felixonmars) fixed a typo in the README.
|
||||
317. [HO-COOH](https://github.com/HO-COOH) fixed a parenthesis in the documentation.
|
||||
318. [miny1233](https://github.com/miny1233) fixed a parenthesis in the documentation.
|
||||
319. [tomalakgeretkal](https://github.com/tomalakgeretkal) fixed a compilation error.
|
||||
320. [alferov](https://github.com/ALF-ONE) fixed a compilation error and fixed a version in the documentation.
|
||||
321. [Craig Scott](https://github.com/craigscott-crascit) fixed a deprecation warning in CMake.
|
||||
322. [Vyacheslav Zhdanovskiy](https://github.com/ZeronSix) added macros for serialization-only types.
|
||||
323. [Mathieu Westphal](https://github.com/mwestphal) fixed typos.
|
||||
324. [scribam](https://github.com/scribam) fixed the MinGW workflow.
|
||||
325. [Aleksei Sapitskii](https://github.com/aleksproger) added support for Apple's Swift Package Manager.
|
||||
326. [Benjamin Buch](https://github.com/bebuch) fixed the installation path in CMake.
|
||||
327. [Colby Haskell](https://github.com/colbychaskell) clarified the parse error message in case a file cannot be opened.
|
||||
328. [Juan Carlos Arevalo Baeza](https://github.com/TheJCAB) fixed the enum conversion.
|
||||
329. [ss](https://github.com/serge-s) fixed the amalgamation call.
|
||||
330. [AniketDhemare](https://github.com/AniketDhemare) fixed a version in the documentation.
|
||||
331. [Philip Müller](https://github.com/philip-paul-mueller) fixed an example.
|
||||
332. [Leila Shcheglova](https://github.com/LeilaShcheglova) fixed a warning in a test.
|
||||
333. [Alex Prabhat Bara](https://github.com/alexprabhat99) fixed a function name in the documentation.
|
||||
334. [laterlaugh](https://github.com/laterlaugh) fixed some typos.
|
||||
335. [Yuanhao Jia](https://github.com/MrJia1997) fixed the GDB pretty printer.
|
||||
336. [Fallen_Breath](https://github.com/Fallen-Breath) fixed an example for JSON Pointer.
|
||||
337. [Nikhil Idiculla](https://github.com/tsnl) fixed some typos.
|
||||
338. [Griffin Myers](https://github.com/gmyers18) updated the Natvis file.
|
||||
339. [thetimr](https://github.com/thetimr) fixed a typo in the documentation.
|
||||
340. [Balazs Erseki](https://github.com/zerocukor287) fixed a URL in the contribution guidelines.
|
||||
341. [Niccolò Iardella](https://github.com/rotolof) added `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||
342. [Borislav Stanimirov](https://github.com/iboB) allowed overriding the CMake target name.
|
||||
343. [Captain Crutches](https://github.com/captaincrutches) made `iterator_proxy_value` a `std::forward_iterator`.
|
||||
344. [Fredrik Sandhei](https://github.com/fsandhei) added type conversion support for `std::optional`.
|
||||
345. [jh96](https://github.com/jordan-hoang) added exceptions when `nullptr` is passed to `parse`.
|
||||
346. [Stuart Gorman](https://github.com/StuartGorman) fixed number parsing when `EINTR` set in `errno`.
|
||||
347. [Dylan Baker](https://github.com/dcbaker) generated a pkg-config file that follows the pkg-config conventions.
|
||||
348. [Tianyi Chen](https://github.com/TianyiChen) optimized the binary `get_number` implementation.
|
||||
349. [peng-wang-cn](https://github.com/peng-wang-cn) added type conversion support for multidimensional arrays.
|
||||
350. [Einars Netlis-Galejs](https://github.com/EinarsNG) added `ONLY_SERIALIZE` for `NLOHMANN_DEFINE_DERIVED_TYPE_*` macros.
|
||||
351. [Marcel](https://github.com/mering) removed `alwayslink=True` Bazel flag.
|
||||
352. [Harinath Nampally](https://github.com/hnampally) added diagnostic positions to exceptions.
|
||||
353. [Nissim Armand Ben Danan](https://github.com/NissimBendanan) fixed `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` with an empty JSON instance.
|
||||
354. [Michael Valladolid](https://github.com/codenut) added support for BSON uint64 serialization/deserialization.
|
||||
355. [Nikhil](https://github.com/nikhilreddydev) updated the documentation.
|
||||
356. [Nebojša Cvetković](https://github.com/nebkat) added support for BJDATA optimized binary array type.
|
||||
357. [Sushrut Shringarputale](https://github.com/sushshring) added support for diagnostic positions.
|
||||
358. [kimci86](https://github.com/kimci86) templated to `NLOHMANN_DEFINE_TYPE` macros to also support `ordered_json`.
|
||||
359. [Richard Topchii](https://github.com/richardtop) added support for VisionOS in the Swift Package Manager.
|
||||
360. [Robert Chisholm](https://github.com/Robadob) fixed a typo.
|
||||
361. [zjyhjqs](https://github.com/zjyhjqs) added CPack support.
|
||||
362. [bitFiedler](https://github.com/bitFiedler) made GDB pretty printer work with Python 3.8.
|
||||
363. [Gianfranco Costamagna](https://github.com/LocutusOfBorg) fixed a compiler warning.
|
||||
364. [risa2000](https://github.com/risa2000) made `std::filesystem::path` conversion to/from UTF-8 encoded string explicit.
|
||||
365. [AM](https://github.com/maqnouch) fixed typos in the README.
|
||||
366. [dmenendez-gruposantander](https://github.com/dmenendez-gruposantander) fixed typos in the comments of the examples.
|
||||
367. [Mihai Stan](https://github.com/mstan-xx) fixed comparisons against the literal `0`.
|
||||
368. [Matt Gumbel](https://github.com/intelmatt) fixed some `-Weffc++` warnings.
|
||||
369. [vimpunk](https://github.com/vimpunk) moved a lambda out of an unevaluated context to support older compilers.
|
||||
370. [Chris Harris](https://github.com/cjh1) fixed the compilation with GCC 4.8.
|
||||
371. [Palmer Dabbelt](https://github.com/palmer-dabbelt) generated and installed a pkg-config file.
|
||||
372. [Gus Pozuelo](https://github.com/ap-viavi) made `ordered_map` compatible with GCC 5.5, Clang 3.6, and Xcode 9.
|
||||
373. [AK](https://github.com/Lioncky) fixed an MSVC build error caused by the `min`/`max` macros from `windows.h`.
|
||||
374. [Sergiu Deitsch](https://github.com/sergiud) provided a fallback for missing `char8_t` support.
|
||||
375. [Xiaochuan Ye](https://github.com/XueSongTap) fixed `from_msgpack` for `std::byte` input by specializing `std::char_traits`.
|
||||
376. [Ville Vesilehto](https://github.com/thevilledev) fixed an overflow in the BJData size calculation and rejected overflowing negative integers in CBOR.
|
||||
377. [NmPassTHFan](https://github.com/nmpassthf) replaced the deprecated `std::is_trivial` for C++26.
|
||||
378. [Chris Ever](https://github.com/chirsz-ever) added the `ignore_trailing_commas` parser option.
|
||||
379. [Kuan-Fu Wu](https://github.com/kfwu1999) fixed the example code for `json_pointer` initialization.
|
||||
380. [David Kilzer](https://github.com/ddkilzer) added a missing header to the input adapters.
|
||||
381. [Miko](https://github.com/mikomikotaishi) added proper C++20 module support, simplified the module API, and fixed missing exports.
|
||||
382. [hitgirl](https://github.com/hitgil) fixed the CMake configuration when cross-compiling.
|
||||
383. [Devon Thomas](https://github.com/ThomaDevOSU) mentioned the Artistic Style formatting in the contribution guidelines.
|
||||
384. [Erik Hu](https://github.com/Erikhu1) made Coveralls upload errors non-fatal in the CI.
|
||||
385. [co63oc](https://github.com/co63oc) fixed typos.
|
||||
386. [DmitriBogdanov](https://github.com/DmitriBogdanov) fixed broken package manager links in the documentation.
|
||||
387. [Bander](https://github.com/banderzhm) improved the MSVC compatibility of the C++ modules.
|
||||
388. [Andy Choi](https://github.com/ccpong) removed an unnecessary `template` keyword before `get` in the README and the documentation.
|
||||
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`.
|
||||
390. [Aditya](https://github.com/Lumowhisp) improved the documentation of the documentation generation.
|
||||
391. [cheese1](https://github.com/cheese1) clarified the README.
|
||||
392. [KhloodElhossiny](https://github.com/khloodelhossiny) enabled `std::string_view` keys in `operator[]`.
|
||||
393. [Charles Cabergs](https://github.com/cacharle) fixed a `-Wtautological-constant-out-of-range-compare` warning.
|
||||
394. [EALePain](https://github.com/EALePain) made the `std::tuple` conversion work with reference types such as `std::tie`.
|
||||
395. [koala_oishi](https://github.com/chibi-dogs) fixed grammatical wording in the README.
|
||||
396. [riccardoori11](https://github.com/riccardoori11) fixed a typo in the documentation.
|
||||
397. [Swastik Bose](https://github.com/VasuBhakt) fixed the parent pointers after `update()` with `JSON_DIAGNOSTICS` and fixed the Doxygen autolinking of requirements.
|
||||
398. [trdesilva](https://github.com/trdesilva) added `front`, `pop_front`, and `push_front` to `json_pointer`.
|
||||
399. [Akhilesh Arora](https://github.com/akhilesharora) fixed an incomplete-type error with `ordered_json`.
|
||||
400. [Hariom Phulre](https://github.com/hariomphulre) fixed the C++20 modules compilation with GCC.
|
||||
401. [Kirill Lokotkov](https://github.com/RUSLoker) fixed printing `long double` values.
|
||||
402. [George Sedov](https://github.com/radistmorse) added the `NLOHMANN_DEFINE_TYPE_*_WITH_NAMES` macros.
|
||||
403. [Caillin Nugent](https://github.com/nugentcaillin) added the `NLOHMANN_JSON_SERIALIZE_ENUM_STRICT` macro.
|
||||
404. [Cosmin D.](https://github.com/drcosmin) fixed `std::filesystem::path` conversions and added an MSVC workaround for `std::unique_ptr`.
|
||||
405. [Paul Dreik](https://github.com/pauldreik) fixed a test relying on implementation-specific behavior.
|
||||
406. [Daniel Falk](https://github.com/daniel-falk) added missing copyright notices to the SBOM.
|
||||
407. [Federico Sfriso](https://github.com/federicosfriso05-dotcom) added support for constructing JSON values from C++20 range views.
|
||||
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.
|
||||
409. [Patrick Armstrong](https://github.com/Patrick10199) updated the CBOR references and the half-precision float assertions.
|
||||
410. [Yash Bavadiya](https://github.com/xevrion) added checks to all BSON reads.
|
||||
411. [hum4nBeing](https://github.com/hum4nBeing) fixed the overflow handling of high-precision numbers in UBJSON.
|
||||
412. [tomatotomata](https://github.com/tomatotomata) added checks for reading CBOR tagged subtypes.
|
||||
413. [YingqiDuan](https://github.com/YingqiDuan) documented the BSON interoperability.
|
||||
414. [KBS](https://github.com/youdie006) documented the standards compliance and the strictness of `parse()` and `operator>>`.
|
||||
415. [Petr Bělohlávek](https://github.com/petrbel) added Clang 21 and 22 to the CI.
|
||||
416. [Dmitry Rantovov](https://github.com/darkdi) fixed the placement of a CBOR documentation block.
|
||||
417. [ljcjclljc](https://github.com/ljcjclljc) fixed the comparison of large unsigned integers with signed integers.
|
||||
418. [Sahil Kamate](https://github.com/sahilkamate03) fixed the handling of CBOR tags 0-5 and 21-23.
|
||||
419. [Krishnanand G](https://github.com/Krishnanand-G) made the UBJSON writer reject `use_type` without `use_size`.
|
||||
420. [whn](https://github.com/Whning0513) documented the lenient BSON input handling and corrected the complexity of `to_bson`.
|
||||
421. [elix3r](https://github.com/22elix3r) fixed `update()` with `merge_objects` when merging a primitive into an object.
|
||||
422. [Avionic Harshit](https://github.com/avionicharshit-byte) made `diff()` linear when an array shrinks.
|
||||
423. [Qatadaha Bin Matloob](https://github.com/qatcod) fixed comparisons between integers and floats and fixed unparsable BJData output.
|
||||
424. [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.
|
||||
|
||||
@@ -1879,21 +1851,28 @@ 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
|
||||
- [**Artistic Style**](https://astyle.sourceforge.net) for automatic source code indentation
|
||||
- [**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
|
||||
- [**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)
|
||||
- [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json)
|
||||
- [**cppcheck**](https://cppcheck.sourceforge.io) for static analysis
|
||||
- [**doctest**](https://github.com/onqtam/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)
|
||||
- [**cpplint**](https://github.com/cpplint/cpplint) for style checks
|
||||
- [**doctest**](https://github.com/doctest/doctest) for the unit tests
|
||||
- [**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
|
||||
- [**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
|
||||
- [**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
|
||||
- [**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))
|
||||
- [**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
|
||||
|
||||
## Notes
|
||||
@@ -1987,10 +1966,10 @@ If the testdata is not found, several test suites will fail like this:
|
||||
|
||||
```
|
||||
===============================================================================
|
||||
json/tests/src/make_test_data_available.hpp:21:
|
||||
json/tests/src/make_test_data_available.hpp:26:
|
||||
TEST CASE: check test suite is downloaded
|
||||
|
||||
json/tests/src/make_test_data_available.hpp:23: FATAL ERROR: REQUIRE( utils::check_testsuite_downloaded() ) is NOT correct!
|
||||
json/tests/src/make_test_data_available.hpp:28: FATAL ERROR: REQUIRE( utils::check_testsuite_downloaded() ) is NOT correct!
|
||||
values: REQUIRE( false )
|
||||
logged: Test data not found in 'json/cmake-build-debug/json_test_data'.
|
||||
Please execute target 'download_test_data' before running this test suite.
|
||||
@@ -2001,10 +1980,10 @@ json/tests/src/make_test_data_available.hpp:23: 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.
|
||||
|
||||
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 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 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 `cmake -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 `ctest -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.
|
||||
+8
-2
@@ -10,10 +10,10 @@ SPDX-FileCopyrightText = "2013-2026 Niels Lohmann <https://nlohmann.me>"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "include/nlohmann/thirdparty/hedley.hpp"
|
||||
path = "include/nlohmann/thirdparty/hedley/hedley.hpp"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2016-2021 Evan Nemerson <evan@nemerson.com>"
|
||||
SPDX-License-Identifier = "CC0"
|
||||
SPDX-License-Identifier = "CC0-1.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "include/nlohmann/detail/meta/cpp_future.hpp"
|
||||
@@ -50,3 +50,9 @@ path = "tools/gdb_pretty_printer/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2020 Hannes Domani <https://github.com/ssbssa>"
|
||||
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"
|
||||
+13
-16
@@ -5,15 +5,14 @@ set(N 10)
|
||||
# Needed tools.
|
||||
###############################################################################
|
||||
|
||||
include(FindPython3)
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
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++)
|
||||
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)
|
||||
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}")
|
||||
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
||||
|
||||
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)
|
||||
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)
|
||||
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}")
|
||||
message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
|
||||
@@ -69,9 +68,7 @@ string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_V
|
||||
message(STATUS "🔖 Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})")
|
||||
|
||||
find_program(GENHTML_TOOL NAMES genhtml)
|
||||
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)
|
||||
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)
|
||||
|
||||
# the individual source files
|
||||
file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp)
|
||||
@@ -367,7 +364,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} -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 genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage 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
|
||||
|
||||
COMMENT "Compile and test with coverage"
|
||||
)
|
||||
@@ -392,8 +389,8 @@ add_custom_target(ci_test_clang_sanitizer
|
||||
# Check if header is amalgamated and sources are properly indented.
|
||||
###############################################################################
|
||||
|
||||
# Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
|
||||
# (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
|
||||
# Same file set as .github/workflows/check_amalgamation.yml, so this CMake target (which can be run locally) is held
|
||||
# to the same standard as the workflow (which runs for pull requests and for pushes to develop/master/release/*).
|
||||
file(GLOB_RECURSE INDENT_FILES
|
||||
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
||||
@@ -423,7 +420,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_fwd.json -s .
|
||||
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
|
||||
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 ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
|
||||
|
||||
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
||||
@@ -434,6 +431,8 @@ add_custom_target(ci_test_amalgamation
|
||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
||||
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}
|
||||
COMMENT "Check amalgamation, formatting, and BUILD.bazel"
|
||||
)
|
||||
@@ -719,7 +718,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
|
||||
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
||||
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
|
||||
JSON_DisableTupleReferenceConversion JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
|
||||
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_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
||||
@@ -776,17 +775,14 @@ add_custom_target(ci_cmake_flags
|
||||
# Use more installed compilers.
|
||||
###############################################################################
|
||||
|
||||
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)
|
||||
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6)
|
||||
find_program(COMPILER_TOOL NAMES ${COMPILER})
|
||||
if (COMPILER_TOOL)
|
||||
unset(ADDITIONAL_FLAGS)
|
||||
|
||||
add_custom_target(ci_test_compiler_${COMPILER}
|
||||
COMMAND CXX=${COMPILER} ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
|
||||
${ADDITIONAL_FLAGS}
|
||||
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
|
||||
COMMENT "Compile and test with ${COMPILER}"
|
||||
@@ -800,7 +796,6 @@ add_custom_target(ci_test_compiler_default
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-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 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"
|
||||
@@ -825,8 +820,10 @@ add_custom_target(ci_module_cpp20
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-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
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/ci_module_cpp20
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -49,6 +49,7 @@ cc_library(
|
||||
hdrs = [
|
||||
"single_include/nlohmann/json.hpp",
|
||||
"single_include/nlohmann/json_fwd.hpp",
|
||||
"single_include/nlohmann/json_literals.hpp",
|
||||
],
|
||||
includes = ["single_include"],
|
||||
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.
|
||||
|
||||
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.10.2`):
|
||||
using tag `v3.12.0`):
|
||||
|
||||
```shell
|
||||
git clone https://github.com/nlohmann/json.git
|
||||
cd json
|
||||
git checkout v3.10.2
|
||||
git checkout v3.12.0
|
||||
make install_venv serve -C docs/mkdocs
|
||||
```
|
||||
|
||||
|
||||
+11
-55
@@ -1,48 +1,24 @@
|
||||
SHELL=/usr/bin/env bash
|
||||
SED ?= $(shell which gsed 2>/dev/null || which sed)
|
||||
|
||||
MKDOCS_PAGES=$(shell cd ../mkdocs/docs/ && find * -type f -name '*.md' | sort)
|
||||
PYTHON=../mkdocs/venv/bin/python3
|
||||
|
||||
.PHONY: all
|
||||
all: JSON_for_Modern_C++.tgz
|
||||
|
||||
docSet.dsidx: docSet.sql
|
||||
# generate index
|
||||
sqlite3 docSet.dsidx <docSet.sql
|
||||
# generate the search index (the docset target does this itself, this is
|
||||
# only handy for inspecting the index)
|
||||
docSet.dsidx: generate_docset.py
|
||||
$(PYTHON) generate_docset.py index docSet.dsidx
|
||||
|
||||
JSON_for_Modern_C++.docset: Info.plist docSet.dsidx
|
||||
rm -fr JSON_for_Modern_C++.docset JSON_for_Modern_C++.tgz
|
||||
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
|
||||
# build the documentation and turn it into a self-contained docset
|
||||
.PHONY: JSON_for_Modern_C++.docset
|
||||
JSON_for_Modern_C++.docset:
|
||||
$(MAKE) install_venv -C ../mkdocs
|
||||
$(MAKE) build -C ../mkdocs
|
||||
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/
|
||||
$(PYTHON) generate_docset.py docset ../mkdocs/site .
|
||||
|
||||
.PHONY: JSON_for_Modern_C++.tgz
|
||||
JSON_for_Modern_C++.tgz: JSON_for_Modern_C++.docset
|
||||
tar --exclude='.DS_Store' -cvzf JSON_for_Modern_C++.tgz JSON_for_Modern_C++.docset
|
||||
$(PYTHON) generate_docset.py tgz .
|
||||
|
||||
# install docset for Zeal documentation browser (https://zealdocs.org/)
|
||||
.PHONY: install_docset_zeal
|
||||
@@ -52,26 +28,6 @@ install_docset_zeal: JSON_for_Modern_C++.docset
|
||||
mkdir -p $$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
|
||||
clean:
|
||||
rm -f docSet.dsidx
|
||||
|
||||
@@ -4,7 +4,8 @@ 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
|
||||
[Zeal](https://zealdocs.org).
|
||||
|
||||
The docset can be created with
|
||||
The docset (pages and search index) is generated by `generate_docset.py` from the mkdocs site and `mkdocs.yml`. It
|
||||
can be created with
|
||||
|
||||
```sh
|
||||
make JSON_for_Modern_C++.docset
|
||||
@@ -12,6 +13,7 @@ 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
|
||||
`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).
|
||||
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
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');
|
||||
Executable
+532
@@ -0,0 +1,532 @@
|
||||
#!/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,6 +17,7 @@ build: style_check
|
||||
|
||||
style_check:
|
||||
@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)
|
||||
# This target is used in the CI (ci_test_documentation_mermaid).
|
||||
|
||||
@@ -241,4 +241,6 @@ 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
|
||||
already supported by [`operator[]`](operator[].md), [`value`](value.md), [`find`](find.md), and other lookup
|
||||
functions.
|
||||
4. Added in version 2.0.0.
|
||||
4. Added in version 2.0.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.
|
||||
@@ -64,18 +64,7 @@ values of that type directly to a `basic_json` instance, and they will automatic
|
||||
rather than arrays:
|
||||
|
||||
```cpp
|
||||
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
|
||||
>;
|
||||
using custom_json = nlohmann::ordered_json::with_binary_t<std::vector<std::byte>>;
|
||||
|
||||
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
|
||||
|
||||
@@ -10,6 +10,10 @@ bool contains(KeyType&& key) const;
|
||||
|
||||
// (3)
|
||||
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
|
||||
@@ -17,6 +21,9 @@ bool contains(const json_pointer& ptr) const;
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -39,6 +46,7 @@ bool contains(const json_pointer& ptr) const;
|
||||
is not an object, `#!cpp false` is returned.
|
||||
2. See 1.
|
||||
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
|
||||
|
||||
@@ -49,6 +57,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
||||
1. The function does not throw exceptions.
|
||||
2. 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
|
||||
|
||||
|
||||
@@ -7,12 +7,19 @@ size_type count(const typename object_t::key_type& key) const;
|
||||
// (2)
|
||||
template<typename KeyType>
|
||||
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
|
||||
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
|
||||
`#!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
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ Linear.
|
||||
|
||||
## 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:
|
||||
|
||||
- "bytes": an array of bytes as integers
|
||||
@@ -97,3 +100,5 @@ Binary values are serialized as an object containing two keys:
|
||||
- Error handlers added in version 3.4.0.
|
||||
- Serialization of binary values added in version 3.8.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
|
||||
|
||||
keep
|
||||
: keep invalid UTF-8 sequences unchanged; only meaningful for the binary formats mentioned above, since [`dump`]
|
||||
(dump.md) itself must produce text, and `keep` there writes the ill-formed bytes to the output as is, so the
|
||||
: keep invalid UTF-8 sequences unchanged; only meaningful for the binary formats mentioned above, since
|
||||
[`dump`](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
|
||||
characters, which are still escaped as usual)
|
||||
|
||||
|
||||
@@ -10,12 +10,21 @@ template<typename KeyType>
|
||||
iterator find(KeyType&& key);
|
||||
template<typename KeyType>
|
||||
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
|
||||
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
|
||||
`#!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
|
||||
|
||||
|
||||
@@ -124,7 +124,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.13.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
|
||||
@@ -110,7 +110,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.13.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
|
||||
@@ -126,7 +126,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.8.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
|
||||
@@ -135,7 +135,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.8.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
|
||||
@@ -127,7 +127,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.8.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
|
||||
@@ -125,7 +125,8 @@ Linear in the size of the input.
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- 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. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
deprecated in version 3.8.0. In version 4.0.0, this overload
|
||||
will be deleted (`= delete`) rather than removed. Please replace all calls like
|
||||
`#!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
|
||||
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
|
||||
|
||||
- Added in version 3.12.0.
|
||||
- Added in version 3.11.3.
|
||||
- Made a public member type in version 3.13.0; it was private before, so it could not be named outside the class.
|
||||
@@ -23,9 +23,10 @@ type to use.
|
||||
## Template parameters
|
||||
|
||||
`NumberFloatType`
|
||||
: the type to store floating-point numbers. Parsing and serialization are implemented in terms of
|
||||
`#!cpp std::strtof`/`#!cpp std::strtod`/`#!cpp std::strtold` and `#!cpp std::snprintf`, so the type must be
|
||||
`#!cpp float`, `#!cpp double`, or `#!cpp long double`. The
|
||||
: the type to store floating-point numbers. The type must be `#!cpp float`, `#!cpp double`, or
|
||||
`#!cpp long double`. The parser converts `#!cpp float`, `#!cpp double`, and a `#!cpp long double` that is IEEE 754
|
||||
binary64 itself. It converts other `#!cpp long double` formats with `#!cpp std::from_chars` where available, or
|
||||
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`,
|
||||
because they have no encoding for `#!cpp long double`. See
|
||||
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
|
||||
|
||||
@@ -286,4 +286,6 @@ 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
|
||||
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
|
||||
version 3.13.0.
|
||||
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.
|
||||
@@ -112,3 +112,6 @@ 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.
|
||||
- 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.
|
||||
- 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,3 +110,6 @@ function throws an exception.
|
||||
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
|
||||
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,6 +41,8 @@ With (2), the bytes written before the exception remain in the output adapter.
|
||||
above 9223372036854775807, which BON8 cannot represent
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if `j` contains a string that is not
|
||||
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
|
||||
|
||||
|
||||
@@ -36,8 +36,9 @@ 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
|
||||
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
|
||||
(because one of its keys is `0`) and another key at that level cannot be an array index; example:
|
||||
`"unresolved reference token 'x'"`
|
||||
(because one of its keys is `0`) and another key at that level begins with a digit but is not a valid array index
|
||||
(such as `1a`), or is `-`; example:
|
||||
`"unresolved reference token '-'"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -80,3 +81,6 @@ Apart from these two cases, for a JSON value `j`, the following is always true:
|
||||
|
||||
- Added in version 2.0.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,6 +119,14 @@ changes to any JSON value.
|
||||
|
||||
## 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"
|
||||
|
||||
The value function is a template, and the return type of the function is determined by the type of the provided
|
||||
@@ -227,4 +235,6 @@ changes to any JSON value.
|
||||
[`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
|
||||
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
||||
`default_value`, as documented).
|
||||
`default_value`, as documented). Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109)
|
||||
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,6 +27,7 @@ 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_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_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
|
||||
|
||||
@@ -49,6 +49,6 @@ The default value is detected based on preprocessor macros such as `#!cpp __cplu
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.10.5.
|
||||
- Added in version 3.10.0.
|
||||
- Added `JSON_HAS_CPP_23` in version 3.12.0.
|
||||
- Added `JSON_HAS_CPP_26` in version 3.13.0.
|
||||
@@ -0,0 +1,43 @@
|
||||
# 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))
|
||||
- **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 #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))
|
||||
- **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
|
||||
under these two toolkit versions; fixed in CUDA 12.2; [issue #3907](https://github.com/nlohmann/json/issues/3907))
|
||||
@@ -44,9 +44,12 @@ 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_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`
|
||||
support
|
||||
|
||||
## Version history
|
||||
|
||||
- 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,7 +20,10 @@ The macro does not affect:
|
||||
- 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_bson`](../basic_json/from_bson.md)): none of these formats requires a decoder to reject ill-formed UTF-8, so
|
||||
they always return the bytes unchanged.
|
||||
by default they return the bytes unchanged (`error_handler_t::keep`), independent of this macro. Pass an
|
||||
`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
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ By default, implicit conversions are enabled.
|
||||
`JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`:
|
||||
|
||||
```cpp
|
||||
using wjson = nlohmann::basic_json<std::map, std::vector, std::wstring>;
|
||||
using wjson = nlohmann::json::with_string_t<std::wstring>;
|
||||
|
||||
void load(const nlohmann::json& j);
|
||||
|
||||
|
||||
@@ -190,3 +190,5 @@ void to_json(BasicJsonType& j, const B& b) {
|
||||
4. Added in version 3.12.0.
|
||||
5. 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,3 +186,6 @@ See the examples below for the concrete generated code.
|
||||
1. Added in version 3.9.0.
|
||||
2. Added in version 3.11.0.
|
||||
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,3 +185,6 @@ See the examples below for the concrete generated code.
|
||||
1. Added in version 3.9.0.
|
||||
2. Added in version 3.11.0.
|
||||
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,4 +38,6 @@ the library.
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.11.0. Changed inline namespace name in version 3.11.2.
|
||||
- Added in version 3.11.0. Changed inline namespace name in version 3.11.2. Added the ABI tag `_dp` in
|
||||
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
|
||||
|
||||
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`:
|
||||
|
||||
|
||||
@@ -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
|
||||
variables, and does not implement cryptography or handle credentials.
|
||||
|
||||
The primary threat is therefore **untrusted input**: JSON text or binary data (BJData, BSON, CBOR, MessagePack, UBJSON)
|
||||
The primary threat is therefore **untrusted input**: JSON text or binary data (BJData, BON8, BSON, CBOR, MessagePack, UBJSON)
|
||||
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
|
||||
[`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: 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.
|
||||
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.
|
||||
|
||||
- [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.
|
||||
@@ -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
|
||||
and fix language deprecations early.
|
||||
- [x] The library is checked for compiler warnings:
|
||||
- On Clang, `-Weverything` is used with 8 exceptions.
|
||||
- On Clang, `-Weverything` is used with 7 exceptions.
|
||||
|
||||
??? abstract "Clang warnings"
|
||||
|
||||
|
||||
@@ -36,13 +36,26 @@ work items are tracked in the [GitHub milestones](https://github.com/nlohmann/js
|
||||
## API stability
|
||||
|
||||
Releases follow [semantic versioning](https://semver.org): a minor or patch release of version 3.x does not break code
|
||||
that uses the public API. In particular, a 3.x release does not:
|
||||
that uses the public API, unless that code opts in to a change with a macro as described [below](#version-40). In
|
||||
particular, a 3.x release does not:
|
||||
|
||||
- change the signature of a function (its parameter types, return type, number of parameters, or the const-ness of a
|
||||
member function);
|
||||
- remove or rename a function or class;
|
||||
- make breaking changes to the signature of a function: the types or order of its existing parameters, its return type,
|
||||
its `noexcept` or `constexpr` specifier, or the const-ness of a member function. New parameters may be added if they
|
||||
have a default value;
|
||||
- remove or rename a function or class, or change the template parameters of a public class template;
|
||||
- change which exceptions a function throws, or the [exception ids](../home/exceptions.md);
|
||||
- change access specifiers or default arguments.
|
||||
- change access specifiers, or change or remove existing default arguments. New default arguments may be added;
|
||||
- change the JSON type that a valid input parses to, or the text that `dump()` produces for a valid value;
|
||||
- accept input that was rejected before, or reject input that was accepted before;
|
||||
- change the order in which the keys of an object are iterated. The default type sorts keys, and
|
||||
[`ordered_json`](../api/ordered_json.md) keeps insertion order;
|
||||
- change when iterators, pointers, or references are invalidated, or the state of a moved-from `basic_json`;
|
||||
- add or remove implicit conversions from `basic_json`;
|
||||
- change how `to_json` and `from_json` functions are found, or the behavior of
|
||||
[`adl_serializer`](../api/adl_serializer/index.md);
|
||||
- add pure virtual functions to the [`json_sax`](../api/json_sax/index.md) interface;
|
||||
- remove, rename, renumber, or add enumerators of `value_t`;
|
||||
- remove or rename a documented macro, CMake option, CMake target, or header, or change what a documented macro does.
|
||||
|
||||
Exceptions to these rules, for instance when fixing a bug requires changing the exception a function throws, are
|
||||
documented in the [release notes](../home/releases.md).
|
||||
@@ -51,13 +64,14 @@ The following are **not** part of the public API and may change in any release,
|
||||
|
||||
- The text of exception messages returned by `what()`. Use the [exception id](../home/exceptions.md) to tell errors
|
||||
apart.
|
||||
- The ABI, including `sizeof(basic_json)` and the memory layout of its values. Recompile your code when you upgrade the
|
||||
library. The [versioned inline namespace](../features/namespace.md) turns mixing versions into a link error.
|
||||
- The ABI, including `sizeof(basic_json)` and the memory layout of its values. The
|
||||
[versioned inline namespace](../features/namespace.md) turns mixing versions into a link error.
|
||||
- The hash values returned by `std::hash` for `basic_json`. Numbers that compare equal still hash equally.
|
||||
- Everything in namespace `nlohmann::detail`, and macros and type traits that are not documented in the
|
||||
[API reference](../api/basic_json/index.md).
|
||||
|
||||
Changes that would break the public API are only added behind a macro whose default keeps the 3.x behavior, see
|
||||
[Version 4.0](#version-40).
|
||||
Breaking changes are only added behind a macro whose default keeps the 3.x behavior. See [Version 4.0](#version-40) and
|
||||
the [macro overview](../features/macros.md).
|
||||
|
||||
## Version 4.0
|
||||
|
||||
|
||||
@@ -15,19 +15,7 @@ class 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
|
||||
>;
|
||||
using json = nlohmann::json::with_base_class_t<base_class_with_hidden_members>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -19,25 +19,9 @@ int main()
|
||||
<< j.contains("/array/1"_json_pointer) << '\n'
|
||||
<< j.contains("/array/-"_json_pointer) << '\n'
|
||||
<< j.contains("/array/4"_json_pointer) << '\n'
|
||||
<< j.contains("/baz"_json_pointer) << std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
// 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';
|
||||
}
|
||||
<< j.contains("/baz"_json_pointer) << '\n'
|
||||
// an array index with a leading '0' is not found
|
||||
<< j.contains("/array/01"_json_pointer) << '\n'
|
||||
// an array index that is not a number is not found
|
||||
<< j.contains("/array/one"_json_pointer) << std::endl;
|
||||
}
|
||||
@@ -5,3 +5,5 @@ true
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
false
|
||||
@@ -1,11 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_array_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, custom_array_type>;
|
||||
using custom_json = nlohmann::json::with_array_t<custom_array_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_binary_type.hpp"
|
||||
|
||||
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>;
|
||||
using custom_json = nlohmann::json::with_binary_t<custom_binary_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_object_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<custom_object_type, std::vector>;
|
||||
using custom_json = nlohmann::json::with_object_t<custom_object_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "custom_string_type.hpp"
|
||||
|
||||
using custom_json = nlohmann::basic_json<std::map, std::vector, custom_string_type>;
|
||||
using custom_json = nlohmann::json::with_string_t<custom_string_type>;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ int main()
|
||||
try
|
||||
{
|
||||
// parsing input with a syntax error
|
||||
json::parse("[1,2,3,]");
|
||||
json j = json::parse("[1,2,3,]");
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
|
||||
@@ -347,6 +347,13 @@ struct adl_serializer<boost::optional<T>> {
|
||||
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"
|
||||
|
||||
Use [`NLOHMANN_JSON_NAMESPACE_BEGIN`](../api/macros/nlohmann_json_namespace_begin.md) and `NLOHMANN_JSON_NAMESPACE_END`
|
||||
|
||||
@@ -217,7 +217,8 @@ 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
|
||||
to incomplete C++20 ranges support there.
|
||||
to incomplete C++20 ranges support there; see
|
||||
[`JSON_HAS_RANGE_VIEW_CONVERSION`](../api/macros/json_has_range_view_conversion.md).
|
||||
|
||||
## Your own types
|
||||
|
||||
|
||||
@@ -30,6 +30,47 @@ 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("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
|
||||
|
||||
!!! failure "Exceptions"
|
||||
@@ -37,6 +78,31 @@ you want to access and a default value in case there is no value stored with tha
|
||||
- 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.
|
||||
|
||||
!!! 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"
|
||||
|
||||
The value function is a template, and the return type of the function is determined by the type of the provided
|
||||
@@ -63,3 +129,6 @@ you want to access and a default value in case there is no value stored with tha
|
||||
|
||||
- [`value`](../../api/basic_json/value.md) for access with default value
|
||||
- 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,6 +77,10 @@ auto val2 = j.at(json::json_pointer("/nested/three/1")); // false
|
||||
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"
|
||||
|
||||
See the [`operator[]` notes](../api/basic_json/operator%5B%5D.md#return-value) for how array vs. object is
|
||||
@@ -126,6 +130,8 @@ auto j_original = j_flat.unflatten();
|
||||
## See also
|
||||
|
||||
- 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 [`unflatten`](../api/basic_json/unflatten.md)
|
||||
- [JSON Patch](json_patch.md) - paths inside a patch are JSON Pointers
|
||||
|
||||
@@ -82,6 +82,45 @@ 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).
|
||||
|
||||
## `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`
|
||||
|
||||
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
|
||||
|
||||
@@ -9,6 +9,13 @@ 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
|
||||
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
|
||||
|
||||
The following code shows how a JSON Merge Patch is applied to a JSON document.
|
||||
@@ -28,3 +35,4 @@ 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 Pointer](json_pointer.md) - the addressing scheme used by JSON Patch
|
||||
- Function [`merge_patch`](../api/basic_json/merge_patch.md)
|
||||
- Function [`update`](../api/basic_json/update.md) - merge objects, optionally recursively
|
||||
@@ -35,8 +35,12 @@ the insertion happened — useful for "add if absent" semantics.
|
||||
|
||||
## Merging objects
|
||||
|
||||
To merge one object into another, [`update`](../api/basic_json/update.md) copies all members from another object,
|
||||
overwriting existing keys (similar to Python's `dict.update`). This is the idiomatic way to combine two objects.
|
||||
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:
|
||||
|
||||
- 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
|
||||
|
||||
@@ -50,9 +54,22 @@ overwriting existing keys (similar to Python's `dict.update`). This is the idiom
|
||||
--8<-- "examples/update.output"
|
||||
```
|
||||
|
||||
For a recursive merge that follows [RFC 7386](https://tools.ietf.org/html/rfc7386), see
|
||||
[JSON Merge Patch](merge_patch.md). To apply a sequence of well-defined edit operations, see
|
||||
[JSON Patch](json_patch.md).
|
||||
A common use of the recursive mode is combining defaults with user settings. Nested defaults that the user did not set
|
||||
are kept:
|
||||
|
||||
```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
|
||||
|
||||
@@ -72,6 +89,7 @@ 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
|
||||
- [`emplace`](../api/basic_json/emplace.md) - insert into an object if the key is absent
|
||||
- [`update`](../api/basic_json/update.md) - merge objects
|
||||
- [`update`](../api/basic_json/update.md) - merge objects (shallow, or recursive with `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
|
||||
- [JSON Patch and Diff](json_patch.md) and [JSON Merge Patch](merge_patch.md) - structured modifications
|
||||
@@ -101,3 +101,9 @@ follows:
|
||||
|
||||
- Introduced inline namespace (`json_v3_11_0[_abi-tag]*`) in version 3.11.0.
|
||||
- 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,12 +82,13 @@ flowchart TD
|
||||
|
||||
- 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).
|
||||
- Integers are converted by the library's own digit parser. Floating-point numbers are converted with
|
||||
[`std::from_chars`](https://en.cppreference.com/w/cpp/utility/from_chars) if the library is compiled with C++17
|
||||
and the standard library supports it, then with an exact fast path for `#!c double` values with few significant
|
||||
digits, and otherwise with the locale-aware
|
||||
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof) (`std::strtof`/`std::strtold` for the
|
||||
other floating-point types). Before version 3.13.0, the conversion was realized by
|
||||
- The library converts integers and floating-point numbers itself, independent of the locale. Floating-point
|
||||
numbers are correctly rounded (to nearest, ties to even). Only a `#!c long double` that is not IEEE 754 binary64
|
||||
(e.g., the 80-bit x87 format) is converted with `#!cpp std::from_chars` where available, or else with
|
||||
[`std::strtold`](https://en.cppreference.com/w/cpp/string/byte/strtof). For that call, the library temporarily
|
||||
replaces the `.` with the decimal point of the current locale (which may be longer than one byte, e.g., in
|
||||
`fa_IR.UTF-8`), so the result does not depend on the locale either. Changing the locale in another thread during
|
||||
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::strtoll`](https://en.cppreference.com/w/cpp/string/byte/strtol), and `std::strtod`, respectively.
|
||||
|
||||
@@ -100,10 +101,10 @@ flowchart TD
|
||||
### Number limits
|
||||
|
||||
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
||||
- 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
|
||||
- Numbers exceeding the limits of `#!c double` (i.e., numbers whose rounded value is not satisfying
|
||||
[`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.
|
||||
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing. Numbers too
|
||||
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
|
||||
`#!c 3.141592653589793238462643383279` is stored as [`0x400921fb54442d18`](https://float.exposed/0x400921fb54442d18).
|
||||
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
||||
@@ -133,9 +134,10 @@ That is, `-0` is stored as a signed integer, but the serialization does not repr
|
||||
### Number serialization
|
||||
|
||||
- Integer numbers are serialized as is; that is, no scientific notation is used.
|
||||
- Floating-point numbers are serialized as specified by the `#!c %g` printf modifier with
|
||||
[`std::numeric_limits<double>::max_digits10`](https://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10)
|
||||
significant digits. The rationale is to use the shortest representation while still allowing round-tripping.
|
||||
- Floating-point numbers are serialized with the fewest digits that read back as the same value (the closest such
|
||||
digits if there are several), in the layout of the `#!c %g` printf modifier: `#!c 1.5`, `#!c 100.0`, `#!c 1e+100`.
|
||||
Doubles are converted with the algorithm of [Żmij](https://github.com/vitaut/zmij), floats with Grisu2, which
|
||||
can write more digits than necessary.
|
||||
|
||||
!!! hint "Notes regarding precision of floating-point numbers"
|
||||
|
||||
@@ -351,9 +353,8 @@ The number types can be changed with template parameters.
|
||||
|
||||
A `basic_json` type that uses `#!c long double` as floating-point type.
|
||||
|
||||
```cpp hl_lines="2"
|
||||
using json_ld = nlohmann::basic_json<std::map, std::vector, std::string, bool,
|
||||
std::int64_t, std::uint64_t, long double>;
|
||||
```cpp hl_lines="1"
|
||||
using json_ld = nlohmann::json::with_float_t<long double>;
|
||||
```
|
||||
|
||||
Note values should then be parsed with `json_ld::parse` rather than `json::parse` as the latter would parse
|
||||
|
||||
@@ -8,6 +8,10 @@ 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,
|
||||
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
|
||||
|
||||
Requirements are split into two groups:
|
||||
@@ -26,9 +30,9 @@ Requirements are split into two groups:
|
||||
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
||||
the library. Four violations are not caught at compile time at all:
|
||||
|
||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and can silently misparse
|
||||
floating-point numbers, because the lexer may hand the buffer to `#!cpp std::strtod`, which reads up to the
|
||||
terminating null character.
|
||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers
|
||||
stored as a `#!cpp long double` that is not IEEE 754 binary64 (e.g., the 80-bit x87 format), because the lexer
|
||||
hands the buffer to `#!cpp std::strtold`.
|
||||
- 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.
|
||||
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
||||
@@ -143,7 +147,7 @@ struct unordered_map_object
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
using unordered_json = nlohmann::basic_json<unordered_map_object>;
|
||||
using unordered_json = nlohmann::json::with_object_t<unordered_map_object>;
|
||||
```
|
||||
|
||||
Whether `#!cpp std::unordered_map` can be instantiated at all depends on the standard library: `object_t` is formed
|
||||
@@ -176,7 +180,7 @@ struct flat_hash_object
|
||||
using base_t::base_t;
|
||||
};
|
||||
|
||||
using flat_hash_json = nlohmann::basic_json<flat_hash_object>;
|
||||
using flat_hash_json = nlohmann::json::with_object_t<flat_hash_object>;
|
||||
```
|
||||
|
||||
`absl::node_hash_map` keeps references to the mapped values valid across insertions; `absl::flat_hash_map` does not,
|
||||
@@ -349,16 +353,21 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
||||
### Always required
|
||||
|
||||
- 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::strtod`.
|
||||
encoded `char` data and passes `data()` to functions that take a `#!cpp const char*`, such as `#!cpp std::strtold`
|
||||
(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
|
||||
[wide string handling](../../home/faq.md#wide-string-handling).
|
||||
- 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.
|
||||
- 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.
|
||||
- `data()` must return a pointer to a contiguous, **null-terminated** buffer -- the parser may hand it to
|
||||
`#!cpp std::strtod`, which reads up to the null character. A type whose `data()` is not null-terminated does not
|
||||
fail to compile; it can silently misparse floating-point numbers.
|
||||
- `data()` must return a pointer to a contiguous, **null-terminated** buffer. `#!cpp float`, `#!cpp double`, and a
|
||||
`#!cpp long double` that is IEEE 754 binary64 are converted by the library itself and do not depend on this. For any
|
||||
other `NumberFloatType` (a `#!cpp long double` of another format), the parser falls back to `#!cpp std::strtold` when
|
||||
`#!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&)`,
|
||||
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+=`,
|
||||
@@ -537,16 +546,18 @@ therefore silently changes parse results rather than raising an error. See
|
||||
|
||||
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
||||
|
||||
- The [parser](../parsing/index.md) converts number literals with `#!cpp std::from_chars` or, as a fallback, with
|
||||
`#!cpp std::strtof`, `#!cpp std::strtod`, or `#!cpp std::strtold`; the library provides overloads for exactly these
|
||||
three types.
|
||||
- The [parser](../parsing/index.md) converts number literals to `#!cpp float`, `#!cpp double`, and a
|
||||
`#!cpp long double` that is IEEE 754 binary64 itself; other `#!cpp long double` formats are converted with
|
||||
`#!cpp std::from_chars` where available, or with `#!cpp std::strtold`. The library provides overloads for exactly
|
||||
these three types.
|
||||
- [`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
|
||||
(`#!cpp float` is promoted to `#!cpp double`).
|
||||
|
||||
If `#!cpp std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary32 or binary64 number, `dump` uses the
|
||||
Grisu2 algorithm, which produces the shortest representation that round-trips. Otherwise the `snprintf` fallback with
|
||||
`max_digits10` digits is used.
|
||||
If `#!cpp std::numeric_limits<NumberFloatType>` describes an IEEE 754 binary64 number, `dump` uses the algorithm of
|
||||
Żmij, which produces the shortest representation that round-trips. For IEEE 754 binary32 numbers, it uses Grisu2,
|
||||
which produces a short representation that round-trips. Otherwise the `snprintf` fallback with `max_digits10` digits is
|
||||
used.
|
||||
|
||||
### Required for the binary formats
|
||||
|
||||
@@ -558,7 +569,7 @@ binary32 or binary64 field and have no encoding for `#!cpp long double`.
|
||||
|
||||
| Type | Support |
|
||||
|--------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
||||
| `#!cpp double` (default) | full; short round-trip output through Grisu2 |
|
||||
| `#!cpp double` (default) | full; shortest round-trip output through Żmij |
|
||||
| `#!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 |
|
||||
| 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
|
||||
the parser.
|
||||
- **Binary formats** (BJData, BSON, CBOR, MessagePack, UBJSON) are read by an input adapter and turned into the same SAX
|
||||
- **Binary formats** (BJData, BON8, BSON, CBOR, MessagePack, UBJSON) are read by an input adapter and turned into the same SAX
|
||||
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
|
||||
`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.
|
||||
|
||||
- **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).
|
||||
- **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).
|
||||
|
||||
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.
|
||||
|
||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
|
||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/develop/.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
|
||||
|
||||
The library throws this exception when a parse error occurs. Parse errors
|
||||
can occur during the deserialization of JSON text, CBOR, MessagePack, as well
|
||||
can occur during the deserialization of JSON text or of one of the binary formats (BJData, BON8, BSON, CBOR, MessagePack, UBJSON), as well
|
||||
as when using JSON Patch.
|
||||
|
||||
Exceptions have ids 1xx.
|
||||
@@ -190,7 +190,7 @@ This error indicates a syntax error while deserializing a JSON text. The error m
|
||||
!!! 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.
|
||||
- Paste the input to a JSON validator like <http://jsonlint.com> or a tool like [jq](https://stedolan.github.io/jq/).
|
||||
- Paste the input to a JSON validator like <https://jsonlint.com> or a tool like [jq](https://jqlang.github.io/jq/).
|
||||
|
||||
### json.exception.parse_error.102
|
||||
|
||||
@@ -278,7 +278,9 @@ In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
|
||||
|
||||
### json.exception.parse_error.109
|
||||
|
||||
A JSON Pointer array index must be a number.
|
||||
A JSON Pointer array index must be a number. This exception is thrown for an array index that does not begin with a
|
||||
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"
|
||||
|
||||
@@ -289,6 +291,11 @@ A JSON Pointer array index must be 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
|
||||
|
||||
When parsing a [binary format](../features/binary_formats/index.md), the byte vector ends before the complete value has
|
||||
@@ -810,7 +817,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
|
||||
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
|
||||
nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, or BSON.
|
||||
nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, BSON, or BON8.
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
@@ -871,7 +878,8 @@ The provided key was not found in the JSON object.
|
||||
|
||||
### json.exception.out_of_range.404
|
||||
|
||||
A reference token in a JSON Pointer could not be resolved.
|
||||
A reference token in a JSON Pointer could not be resolved, for instance an array index that begins with a digit but
|
||||
contains other characters (e.g., `1a`), or `-` where it cannot be used.
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ 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 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 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
|
||||
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
|
||||
@@ -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
|
||||
[BSON](../features/binary_formats/bson.md).
|
||||
- Adds multidimensional C-array conversion and UTF-8 encoded `std::filesystem::path` conversions, and
|
||||
lowers the minimum [CMake](../integration/cmake.md) version to allow CMake 4.0.
|
||||
raises the minimum [CMake](../integration/cmake.md) version to 3.5 and supports CMake 4.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")
|
||||
HunterGate(
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
|
||||
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
|
||||
URL "https://github.com/cpp-pm/hunter/archive/v0.26.12.tar.gz"
|
||||
SHA1 "6498c5d0dec25d7fffb2b0574ebaf265179b894d"
|
||||
)
|
||||
|
||||
project(json_example)
|
||||
|
||||
@@ -116,7 +116,7 @@ function to use instead.
|
||||
=== "Deprecated"
|
||||
|
||||
```cpp
|
||||
using my_json = nlohmann::basic_json<std::map, std::vector, my_string_type>;
|
||||
using my_json = nlohmann::json::with_string_t<my_string_type>;
|
||||
nlohmann::json_pointer<my_json> ptr("/foo/bar/1");
|
||||
```
|
||||
|
||||
|
||||
@@ -2,12 +2,30 @@
|
||||
|
||||
# Creates a `<path>.md` sibling of each HTML output (for example,
|
||||
# `features/comments/` becomes `features/comments.md`) so agents and tools can
|
||||
# fetch the raw Markdown directly instead of parsing rendered HTML.
|
||||
# fetch the raw Markdown directly instead of parsing rendered HTML. The
|
||||
# `--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 shutil
|
||||
|
||||
import markdown
|
||||
from pymdownx.snippets import SnippetMissingError
|
||||
|
||||
_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):
|
||||
@@ -22,4 +40,11 @@ def on_post_build(config):
|
||||
url = file.url.rstrip("/")
|
||||
target = os.path.join(site_dir, (url or "index") + ".md")
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||
shutil.copyfile(file.abs_src_path, target)
|
||||
with io.open(file.abs_src_path, encoding="utf-8", newline="") as source:
|
||||
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 -->
|
||||
|
||||
*[ADL]: Argument-dependent lookup
|
||||
*[API]: Application Programming Interfaces
|
||||
*[API]: Application Programming Interface
|
||||
*[ASCII]: American Standard Code for Information Interchange
|
||||
*[BDFL]: Benevolent Dictator for Life
|
||||
*[BJData]: Binary JData
|
||||
|
||||
@@ -299,6 +299,7 @@ nav:
|
||||
- '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_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_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
||||
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
||||
|
||||
@@ -288,36 +288,6 @@ def check_header_links() -> None:
|
||||
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__":
|
||||
print(120 * "-")
|
||||
check_structure()
|
||||
@@ -327,7 +297,6 @@ if __name__ == "__main__":
|
||||
check_heading_levels()
|
||||
check_image_alt_text()
|
||||
check_header_links()
|
||||
check_docset()
|
||||
print(120 * "-")
|
||||
|
||||
if warnings > 0:
|
||||
|
||||
@@ -9,12 +9,16 @@
|
||||
#pragma once
|
||||
|
||||
#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/abi_macros.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp> // JSON_HEDLEY_ALWAYS_INLINE, NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
// Portable bit-level helpers for the number and string scanners. They use
|
||||
// compiler builtins where available and plain C++ otherwise, so they need no
|
||||
// platform headers and work regardless of byte order.
|
||||
// compiler builtins or platform-specific intrinsics where available and plain
|
||||
// C++ otherwise, so they work regardless of byte order.
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
@@ -25,6 +29,10 @@ inline int count_leading_zeros(std::uint64_t x) noexcept
|
||||
{
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
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
|
||||
int n = 0;
|
||||
for (int shift = 32; shift != 0; shift >>= 1)
|
||||
@@ -39,6 +47,29 @@ inline int count_leading_zeros(std::uint64_t x) noexcept
|
||||
#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
|
||||
struct uint128_parts
|
||||
{
|
||||
@@ -52,6 +83,12 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
||||
__extension__ using uint128 = unsigned __int128;
|
||||
const uint128 r = static_cast<uint128>(a) * b;
|
||||
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
|
||||
const std::uint64_t a_lo = a & 0xFFFFFFFFu;
|
||||
const std::uint64_t a_hi = a >> 32u;
|
||||
@@ -66,15 +103,27 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
||||
#endif
|
||||
}
|
||||
|
||||
/// eight bytes as a little-endian word (compilers fold this into one load on
|
||||
/// little-endian targets)
|
||||
inline std::uint64_t read_eight_bytes(const char* p) noexcept
|
||||
/// eight bytes as a little-endian word (a single load on little-endian
|
||||
/// targets; always inlined, as GCC otherwise calls it in the number loops)
|
||||
JSON_HEDLEY_ALWAYS_INLINE std::uint64_t read_eight_bytes(const unsigned char* b) noexcept
|
||||
{
|
||||
const auto* b = reinterpret_cast<const unsigned char*>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
#if defined(_MSC_VER) || defined(__x86_64__) || defined(__i386__) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
// 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)
|
||||
| (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[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
|
||||
|
||||
@@ -48,7 +48,7 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("null", j);
|
||||
}
|
||||
n = nullptr;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("number", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t&
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("boolean", j);
|
||||
}
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
l.clear();
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
l.resize(j.size());
|
||||
std::transform(j.begin(), j.end(), std::begin(l),
|
||||
@@ -305,7 +305,7 @@ void())
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("binary", j);
|
||||
}
|
||||
|
||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||
@@ -356,7 +356,7 @@ inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be binary or array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("binary or array", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("object", j);
|
||||
}
|
||||
|
||||
ConstructibleObjectType ret;
|
||||
@@ -432,7 +432,7 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("number", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,7 +504,7 @@ auto from_json(const BasicJsonType& j, TupleRelated&& t)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
m.clear();
|
||||
for (const auto& p : j)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
throw_type_must_be("array", p);
|
||||
}
|
||||
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()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
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
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// 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-License-Identifier: MIT
|
||||
|
||||
@@ -11,11 +12,32 @@
|
||||
|
||||
#include <array> // array
|
||||
#include <cmath> // signbit, isfinite
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // intN_t, uintN_t
|
||||
#include <cstring> // memcpy, memmove
|
||||
#include <limits> // numeric_limits
|
||||
#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>
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
@@ -1047,6 +1069,381 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||
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
|
||||
|
||||
/*!
|
||||
@@ -1064,7 +1461,6 @@ JSON_HEDLEY_NON_NULL(1, 2)
|
||||
JSON_HEDLEY_RETURNS_NON_NULL
|
||||
char* to_chars(char* first, const char* last, FloatType value)
|
||||
{
|
||||
static_cast<void>(last); // maybe unused - fix warning
|
||||
JSON_ASSERT(std::isfinite(value));
|
||||
|
||||
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
||||
@@ -1090,28 +1486,7 @@ char* to_chars(char* first, const char* last, FloatType value)
|
||||
JSON_HEDLEY_DIAGNOSTIC_POP
|
||||
#endif
|
||||
|
||||
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);
|
||||
return dtoa_impl::write_positive(first, last, value);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -414,13 +414,13 @@ inline void to_json(BasicJsonType& j, const EnumKeyedMap& map)
|
||||
BasicJsonType key = p.first;
|
||||
if (JSON_HEDLEY_UNLIKELY(!key.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", key.type_name()), &key));
|
||||
throw_type_must_be("string", key);
|
||||
}
|
||||
|
||||
auto& key_string = *key.template get_ptr<typename BasicJsonType::string_t*>();
|
||||
if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second))
|
||||
{
|
||||
JSON_THROW(type_error::create(318, concat("duplicate object key '", key_string, "'"), &key));
|
||||
JSON_THROW(type_error::create(exception_id::enum_key_duplicate, concat("duplicate object key '", key_string, "'"), &key));
|
||||
}
|
||||
}
|
||||
external_constructor<value_t::object>::construct(j, std::move(obj));
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | 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,6 +45,84 @@ namespace detail
|
||||
// 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
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/exception/
|
||||
class exception : public std::exception
|
||||
@@ -195,6 +273,18 @@ class parse_error : public exception
|
||||
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
|
||||
|
||||
@@ -229,6 +319,12 @@ class invalid_iterator : public exception
|
||||
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:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
invalid_iterator(int id_, const char* what_arg)
|
||||
@@ -247,6 +343,12 @@ class type_error : public exception
|
||||
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:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -264,6 +366,12 @@ class out_of_range : public exception
|
||||
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:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -281,6 +389,12 @@ class other_error : public exception
|
||||
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:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -307,6 +421,36 @@ void templated_json_throw(ExceptionType 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
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cmath> // ldexp
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t, uintmax_t
|
||||
#include <cstdio> // snprintf
|
||||
#include <cstring> // memcpy
|
||||
#include <iterator> // back_inserter
|
||||
#include <limits> // numeric_limits
|
||||
@@ -196,8 +195,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_end_of_input, concat("expected end of input; last byte: 0x", get_token_string()), "value");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,8 +317,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||
{
|
||||
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 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 true;
|
||||
}
|
||||
@@ -512,9 +509,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 1))
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("string length must be at least 1, is ", std::to_string(len)), "string");
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_string(len - static_cast<NumberType>(1), result)))
|
||||
@@ -524,10 +519,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(get() != 0x00))
|
||||
{
|
||||
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 last_byte_error(exception_id::unexpected_byte, "BSON string is not null-terminated", "string");
|
||||
}
|
||||
|
||||
return check_string_utf8(result, "string");
|
||||
@@ -547,9 +539,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary");
|
||||
}
|
||||
|
||||
// All BSON binary values have a subtype
|
||||
@@ -639,11 +629,9 @@ class binary_reader
|
||||
|
||||
default: // anything else is not supported (yet)
|
||||
{
|
||||
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()};
|
||||
const std::string cr_str = hex_byte(static_cast<std::uint8_t>(element_type));
|
||||
return sax->parse_error(element_type_parse_position, cr_str,
|
||||
parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
||||
parse_error::create(exception_id::bson_unsupported_type, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -967,9 +955,7 @@ class binary_reader
|
||||
{
|
||||
if (tag_handler == cbor_tag_handler_t::error)
|
||||
{
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
// ignore and store: the tag value is already in the head, so
|
||||
@@ -989,9 +975,7 @@ class binary_reader
|
||||
{
|
||||
case cbor_tag_handler_t::error:
|
||||
{
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
case cbor_tag_handler_t::ignore:
|
||||
@@ -1065,9 +1049,7 @@ class binary_reader
|
||||
|
||||
default: // anything else (0xFF is handled inside the other types)
|
||||
{
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1080,10 +1062,7 @@ class binary_reader
|
||||
*/
|
||||
bool cbor_indefinite_string_error(const char* type_name, const char* 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));
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1160,9 +1139,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
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));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1292,9 +1269,7 @@ class binary_reader
|
||||
break;
|
||||
}
|
||||
|
||||
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));
|
||||
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");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1375,9 +1350,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
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));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1523,7 +1496,7 @@ class binary_reader
|
||||
{
|
||||
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(408,
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message(concat("excessive ", context, " size"), "size"), nullptr));
|
||||
}
|
||||
result = conditional_static_cast<std::size_t>(len);
|
||||
@@ -2011,9 +1984,7 @@ class binary_reader
|
||||
|
||||
default: // anything else
|
||||
{
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2094,9 +2065,7 @@ class binary_reader
|
||||
|
||||
default:
|
||||
{
|
||||
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));
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2188,9 +2157,7 @@ class binary_reader
|
||||
break;
|
||||
}
|
||||
|
||||
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));
|
||||
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");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2499,8 +2466,7 @@ class binary_reader
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(len < 0))
|
||||
{
|
||||
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 last_byte_error(exception_id::invalid_string_or_size, "string length must not be negative", "string");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2600,18 +2566,7 @@ class binary_reader
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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));
|
||||
return length_type_error("", "string");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2696,12 +2651,11 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(number < 0))
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "count in an optimized container must be positive", "size");
|
||||
}
|
||||
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(408,
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
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
|
||||
@@ -2799,7 +2753,7 @@ class binary_reader
|
||||
}
|
||||
if (!value_in_range_of<std::size_t>(number))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message("integer value overflow", "size"), nullptr));
|
||||
}
|
||||
result = detail::conditional_static_cast<std::size_t>(number);
|
||||
@@ -2814,7 +2768,7 @@ class binary_reader
|
||||
}
|
||||
if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "ndarray dimensional vector is not allowed", "size");
|
||||
}
|
||||
std::vector<size_t> dim;
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
|
||||
@@ -2850,9 +2804,7 @@ class binary_reader
|
||||
const char* type_name = bjd_type_name(ndarray_dtype);
|
||||
if (JSON_HEDLEY_UNLIKELY(type_name == nullptr))
|
||||
{
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "type");
|
||||
}
|
||||
|
||||
string_t type_key = "_ArrayType_";
|
||||
@@ -2880,7 +2832,7 @@ class binary_reader
|
||||
// or SIZE_MAX.
|
||||
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(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
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));
|
||||
}
|
||||
result *= i;
|
||||
// the pre-check above already rules out result becoming 0
|
||||
@@ -2889,7 +2841,7 @@ class binary_reader
|
||||
// unknown-size container (see get_ubjson_size_type())
|
||||
if (result == npos)
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message("excessive ndarray size caused overflow", "size"), nullptr));
|
||||
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));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!emit_unsigned(i)))
|
||||
{
|
||||
@@ -2906,18 +2858,7 @@ class binary_reader
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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));
|
||||
return length_type_error(" after '#'", "size");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2950,9 +2891,7 @@ class binary_reader
|
||||
if (input_format == input_format_t::bjdata
|
||||
&& JSON_HEDLEY_UNLIKELY(is_bjd_excluded_optimized_type(result.second)))
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("marker 0x", get_token_string(), " is not a permitted optimized array type"), "type");
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof("type")))
|
||||
@@ -2967,9 +2906,7 @@ class binary_reader
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_byte, concat("expected '#' after type information; last byte: 0x", get_token_string()), "size");
|
||||
}
|
||||
|
||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray, 0, result.second);
|
||||
@@ -2988,8 +2925,7 @@ class binary_reader
|
||||
const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
|
||||
if (input_format == input_format_t::bjdata && is_ndarray && !inside_ndarray)
|
||||
{
|
||||
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 last_byte_error(exception_id::unexpected_byte, "ndarray requires both type and size", "size");
|
||||
}
|
||||
return is_error;
|
||||
}
|
||||
@@ -3121,9 +3057,7 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(current > 127))
|
||||
{
|
||||
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));
|
||||
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");
|
||||
}
|
||||
string_t s(1, static_cast<typename string_t::value_type>(current));
|
||||
return sax->string(s);
|
||||
@@ -3144,8 +3078,7 @@ class binary_reader
|
||||
default: // anything else
|
||||
break;
|
||||
}
|
||||
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));
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3208,7 +3141,7 @@ class binary_reader
|
||||
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))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
|
||||
return sax->parse_error(chars_read, get_token_string(), out_of_range::create(exception_id::container_too_large,
|
||||
exception_message("excessive array size", "size"), nullptr));
|
||||
}
|
||||
|
||||
@@ -3244,9 +3177,7 @@ class binary_reader
|
||||
// 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)
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::unexpected_byte, "BJData object does not support ND-array size in optimized format", "object");
|
||||
}
|
||||
|
||||
if (size_and_type.first != npos)
|
||||
@@ -3283,7 +3214,7 @@ class binary_reader
|
||||
// the lexer would stop at a NUL and accept the digits before it
|
||||
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
||||
{
|
||||
return sax->parse_error(chars_read, "00", parse_error::create(115, chars_read,
|
||||
return sax->parse_error(chars_read, "00", parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr));
|
||||
}
|
||||
number_vector.push_back(static_cast<char>(current));
|
||||
@@ -3300,7 +3231,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
|
||||
{
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
||||
}
|
||||
|
||||
@@ -3318,7 +3249,7 @@ class binary_reader
|
||||
return sax->parse_error(
|
||||
chars_read,
|
||||
number_string,
|
||||
out_of_range::create(406, concat("number overflow parsing '", number_string, '\''), nullptr));
|
||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", number_string, '\''), nullptr));
|
||||
}
|
||||
// number_string is a std::string, while the SAX interface takes a
|
||||
// string_t; convert explicitly, as the two are only implicitly
|
||||
@@ -3340,7 +3271,7 @@ class binary_reader
|
||||
case token_type::end_of_input:
|
||||
case token_type::literal_or_value:
|
||||
default:
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
|
||||
return sax->parse_error(chars_read, number_string, parse_error::create(exception_id::invalid_high_precision_number, chars_read,
|
||||
exception_message(concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
|
||||
}
|
||||
}
|
||||
@@ -3399,20 +3330,6 @@ class binary_reader
|
||||
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
|
||||
|
||||
@@ -3628,7 +3545,7 @@ class binary_reader
|
||||
}
|
||||
|
||||
// 0xFE: end of container where a value is expected
|
||||
return bon8_error("invalid byte", "value");
|
||||
return unexpected_byte("invalid byte", "value");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3755,7 +3672,7 @@ class binary_reader
|
||||
current = byte;
|
||||
}
|
||||
|
||||
return bon8_error("expected a string; last byte", "key");
|
||||
return unexpected_byte("expected a string; last byte", "key");
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3878,7 +3795,7 @@ class binary_reader
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!valid_second))
|
||||
{
|
||||
return bon8_error("invalid UTF-8 byte", "string");
|
||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
||||
}
|
||||
|
||||
result.push_back(static_cast<typename string_t::value_type>(byte));
|
||||
@@ -3892,7 +3809,7 @@ class binary_reader
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!is_bon8_continuation(current)))
|
||||
{
|
||||
return bon8_error("invalid UTF-8 byte", "string");
|
||||
return unexpected_byte("invalid UTF-8 byte", "string");
|
||||
}
|
||||
result.push_back(static_cast<typename string_t::value_type>(current));
|
||||
}
|
||||
@@ -3937,7 +3854,7 @@ class binary_reader
|
||||
{
|
||||
// in case of failure, advance position by 1 to report the failing location
|
||||
++chars_read;
|
||||
sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
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));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -4091,7 +4008,7 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(std::isfinite(number) && !std::isfinite(result)))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(),
|
||||
out_of_range::create(406, exception_message("number overflow", "value"), nullptr));
|
||||
out_of_range::create(exception_id::number_overflow, exception_message("number overflow", "value"), nullptr));
|
||||
}
|
||||
return sax->number_float(result, "");
|
||||
}
|
||||
@@ -4211,9 +4128,7 @@ class binary_reader
|
||||
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
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));
|
||||
return last_byte_error(exception_id::invalid_string_or_size, "invalid string: ill-formed UTF-8 byte", context);
|
||||
}
|
||||
|
||||
result = sanitize_utf8(result, error_handler);
|
||||
@@ -4309,19 +4224,53 @@ class binary_reader
|
||||
if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
|
||||
{
|
||||
return sax->parse_error(chars_read, "<end of file>",
|
||||
parse_error::create(110, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
parse_error::create(exception_id::unexpected_end_of_input, chars_read, exception_message("unexpected end of input", context), nullptr));
|
||||
}
|
||||
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
|
||||
*/
|
||||
std::string get_token_string() const
|
||||
{
|
||||
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()};
|
||||
return hex_byte(static_cast<std::uint8_t>(current));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -581,7 +581,7 @@ class wide_string_input_adapter
|
||||
template<class T>
|
||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||
{
|
||||
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::unexpected_byte, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -793,7 +793,7 @@ inline file_input_adapter input_adapter(std::FILE* file)
|
||||
{
|
||||
if (file == 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));
|
||||
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));
|
||||
}
|
||||
return file_input_adapter(file);
|
||||
}
|
||||
@@ -802,7 +802,7 @@ inline input_stream_adapter input_adapter(std::istream& stream)
|
||||
{
|
||||
if (stream.rdbuf() == 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));
|
||||
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));
|
||||
}
|
||||
return input_stream_adapter(stream);
|
||||
}
|
||||
@@ -827,7 +827,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||
{
|
||||
if (b == 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));
|
||||
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));
|
||||
}
|
||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||
|
||||
@@ -176,6 +176,27 @@ template<typename ArrayType>
|
||||
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
|
||||
/*!
|
||||
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
||||
@@ -185,6 +206,35 @@ befriends this struct, as the position members are private.
|
||||
*/
|
||||
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] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
@@ -349,22 +399,11 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||
|
||||
#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.
|
||||
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;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
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 check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
|
||||
bool key(string_t& val)
|
||||
@@ -383,11 +422,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
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();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -400,17 +435,13 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||
|
||||
#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.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -427,11 +458,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_array());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
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();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -611,21 +638,11 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#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.
|
||||
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;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// 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 check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -695,11 +712,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
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();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -710,13 +723,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||
{
|
||||
@@ -742,20 +749,13 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#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.
|
||||
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;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// check array limit
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -779,11 +779,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
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();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -809,13 +805,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
// remove discarded value
|
||||
if (!ref_stack.empty() && ref_stack.back())
|
||||
@@ -902,6 +892,23 @@ class json_sax_dom_callback_parser
|
||||
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,
|
||||
unless it is a duplicate key's slot with a stashed previous value, in
|
||||
|
||||
Loaded 100 of 163 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user