mirror of
https://github.com/nlohmann/json.git
synced 2026-10-10 16:37:14 +00:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48188b4569 | ||
|
|
6a28560c87 | ||
|
|
fc32fb6aed | ||
|
|
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:
|
||||
|
||||
+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
|
||||
@@ -81,6 +81,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.
|
||||
|
||||
@@ -1437,436 +1428,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 +1850,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 +1965,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 +1979,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"
|
||||
+14
-17
@@ -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"
|
||||
@@ -823,10 +818,12 @@ add_custom_target(ci_cuda_example
|
||||
|
||||
add_custom_target(ci_module_cpp20
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-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
+528
@@ -0,0 +1,528 @@
|
||||
#!/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)
|
||||
req = urllib.request.Request(u.geturl(), headers={'User-Agent': USER_AGENT})
|
||||
with urllib.request.urlopen(req, timeout=20) as r:
|
||||
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()).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:
|
||||
return yaml.load(f, Loader=Loader)
|
||||
|
||||
|
||||
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).
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -26,7 +26,8 @@ To store objects in C++, a type is defined by the template parameters described
|
||||
|
||||
`StringType`
|
||||
: the type of the keys or names (e.g., `std::string`). The comparison function `std::less<StringType>` is used to
|
||||
order elements inside the container.
|
||||
order elements inside the container. `object_t::key_type` must be implicitly convertible to `string_t` (required by the
|
||||
binary formats).
|
||||
|
||||
`AllocatorType`
|
||||
: the allocator to use for objects (e.g., `std::allocator`)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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.
|
||||
@@ -351,9 +351,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:
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
#if !defined(__SIZEOF_INT128__) && defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
#include <intrin0.h> // __umulh, _umul128
|
||||
#endif
|
||||
|
||||
#include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
// 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
|
||||
@@ -52,6 +55,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;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include <iosfwd> // ostream
|
||||
#endif // JSON_NO_IO
|
||||
#include <limits> // max
|
||||
#include <map> // map
|
||||
#include <numeric> // accumulate
|
||||
#include <set> // set
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
@@ -359,33 +359,82 @@ class json_pointer
|
||||
|
||||
private:
|
||||
/*!
|
||||
@brief the reference token sequences that denote arrays
|
||||
@brief the pointer prefixes of a flattened object, and which of them denote arrays
|
||||
|
||||
@ref unflatten collects the pointer prefixes that have a reference token 0
|
||||
among their children; @ref get_and_create creates arrays exactly below
|
||||
those prefixes and objects everywhere else. Deciding this up front keeps
|
||||
the result independent of the order in which the flattened object is
|
||||
iterated, which is unspecified for some object types.
|
||||
|
||||
The prefixes form a tree and are numbered, so each of them is stored only
|
||||
once (as a node) rather than as a copy of all of its reference tokens.
|
||||
*/
|
||||
using array_parents_t = std::set<std::vector<string_t>>;
|
||||
struct prefix_tree
|
||||
{
|
||||
// children[id] maps a reference token to the number of the prefix
|
||||
// extended by that token; number 0 is the empty prefix
|
||||
std::vector<std::map<string_t, std::size_t>> children;
|
||||
// is_array[id] is true iff some flattened key has the reference token
|
||||
// 0 directly below the prefix with number id
|
||||
std::vector<bool> is_array;
|
||||
|
||||
// start with the empty prefix only
|
||||
prefix_tree()
|
||||
: children(1)
|
||||
, is_array(1, false)
|
||||
{}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, adding it if it is new
|
||||
std::size_t add_child(std::size_t id, string_t&& reference_token)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
is_array[id] = true;
|
||||
}
|
||||
|
||||
// read the number before the emplace_back below, which may
|
||||
// reallocate children and invalidate the iterator
|
||||
const std::size_t next = children.size();
|
||||
const auto inserted = children[id].emplace(std::move(reference_token), next);
|
||||
const std::size_t child = inserted.first->second;
|
||||
if (inserted.second)
|
||||
{
|
||||
children.emplace_back();
|
||||
is_array.push_back(false);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, which must have been added before
|
||||
std::size_t find_child(std::size_t id, const string_t& reference_token) const
|
||||
{
|
||||
const auto it = children[id].find(reference_token);
|
||||
JSON_ASSERT(it != children[id].end());
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief create and return a reference to the pointed to value
|
||||
|
||||
Complexity: Linear in the number of reference tokens.
|
||||
Complexity: Linear in the number of reference tokens (times the logarithm
|
||||
of the number of siblings for the prefix lookup).
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if array index is not a number
|
||||
@throw type_error.313 if value cannot be unflattened
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const array_parents_t& array_parents) const
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const prefix_tree& tree) const
|
||||
{
|
||||
auto* result = &j;
|
||||
|
||||
// the reference tokens that have been consumed so far; used to look up
|
||||
// whether the value to be created below is an array or an object
|
||||
std::vector<string_t> prefix;
|
||||
// the number of the prefix consumed so far; used to look up whether
|
||||
// the value to be created below is an array or an object
|
||||
std::size_t id = 0;
|
||||
|
||||
// in case no reference tokens exist, return a reference to the JSON value
|
||||
// j which will be overwritten by a primitive value
|
||||
@@ -395,7 +444,7 @@ class json_pointer
|
||||
{
|
||||
case detail::value_t::null:
|
||||
{
|
||||
if (array_parents.find(prefix) != array_parents.end())
|
||||
if (tree.is_array[id])
|
||||
{
|
||||
// some reference token below this position is 0, so the
|
||||
// value is an array
|
||||
@@ -440,7 +489,7 @@ class json_pointer
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
|
||||
}
|
||||
|
||||
prefix.push_back(reference_token);
|
||||
id = tree.find_child(id, reference_token);
|
||||
}
|
||||
|
||||
return *result;
|
||||
@@ -878,64 +927,131 @@ class json_pointer
|
||||
@param[in,out] result the result object to insert values to
|
||||
|
||||
@note Empty objects or arrays are flattened to `null`.
|
||||
|
||||
The value is walked with an explicit stack rather than the call stack, so
|
||||
arbitrarily deeply nested values can be flattened.
|
||||
|
||||
@sa https://github.com/nlohmann/json/issues/5393
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
static void flatten(const string_t& reference_string,
|
||||
const BasicJsonType& value,
|
||||
BasicJsonType& result)
|
||||
{
|
||||
switch (value.type())
|
||||
using object_const_iterator = typename BasicJsonType::object_t::const_iterator;
|
||||
|
||||
// an array or object being walked: the container, the array index or
|
||||
// object iterator of the next child, and the length of the path of the
|
||||
// container itself
|
||||
struct frame
|
||||
{
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (value.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate array and use index as a reference string
|
||||
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
|
||||
value.m_data.m_value.array->operator[](i), result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
frame(const BasicJsonType* container_, object_const_iterator member_, const std::size_t path_length_) noexcept
|
||||
: container(container_), member(std::move(member_)), path_length(path_length_)
|
||||
{}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (value.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate object and use keys as reference string
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
const BasicJsonType* container;
|
||||
std::size_t index = 0;
|
||||
object_const_iterator member;
|
||||
std::size_t path_length;
|
||||
};
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
// The containers being flattened are kept on an explicit stack, and
|
||||
// every child is flattened completely before the next one, so the
|
||||
// entries come out in the same order as with a recursive walk. The
|
||||
// path of the value being flattened is kept in one buffer that grows
|
||||
// and shrinks with the stack, rather than in a new string per level.
|
||||
std::vector<frame> stack;
|
||||
string_t path = reference_string;
|
||||
|
||||
// flatten `v`, whose path is `path`: primitives and empty containers
|
||||
// are added to the result right away; other containers get a frame
|
||||
const auto enter = [&stack, &path, &result](const BasicJsonType & v)
|
||||
{
|
||||
switch (v.type())
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[reference_string] = value;
|
||||
break;
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (v.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, object_const_iterator(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (v.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, v.m_data.m_value.object->begin(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[path] = v;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enter(value);
|
||||
while (!stack.empty())
|
||||
{
|
||||
// the frame is changed through stack.back(): enter() may push a
|
||||
// frame, which would invalidate a reference to it
|
||||
const BasicJsonType* const container = stack.back().container;
|
||||
|
||||
// drop the path of the previous child
|
||||
path.resize(stack.back().path_length);
|
||||
|
||||
if (container->is_array())
|
||||
{
|
||||
const auto& array = *container->m_data.m_value.array;
|
||||
const std::size_t i = stack.back().index;
|
||||
if (i == array.size())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate array and use index as a reference string
|
||||
++stack.back().index;
|
||||
detail::concat_into(path, '/', detail::to_string<string_t>(i));
|
||||
enter(array[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const object_const_iterator it = stack.back().member;
|
||||
if (it == container->m_data.m_value.object->end())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate object and use keys as reference string
|
||||
++stack.back().member;
|
||||
detail::concat_into(path, '/', detail::escape(it->first));
|
||||
enter(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -963,19 +1079,15 @@ class json_pointer
|
||||
|
||||
// collect the pointer prefixes that have a reference token 0 among
|
||||
// their children; the values below them are arrays, all others are
|
||||
// objects (see array_parents_t)
|
||||
array_parents_t array_parents;
|
||||
// objects (see prefix_tree)
|
||||
prefix_tree tree;
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
json_pointer ptr(element.first);
|
||||
std::vector<string_t> prefix;
|
||||
std::size_t id = 0;
|
||||
for (auto& reference_token : ptr.reference_tokens)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
array_parents.insert(prefix);
|
||||
}
|
||||
prefix.push_back(std::move(reference_token));
|
||||
id = tree.add_child(id, std::move(reference_token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,7 +1103,7 @@ class json_pointer
|
||||
// that if the JSON pointer is "" (i.e., points to the whole value),
|
||||
// function get_and_create returns a reference to the result itself.
|
||||
// An assignment will then create a primitive value.
|
||||
json_pointer(element.first).get_and_create(result, array_parents) = element.second;
|
||||
json_pointer(element.first).get_and_create(result, tree) = element.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -85,6 +85,12 @@ template<typename BasicJsonType, typename CharType, typename OutputSinkType = ou
|
||||
class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
|
||||
/// an object key as string_t: a reference when object_t::key_type already is
|
||||
/// string_t, otherwise a converted copy that outlives sanitize_utf8_for_write's result
|
||||
using object_key_string_t = typename std::conditional <
|
||||
std::is_same<typename BasicJsonType::object_t::key_type, string_t>::value,
|
||||
const string_t&, string_t >::type;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
@@ -244,16 +250,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, value.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_cbor_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -316,23 +313,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_cbor_head(0xA0, j.m_data.m_value.object->size());
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// el.first is checked here, against the object as
|
||||
// diagnostics context, because write_cbor(el.first)
|
||||
// converts it to a temporary basic_json that would be
|
||||
// used as the context instead; for error_handler_t::keep
|
||||
// and ::replace/::ignore the recursive write_cbor(el.first)
|
||||
// call below handles the key like any other string, so no
|
||||
// separate check is needed here for those
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_cbor(el.first);
|
||||
// el.first is written directly (not via a temporary
|
||||
// basic_json), with the object as diagnostics context
|
||||
write_cbor_string(el.first, j);
|
||||
write_cbor(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -491,39 +485,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(value.size(), j);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_msgpack_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -629,19 +591,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_msgpack_object_prefix(j.m_data.m_value.object->size(), j);
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// as in write_cbor, el.first is checked here against the
|
||||
// object as diagnostics context; the recursive call below
|
||||
// handles keep/replace/ignore like any other string
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_msgpack(el.first);
|
||||
// as in write_cbor, el.first is written directly with the
|
||||
// object as diagnostics context
|
||||
write_msgpack_string(el.first, j);
|
||||
write_msgpack(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -819,8 +782,10 @@ class binary_writer
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = el.first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(el.first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -1025,13 +990,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// el.first is checked here, against the object as diagnostics
|
||||
// context, like the matching check in write_cbor's object case
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_cbor(current.object_it->first);
|
||||
// the key is written directly (not via a temporary basic_json),
|
||||
// with the object as diagnostics context, as in write_cbor
|
||||
write_cbor_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_cbor_value_or_push(*child, stack);
|
||||
@@ -1106,11 +1067,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_msgpack(current.object_it->first);
|
||||
// as in write_cbor_iterative, the key is written directly with
|
||||
// the object as diagnostics context
|
||||
write_msgpack_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_msgpack_value_or_push(*child, stack);
|
||||
@@ -1366,8 +1325,10 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = current.object_it->first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(current.object_it->first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -1988,6 +1949,85 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief write a CBOR text string
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context (the string value itself, or the object a key belongs to) used
|
||||
as diagnostics context; this avoids converting object keys to a temporary
|
||||
basic_json just to write them
|
||||
|
||||
@note When object_t::key_type is not string_t, @a value is a temporary
|
||||
string_t converted from the key, which lives only until the end of
|
||||
the caller's statement. The reference returned by
|
||||
@ref sanitize_utf8_for_write may refer to it, so it must not escape
|
||||
this function.
|
||||
*/
|
||||
void write_cbor_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, sanitized.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
/////////////
|
||||
// MsgPack //
|
||||
/////////////
|
||||
|
||||
/*!
|
||||
@brief write a MessagePack str
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context used as diagnostics context, as in @ref write_cbor_string
|
||||
|
||||
@note As in @ref write_cbor_string, @a value may be a temporary string_t
|
||||
converted from a key, so the reference returned by
|
||||
@ref sanitize_utf8_for_write must not escape this function.
|
||||
*/
|
||||
void write_msgpack_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(sanitized.size(), context);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
////////////
|
||||
// UBJSON //
|
||||
////////////
|
||||
@@ -2730,6 +2770,11 @@ class binary_writer
|
||||
itself in every case but a sanitized `replace`/`ignore` one, so @a
|
||||
storage must outlive the returned reference only then.
|
||||
|
||||
@a s must be an lvalue that outlives the returned reference. An object key
|
||||
whose `key_type` is not @ref string_t must therefore first be converted
|
||||
into a named string_t (see @ref object_key_string_t); the deleted overload
|
||||
below enforces this at compile time.
|
||||
|
||||
@param[in] s the string (value or object key) to write
|
||||
@param[in] context the value @a s belongs to (for diagnostics)
|
||||
@param[out] storage backing storage for a sanitized copy
|
||||
@@ -2759,6 +2804,10 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/// deleted: anything but a string_t would bind a temporary that dies before the returned reference is used
|
||||
template < typename T, enable_if_t < !std::is_same<T, string_t>::value, int > = 0 >
|
||||
const string_t& sanitize_utf8_for_write(const T& /*s*/, const BasicJsonType& /*context*/, string_t& /*storage*/) const = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete): a private helper's guard, not part of the interface
|
||||
|
||||
/*!
|
||||
@brief write an integer in the shortest encoding
|
||||
|
||||
|
||||
@@ -108,8 +108,8 @@ void encode_utf8(std::uint32_t cp, const Out& out)
|
||||
///////////////////
|
||||
|
||||
// UTF-8 decoder states used by decode() below
|
||||
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
|
||||
/*!
|
||||
@brief process a byte of a UTF-8 sequence
|
||||
|
||||
Generated
+318
-148
@@ -6395,8 +6395,8 @@ void encode_utf8(std::uint32_t cp, const Out& out)
|
||||
///////////////////
|
||||
|
||||
// UTF-8 decoder states used by decode() below
|
||||
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
JSON_INLINE_VARIABLE constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
|
||||
/*!
|
||||
@brief process a byte of a UTF-8 sequence
|
||||
@@ -8791,13 +8791,16 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
|
||||
#include <cstdint> // uint64_t
|
||||
#if !defined(__SIZEOF_INT128__) && defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
|
||||
#include <intrin0.h> // __umulh, _umul128
|
||||
#endif
|
||||
|
||||
// #include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
|
||||
// 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
|
||||
@@ -8835,6 +8838,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;
|
||||
@@ -19919,8 +19928,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
#include <iosfwd> // ostream
|
||||
#endif // JSON_NO_IO
|
||||
#include <limits> // max
|
||||
#include <map> // map
|
||||
#include <numeric> // accumulate
|
||||
#include <set> // set
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
@@ -20268,33 +20277,82 @@ class json_pointer
|
||||
|
||||
private:
|
||||
/*!
|
||||
@brief the reference token sequences that denote arrays
|
||||
@brief the pointer prefixes of a flattened object, and which of them denote arrays
|
||||
|
||||
@ref unflatten collects the pointer prefixes that have a reference token 0
|
||||
among their children; @ref get_and_create creates arrays exactly below
|
||||
those prefixes and objects everywhere else. Deciding this up front keeps
|
||||
the result independent of the order in which the flattened object is
|
||||
iterated, which is unspecified for some object types.
|
||||
|
||||
The prefixes form a tree and are numbered, so each of them is stored only
|
||||
once (as a node) rather than as a copy of all of its reference tokens.
|
||||
*/
|
||||
using array_parents_t = std::set<std::vector<string_t>>;
|
||||
struct prefix_tree
|
||||
{
|
||||
// children[id] maps a reference token to the number of the prefix
|
||||
// extended by that token; number 0 is the empty prefix
|
||||
std::vector<std::map<string_t, std::size_t>> children;
|
||||
// is_array[id] is true iff some flattened key has the reference token
|
||||
// 0 directly below the prefix with number id
|
||||
std::vector<bool> is_array;
|
||||
|
||||
// start with the empty prefix only
|
||||
prefix_tree()
|
||||
: children(1)
|
||||
, is_array(1, false)
|
||||
{}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, adding it if it is new
|
||||
std::size_t add_child(std::size_t id, string_t&& reference_token)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
is_array[id] = true;
|
||||
}
|
||||
|
||||
// read the number before the emplace_back below, which may
|
||||
// reallocate children and invalidate the iterator
|
||||
const std::size_t next = children.size();
|
||||
const auto inserted = children[id].emplace(std::move(reference_token), next);
|
||||
const std::size_t child = inserted.first->second;
|
||||
if (inserted.second)
|
||||
{
|
||||
children.emplace_back();
|
||||
is_array.push_back(false);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
// return the number of the prefix with number id extended by
|
||||
// reference_token, which must have been added before
|
||||
std::size_t find_child(std::size_t id, const string_t& reference_token) const
|
||||
{
|
||||
const auto it = children[id].find(reference_token);
|
||||
JSON_ASSERT(it != children[id].end());
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief create and return a reference to the pointed to value
|
||||
|
||||
Complexity: Linear in the number of reference tokens.
|
||||
Complexity: Linear in the number of reference tokens (times the logarithm
|
||||
of the number of siblings for the prefix lookup).
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if array index is not a number
|
||||
@throw type_error.313 if value cannot be unflattened
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const array_parents_t& array_parents) const
|
||||
BasicJsonType& get_and_create(BasicJsonType& j, const prefix_tree& tree) const
|
||||
{
|
||||
auto* result = &j;
|
||||
|
||||
// the reference tokens that have been consumed so far; used to look up
|
||||
// whether the value to be created below is an array or an object
|
||||
std::vector<string_t> prefix;
|
||||
// the number of the prefix consumed so far; used to look up whether
|
||||
// the value to be created below is an array or an object
|
||||
std::size_t id = 0;
|
||||
|
||||
// in case no reference tokens exist, return a reference to the JSON value
|
||||
// j which will be overwritten by a primitive value
|
||||
@@ -20304,7 +20362,7 @@ class json_pointer
|
||||
{
|
||||
case detail::value_t::null:
|
||||
{
|
||||
if (array_parents.find(prefix) != array_parents.end())
|
||||
if (tree.is_array[id])
|
||||
{
|
||||
// some reference token below this position is 0, so the
|
||||
// value is an array
|
||||
@@ -20349,7 +20407,7 @@ class json_pointer
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
|
||||
}
|
||||
|
||||
prefix.push_back(reference_token);
|
||||
id = tree.find_child(id, reference_token);
|
||||
}
|
||||
|
||||
return *result;
|
||||
@@ -20787,64 +20845,131 @@ class json_pointer
|
||||
@param[in,out] result the result object to insert values to
|
||||
|
||||
@note Empty objects or arrays are flattened to `null`.
|
||||
|
||||
The value is walked with an explicit stack rather than the call stack, so
|
||||
arbitrarily deeply nested values can be flattened.
|
||||
|
||||
@sa https://github.com/nlohmann/json/issues/5393
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
static void flatten(const string_t& reference_string,
|
||||
const BasicJsonType& value,
|
||||
BasicJsonType& result)
|
||||
{
|
||||
switch (value.type())
|
||||
using object_const_iterator = typename BasicJsonType::object_t::const_iterator;
|
||||
|
||||
// an array or object being walked: the container, the array index or
|
||||
// object iterator of the next child, and the length of the path of the
|
||||
// container itself
|
||||
struct frame
|
||||
{
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (value.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate array and use index as a reference string
|
||||
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
|
||||
value.m_data.m_value.array->operator[](i), result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
frame(const BasicJsonType* container_, object_const_iterator member_, const std::size_t path_length_) noexcept
|
||||
: container(container_), member(std::move(member_)), path_length(path_length_)
|
||||
{}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (value.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[reference_string] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// iterate object and use keys as reference string
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
const BasicJsonType* container;
|
||||
std::size_t index = 0;
|
||||
object_const_iterator member;
|
||||
std::size_t path_length;
|
||||
};
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
// The containers being flattened are kept on an explicit stack, and
|
||||
// every child is flattened completely before the next one, so the
|
||||
// entries come out in the same order as with a recursive walk. The
|
||||
// path of the value being flattened is kept in one buffer that grows
|
||||
// and shrinks with the stack, rather than in a new string per level.
|
||||
std::vector<frame> stack;
|
||||
string_t path = reference_string;
|
||||
|
||||
// flatten `v`, whose path is `path`: primitives and empty containers
|
||||
// are added to the result right away; other containers get a frame
|
||||
const auto enter = [&stack, &path, &result](const BasicJsonType & v)
|
||||
{
|
||||
switch (v.type())
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[reference_string] = value;
|
||||
break;
|
||||
case detail::value_t::array:
|
||||
{
|
||||
if (v.m_data.m_value.array->empty())
|
||||
{
|
||||
// flatten empty array as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, object_const_iterator(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (v.m_data.m_value.object->empty())
|
||||
{
|
||||
// flatten empty object as null
|
||||
result[path] = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.emplace_back(&v, v.m_data.m_value.object->begin(), path.size());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case detail::value_t::null:
|
||||
case detail::value_t::string:
|
||||
case detail::value_t::boolean:
|
||||
case detail::value_t::number_integer:
|
||||
case detail::value_t::number_unsigned:
|
||||
case detail::value_t::number_float:
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
{
|
||||
// add a primitive value with its reference string
|
||||
result[path] = v;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enter(value);
|
||||
while (!stack.empty())
|
||||
{
|
||||
// the frame is changed through stack.back(): enter() may push a
|
||||
// frame, which would invalidate a reference to it
|
||||
const BasicJsonType* const container = stack.back().container;
|
||||
|
||||
// drop the path of the previous child
|
||||
path.resize(stack.back().path_length);
|
||||
|
||||
if (container->is_array())
|
||||
{
|
||||
const auto& array = *container->m_data.m_value.array;
|
||||
const std::size_t i = stack.back().index;
|
||||
if (i == array.size())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate array and use index as a reference string
|
||||
++stack.back().index;
|
||||
detail::concat_into(path, '/', detail::to_string<string_t>(i));
|
||||
enter(array[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const object_const_iterator it = stack.back().member;
|
||||
if (it == container->m_data.m_value.object->end())
|
||||
{
|
||||
stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// iterate object and use keys as reference string
|
||||
++stack.back().member;
|
||||
detail::concat_into(path, '/', detail::escape(it->first));
|
||||
enter(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20872,19 +20997,15 @@ class json_pointer
|
||||
|
||||
// collect the pointer prefixes that have a reference token 0 among
|
||||
// their children; the values below them are arrays, all others are
|
||||
// objects (see array_parents_t)
|
||||
array_parents_t array_parents;
|
||||
// objects (see prefix_tree)
|
||||
prefix_tree tree;
|
||||
for (const auto& element : *value.m_data.m_value.object)
|
||||
{
|
||||
json_pointer ptr(element.first);
|
||||
std::vector<string_t> prefix;
|
||||
std::size_t id = 0;
|
||||
for (auto& reference_token : ptr.reference_tokens)
|
||||
{
|
||||
if (reference_token == "0")
|
||||
{
|
||||
array_parents.insert(prefix);
|
||||
}
|
||||
prefix.push_back(std::move(reference_token));
|
||||
id = tree.add_child(id, std::move(reference_token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20900,7 +21021,7 @@ class json_pointer
|
||||
// that if the JSON pointer is "" (i.e., points to the whole value),
|
||||
// function get_and_create returns a reference to the result itself.
|
||||
// An assignment will then create a primitive value.
|
||||
json_pointer(element.first).get_and_create(result, array_parents) = element.second;
|
||||
json_pointer(element.first).get_and_create(result, tree) = element.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -21581,6 +21702,12 @@ template<typename BasicJsonType, typename CharType, typename OutputSinkType = ou
|
||||
class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
|
||||
/// an object key as string_t: a reference when object_t::key_type already is
|
||||
/// string_t, otherwise a converted copy that outlives sanitize_utf8_for_write's result
|
||||
using object_key_string_t = typename std::conditional <
|
||||
std::is_same<typename BasicJsonType::object_t::key_type, string_t>::value,
|
||||
const string_t&, string_t >::type;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
@@ -21740,16 +21867,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, value.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_cbor_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21812,23 +21930,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_cbor_head(0xA0, j.m_data.m_value.object->size());
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// el.first is checked here, against the object as
|
||||
// diagnostics context, because write_cbor(el.first)
|
||||
// converts it to a temporary basic_json that would be
|
||||
// used as the context instead; for error_handler_t::keep
|
||||
// and ::replace/::ignore the recursive write_cbor(el.first)
|
||||
// call below handles the key like any other string, so no
|
||||
// separate check is needed here for those
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_cbor(el.first);
|
||||
// el.first is written directly (not via a temporary
|
||||
// basic_json), with the object as diagnostics context
|
||||
write_cbor_string(el.first, j);
|
||||
write_cbor(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -21987,39 +22102,7 @@ class binary_writer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& value = sanitize_utf8_for_write(*j.m_data.m_value.string, j, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(value.size(), j);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.data()),
|
||||
value.size());
|
||||
write_msgpack_string(*j.m_data.m_value.string, j);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -22125,19 +22208,20 @@ class binary_writer
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
static_assert(
|
||||
std::is_convertible <
|
||||
typename BasicJsonType::object_t::key_type,
|
||||
string_t >::value,
|
||||
"object_t::key_type must be implicitly convertible to string_t");
|
||||
|
||||
// step 1: write control byte and the object size
|
||||
write_msgpack_object_prefix(j.m_data.m_value.object->size(), j);
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// as in write_cbor, el.first is checked here against the
|
||||
// object as diagnostics context; the recursive call below
|
||||
// handles keep/replace/ignore like any other string
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(el.first, j);
|
||||
}
|
||||
write_msgpack(el.first);
|
||||
// as in write_cbor, el.first is written directly with the
|
||||
// object as diagnostics context
|
||||
write_msgpack_string(el.first, j);
|
||||
write_msgpack(el.second, depth + 1);
|
||||
}
|
||||
break;
|
||||
@@ -22315,8 +22399,10 @@ class binary_writer
|
||||
|
||||
for (const auto& el : *j.m_data.m_value.object)
|
||||
{
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = el.first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(el.first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -22521,13 +22607,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// el.first is checked here, against the object as diagnostics
|
||||
// context, like the matching check in write_cbor's object case
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_cbor(current.object_it->first);
|
||||
// the key is written directly (not via a temporary basic_json),
|
||||
// with the object as diagnostics context, as in write_cbor
|
||||
write_cbor_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_cbor_value_or_push(*child, stack);
|
||||
@@ -22602,11 +22684,9 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error_handler == error_handler_t::strict)
|
||||
{
|
||||
check_utf8(current.object_it->first, *current.value);
|
||||
}
|
||||
write_msgpack(current.object_it->first);
|
||||
// as in write_cbor_iterative, the key is written directly with
|
||||
// the object as diagnostics context
|
||||
write_msgpack_string(current.object_it->first, *current.value);
|
||||
const BasicJsonType* child = &(current.object_it->second);
|
||||
++stack.back().object_it;
|
||||
write_msgpack_value_or_push(*child, stack);
|
||||
@@ -22862,8 +22942,10 @@ class binary_writer
|
||||
continue;
|
||||
}
|
||||
|
||||
// a converted key must outlive the reference returned by sanitize_utf8_for_write
|
||||
const object_key_string_t key_string = current.object_it->first;
|
||||
string_t storage;
|
||||
const string_t& key = sanitize_utf8_for_write(current.object_it->first, j, storage);
|
||||
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
|
||||
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(key.data()),
|
||||
@@ -23484,6 +23566,85 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief write a CBOR text string
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context (the string value itself, or the object a key belongs to) used
|
||||
as diagnostics context; this avoids converting object keys to a temporary
|
||||
basic_json just to write them
|
||||
|
||||
@note When object_t::key_type is not string_t, @a value is a temporary
|
||||
string_t converted from the key, which lives only until the end of
|
||||
the caller's statement. The reference returned by
|
||||
@ref sanitize_utf8_for_write may refer to it, so it must not escape
|
||||
this function.
|
||||
*/
|
||||
void write_cbor_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
write_cbor_head(0x60, sanitized.size());
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
/////////////
|
||||
// MsgPack //
|
||||
/////////////
|
||||
|
||||
/*!
|
||||
@brief write a MessagePack str
|
||||
|
||||
@a value is checked or sanitized according to @ref error_handler, with
|
||||
@a context used as diagnostics context, as in @ref write_cbor_string
|
||||
|
||||
@note As in @ref write_cbor_string, @a value may be a temporary string_t
|
||||
converted from a key, so the reference returned by
|
||||
@ref sanitize_utf8_for_write must not escape this function.
|
||||
*/
|
||||
void write_msgpack_string(const string_t& value, const BasicJsonType& context)
|
||||
{
|
||||
string_t storage;
|
||||
const string_t& sanitized = sanitize_utf8_for_write(value, context, storage);
|
||||
|
||||
// step 1: write control byte and the string length
|
||||
const auto N = to_msgpack_length(sanitized.size(), context);
|
||||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else
|
||||
{
|
||||
// str 32
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(sanitized.data()),
|
||||
sanitized.size());
|
||||
}
|
||||
|
||||
////////////
|
||||
// UBJSON //
|
||||
////////////
|
||||
@@ -24226,6 +24387,11 @@ class binary_writer
|
||||
itself in every case but a sanitized `replace`/`ignore` one, so @a
|
||||
storage must outlive the returned reference only then.
|
||||
|
||||
@a s must be an lvalue that outlives the returned reference. An object key
|
||||
whose `key_type` is not @ref string_t must therefore first be converted
|
||||
into a named string_t (see @ref object_key_string_t); the deleted overload
|
||||
below enforces this at compile time.
|
||||
|
||||
@param[in] s the string (value or object key) to write
|
||||
@param[in] context the value @a s belongs to (for diagnostics)
|
||||
@param[out] storage backing storage for a sanitized copy
|
||||
@@ -24255,6 +24421,10 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
/// deleted: anything but a string_t would bind a temporary that dies before the returned reference is used
|
||||
template < typename T, enable_if_t < !std::is_same<T, string_t>::value, int > = 0 >
|
||||
const string_t& sanitize_utf8_for_write(const T& /*s*/, const BasicJsonType& /*context*/, string_t& /*storage*/) const = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete): a private helper's guard, not part of the interface
|
||||
|
||||
/*!
|
||||
@brief write an integer in the shortest encoding
|
||||
|
||||
|
||||
@@ -138,7 +138,8 @@ json_test_set_test_options(test-disabled_exceptions
|
||||
# only the #972 regression test needs thirdparty/fifo_map on its include path
|
||||
json_test_set_test_options(test-regression1 LINK_LIBRARIES fifo_map_include)
|
||||
|
||||
# GCC's false -Warray-bounds error with JSON_DIAGNOSTICS only shows up when optimizing (#5742).
|
||||
# Regression test for GCC's false -Warray-bounds error with JSON_DIAGNOSTICS (#5742, fixed in #5585). It only
|
||||
# showed up when optimizing, so build this test with -O3 and the warning as an error.
|
||||
# -O3 makes the optimizer-driven warnings of the ci_test_gcc flag set (-Winline,
|
||||
# -Wsuggest-attribute=...) fire on the library's inline functions; they are not
|
||||
# what this test checks, so turn them off for it.
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace custom_object_key_test
|
||||
{
|
||||
class key
|
||||
{
|
||||
public:
|
||||
key() = default;
|
||||
|
||||
key(const char* value)
|
||||
: m_value(value)
|
||||
{}
|
||||
|
||||
key(std::string value)
|
||||
: m_value(std::move(value))
|
||||
{}
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// Required by JSON_DIAGNOSTICS, which reads object keys through data()
|
||||
// when building the path of an exception.
|
||||
const char* data() const noexcept
|
||||
{
|
||||
return m_value.data();
|
||||
}
|
||||
|
||||
friend bool operator<(const key& lhs, const key& rhs)
|
||||
{
|
||||
return lhs.m_value < rhs.m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
template<typename Key, typename Value, typename Compare, typename Allocator>
|
||||
class object
|
||||
: public std::map <
|
||||
key,
|
||||
Value,
|
||||
std::less<key>, // NOLINT(modernize-use-transparent-functors)
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc <
|
||||
std::pair<const key, Value >>>
|
||||
{
|
||||
private:
|
||||
using allocator_type =
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc <
|
||||
std::pair<const key, Value >>;
|
||||
|
||||
using base_type =
|
||||
std::map<key, Value, std::less<key>, allocator_type>; // NOLINT(modernize-use-transparent-functors)
|
||||
|
||||
public:
|
||||
using base_type::base_type;
|
||||
};
|
||||
|
||||
using json = nlohmann::basic_json<object>;
|
||||
} // namespace custom_object_key_test
|
||||
@@ -370,14 +370,7 @@ TEST_CASE("copy of a deeply nested value survives a failing allocation (#5640)")
|
||||
#if !(defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL > 0)
|
||||
SECTION("std::map-backed object_t")
|
||||
{
|
||||
using bad_alloc_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
nth_alloc_fails_allocator>;
|
||||
using bad_alloc_json = nlohmann::json::with_allocator_t<nth_alloc_fails_allocator>;
|
||||
|
||||
check_deep_copy_survives_failing_allocation<bad_alloc_json>(false);
|
||||
check_deep_copy_survives_failing_allocation<bad_alloc_json>(true);
|
||||
@@ -385,14 +378,7 @@ TEST_CASE("copy of a deeply nested value survives a failing allocation (#5640)")
|
||||
|
||||
SECTION("ordered_map-backed object_t")
|
||||
{
|
||||
using bad_alloc_ordered_json = nlohmann::basic_json<nlohmann::ordered_map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
nth_alloc_fails_allocator>;
|
||||
using bad_alloc_ordered_json = nlohmann::ordered_json::with_allocator_t<nth_alloc_fails_allocator>;
|
||||
|
||||
check_deep_copy_survives_failing_allocation<bad_alloc_ordered_json>(false);
|
||||
check_deep_copy_survives_failing_allocation<bad_alloc_ordered_json>(true);
|
||||
@@ -450,14 +436,7 @@ struct scratch_counting_allocator : std::allocator<T>
|
||||
|
||||
TEST_CASE("deep copy uses the provided allocator")
|
||||
{
|
||||
using counting_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
scratch_counting_allocator>;
|
||||
using counting_json = nlohmann::json::with_allocator_t<scratch_counting_allocator>;
|
||||
|
||||
// deeper than the 128 levels the copy constructor descends into, so the
|
||||
// innermost objects are copied by the iterative deep copy
|
||||
@@ -516,14 +495,7 @@ TEST_CASE("converting a deeply nested value from another specialization fails cl
|
||||
// the allocator in noexcept constructors, so a failing construction crashes
|
||||
// the program there instead of throwing std::bad_alloc. Nothing to check.
|
||||
#if !(defined(_MSC_VER) && _MSC_VER < 1910 && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL > 0)
|
||||
using countdown_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
countdown_allocator>;
|
||||
using countdown_json = nlohmann::json::with_allocator_t<countdown_allocator>;
|
||||
|
||||
// deeper than the 128 levels the converting constructor descends into, so
|
||||
// that failures land on both sides of the bound - or, built with
|
||||
@@ -631,14 +603,7 @@ TEST_CASE("destructor performs no allocation, only deallocation")
|
||||
// Since that stack could itself throw bad_alloc from inside the
|
||||
// noexcept destructor (#5135), destroy() no longer allocates anything:
|
||||
// it only ever frees what is already there.
|
||||
using counting_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
counting_allocator>;
|
||||
using counting_json = nlohmann::json::with_allocator_t<counting_allocator>;
|
||||
|
||||
SECTION("array")
|
||||
{
|
||||
@@ -683,14 +648,7 @@ TEST_CASE("destructor performs no allocation, only deallocation")
|
||||
TEST_CASE("a failed allocation leaves the value unchanged")
|
||||
{
|
||||
// create JSON type using the throwing allocator
|
||||
using my_json = nlohmann::basic_json<std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
my_allocator>;
|
||||
using my_json = nlohmann::json::with_allocator_t<my_allocator>;
|
||||
|
||||
// Each of these creates a string, array, object, or binary value. The
|
||||
// value must be created before the type is changed: otherwise, a failed
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace
|
||||
// the binary formats as function pointers for "Binary formats with narrow number types";
|
||||
// named functions rather than lambdas, because clang 3.5 cannot convert a lambda
|
||||
// to a function pointer in the braced initializer of the format table
|
||||
using narrow_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int32_t, std::uint32_t, float>;
|
||||
using narrow_json = nlohmann::json::with_integers_t<std::int32_t, std::uint32_t>::with_float_t<float>;
|
||||
using bytes = std::vector<std::uint8_t>;
|
||||
|
||||
bytes encode_cbor(const json& j)
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
@@ -55,6 +59,53 @@ std::string dump_and_parse(const std::string& raw, eh error_handler)
|
||||
return json::parse(json(raw).dump(-1, ' ', false, error_handler)).get<std::string>();
|
||||
}
|
||||
|
||||
// an object key type that is not string_t, but converts implicitly to it;
|
||||
// data() is only used when JSON_DIAGNOSTICS is enabled
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
|
||||
class converting_key
|
||||
{
|
||||
public:
|
||||
converting_key(const char* s) : m_value(s) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
converting_key(std::string s) : m_value(std::move(s)) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
|
||||
// the conversion yields a temporary string_t
|
||||
operator std::string() const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// read by the exception messages when JSON_DIAGNOSTICS is enabled
|
||||
const char* data() const noexcept
|
||||
{
|
||||
return m_value.data();
|
||||
}
|
||||
|
||||
friend bool operator<(const converting_key& lhs, const converting_key& rhs)
|
||||
{
|
||||
return lhs.m_value < rhs.m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_POP
|
||||
|
||||
// ObjectType using converting_key; the Key template argument is ignored
|
||||
template<typename Key, typename Value, typename Compare, typename Allocator>
|
||||
class converting_key_object : public std::map<converting_key, Value, std::less<converting_key>, // NOLINT(modernize-use-transparent-functors)
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<const converting_key, Value>>>
|
||||
{
|
||||
using base_type = std::map<converting_key, Value, std::less<converting_key>, // NOLINT(modernize-use-transparent-functors)
|
||||
typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<const converting_key, Value>>>;
|
||||
|
||||
public:
|
||||
using base_type::base_type;
|
||||
using base_type::operator=;
|
||||
};
|
||||
|
||||
using converting_key_json = nlohmann::basic_json<converting_key_object>;
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
@@ -370,3 +421,109 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// The UBJSON and BJData writers bind the (possibly sanitized) key to a const
|
||||
// string_t&. If key_type is not string_t but converts to it, the converted
|
||||
// temporary must outlive that reference; this was a use-after-scope found by
|
||||
// AddressSanitizer. Keys exceed the small string optimization on purpose.
|
||||
TEST_CASE("UBJSON and BJData writers with an object_t whose key_type is not string_t")
|
||||
{
|
||||
const std::string long_prefix(70, 'k');
|
||||
|
||||
SECTION("well-formed keys, every error_handler")
|
||||
{
|
||||
const std::string key1 = long_prefix + "-first";
|
||||
const std::string key2 = long_prefix + "-second";
|
||||
|
||||
converting_key_json::object_t o;
|
||||
o.emplace(converting_key(key1), 1);
|
||||
o.emplace(converting_key(key2), "value");
|
||||
const converting_key_json v(std::move(o));
|
||||
|
||||
json expected;
|
||||
expected[key1] = 1;
|
||||
expected[key2] = "value";
|
||||
|
||||
const std::array<std::pair<bool, bool>, 3> combos = {{{false, false}, {true, false}, {true, true}}};
|
||||
for (const auto h : all_handlers())
|
||||
{
|
||||
CAPTURE(static_cast<int>(h))
|
||||
for (const auto& combo : combos)
|
||||
{
|
||||
const bool use_count = combo.first;
|
||||
const bool use_type = combo.second;
|
||||
CAPTURE(use_count)
|
||||
CAPTURE(use_type)
|
||||
|
||||
CHECK(json::from_ubjson(converting_key_json::to_ubjson(v, use_count, use_type, h)) == expected);
|
||||
CHECK(json::from_bjdata(converting_key_json::to_bjdata(v, use_count, use_type, json::bjdata_version_t::draft2, h)) == expected);
|
||||
CHECK(json::from_bjdata(converting_key_json::to_bjdata(v, use_count, use_type, json::bjdata_version_t::draft3, h)) == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("ill-formed keys")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name)
|
||||
const std::string key = long_prefix + c.bytes;
|
||||
|
||||
converting_key_json::object_t o;
|
||||
o.emplace(converting_key(key), 1);
|
||||
const converting_key_json v(std::move(o));
|
||||
|
||||
CHECK_THROWS_AS(converting_key_json::to_ubjson(v, false, false, eh::strict), converting_key_json::type_error&);
|
||||
CHECK_THROWS_AS(converting_key_json::to_bjdata(v, false, false, json::bjdata_version_t::draft2, eh::strict), converting_key_json::type_error&);
|
||||
|
||||
for (const auto h :
|
||||
{
|
||||
eh::replace, eh::ignore
|
||||
})
|
||||
{
|
||||
CAPTURE(static_cast<int>(h))
|
||||
const std::string expected = dump_and_parse(key, h);
|
||||
|
||||
CHECK(json::from_ubjson(converting_key_json::to_ubjson(v, false, false, h)).begin().key() == expected);
|
||||
CHECK(json::from_bjdata(converting_key_json::to_bjdata(v, false, false, json::bjdata_version_t::draft2, h)).begin().key() == expected);
|
||||
}
|
||||
|
||||
CHECK(json::from_ubjson(converting_key_json::to_ubjson(v, false, false, eh::keep)).begin().key() == key);
|
||||
CHECK(json::from_bjdata(converting_key_json::to_bjdata(v, false, false, json::bjdata_version_t::draft2, eh::keep)).begin().key() == key);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("nested deeper than the recursion limit")
|
||||
{
|
||||
// wrap the previous value, innermost first
|
||||
converting_key_json v = 42;
|
||||
json expected = 42;
|
||||
for (int i = 199; i >= 0; --i)
|
||||
{
|
||||
const std::string key = "level-" + std::to_string(i) + "-" + std::string(64, 'x');
|
||||
|
||||
converting_key_json::object_t o;
|
||||
o.emplace(converting_key(key), std::move(v));
|
||||
v = converting_key_json(std::move(o));
|
||||
|
||||
json e;
|
||||
e[key] = std::move(expected);
|
||||
expected = std::move(e);
|
||||
}
|
||||
|
||||
for (const auto h : all_handlers())
|
||||
{
|
||||
CAPTURE(static_cast<int>(h))
|
||||
for (const bool use_count :
|
||||
{
|
||||
false, true
|
||||
})
|
||||
{
|
||||
CAPTURE(use_count)
|
||||
|
||||
CHECK(json::from_ubjson(converting_key_json::to_ubjson(v, use_count, false, h)) == expected);
|
||||
CHECK(json::from_bjdata(converting_key_json::to_bjdata(v, use_count, false, json::bjdata_version_t::draft2, h)) == expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,9 +46,7 @@ class huge_binary_t : public std::vector<std::uint8_t>
|
||||
}
|
||||
};
|
||||
|
||||
using huge_binary_json = nlohmann::basic_json <
|
||||
std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t,
|
||||
double, std::allocator, nlohmann::adl_serializer, huge_binary_t, void >;
|
||||
using huge_binary_json = nlohmann::json::with_binary_t<huge_binary_t>;
|
||||
|
||||
// a string type that can be made to report a size beyond INT32_MAX without
|
||||
// allocating that much memory, so BSON length overflow can be tested for
|
||||
@@ -96,9 +94,7 @@ class huge_string_t : public std::string
|
||||
bool pretend_huge = false;
|
||||
};
|
||||
|
||||
using huge_string_json = nlohmann::basic_json <
|
||||
std::map, std::vector, huge_string_t, bool, std::int64_t, std::uint64_t,
|
||||
double, std::allocator, nlohmann::adl_serializer, std::vector<std::uint8_t>, void >;
|
||||
using huge_string_json = nlohmann::json::with_string_t<huge_string_t>;
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("BSON")
|
||||
|
||||
@@ -17,6 +17,7 @@ using nlohmann::json;
|
||||
#include <cstdint> // uint32_t, uint64_t
|
||||
#include <cstdlib> // strtod
|
||||
#include <cstring> // memcpy
|
||||
#include <limits> // numeric_limits
|
||||
#include <sstream> // stringstream
|
||||
#include <string> // string
|
||||
#include <utility> // pair
|
||||
@@ -891,8 +892,39 @@ TEST_CASE("Eisel-Lemire float conversion")
|
||||
|
||||
SECTION("128-bit products and leading zeros")
|
||||
{
|
||||
const auto check_product = [](std::uint64_t a, std::uint64_t b)
|
||||
{
|
||||
const auto product = nlohmann::detail::full_multiplication(a, b);
|
||||
CHECK(big_from(product.high, product.low) == big_mul(big_from(0, a), big_from(0, b)));
|
||||
};
|
||||
|
||||
const std::uint64_t max = (std::numeric_limits<std::uint64_t>::max)();
|
||||
const std::array<std::pair<std::uint64_t, std::uint64_t>, 13> edge_cases =
|
||||
{
|
||||
{
|
||||
{0, 0},
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{1, max},
|
||||
{0xFFFFFFFFu, 0x100000000u},
|
||||
{0x100000000u, 0x100000000u},
|
||||
{0x100000001u, 0x100000001u},
|
||||
{max, max},
|
||||
{max, 2},
|
||||
{0xFFFFFFFF00000000u, 0x100000001u},
|
||||
{0x100000001u, 0xFFFFFFFF00000000u},
|
||||
{max, 1},
|
||||
{2, max},
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto& test : edge_cases)
|
||||
{
|
||||
check_product(test.first, test.second);
|
||||
}
|
||||
|
||||
// whichever implementation the compiler gets (with or without a
|
||||
// 128-bit integer type or a builtin)
|
||||
// 128-bit integer type or a builtin / intrinsic)
|
||||
std::uint64_t state = 42;
|
||||
for (int i = 0; i < 10000; ++i)
|
||||
{
|
||||
@@ -901,8 +933,7 @@ TEST_CASE("Eisel-Lemire float conversion")
|
||||
state ^= state << 17u;
|
||||
const std::uint64_t a = state;
|
||||
const std::uint64_t b = (state * 0x9E3779B97F4A7C15u) >> (i % 64);
|
||||
const auto product = nlohmann::detail::full_multiplication(a, b);
|
||||
CHECK(big_from(product.high, product.low) == big_mul(big_from(0, a), big_from(0, b)));
|
||||
check_product(a, b);
|
||||
|
||||
const int k = i % 64;
|
||||
const std::uint64_t x = (std::uint64_t{1} << k) | (a & ((std::uint64_t{1} << k) - 1));
|
||||
|
||||
@@ -824,7 +824,7 @@ struct unordered_object_t : std::map<Key, Value, directed_less<Key>, Allocator>
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
using unordered_json = nlohmann::basic_json<unordered_object_t>;
|
||||
using unordered_json = nlohmann::json::with_object_t<unordered_object_t>;
|
||||
|
||||
// the entries "0" to "9", enumerated in ascending or in descending order
|
||||
unordered_json make_unordered_object(const bool descending)
|
||||
@@ -875,7 +875,7 @@ struct key_case_less
|
||||
|
||||
template<class Key, class Value, class /*Compare*/, class Allocator>
|
||||
using key_case_map = std::map<Key, Value, key_case_less, Allocator>;
|
||||
using key_case_json = nlohmann::basic_json<key_case_map>;
|
||||
using key_case_json = nlohmann::json::with_object_t<key_case_map>;
|
||||
|
||||
// the innermost value of a chain of single-element arrays
|
||||
template<typename Json>
|
||||
@@ -905,7 +905,7 @@ struct case_insensitive_less
|
||||
|
||||
template<class Key, class Value, class /*Compare*/, class Allocator>
|
||||
using case_insensitive_map = std::map<Key, Value, case_insensitive_less, Allocator>;
|
||||
using ci_json = nlohmann::basic_json<case_insensitive_map>;
|
||||
using ci_json = nlohmann::json::with_object_t<case_insensitive_map>;
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("equality of objects whose entries have no fixed order")
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace
|
||||
|
||||
// std::deque has no capacity() member function, which the library only needs
|
||||
// to detect a reallocation for JSON_DIAGNOSTICS
|
||||
using deque_json = nlohmann::basic_json<std::map, std::deque>;
|
||||
using deque_json = nlohmann::json::with_array_t<std::deque>;
|
||||
|
||||
// a std::vector whose at() is hidden: the library performs its own bounds
|
||||
// check and must not fall back to the container's checked accessor
|
||||
@@ -39,7 +39,7 @@ class vector_without_at : public std::vector<T, Allocator>
|
||||
void at() = delete;
|
||||
};
|
||||
|
||||
using no_at_json = nlohmann::basic_json<std::map, vector_without_at>;
|
||||
using no_at_json = nlohmann::json::with_array_t<vector_without_at>;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -400,20 +400,7 @@ class base_class_with_hidden_members
|
||||
std::size_t m_size = 42;
|
||||
};
|
||||
|
||||
using json_with_hidden_base_members =
|
||||
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_with_hidden_base_members = nlohmann::json::with_base_class_t<base_class_with_hidden_members>;
|
||||
|
||||
TEST_CASE("JSON Node as_base_class")
|
||||
{
|
||||
@@ -459,19 +446,7 @@ struct const_member_base
|
||||
const int id = 7; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
};
|
||||
|
||||
using json_with_const_base = 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>,
|
||||
const_member_base
|
||||
>;
|
||||
using json_with_const_base = nlohmann::json::with_base_class_t<const_member_base>;
|
||||
|
||||
// build an array nested @a depth levels deep, with the innermost value 1;
|
||||
// every level is constructed (never assigned), since const_member_base does
|
||||
|
||||
@@ -26,15 +26,11 @@ namespace
|
||||
|
||||
// a BinaryType whose value type is signed: the elements must still be
|
||||
// processed as the numbers 0..255
|
||||
using char_binary_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<char>, void >;
|
||||
using char_binary_json = nlohmann::json::with_binary_t<std::vector<char>>;
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
// a BinaryType whose value type is not an integer type at all
|
||||
using byte_binary_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::byte>, void >;
|
||||
using byte_binary_json = nlohmann::json::with_binary_t<std::vector<std::byte>>;
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "custom_object_key_type.hpp"
|
||||
|
||||
// These tests instantiate a second basic_json specialization. They live in
|
||||
// their own file rather than in unit-cbor.cpp and unit-msgpack.cpp to keep
|
||||
// those objects below 65535 sections: the MinGW linker stores the section a
|
||||
// COMDAT section is associated with in 16 bits, so it misplaces the jump
|
||||
// tables of larger objects (see the clang job in windows.yml).
|
||||
|
||||
TEST_CASE("CBOR supports custom object key types")
|
||||
{
|
||||
using custom_json = custom_object_key_test::json;
|
||||
using custom_key = custom_object_key_test::key;
|
||||
|
||||
custom_json::object_t object;
|
||||
object.emplace(custom_key{"short"}, 1);
|
||||
object.emplace(
|
||||
custom_key{"a key longer than twenty-three characters"},
|
||||
2);
|
||||
|
||||
const custom_json value(std::move(object));
|
||||
const auto encoded = custom_json::to_cbor(value);
|
||||
|
||||
CHECK(nlohmann::json::from_cbor(encoded) == nlohmann::json
|
||||
{
|
||||
{"short", 1},
|
||||
{"a key longer than twenty-three characters", 2}
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("CBOR supports custom object key types nested deeper than the recursion depth limit")
|
||||
{
|
||||
// below detail::recursion_depth_limit(), keys are written by
|
||||
// write_cbor_iterative instead of write_cbor
|
||||
using custom_json = custom_object_key_test::json;
|
||||
using custom_key = custom_object_key_test::key;
|
||||
|
||||
const std::size_t depth = nlohmann::detail::recursion_depth_limit() + 10;
|
||||
|
||||
custom_json value = 1;
|
||||
nlohmann::json expected = 1;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
// alternate short keys with ones long enough to need a length byte
|
||||
const std::string name = (i % 2 == 0) ? "k" + std::to_string(i)
|
||||
: "a key longer than thirty-one characters " + std::to_string(i);
|
||||
|
||||
custom_json::object_t object;
|
||||
object.emplace(custom_key{name}, std::move(value));
|
||||
value = custom_json(std::move(object));
|
||||
|
||||
nlohmann::json::object_t expected_object;
|
||||
expected_object.emplace(name, std::move(expected));
|
||||
expected = nlohmann::json(std::move(expected_object));
|
||||
}
|
||||
|
||||
const auto encoded = custom_json::to_cbor(value);
|
||||
CHECK(encoded == nlohmann::json::to_cbor(expected));
|
||||
CHECK(nlohmann::json::from_cbor(encoded) == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("MessagePack supports custom object key types")
|
||||
{
|
||||
using custom_json = custom_object_key_test::json;
|
||||
using custom_key = custom_object_key_test::key;
|
||||
|
||||
custom_json::object_t object;
|
||||
object.emplace(custom_key{"short"}, 1);
|
||||
object.emplace(
|
||||
custom_key{"a key longer than thirty-one characters"},
|
||||
2);
|
||||
|
||||
const custom_json value(std::move(object));
|
||||
const auto encoded = custom_json::to_msgpack(value);
|
||||
|
||||
CHECK(nlohmann::json::from_msgpack(encoded) == nlohmann::json
|
||||
{
|
||||
{"short", 1},
|
||||
{"a key longer than thirty-one characters", 2}
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("MessagePack supports custom object key types nested deeper than the recursion depth limit")
|
||||
{
|
||||
// below detail::recursion_depth_limit(), keys are written by
|
||||
// write_msgpack_iterative instead of write_msgpack
|
||||
using custom_json = custom_object_key_test::json;
|
||||
using custom_key = custom_object_key_test::key;
|
||||
|
||||
const std::size_t depth = nlohmann::detail::recursion_depth_limit() + 10;
|
||||
|
||||
custom_json value = 1;
|
||||
nlohmann::json expected = 1;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
// alternate short keys with ones long enough to need a length byte
|
||||
const std::string name = (i % 2 == 0) ? "k" + std::to_string(i)
|
||||
: "a key longer than thirty-one characters " + std::to_string(i);
|
||||
|
||||
custom_json::object_t object;
|
||||
object.emplace(custom_key{name}, std::move(value));
|
||||
value = custom_json(std::move(object));
|
||||
|
||||
nlohmann::json::object_t expected_object;
|
||||
expected_object.emplace(name, std::move(expected));
|
||||
expected = nlohmann::json(std::move(expected_object));
|
||||
}
|
||||
|
||||
const auto encoded = custom_json::to_msgpack(value);
|
||||
CHECK(encoded == nlohmann::json::to_msgpack(expected));
|
||||
CHECK(nlohmann::json::from_msgpack(encoded) == expected);
|
||||
}
|
||||
@@ -179,7 +179,7 @@ class no_key_compare_map
|
||||
}
|
||||
};
|
||||
|
||||
using no_key_compare_json = nlohmann::basic_json<no_key_compare_map>;
|
||||
using no_key_compare_json = nlohmann::json::with_object_t<no_key_compare_map>;
|
||||
|
||||
// An ObjectType whose erase(iterator) returns void rather than the following
|
||||
// iterator, as for instance Abseil's hash maps do
|
||||
@@ -196,7 +196,7 @@ struct void_erase_map : std::map<Key, T, Compare, Allocator>
|
||||
}
|
||||
};
|
||||
|
||||
using void_erase_json = nlohmann::basic_json<void_erase_map>;
|
||||
using void_erase_json = nlohmann::json::with_object_t<void_erase_map>;
|
||||
|
||||
// wraps an iterator, but only offers the LegacyForwardIterator operations,
|
||||
// like the iterators of std::unordered_map and other hash maps
|
||||
@@ -388,7 +388,7 @@ class forward_only_map
|
||||
}
|
||||
};
|
||||
|
||||
using forward_only_json = nlohmann::basic_json<forward_only_map>;
|
||||
using forward_only_json = nlohmann::json::with_object_t<forward_only_map>;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -157,13 +157,13 @@ TEST_CASE("hash<nlohmann::json>")
|
||||
// the ends of the integer ranges, which equal floats exactly
|
||||
const auto int_min = (std::numeric_limits<json::number_integer_t>::min)();
|
||||
const auto int_max = (std::numeric_limits<json::number_integer_t>::max)();
|
||||
const auto two_63 = json::number_unsigned_t(1) << 63U;
|
||||
const auto two_63 = static_cast<json::number_unsigned_t>(1) << 63U;
|
||||
CHECK(json(int_min) == json(-9223372036854775808.0));
|
||||
CHECK(std::hash<json> {}(json(int_min)) == std::hash<json> {}(json(-9223372036854775808.0)));
|
||||
CHECK(json(two_63) == json(9223372036854775808.0));
|
||||
CHECK(std::hash<json> {}(json(two_63)) == std::hash<json> {}(json(9223372036854775808.0)));
|
||||
CHECK(json(json::number_unsigned_t(int_max)) == json(int_max));
|
||||
CHECK(std::hash<json> {}(json(json::number_unsigned_t(int_max))) == std::hash<json> {}(json(int_max)));
|
||||
CHECK(json(static_cast<json::number_unsigned_t>(int_max)) == json(int_max));
|
||||
CHECK(std::hash<json> {}(json(static_cast<json::number_unsigned_t>(int_max))) == std::hash<json> {}(json(int_max)));
|
||||
}
|
||||
|
||||
TEST_CASE("hash<nlohmann::ordered_json>")
|
||||
|
||||
@@ -939,3 +939,114 @@ TEST_CASE("unescaping keeps a '~' that does not start an escape sequence")
|
||||
nlohmann::detail::unescape(s);
|
||||
CHECK(s == "~/~");
|
||||
}
|
||||
|
||||
TEST_CASE("flatten of structured values")
|
||||
{
|
||||
SECTION("values nested too deeply for the call stack (#5393)")
|
||||
{
|
||||
// flatten() used to recurse once per nesting level
|
||||
const std::size_t depth = 100000;
|
||||
for (const bool objects :
|
||||
{
|
||||
false, true
|
||||
})
|
||||
{
|
||||
CAPTURE(objects)
|
||||
std::string text;
|
||||
std::string path;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
text += objects ? "{\"a\":" : "[";
|
||||
path += objects ? "/a" : "/0";
|
||||
}
|
||||
text += "0";
|
||||
text += std::string(depth, objects ? '}' : ']');
|
||||
const auto value = json::parse(text);
|
||||
|
||||
const auto flat = value.flatten();
|
||||
REQUIRE(flat.size() == 1);
|
||||
REQUIRE(flat.begin().key().size() == path.size());
|
||||
CHECK(flat.begin().key() == path);
|
||||
CHECK(flat.begin().value() == 0);
|
||||
|
||||
// unflatten() is linear in the depth, so the value roundtrips
|
||||
CHECK(flat.unflatten() == value);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("unflatten of a deeply nested pointer")
|
||||
{
|
||||
const std::size_t depth = 100000;
|
||||
for (const bool objects :
|
||||
{
|
||||
false, true
|
||||
})
|
||||
{
|
||||
CAPTURE(objects)
|
||||
std::string path;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
path += objects ? "/a" : "/0";
|
||||
}
|
||||
|
||||
json flat = json::object();
|
||||
flat[path] = 1;
|
||||
const json value = flat.unflatten();
|
||||
|
||||
// walk down iteratively
|
||||
std::size_t levels = 0;
|
||||
const json* current = &value;
|
||||
while (objects ? current->is_object() : current->is_array())
|
||||
{
|
||||
REQUIRE(current->size() == 1);
|
||||
current = objects ? ¤t->at("a") : ¤t->at(0);
|
||||
++levels;
|
||||
}
|
||||
CHECK(levels == depth);
|
||||
CHECK(*current == 1);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("unflatten does not depend on the iteration order")
|
||||
{
|
||||
// the "0" key comes after its sibling in iteration order
|
||||
const nlohmann::ordered_json flat_array = nlohmann::ordered_json::parse(R"({"/a/1": 2, "/a/0": 1})");
|
||||
CHECK(flat_array.unflatten() == nlohmann::ordered_json::parse(R"({"a": [1, 2]})"));
|
||||
|
||||
const nlohmann::ordered_json flat_object = nlohmann::ordered_json::parse(R"({"/b/1": 2})");
|
||||
CHECK(flat_object.unflatten() == nlohmann::ordered_json::parse(R"({"b": {"1": 2}})"));
|
||||
}
|
||||
|
||||
SECTION("objects and arrays interleaved")
|
||||
{
|
||||
const json value =
|
||||
{
|
||||
{"a", {1, {{"b", json::array()}, {"c", json::object()}}, json::array({{{"x~/", {true, nullptr}}}})}},
|
||||
{"a/b", {{"~", 1}}},
|
||||
{"z", "s"}
|
||||
};
|
||||
|
||||
const json expected =
|
||||
{
|
||||
{"/a/0", 1},
|
||||
{"/a/1/b", nullptr},
|
||||
{"/a/1/c", nullptr},
|
||||
{"/a/2/0/x~0~1/0", true},
|
||||
{"/a/2/0/x~0~1/1", nullptr},
|
||||
{"/a~1b/~0", 1},
|
||||
{"/z", "s"}
|
||||
};
|
||||
|
||||
CHECK(value.flatten() == expected);
|
||||
}
|
||||
|
||||
SECTION("order of the entries of an ordered_json")
|
||||
{
|
||||
const auto value = nlohmann::ordered_json::parse(
|
||||
R"({"z":"s","a/b":{"~":1,"k":[]},"a":[1,{"c":{},"b":[]},[{"x~/":[true,null],"w":2}]]})");
|
||||
|
||||
const auto flat = value.flatten();
|
||||
CHECK(flat.dump() ==
|
||||
R"({"/z":"s","/a~1b/~0":1,"/a~1b/k":null,"/a/0":1,"/a/1/c":null,"/a/1/b":null,"/a/2/0/x~0~1/0":true,"/a/2/0/x~0~1/1":null,"/a/2/0/w":2})");
|
||||
}
|
||||
}
|
||||
@@ -426,7 +426,7 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
{
|
||||
for (std::size_t depth = 120; depth <= 140; ++depth)
|
||||
{
|
||||
CAPTURE(depth);
|
||||
CAPTURE(depth)
|
||||
|
||||
const json array = nested_array(depth, json(7));
|
||||
CHECK(json::from_cbor(json::to_cbor(array)) == array);
|
||||
@@ -464,7 +464,7 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
nlohmann::detail::recursion_depth_limit() + 1, nlohmann::detail::recursion_depth_limit() + 2
|
||||
})
|
||||
{
|
||||
CAPTURE(depth);
|
||||
CAPTURE(depth)
|
||||
const json array = nested_array(depth, json(0));
|
||||
|
||||
std::vector<std::uint8_t> expected_cbor(depth, 0x81);
|
||||
@@ -505,10 +505,22 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
const json discarded_leaf(json::value_t::discarded);
|
||||
const json deep_discarded = nested_array(depth, discarded_leaf);
|
||||
|
||||
CHECK_THROWS_WITH_AS(json::to_cbor(deep_discarded), "[json.exception.type_error.321] cannot serialize discarded value to CBOR", json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_msgpack(deep_discarded), "[json.exception.type_error.321] cannot serialize discarded value to MessagePack", json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_ubjson(deep_discarded), "[json.exception.type_error.321] cannot serialize discarded value to UBJSON", json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_bjdata(deep_discarded), "[json.exception.type_error.321] cannot serialize discarded value to BJData", json::type_error);
|
||||
// with diagnostics, the message names the path to the discarded leaf
|
||||
#if JSON_DIAGNOSTICS
|
||||
std::string path;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
path += "/0";
|
||||
}
|
||||
const std::string prefix = "[json.exception.type_error.321] (" + path + ") ";
|
||||
#else
|
||||
const std::string prefix = "[json.exception.type_error.321] ";
|
||||
#endif
|
||||
|
||||
CHECK_THROWS_WITH_AS(json::to_cbor(deep_discarded), (prefix + "cannot serialize discarded value to CBOR").c_str(), json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_msgpack(deep_discarded), (prefix + "cannot serialize discarded value to MessagePack").c_str(), json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_ubjson(deep_discarded), (prefix + "cannot serialize discarded value to UBJSON").c_str(), json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json::to_bjdata(deep_discarded), (prefix + "cannot serialize discarded value to BJData").c_str(), json::type_error);
|
||||
}
|
||||
|
||||
SECTION("does not overflow the C++ stack")
|
||||
|
||||
@@ -172,7 +172,7 @@ TEST_CASE("locale-dependent test (LC_NUMERIC=de_DE)")
|
||||
// a floating-point type that is not a float or a double is written
|
||||
// with snprintf, whose locale-specific decimal point and thousands
|
||||
// separator are undone afterwards
|
||||
using long_double_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, long double>;
|
||||
using long_double_json = nlohmann::json::with_float_t<long double>;
|
||||
CHECK(long_double_json(12345.5L).dump() == "12345.5");
|
||||
CHECK(long_double_json(1.0L).dump() == "1.0");
|
||||
CHECK(long_double_json(-0.25L).dump() == "-0.25");
|
||||
@@ -272,7 +272,7 @@ TEST_CASE("locale changes between lexer construction and number conversion (#519
|
||||
}
|
||||
text += "]";
|
||||
|
||||
using long_double_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, long double>;
|
||||
using long_double_json = nlohmann::json::with_float_t<long double>;
|
||||
|
||||
// reference values, parsed without a locale switch
|
||||
REQUIRE(std::setlocale(LC_NUMERIC, "C") != nullptr);
|
||||
@@ -432,7 +432,7 @@ TEST_CASE("locale changes during a single dump() (#5709 item 3)")
|
||||
// long double on 64-bit Arm, where it is IEEE-754 double) takes the
|
||||
// locale-independent to_chars() path instead, and this test is a no-op
|
||||
// there.
|
||||
using long_double_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, long double>;
|
||||
using long_double_json = nlohmann::json::with_float_t<long double>;
|
||||
using ld_limits = std::numeric_limits<long_double_json::number_float_t>;
|
||||
const bool is_ieee_single_or_double =
|
||||
(ld_limits::is_iec559 && ld_limits::digits == 24 && ld_limits::max_exponent == 128) ||
|
||||
|
||||
@@ -2201,10 +2201,7 @@ struct huge_array : std::vector<T, A>
|
||||
}
|
||||
};
|
||||
|
||||
using huge_array_json = nlohmann::basic_json <
|
||||
std::map, huge_array, std::string, bool, std::int64_t, std::uint64_t,
|
||||
double, std::allocator, nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>, void >;
|
||||
using huge_array_json = nlohmann::json::with_array_t<huge_array>;
|
||||
|
||||
TEST_CASE("MessagePack Size above uint32 for array")
|
||||
{
|
||||
@@ -2249,18 +2246,7 @@ template<typename K, typename V,
|
||||
}
|
||||
};
|
||||
|
||||
using huge_object_json = nlohmann::basic_json <
|
||||
huge_map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
void >;
|
||||
using huge_object_json = nlohmann::json::with_object_t<huge_map>;
|
||||
|
||||
TEST_CASE("MessagePack Size above uint32 for object")
|
||||
{
|
||||
@@ -2295,18 +2281,7 @@ struct huge_string : std::string
|
||||
}
|
||||
};
|
||||
|
||||
using huge_string_json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
huge_string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
void >;
|
||||
using huge_string_json = nlohmann::json::with_string_t<huge_string>;
|
||||
|
||||
TEST_CASE("MessagePack Size above uint32 for string")
|
||||
{
|
||||
@@ -2329,18 +2304,7 @@ struct huge_binary : std::vector<std::uint8_t>
|
||||
}
|
||||
};
|
||||
|
||||
using huge_binary_json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
huge_binary,
|
||||
void >;
|
||||
using huge_binary_json = nlohmann::json::with_binary_t<huge_binary>;
|
||||
|
||||
TEST_CASE("MessagePack Size above uint32 for binary")
|
||||
{
|
||||
@@ -2390,14 +2354,10 @@ class beyond_uint32_string_t : public std::string
|
||||
}
|
||||
};
|
||||
|
||||
using beyond_uint32_string_json = nlohmann::basic_json <
|
||||
std::map, std::vector, beyond_uint32_string_t, bool, std::int64_t, std::uint64_t,
|
||||
double, std::allocator, nlohmann::adl_serializer, std::vector<std::uint8_t>, void >;
|
||||
using beyond_uint32_string_json = nlohmann::json::with_string_t<beyond_uint32_string_t>;
|
||||
#endif
|
||||
|
||||
using beyond_uint32_binary_json = nlohmann::basic_json <
|
||||
std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t,
|
||||
double, std::allocator, nlohmann::adl_serializer, beyond_uint32_binary_t, void >;
|
||||
using beyond_uint32_binary_json = nlohmann::json::with_binary_t<beyond_uint32_binary_t>;
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("MessagePack lengths beyond UINT32_MAX cannot be serialized")
|
||||
@@ -2432,8 +2392,8 @@ TEST_CASE("MessagePack numbers use the active union member (see #5644)")
|
||||
// used to read the union member that was not the active one, writing
|
||||
// wrong bytes for some values; std::int64_t/std::uint64_t (the default
|
||||
// types, where both members have the same width) were not affected
|
||||
using int32_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int32_t, std::uint64_t, double>;
|
||||
using int16_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int16_t, std::uint64_t, double>;
|
||||
using int32_json = nlohmann::json::with_integers_t<std::int32_t, std::uint64_t>;
|
||||
using int16_json = nlohmann::json::with_integers_t<std::int16_t, std::uint64_t>;
|
||||
|
||||
SECTION("number_integer_t = std::int32_t")
|
||||
{
|
||||
|
||||
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user