Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7a7534872 | ||
|
|
eaee875178 | ||
|
|
3724295333 |
No files matched your search
@@ -28,7 +28,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -67,10 +67,10 @@ jobs:
|
||||
- name: Install astyle
|
||||
run: |
|
||||
python3 -mvenv venv
|
||||
venv/bin/pip3 install --require-hashes -r $MAIN_DIR/tools/astyle/requirements.txt
|
||||
venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
|
||||
|
||||
- name: Install generate_natvis dependencies
|
||||
run: pip3 install --require-hashes -r $NATVIS_TOOL_DIR/requirements.txt
|
||||
run: pip3 install -r $NATVIS_TOOL_DIR/requirements.txt
|
||||
|
||||
- name: Regenerate the tools/macro_builder tables in macro_scope.hpp
|
||||
run: |
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -38,13 +38,14 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
with:
|
||||
languages: c-cpp
|
||||
# Analyze the sources without compiling them. Autobuild compiled the
|
||||
# whole test suite and the resulting database was so large that the
|
||||
# runner often lost communication with the server while importing it.
|
||||
build-mode: none
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -48,6 +48,6 @@ jobs:
|
||||
output: 'flawfinder_results.sarif'
|
||||
|
||||
- name: Upload analysis results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
with:
|
||||
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -80,6 +80,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -52,12 +52,8 @@ jobs:
|
||||
# the old action fell back to, running community rules with no token.
|
||||
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a
|
||||
# token is ever added.
|
||||
# The version is pinned, but not by hash: Semgrep pins its own dependencies
|
||||
# to exact or compatible-release versions, so a hash-pinned lock file broke
|
||||
# on almost every Dependabot bump of a transitive dependency. Dependabot
|
||||
# only bumps the semgrep line; pip resolves the rest.
|
||||
- name: Install Semgrep
|
||||
run: python3 -m pip install --user -r cmake/requirements/requirements-semgrep.txt
|
||||
run: python3 -m pip install --user semgrep==1.168.0
|
||||
|
||||
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
|
||||
# is a safety net so the SARIF upload still runs if the scan itself errors.
|
||||
@@ -69,7 +65,7 @@ jobs:
|
||||
|
||||
# Upload SARIF file generated in previous step
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
||||
with:
|
||||
sarif_file: semgrep.sarif
|
||||
if: always()
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -38,11 +38,11 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Check that Meson and pkg-config offer the CMake options
|
||||
run: make check_build_options
|
||||
- name: Install Meson
|
||||
run: pip install --require-hashes -r cmake/requirements/requirements-meson.txt
|
||||
run: pip install meson
|
||||
- name: Install with Meson
|
||||
run: |
|
||||
meson setup build-meson --prefix=${{ github.workspace }}/install
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
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@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -142,7 +142,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
container: ubuntu:24.04
|
||||
strategy:
|
||||
matrix:
|
||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local, ci_test_recursion_depth_limit_0]
|
||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local]
|
||||
steps:
|
||||
- name: Install build-essential
|
||||
run: apt-get update ; apt-get install -y build-essential unzip wget git
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -244,7 +244,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -262,7 +262,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -279,7 +279,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- 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' }}
|
||||
@@ -299,7 +299,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -319,7 +319,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build with libc++
|
||||
@@ -346,7 +346,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -366,7 +366,7 @@ jobs:
|
||||
# import-std support. Its opt-in token is CMake-version-specific, so pin
|
||||
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
|
||||
- name: Get pinned CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
with:
|
||||
cmakeVersion: 4.3.4
|
||||
# Clang: the std library module is provided by libc++ (the image's libstdc++
|
||||
@@ -392,7 +392,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -409,7 +409,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -423,7 +423,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DJSON_CI=On
|
||||
- name: Build
|
||||
@@ -433,7 +433,7 @@ jobs:
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -443,7 +443,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Run CMake
|
||||
run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -GNinja
|
||||
- name: Build
|
||||
@@ -456,7 +456,7 @@ jobs:
|
||||
target: [ci_test_examples, ci_test_build_documentation, ci_test_documentation_mermaid]
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@46b06cea07f9e64621fdf066ba77ac6915163d43 # v2.22.3
|
||||
uses: step-security/harden-runner@dc2769abcc0fcfbadfc1df54081c1608579ef6b2 # v2.22.2
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
@@ -484,7 +484,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Check that the job runs natively on arm64
|
||||
run: uname -m && test "$(uname -m)" = aarch64
|
||||
- name: Run CMake
|
||||
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Get latest CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
- name: Set extra CXX_FLAGS for latest std_version
|
||||
# /wd5285 silences C5285 emitted by the bundled third-party doctest.h, which
|
||||
# specializes std::tuple (newly diagnosed by the VS2026 v145 toolset)
|
||||
@@ -216,7 +216,7 @@ jobs:
|
||||
# import-std support. Its opt-in token is CMake-version-specific, so pin
|
||||
# CMake to the version whose token is set in tests/module_cpp20/CMakeLists.txt.
|
||||
- name: Get pinned CMake and ninja
|
||||
uses: lukka/get-cmake@f86dd60acae0d132056913e248bdabf0e0580b7a # v4.4.5
|
||||
uses: lukka/get-cmake@a89e43e22a96abafcd7a62db652a65ecd33052c9 # v4.4.4
|
||||
with:
|
||||
cmakeVersion: 4.3.4
|
||||
# CMAKE_CXX_FLAGS replaces CMake's MSVC defaults (which include /EHsc), and
|
||||
|
||||
@@ -30,7 +30,6 @@ cc_library(
|
||||
"include/nlohmann/detail/exceptions.hpp",
|
||||
"include/nlohmann/detail/hash.hpp",
|
||||
"include/nlohmann/detail/input/binary_reader.hpp",
|
||||
"include/nlohmann/detail/input/contiguous_parser.hpp",
|
||||
"include/nlohmann/detail/input/input_adapters.hpp",
|
||||
"include/nlohmann/detail/input/json_sax.hpp",
|
||||
"include/nlohmann/detail/input/lexer.hpp",
|
||||
|
||||
+3272
File diff suppressed because it is too large.
Load diff
@@ -1,4 +1,4 @@
|
||||
.PHONY: all amalgamate check-amalgamation check_build_options pretty install_astyle clean release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check run_benchmarks pvs_studio serve_header reuse spdx
|
||||
.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
|
||||
@@ -40,6 +40,7 @@ MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp
|
||||
all:
|
||||
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals,_view}.hpp from the include/nlohmann sources"
|
||||
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
||||
@echo "ChangeLog.md - generate ChangeLog file"
|
||||
@echo "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"
|
||||
@@ -174,6 +175,22 @@ check-amalgamation:
|
||||
BUILD.bazel:
|
||||
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
||||
|
||||
##########################################################################
|
||||
# ChangeLog
|
||||
##########################################################################
|
||||
|
||||
# Create a ChangeLog based on the git log using the GitHub Changelog Generator
|
||||
# (<https://github.com/github-changelog-generator/github-changelog-generator>).
|
||||
|
||||
# variable to control the diffs between the last released version and the current repository state
|
||||
NEXT_VERSION ?= "unreleased"
|
||||
|
||||
ChangeLog.md:
|
||||
github_changelog_generator -o ChangeLog.md --user nlohmann --project json --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s --future-release $(NEXT_VERSION)
|
||||
$(SED) -i 's|https://github.com/nlohmann/json/releases/tag/HEAD|https://github.com/nlohmann/json/tree/HEAD|' ChangeLog.md
|
||||
$(SED) -i '2i All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).' ChangeLog.md
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Release files
|
||||
##########################################################################
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
<a href="https://github.com/nlohmann/json/releases">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="docs/mkdocs/docs/images/json-dark.svg">
|
||||
<img src="docs/mkdocs/docs/images/json-light.svg" alt="JSON for Modern C++: animated feature slideshow">
|
||||
</picture>
|
||||
</a>
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
|
||||
[](https://ci.appveyor.com/project/nlohmann/json)
|
||||
[](https://github.com/nlohmann/json/actions?query=workflow%3AUbuntu)
|
||||
@@ -44,7 +39,6 @@
|
||||
- [Conversions to/from arbitrary types](#arbitrary-types-conversions)
|
||||
- [Specializing enum conversion](#specializing-enum-conversion)
|
||||
- [Binary formats (BSON, CBOR, MessagePack, UBJSON, BJData, and BON8)](#binary-formats-bson-cbor-messagepack-ubjson-bjdata-and-bon8)
|
||||
- [Zero-copy views](#zero-copy-views)
|
||||
- [Customers](#customers)
|
||||
- [Ecosystem](#ecosystem)
|
||||
- [Supported compilers](#supported-compilers)
|
||||
@@ -74,7 +68,7 @@ Other aspects were not so important to us:
|
||||
|
||||
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
|
||||
|
||||
- **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. The [performance](https://json.nlohmann.me/features/performance/) page shows how to get the most out of the library.
|
||||
- **Speed**. There are certainly [faster JSON libraries](https://github.com/miloyip/nativejson-benchmark#parsing-time) out there. However, if your goal is to speed up your development by adding JSON support with a single header, then this library is the way to go. If you know how to use a `std::vector` or `std::map`, you are already set.
|
||||
|
||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#please-dont) for more information.
|
||||
|
||||
@@ -1058,7 +1052,7 @@ struct less_than_32_serializer {
|
||||
Be **very** careful when reimplementing your serializer, you can stack overflow if you don't pay attention:
|
||||
|
||||
```cpp
|
||||
template <typename T, typename = void>
|
||||
template <typename T, void>
|
||||
struct bad_serializer
|
||||
{
|
||||
template <typename BasicJsonType>
|
||||
@@ -1069,10 +1063,10 @@ struct bad_serializer
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
static void from_json(const BasicJsonType& j, T& value) {
|
||||
static void to_json(const BasicJsonType& j, T& value) {
|
||||
// this calls BasicJsonType::json_serializer<T>::from_json(j, value)
|
||||
// if BasicJsonType::json_serializer == bad_serializer ... oops!
|
||||
value = j.template get<T>(); // oops!
|
||||
value = j.get<T>(); // oops!
|
||||
}
|
||||
};
|
||||
```
|
||||
@@ -1775,7 +1769,7 @@ I deeply appreciate the help of the following people.
|
||||
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 and avoided temporary `basic_json` values for CBOR and MessagePack object keys.
|
||||
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.
|
||||
@@ -1853,7 +1847,7 @@ I deeply appreciate the help of the following people.
|
||||
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) and [AJ369ninja](https://github.com/AJ369ninja) fixed the overflow handling of high-precision numbers in UBJSON.
|
||||
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>>`.
|
||||
@@ -1867,26 +1861,6 @@ I deeply appreciate the help of the following people.
|
||||
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.
|
||||
425. [Alexander Lanin](https://github.com/AlexanderLanin) improved the error message of `get_to()` for `const` arguments.
|
||||
426. [satelliteprogrammer](https://github.com/satelliteprogrammer) added `merge_diff()` to create JSON Merge Patches (RFC 7396).
|
||||
427. [Jeremy Nimmer](https://github.com/jwnimmer-tri) removed `alwayslink` from the Bazel build.
|
||||
428. [Dadi Reddy Sai Praneeth Reddy](https://github.com/dsp0redy) made `to_msgpack()` throw when a size exceeds the MessagePack limit.
|
||||
429. [ayush-singh-0601](https://github.com/ayush-singh-0601) reduced the runtime of the test suite.
|
||||
430. [Kartikey Negi](https://github.com/ReturnKartikey) fixed the CBOR tag handling of tagged values that are not byte strings.
|
||||
431. [Michiel van Slobbe](https://github.com/mvanslobbe) sped up the parser by checking for the expected separator first.
|
||||
432. [Mohd Quamar Tyagi](https://github.com/Tyagiquamar) allowed SAX parsing of tagged CBOR.
|
||||
433. [fhgffy](https://github.com/fhgffy) rejected NUL bytes in UBJSON and BJData high-precision numbers and fixed a `-Wswitch-enum` warning.
|
||||
434. [Suyog Verma](https://github.com/commit-msuyog) used MSVC intrinsics for the 128-bit multiplication in the floating-point serialization.
|
||||
435. [Bas van Dijk](https://github.com/basdedas) fixed a TU-local exposure of `UTF8_ACCEPT` and `UTF8_REJECT` in C++20 modules.
|
||||
436. [Christoph Grüninger](https://github.com/gruenich) fixed a leak and a crash when an allocation throws during parsing.
|
||||
437. [Amelia Barnaby](https://github.com/ameliabarnabyhub) made serializing discarded values to binary formats throw instead of writing corrupt output.
|
||||
438. [Vesko Karaganev](https://github.com/veselink1) made the destructor use the provided allocator.
|
||||
439. [Michael Sam](https://github.com/michaelsam94) kept allocation failures from escaping the `noexcept` destructor.
|
||||
440. [Mihnea Magheru](https://github.com/sakuntalle) added a natvis visualizer for `detail::json_default_base`.
|
||||
441. [Joseph Demarest](https://github.com/JosephDemarest) rejected nested indefinite-length CBOR strings.
|
||||
442. [Afonso Januário](https://github.com/afonsojanu) made `std::hash<basic_json>` consistent with `operator==` for numbers.
|
||||
443. [Kartik Gupta](https://github.com/KartikeyG-world) limited the natvis namespace variants to two ABI tags.
|
||||
444. [manop55555](https://github.com/manop55555) reported a buffer over-read in `dump()` with large indentation values.
|
||||
|
||||
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
|
||||
|
||||
@@ -1909,6 +1883,7 @@ The library itself consists of a single header file licensed under the MIT licen
|
||||
- [**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
|
||||
@@ -1975,7 +1950,7 @@ For more information, see [JSON With Commas and Comments (JWCC)](https://nigelta
|
||||
|
||||
By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs".
|
||||
|
||||
If you do want to preserve the insertion order, you can try the type [`nlohmann::ordered_json`](https://json.nlohmann.me/api/ordered_json/). Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
||||
If you do want to preserve the insertion order, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
||||
|
||||
See the [**documentation on object order**](https://json.nlohmann.me/features/object_order/) for more information.
|
||||
|
||||
|
||||
@@ -342,27 +342,6 @@ add_custom_target(ci_test_no_thread_local
|
||||
COMMENT "Compile and test without thread-local storage"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Change the number of levels the walks over a value recurse into.
|
||||
###############################################################################
|
||||
|
||||
# JSON_RECURSION_DEPTH_LIMIT is 128 by default, which is what the whole test
|
||||
# suite otherwise runs with. 0 sends every walk to its explicit stack at once,
|
||||
# so this target runs the whole suite through the walks that the default only
|
||||
# uses for values nested more deeply than 128 levels: results must not depend on
|
||||
# the limit. The largest limit, 254, is covered by a build of
|
||||
# tests/src/unit-recursion_depth_limit.cpp (see tests/CMakeLists.txt).
|
||||
add_custom_target(ci_test_recursion_depth_limit_0
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-DCMAKE_CXX_FLAGS=-DJSON_RECURSION_DEPTH_LIMIT=0
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with JSON_RECURSION_DEPTH_LIMIT=0"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Coverage.
|
||||
###############################################################################
|
||||
|
||||
@@ -9,11 +9,6 @@
|
||||
# __n2)`, which stores `__n1 - __n2` in a signed difference_type and clamps it to int. Any comparison with a shorter
|
||||
# view wraps that subtraction on purpose, and -fsanitize=integer reports it as implicit-integer-sign-change. json_view
|
||||
# compares keys as string views, so the same check is excluded for <string_view> as well.
|
||||
# std::filesystem::path::u8string() in libstdc++ 14 builds a std::u8string from the native char sequence, so
|
||||
# basic_string's range copy (_S_copy_chars) converts every char >= 0x80 to char8_t, which -fsanitize=integer reports as
|
||||
# implicit-integer-sign-change (test-conversions2_cpp20/cpp23, non-ASCII path). The conversion is intended and happens
|
||||
# inside the standard library, not in this library.
|
||||
[implicit-integer-sign-change]
|
||||
src:*/include/c++/*/format
|
||||
src:*/include/c++/*/string_view
|
||||
src:*/include/c++/*/bits/basic_string.h
|
||||
@@ -1,3 +0,0 @@
|
||||
meson==1.12.1 \
|
||||
--hash=sha256:930bc7542cbd9f57009e182fd014eba48cf1a0180a7b9006d2d32d8f168d8b02 \
|
||||
--hash=sha256:ab0a6ca09f8ef70c564c8241fb5a23957886a0b53fb58412b5e07eaf07dba743
|
||||
@@ -1 +1 @@
|
||||
reuse==6.3.0
|
||||
reuse==6.2.0
|
||||
@@ -1 +0,0 @@
|
||||
semgrep==1.184.0
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
@@ -67,11 +67,7 @@ basic_json(basic_json&& other) noexcept;
|
||||
- **objects**: [`object_t`](object_t.md) and all kinds of compatible associative containers such as `std::map`,
|
||||
`std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to `string_t`
|
||||
and a `value_type` from which a `basic_json` value can be constructed.
|
||||
- **strings**: `string_t`, string literals, and all compatible string containers can be used. Since version 3.13.0,
|
||||
this includes `#!cpp std::u8string` (C++20): its code units are stored as a JSON string and
|
||||
[`get<std::u8string>()`](get.md) reads it back (in version 3.12.0, a `#!cpp std::u8string` was stored as an array
|
||||
of numbers; `get<std::u8string>()` still accepts such an array). `#!cpp std::u8string_view` and `#!cpp char8_t`
|
||||
arrays are not strings; they are stored as arrays of code units.
|
||||
- **strings**: `string_t`, string literals, and all compatible string containers can be used.
|
||||
|
||||
!!! note "Rvalue containers are moved from"
|
||||
|
||||
@@ -97,18 +93,10 @@ basic_json(basic_json&& other) noexcept;
|
||||
The constructor tries to convert the internal `m_value` of the parameter. Each member value (object, array, string,
|
||||
etc.) is serialized via the corresponding `to_json()` overload. For objects and strings, the conversion requires
|
||||
that the *target* `basic_json` type's `object_t::key_type` (or `string_t`) be directly constructible from the
|
||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the result
|
||||
depends on the *source* string type:
|
||||
|
||||
- If it is a range of characters (it has `begin()` and `end()`, as `std::string` does), the conversion falls back to
|
||||
the array-conversion path, which represents objects as arrays of `[key, value]` pairs and strings as arrays of
|
||||
character codes. This result has a different type than the source value, so the constructor's
|
||||
[`JSON_ASSERT`](../macros/json_assert.md) fails; with its default definition, `assert`, the program aborts unless
|
||||
`NDEBUG` is defined, in which case the array is returned.
|
||||
- Otherwise, the conversion does not compile, even though `#!cpp std::is_constructible` reports `#!cpp true`; for
|
||||
example, when converting a `basic_json` whose `string_t` is the `alt_string` of the unit tests to `json`.
|
||||
|
||||
This is a known limitation tracked in [issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the conversion
|
||||
does not fail to compile; instead, it silently falls back to the array-conversion path, which represents objects
|
||||
as arrays of `[key, value]` pairs and strings as arrays of character codes. This is a known limitation tracked in
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||
|
||||
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
||||
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
||||
|
||||
@@ -130,12 +130,6 @@ overload (3).
|
||||
`#!cpp json(true).get<double>()` throw. This is the behavior of all 3.x versions;
|
||||
[`basic_json_view::get<T>()`](../basic_json_view/get.md) behaves the same.
|
||||
|
||||
!!! note "`std::u8string` conversions"
|
||||
|
||||
Since version 3.13.0, `#!cpp get<std::u8string>()` (C++20) reads a JSON string; it also accepts an array of numbers,
|
||||
the form in which version 3.12.0 stored a `#!cpp std::u8string`. Any other JSON type throws
|
||||
[`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) ("type must be string or array").
|
||||
|
||||
!!! note "`std::optional` conversions"
|
||||
|
||||
Prior to version 3.13.0, `#!cpp get<std::optional<T>>()` (and other conversions to `std::optional<T>`) failed to
|
||||
|
||||
@@ -50,7 +50,7 @@ Besides `basic_json`, the library offers a second way to hold a parsed JSON text
|
||||
[`basic_json_document`](../basic_json_document/index.md), which owns or borrows the text and holds a flat index of the
|
||||
values in it, and a [`basic_json_view`](../basic_json_view/index.md), a read-only handle to one value of such a document.
|
||||
Both are defined in the header `<nlohmann/json_view.hpp>`; see
|
||||
[Zero-copy JSON views](../../features/json_view/index.md) for the concept and the trade-offs.
|
||||
[Zero-copy JSON views](../../features/json_view.md) for the concept and the trade-offs.
|
||||
|
||||
- [**json_document**](../json_document.md) / [**ordered_json_document**](../ordered_json_document.md) - read-only
|
||||
documents of the `basic_json` specialization they belong to
|
||||
@@ -363,7 +363,7 @@ Access to the JSON value
|
||||
specification of the JSON data interchange format
|
||||
- [`basic_json_document`](../basic_json_document/index.md) - / [`basic_json_view`](../basic_json_view/index.md) - parse a JSON
|
||||
text into a flat index and read it through a view
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md) - when to use a document and a view instead of a `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view.md) - when to use a document and a view instead of a `basic_json`
|
||||
- [Types](../../features/types/index.md) - how JSON values are stored and which types exist
|
||||
- [Converting values](../../features/conversions.md) - get values out of a JSON value and put values in
|
||||
- [Creating JSON values](../../features/creating_values.md) - all the ways to build a JSON value
|
||||
|
||||
@@ -102,12 +102,9 @@ objects.
|
||||
|
||||
When converting an object from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md) (overload 4), the target `object_t`'s `key_type` must be
|
||||
directly constructible from the source object's key type (with the default `std::map`, the source `basic_json`'s
|
||||
`string_t`). If this requirement is not met and the source string type is a range of characters, the
|
||||
object is converted as an array of key-value pairs, which is incorrect: the converting constructor's
|
||||
[`JSON_ASSERT`](../macros/json_assert.md) fails; with its default definition, `assert`, the program aborts unless
|
||||
`NDEBUG` is defined, in which case the array is returned. If the source string type is not a range of characters, the
|
||||
conversion does not compile at all. See [`basic_json`](basic_json.md) and
|
||||
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
|
||||
source object's key type). If this requirement is not met, the conversion does not fail; instead,
|
||||
the object is silently converted as an array of key-value pairs, which is incorrect. See
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -27,16 +27,6 @@ reference operator+=(initializer_list_t init);
|
||||
`init` is converted into an object element and added using `operator+=(const typename object_t::value_type&)`.
|
||||
Otherwise, `init` is converted to a JSON value and added using `operator+=(basic_json&&)`.
|
||||
|
||||
!!! note "Single braced JSON value"
|
||||
|
||||
For a call such as `#!cpp arr += {obj}`, where the initializer list contains a single JSON value `obj`,
|
||||
compilers may disagree unless
|
||||
[`JSON_BRACE_INIT_COPY_SEMANTICS`](../macros/json_brace_init_copy_semantics.md) is defined to `1`: GCC, for
|
||||
example, selects this overload and appends a single-element array `[obj]`, whereas Clang selects the
|
||||
`basic_json` overload and appends a copy of `obj`. With the macro, GCC and Clang both append a copy of `obj`.
|
||||
To get a portable result without the macro, write `#!cpp arr += obj` to append a copy, or
|
||||
`#!cpp arr += json::array({obj})` to append a single-element array.
|
||||
|
||||
## Iterator invalidation
|
||||
|
||||
For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including
|
||||
|
||||
@@ -60,14 +60,6 @@ Linear.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
|
||||
For arrays and objects, the elements are compared in order. If the comparison reaches a `NaN` and a number (or
|
||||
another `NaN`) before any other difference, the result depends on the language standard. Before C++20, the pair
|
||||
counts as equivalent and the following elements (or the sizes) decide: for instance, `[NaN] < [1, NaN]` and
|
||||
`[1] <= [NaN]` are `#!cpp true`. Since C++20, the whole comparison is unordered, and `<`, `<=`, `>`, and `>=` all
|
||||
yield `#!cpp false`. Otherwise (for example `[1, NaN] < [2, NaN]`, or objects whose keys differ), the result is the
|
||||
same for all language standards. The same program can therefore order such values differently when it is compiled
|
||||
with a different language standard.
|
||||
|
||||
!!! note "Operator overload resolution"
|
||||
|
||||
Since C++20 overload resolution will consider the _rewritten candidate_ generated from
|
||||
|
||||
@@ -60,14 +60,6 @@ Linear.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
|
||||
For arrays and objects, the elements are compared in order. If the comparison reaches a `NaN` and a number (or
|
||||
another `NaN`) before any other difference, the result depends on the language standard. Before C++20, the pair
|
||||
counts as equivalent and the following elements (or the sizes) decide: for instance, `[NaN] < [1, NaN]` and
|
||||
`[1] <= [NaN]` are `#!cpp true`. Since C++20, the whole comparison is unordered, and `<`, `<=`, `>`, and `>=` all
|
||||
yield `#!cpp false`. Otherwise (for example `[1, NaN] < [2, NaN]`, or objects whose keys differ), the result is the
|
||||
same for all language standards. The same program can therefore order such values differently when it is compiled
|
||||
with a different language standard.
|
||||
|
||||
!!! note "Operator overload resolution"
|
||||
|
||||
Since C++20 overload resolution will consider the _rewritten candidate_ generated from
|
||||
|
||||
@@ -61,14 +61,6 @@ Linear.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
|
||||
For arrays and objects, the elements are compared in order. If the comparison reaches a `NaN` and a number (or
|
||||
another `NaN`) before any other difference, the result depends on the language standard. Before C++20, the pair
|
||||
counts as equivalent and the following elements (or the sizes) decide: for instance, `[NaN] < [1, NaN]` and
|
||||
`[1] <= [NaN]` are `#!cpp true`. Since C++20, the whole comparison is unordered, and `<`, `<=`, `>`, and `>=` all
|
||||
yield `#!cpp false`. Otherwise (for example `[1, NaN] < [2, NaN]`, or objects whose keys differ), the result is the
|
||||
same for all language standards. The same program can therefore order such values differently when it is compiled
|
||||
with a different language standard.
|
||||
|
||||
!!! note "Operator overload resolution"
|
||||
|
||||
Since C++20 overload resolution will consider the _rewritten candidate_ generated from
|
||||
|
||||
@@ -71,14 +71,6 @@ Linear.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
|
||||
For arrays and objects, the elements are compared in order. If the comparison reaches a `NaN` and a number (or
|
||||
another `NaN`) before any other difference, the result depends on the language standard. Before C++20, the pair
|
||||
counts as equivalent and the following elements (or the sizes) decide: for instance, `[NaN] < [1, NaN]` and
|
||||
`[1] <= [NaN]` are `#!cpp true`. Since C++20, the whole comparison is unordered, and `<`, `<=`, `>`, and `>=` all
|
||||
yield `#!cpp false`. Otherwise (for example `[1, NaN] < [2, NaN]`, or objects whose keys differ), the result is the
|
||||
same for all language standards. The same program can therefore order such values differently when it is compiled
|
||||
with a different language standard.
|
||||
|
||||
!!! note "Operator overload resolution"
|
||||
|
||||
Since C++20 overload resolution will consider the _rewritten candidate_ generated from
|
||||
|
||||
@@ -55,10 +55,6 @@ Linear.
|
||||
1. Comparing a `NaN` with itself.
|
||||
2. Comparing a `NaN` with another `NaN`.
|
||||
3. Comparing a `NaN` and any other number.
|
||||
- For arrays and objects, the elements are compared in order. If the comparison reaches a `NaN` and a number (or
|
||||
another `NaN`) before any other difference, the result is `std::partial_ordering::unordered`. (Without C++20, the
|
||||
comparison operators `<`, `<=`, `>`, and `>=` use the comparison of the containers, which treats such a pair as
|
||||
equivalent; see [**operator<**](operator_lt.md).)
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -124,19 +124,17 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
|
||||
[`basic_json_document::parse`](../basic_json_document/parse.md) accepts the same inputs and the same options, but
|
||||
keeps the result as a flat index of the parsed values instead of a tree of `basic_json` values. It is faster and uses
|
||||
less memory when only parts of the document are read, and it also accepts a pointer to a null-terminated wide string,
|
||||
which `parse()` does not. See [Zero-copy JSON views](../../features/json_view/index.md).
|
||||
which `parse()` does not. See [Zero-copy JSON views](../../features/json_view.md).
|
||||
|
||||
!!! tip "Performance"
|
||||
|
||||
Contiguous inputs (strings, string views, vectors, arrays, pointer ranges) are the fastest to parse. A
|
||||
`#!cpp std::istream` comes close: the parser scans the characters its stream buffer holds in bulk, without reading
|
||||
ahead, so the stream is left exactly where it would be after reading one character at a time. With glibc
|
||||
and the Apple C library, the characters the `#!cpp FILE` holds in its buffer are scanned in bulk like a stream's;
|
||||
elsewhere a `#!cpp FILE*` is read one character at a time. Where the C library has unlocked stdio functions, the
|
||||
file is locked only once, so other threads that use the same `FILE` object wait until parsing is done, unless
|
||||
[`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) is defined to `1`. See
|
||||
[input sources and performance](../../features/parsing/index.md#input-sources-and-performance) and
|
||||
[`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md).
|
||||
ahead, so the stream is left exactly where it would be after reading one character at a time. A `#!cpp FILE*` is
|
||||
read one character at a time, but the file is locked only once, so other threads that use the same `FILE` object
|
||||
wait until parsing is done. See [input sources and performance](../../features/parsing/index.md#input-sources-and-performance),
|
||||
[`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md), and
|
||||
[`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md).
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -313,10 +311,6 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
|
||||
it as end of input; planned to become the default in version 4.0.0.
|
||||
- Extended empty-input detection to also cover an `std::istream` without a stream buffer, and fixed a crash
|
||||
(`std::terminate`) when parsing from an `std::istream` with `eofbit` in its exception mask, in version 3.13.0.
|
||||
- Fixed the position that a [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) reports for an
|
||||
unexpected number that is followed by a line feed in version 3.13.0: for the input `1`, line feed, `2`, line feed,
|
||||
version 3.12.0 reported "line 2, column 0" and version 3.13.0 reports "line 2, column 1"; for `1 2` and a line feed,
|
||||
the report was "line 1, column 0" and is now "line 1, column 3".
|
||||
- Parsing from an `std::istream` scans the characters in its stream buffer in bulk in version 3.13.0
|
||||
([`JSON_DISABLE_STREAM_BULK_SCAN`](../macros/json_disable_stream_bulk_scan.md) restores reading one character at a
|
||||
time).
|
||||
|
||||
@@ -15,9 +15,7 @@ the patch. This function applies a JSON patch in place and returns void.
|
||||
|
||||
## Exception safety
|
||||
|
||||
No guarantees: if an operation fails, the operations before it stay applied, and a failing `move` operation may already
|
||||
have removed the value at its "from" location. Use [`patch`](patch.md) if the value must be unchanged after a failed
|
||||
patch.
|
||||
No guarantees, value may be corrupted by an unsuccessful patch operation.
|
||||
|
||||
## Exceptions
|
||||
|
||||
@@ -64,19 +62,8 @@ the JSON value, the complexity can usually be neglected.
|
||||
## Notes
|
||||
|
||||
Unlike [`patch`](patch.md), `patch_inplace` applies the operation "in place" and no copy of the JSON value is created.
|
||||
That makes it faster for large documents by avoiding the copy.
|
||||
|
||||
!!! warning "Not atomic"
|
||||
|
||||
`patch_inplace` applies the operations one after the other and does not undo them when one fails. After an
|
||||
exception, the value holds the result of the operations before the failing one, and a failing `move` operation
|
||||
(a "remove" followed by an "add") may already have removed the value at its "from" location; see the second example
|
||||
below. [RFC 6902](https://tools.ietf.org/html/rfc6902#section-5) requires that a patch with a failing operation is
|
||||
not deemed successful, but leaves open what happens to the document.
|
||||
|
||||
If the value must stay unchanged when the patch fails, use [`patch`](patch.md), which applies the patch to a copy:
|
||||
`#!cpp j = j.patch(json_patch);`. Validating the patch beforehand is not enough, as "test" operations and missing
|
||||
paths are only detected while the patch is applied.
|
||||
That makes it faster for large documents by avoiding the copy. However, the JSON value might be corrupted if the
|
||||
function throws an exception.
|
||||
|
||||
Duplicate member names inside an operation object are resolved by the parser before the patch is applied (the last one
|
||||
is kept, see [`object_t`](object_t.md#behavior)), so `#!json {"op": "add", "op": "remove", "path": "/a"}` is a
|
||||
|
||||
@@ -27,16 +27,6 @@ void push_back(initializer_list_t init);
|
||||
`init` is converted into an object element and added using `push_back(const typename object_t::value_type&)`.
|
||||
Otherwise, `init` is converted to a JSON value and added using `push_back(basic_json&&)`.
|
||||
|
||||
!!! note "Single braced JSON value"
|
||||
|
||||
For a call such as `#!cpp arr.push_back({obj})`, where the initializer list contains a single JSON value `obj`,
|
||||
compilers may disagree unless
|
||||
[`JSON_BRACE_INIT_COPY_SEMANTICS`](../macros/json_brace_init_copy_semantics.md) is defined to `1`: GCC, for
|
||||
example, selects this overload and appends a single-element array `[obj]`, whereas Clang selects the
|
||||
`basic_json` overload and appends a copy of `obj`. With the macro, GCC and Clang both append a copy of `obj`.
|
||||
To get a portable result without the macro, write `#!cpp arr.push_back(obj)` to append a copy, or
|
||||
`#!cpp arr.push_back(json::array({obj}))` to append a single-element array.
|
||||
|
||||
## Iterator invalidation
|
||||
|
||||
For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including
|
||||
|
||||
@@ -124,10 +124,9 @@ consumer `sax` has a super-linear complexity.
|
||||
|
||||
A UTF-8 byte order mark is silently ignored.
|
||||
|
||||
When reading from a `#!c FILE*` where the C library has unlocked stdio functions, the file is locked while it is parsed,
|
||||
unless [`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md) is defined to `1`.
|
||||
The lock is recursive, so the SAX handler may use the same file with stdio functions, but it must not wait for another
|
||||
thread that uses the same `FILE` object.
|
||||
When reading from a `#!c FILE*`, the file is locked while it is parsed. The lock is recursive, so the SAX handler may
|
||||
use the same file with stdio functions, but it must not wait for another thread that uses the same `FILE` object; see
|
||||
[`JSON_DISABLE_UNLOCKED_FILE_IO`](../macros/json_disable_unlocked_file_io.md).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -67,7 +67,3 @@ Constant.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.0.
|
||||
- Fixed in version 3.13.0: in version 3.12.0, the start position of a string that contains escape sequences (for
|
||||
example `#!cpp "\n"` or `#!cpp "\u00e4"`) was too large, by the number of bytes the escape sequences add to the
|
||||
source text. The position is now always that of the opening `"`. The "(bytes a-b)" range in the messages of
|
||||
[`JSON_DIAGNOSTICS`](../macros/json_diagnostics.md) was wrong in the same way.
|
||||
@@ -60,11 +60,9 @@ String values are stored as pointers in a `basic_json` type. That is, for any ac
|
||||
When converting a string value from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md) (overload 4), the target `string_t` must be directly
|
||||
constructible from the source `basic_json`'s `string_t` type. If this requirement is not met, the
|
||||
conversion depends on the source string type. If it is a range of characters, the string is converted as an array of
|
||||
character codes, which is incorrect: the converting constructor's [`JSON_ASSERT`](../macros/json_assert.md) fails; with
|
||||
its default definition, `assert`, the program aborts unless `NDEBUG` is defined, in which case the array is returned.
|
||||
If the source string type is not a range of characters, the conversion does not compile at all. See
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||
conversion does not fail; instead, the string is silently converted as an array of character codes,
|
||||
which is incorrect. See [issue #3425](https://github.com/nlohmann/json/issues/3425) for details
|
||||
and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ compile; see [`parse`](parse.md#notes).
|
||||
|
||||
- [`parse`](parse.md) - deserialize from a compatible input
|
||||
- [`BasicJsonType::accept`](../basic_json/accept.md) - the corresponding function of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/differences.md#what-is-the-same) - how parsing a document differs from, and matches, basic_json::parse
|
||||
- [Zero-copy JSON views](../../features/json_view.md#what-is-the-same-as-parse) - how parsing a document differs from, and matches, basic_json::parse
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ Constant.
|
||||
|
||||
- [`parse`](parse.md) - deserialize from a compatible input
|
||||
- [`is_discarded`](is_discarded.md) - return whether the last parse failed
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - who owns the source text and for how long
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - who owns the source text and for how long
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ by an erase, not only those at or after the removed element, since the container
|
||||
- [`root`](root.md) - the view of the root value, the starting point of overload 3
|
||||
- [`BasicJsonType::erase`](../basic_json/erase.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
- [Zero-copy JSON views](../../features/json_view/editing.md) - what an edit guarantees and costs
|
||||
- [Zero-copy JSON views](../../features/json_view.md#editing-a-document) - what an edit guarantees and costs
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -109,17 +109,16 @@ points apply to every edit:
|
||||
anything `BasicJsonType` can be constructed from (numbers, strings, `#!cpp bool`, `#!cpp nullptr`, containers, ...).
|
||||
- [`dump()`](../basic_json_view/dump.md) writes an edited document with members in document order, new members at
|
||||
the end, and, with [`number_format::source`](../basic_json_view/number_format.md), keeps the spelling of every
|
||||
number that was not itself edited — see [Editing a document](../../features/json_view/editing.md) for
|
||||
number that was not itself edited — see [Editing a document](../../features/json_view.md#editing-a-document) for
|
||||
why this matters.
|
||||
- [`read()`](read.md) discards all edits (so its `input` must not be a string obtained from this document),
|
||||
[`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once there are edits, and
|
||||
[`memory_usage()`](memory_usage.md) includes the memory edits use.
|
||||
- [`read()`](read.md) discards all edits, [`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once
|
||||
there are edits, and [`memory_usage()`](memory_usage.md) includes the memory edits use.
|
||||
[`source_offset()`](../basic_json_view/source_offset.md) of a value introduced by an edit is
|
||||
`#!cpp static_cast<std::size_t>(-1)`, the same value it reports for a decoded string.
|
||||
|
||||
## See also
|
||||
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md) - guide to documents and views
|
||||
- [Zero-copy JSON views](../../features/json_view.md) - guide to documents and views
|
||||
- [`basic_json_view`](../basic_json_view/index.md) - the non-owning handle to a value in a document
|
||||
- [`json_document`](../json_document.md) - and [`json_editable_document`](../json_editable_document.md) - the default specializations
|
||||
- [`materialize`](../basic_json_view/materialize.md) - build a `basic_json` value from a view
|
||||
|
||||
@@ -108,7 +108,7 @@ an edit in general.
|
||||
- [`set`](set.md) - replace a value, or set an object member, an array element, or the value a JSON pointer refers to
|
||||
- [`BasicJsonType::insert`](../basic_json/insert.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
- [Zero-copy JSON views](../../features/json_view/editing.md) - what an edit guarantees and costs
|
||||
- [Zero-copy JSON views](../../features/json_view.md#editing-a-document) - what an edit guarantees and costs
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ When the document is discarded, [`root()`](root.md) returns a discarded view (it
|
||||
|
||||
- [`parse`](parse.md) - deserialize from a compatible input
|
||||
- [`basic_json_view::is_discarded`](../basic_json_view/is_discarded.md) - return whether a view is invalid
|
||||
- [Zero-copy JSON views](../../features/json_view/differences.md#what-is-the-same) - how a discarded document arises
|
||||
- [Zero-copy JSON views](../../features/json_view.md#what-is-the-same-as-parse) - how a discarded document arises
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ static basic_json_document load(std::vector<std::uint8_t>&& image,
|
||||
|
||||
In every overload, the node index is copied into storage the document itself owns — so that it is properly aligned,
|
||||
and, for an [editable](index.md#edits) document, can be edited — while the text and the decoded strings stay in
|
||||
`image`. The hash indexes [large objects](../../features/json_view/index.md) use for lookup are rebuilt, exactly as after
|
||||
`image`. The hash indexes [large objects](../../features/json_view.md) use for lookup are rebuilt, exactly as after
|
||||
parsing.
|
||||
|
||||
## Parameters
|
||||
@@ -113,12 +113,11 @@ How thoroughly `load()` validates `image` before trusting it.
|
||||
`full` (the default)
|
||||
: Checks everything the parser itself guarantees: structure and bounds; that every string is valid UTF-8 (and, for a
|
||||
string still in the source text, that it contains no quote, backslash, or control character); and that every number
|
||||
token is well-formed and matches the value stored for it, and has the type the parser gives it (a float node only
|
||||
for a token with a fraction or an exponent, or an integer that does not fit 64 bits). Strings and float tokens may
|
||||
share a range only if the ranges are identical (as nodes that share a value do), and never overlap otherwise.
|
||||
Reading and serializing a checked image is safe and always produces valid JSON, exactly as for a parsed document.
|
||||
This is the right choice for an image from anything you do not fully control — a file, a cache shared with other
|
||||
processes, a peer on the network.
|
||||
token is well-formed and matches the value stored for it. Strings and float tokens may share a range only if the
|
||||
ranges are identical (as nodes that share a value do), and never overlap otherwise. Reading and serializing a
|
||||
checked image is safe and always produces valid JSON, exactly as for a parsed document. This is the right choice for
|
||||
an image from anything you do not fully control — a file, a cache shared with other processes, a peer on the
|
||||
network.
|
||||
|
||||
`bounds`
|
||||
: Checks structure and bounds only: that every offset and count in the node index stays inside the image. So
|
||||
@@ -173,7 +172,7 @@ returned document, and any [view](../basic_json_view/index.md) taken from it, is
|
||||
- [`save`](save.md) - write the document as an image
|
||||
- [`owns_source`](owns_source.md) - return whether the document holds its own copy of the text
|
||||
- [`parse`](parse.md) - deserialize from JSON text instead of an image
|
||||
- [Images](../../features/json_view/images.md) - why and when to use images
|
||||
- [Images](../../features/json_view.md#images) - why and when to use images
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ to observe the effect of [`shrink_to_fit()`](shrink_to_fit.md).
|
||||
|
||||
- [`node_count`](node_count.md) - the number of index entries
|
||||
- [`shrink_to_fit`](shrink_to_fit.md) - release unused index capacity
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md#the-idea) - the flat node index and its memory
|
||||
- [Zero-copy JSON views](../../features/json_view.md#the-idea) - the flat node index and its memory
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ strings and, for an owned document, the text).
|
||||
|
||||
- [`memory_usage`](memory_usage.md) - the number of bytes held by the document
|
||||
- [`shrink_to_fit`](shrink_to_fit.md) - release unused index capacity
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md#the-idea) - the flat node index and its memory
|
||||
- [Zero-copy JSON views](../../features/json_view.md#the-idea) - the flat node index and its memory
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ document (`#!cpp owns_source() == false`) is only valid while the buffer it was
|
||||
- [`parse`](parse.md) - deserialize from a compatible input
|
||||
- [`parse_copy`](parse_copy.md) - deserialize a copy of a compatible input, always owned
|
||||
- [`source`](source.md) - the parsed text
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - who owns the source text and for how long
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - who owns the source text and for how long
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ told apart from other class-type iterators, so their range is read into an owned
|
||||
range (e.g. of a `#!cpp std::list<char>`).
|
||||
|
||||
See [`owns_source`](owns_source.md) to check which happened after a call, and the
|
||||
[feature page](../../features/json_view/index.md) for the reasoning.
|
||||
[feature page](../../features/json_view.md) for the reasoning.
|
||||
|
||||
**Numbers.** As for [`BasicJsonType::parse()`](../basic_json/parse.md), an integer literal too large for the 64-bit
|
||||
integer type becomes a floating-point value.
|
||||
|
||||
@@ -74,7 +74,7 @@ compile; see [`parse`](parse.md#notes).
|
||||
|
||||
- [`parse`](parse.md) - deserialize from a compatible input, borrowing it where possible
|
||||
- [`owns_source`](owns_source.md) - return whether the document holds its own copy of the text
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - borrowing or copying the source text
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - borrowing or copying the source text
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ Like [`set`](set.md) on a member or an element, `push_back` never moves an exist
|
||||
- [`root`](root.md) - the view of the root value
|
||||
- [`BasicJsonType::push_back`](../basic_json/push_back.md) - the corresponding function of `basic_json`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
- [Zero-copy JSON views](../../features/json_view/editing.md) - what an edit guarantees and costs
|
||||
- [Zero-copy JSON views](../../features/json_view.md#editing-a-document) - what an edit guarantees and costs
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -46,34 +46,6 @@ Linear in the length of the input.
|
||||
Every view taken from `#!cpp *this` before the call — including the previous [`root()`](root.md) — is invalidated,
|
||||
whether or not the new parse succeeds; take fresh views from [`root()`](root.md) afterward.
|
||||
|
||||
!!! warning "`input` must not point into the document itself"
|
||||
|
||||
`read()` releases the document's previous text, its decoded strings, and (for an editable document) its edits
|
||||
*before* it parses `input`. An `input` that is, or points into, any of them violates a precondition: it may seem to
|
||||
work, parse empty or garbled text, be reported by a sanitizer, or read freed memory (undefined behavior).
|
||||
|
||||
This applies to every `string_view` obtained from the document whose characters live in memory that `read()`
|
||||
releases:
|
||||
|
||||
- [`source()`](source.md) of a document that owns its text;
|
||||
- [`get_string()`](../basic_json_view/get_string.md) (also as `get<string_view_t>()` or a `string_view` member of a
|
||||
decoded struct) of a string with escapes, of a string of a document that owns its text, and of an edited string;
|
||||
- [`number_token()`](../basic_json_view/number_token.md) of a number of a document that owns its text, and of a
|
||||
number written by an edit;
|
||||
- the key of an object member (`key()`) if it has escapes, was written by an edit, or the document owns its text.
|
||||
|
||||
It does not apply to a text that the caller owns and the document borrows, nor to the strings, keys, and tokens that
|
||||
are read from such a text unchanged, nor to the decoded strings of a borrowed [image](load.md), which live in the
|
||||
caller's image: `read()` never touches them. To parse JSON that a document holds in a string of its own (for
|
||||
example, JSON embedded in a string value), copy the string first, for example with
|
||||
`#!cpp std::string inner(doc.root()["payload"].get_string()); doc.read(inner);`.
|
||||
|
||||
A debug build (one without `NDEBUG`) checks this with `assert()`: an `input` in the document's text, decoded
|
||||
strings, or image, or in the most recent buffer of strings written by edits, ends the program. (Strings written
|
||||
by earlier edits are not covered.) A release build does not check, to keep the cost of reusing a document at a
|
||||
minimum. The check uses `assert()` directly, not [`JSON_ASSERT`](../macros/json_assert.md), which `json.hpp`
|
||||
undefines at its end.
|
||||
|
||||
`input` is borrowed or owned by the same rules as [`parse()`](parse.md#notes); a document can borrow on one call and
|
||||
own on the next, since ownership is decided freshly each time. An input that is copied (see the table in
|
||||
[`parse()`](parse.md#notes)) is written into the document's previous owned copy, reusing its memory; a moved-in
|
||||
@@ -109,7 +81,7 @@ compile; see [`parse`](parse.md#notes).
|
||||
- [`parse`](parse.md) - deserialize from a compatible input
|
||||
- [`root`](root.md) - the view of the root value
|
||||
- [`load`](load.md) - read a document from an image instead of parsing JSON text
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - reusing a document and what it invalidates
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - reusing a document and what it invalidates
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ auto v = doc.root();
|
||||
returned view is valid under the same conditions as any other view of the document — see
|
||||
[Object inspection](../basic_json_view/index.md) — in particular, it is invalidated by the next
|
||||
[`read()`](read.md) or [`shrink_to_fit()`](shrink_to_fit.md) on this document. A view can dangle, like a
|
||||
`#!cpp std::string_view`; see [Ownership and lifetime](../../features/json_view/lifetime.md).
|
||||
`#!cpp std::string_view`; see [Ownership and lifetime](../../features/json_view.md#ownership-and-lifetime).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ big-endian reader could not interpret correctly.
|
||||
- [`load`](load.md) - read an image written by `save()`
|
||||
- [`owns_source`](owns_source.md) - return whether the document holds its own copy of the text
|
||||
- [`basic_json_view::dump`](../basic_json_view/dump.md) - serialize the document to JSON text instead of an image
|
||||
- [Images](../../features/json_view/images.md) - why and when to use images
|
||||
- [Images](../../features/json_view.md#images) - why and when to use images
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ one-node scalar.
|
||||
- [`basic_json_view::dump`](../basic_json_view/dump.md) - serialize the document, keeping an untouched number's
|
||||
spelling with `#!cpp number_format::source`
|
||||
- [Edits](index.md#edits) - what an edit guarantees, for every overload
|
||||
- [Editing a document](../../features/json_view/editing.md) - why editable documents keep the source
|
||||
- [Editing a document](../../features/json_view.md#editing-a-document) - why editable documents keep the source
|
||||
text's order and number spelling
|
||||
|
||||
## Version history
|
||||
|
||||
@@ -56,7 +56,7 @@ possible would be an internal optimization only, not a guarantee to rely on.
|
||||
- [`node_count`](node_count.md) - the number of index entries
|
||||
- [`memory_usage`](memory_usage.md) - the number of bytes held by the document
|
||||
- [`root`](root.md) - the view of the root value
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - what releasing memory invalidates
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - what releasing memory invalidates
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@ Constant.
|
||||
For a borrowed document, `source()` points directly into the caller's buffer, so it is only valid while that buffer
|
||||
is; see [`owns_source`](owns_source.md).
|
||||
|
||||
The text of a document that owns it must not be passed to [`read()`](read.md) of the same document: `read()` releases
|
||||
an owned text before it parses its input. Copy it first. (A borrowed text belongs to the caller and is not affected.)
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -45,7 +42,7 @@ an owned text before it parses its input. Copy it first. (A borrowed text belong
|
||||
|
||||
- [`owns_source`](owns_source.md) - return whether the document holds its own copy of the text
|
||||
- [`source_offset`](../basic_json_view/source_offset.md) - byte offset of a value in the source text
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - who owns the source text and for how long
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - who owns the source text and for how long
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ Pointer path of the value within the document, and with
|
||||
|
||||
If the source text repeats a key, this resolves to the *first* member with it, not to the last one that
|
||||
[`materialize()`](materialize.md) and `parse()` keep. See the [Notes on duplicate keys](operator[].md#notes) of
|
||||
`operator[]` and [Duplicate keys](../../features/json_view/differences.md#duplicate-keys) for the reasons and for how to get
|
||||
`operator[]` and [Duplicate keys](../../features/json_view.md#duplicate-keys) for the reasons and for how to get
|
||||
the last value.
|
||||
|
||||
Unlike [`operator[]`](operator[].md), which returns a [discarded](is_discarded.md) view for a missing key or an
|
||||
|
||||
@@ -58,7 +58,7 @@ placeholder for "no value yet" and later be assigned a real view.
|
||||
- [`is_discarded`](is_discarded.md) - return whether the view is invalid
|
||||
- [`root`](../basic_json_document/root.md) - the view of a document's root value
|
||||
- [`view_mode`](../view_mode.md) - whether a document and its views can be edited
|
||||
- [Zero-copy JSON views](../../features/json_view/lifetime.md) - how long a view stays valid
|
||||
- [Zero-copy JSON views](../../features/json_view.md#ownership-and-lifetime) - how long a view stays valid
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
If the source text repeats a key, this resolves to the *first* member with it, not to the last one that
|
||||
[`materialize()`](materialize.md) and `parse()` keep. See the [Notes on duplicate keys](operator[].md#notes) of
|
||||
`operator[]` and [Duplicate keys](../../features/json_view/differences.md#duplicate-keys) for the reasons and for how to get
|
||||
`operator[]` and [Duplicate keys](../../features/json_view.md#duplicate-keys) for the reasons and for how to get
|
||||
the last value.
|
||||
|
||||
Overload 1 always returns `#!cpp false` when the value is not an object — including a [discarded](is_discarded.md)
|
||||
|
||||
@@ -48,11 +48,8 @@ Strong exception safety: if an exception is thrown, there are no changes to the
|
||||
|
||||
May throw `#!cpp std::bad_alloc` if allocating the output string fails. Unlike
|
||||
[`BasicJsonType::dump`](../basic_json/dump.md), there is no `error_handler` parameter and no
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316): the parser validated the text the view
|
||||
holds as UTF-8, so there is nothing to replace or ignore. Only a document loaded with
|
||||
[`image_check::bounds` or `image_check::none`](../basic_json_document/load.md#image_check) can still throw it: these do
|
||||
not check the strings, so `dump()` writes such a string as it is, which can be invalid UTF-8 or invalid JSON, and
|
||||
`dump()` with `ensure_ascii` set to `#!cpp true` throws `type_error.316` for invalid UTF-8.
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316): the view only ever holds text the parser
|
||||
already validated as UTF-8, so there is nothing to replace or ignore.
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -73,7 +70,7 @@ except that `#!cpp -0` is written as `#!cpp 0`, the way [`BasicJsonType::parse()
|
||||
`#!cpp number_format::source` copies every number exactly as written in the source text instead, with no exception
|
||||
for `#!cpp -0` — `#!cpp 1.50`, `#!cpp 1E2`, `#!cpp -0.0`, `#!cpp -0`, or all digits of an integer literal with more
|
||||
digits than any number type holds (such a literal is itself classified as a float, see
|
||||
[What is different](../../features/json_view/differences.md)) — something `BasicJsonType` cannot do, since
|
||||
[What is different](../../features/json_view.md#what-is-different)) — something `BasicJsonType` cannot do, since
|
||||
parsing already reduces every number to its parsed value.
|
||||
|
||||
## Examples
|
||||
@@ -101,7 +98,7 @@ parsing already reduces every number to its parsed value.
|
||||
- [`operator<<`](operator_ltlt.md) - serialize this value to a stream
|
||||
- [`materialize`](materialize.md) - build a `BasicJsonType` value, e.g. to use `BasicJsonType::dump`'s `error_handler`
|
||||
- [`BasicJsonType::dump`](../basic_json/dump.md) - the corresponding function of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#writing-a-view-back) - writing a view back without building a tree
|
||||
- [Zero-copy JSON views](../../features/json_view.md#writing-a-view-back) - writing a view back without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ constant time on average.
|
||||
|
||||
If the source text repeats a key, this resolves to the *first* member with it, not to the last one that
|
||||
[`materialize()`](materialize.md) and `parse()` keep. See the [Notes on duplicate keys](operator[].md#notes) of
|
||||
`operator[]` and [Duplicate keys](../../features/json_view/differences.md#duplicate-keys) for the reasons and for how to get
|
||||
`operator[]` and [Duplicate keys](../../features/json_view.md#duplicate-keys) for the reasons and for how to get
|
||||
the last value.
|
||||
|
||||
Unlike [`BasicJsonType::find`](../basic_json/find.md), which always returns `#!cpp end()` for a non-object type, this
|
||||
|
||||
@@ -39,14 +39,14 @@ as [`BasicJsonType::parse()`](../basic_json/parse.md) does), as well as the type
|
||||
accept views, e.g. with [`is_json_view`](../is_json_view.md). A `from_json()` that also accepts types that are no JSON
|
||||
values at all, such as the unconstrained `#!cpp template<typename BasicJsonType> void from_json(const BasicJsonType&,
|
||||
T&)` of [arbitrary type conversions](../../features/arbitrary_types.md), is not called with a view: it may use
|
||||
`BasicJsonType` functions a view does not have. See [Writing generic code](../../features/json_view/generic_code.md).
|
||||
`BasicJsonType` functions a view does not have. See [Writing generic code](../../features/json_view.md#writing-generic-code).
|
||||
|
||||
!!! warning "Duplicate keys"
|
||||
|
||||
Such a `from_json()` looks members up in the view, where a repeated key finds the **first** member, while
|
||||
`#!cpp materialize().get<T>()` sees the **last** one, as [`BasicJsonType::parse()`](../basic_json/parse.md)
|
||||
keeps it: for `#!cpp {"x":1,"x":2}`, `#!cpp get<point>()` reads `#!cpp x == 1`. See
|
||||
[Duplicate keys](../../features/json_view/differences.md#duplicate-keys).
|
||||
[Duplicate keys](../../features/json_view.md#duplicate-keys).
|
||||
|
||||
Every other `T` — user types whose `from_json()` is written for `BasicJsonType` only, types without a default
|
||||
constructor, `#!cpp std::tuple`s holding references, ... — is converted by `#!cpp materialize().get<T>()`: the subtree is built into a real `BasicJsonType`
|
||||
@@ -152,7 +152,7 @@ instead: its path is relative to the root of the view's subtree, because `materi
|
||||
- [`number_token`](number_token.md) - a number's token text, without a copy
|
||||
- [`materialize`](materialize.md) - build the `BasicJsonType` value of this subtree
|
||||
- [`BasicJsonType::get`](../basic_json/get.md) - the corresponding function of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#getting-values-out-without-copying) - which conversions avoid building a basic_json value
|
||||
- [Zero-copy JSON views](../../features/json_view.md#getting-values-out-without-copying) - which conversions avoid building a basic_json value
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -46,10 +46,6 @@ The returned [`string_view_t`](index.md#member-types) is valid exactly as long a
|
||||
source text, which for a borrowed document must remain valid **and unmodified** for as long as the document exists,
|
||||
since floating-point values and unescaped strings are read from the source lazily.
|
||||
|
||||
A string with escapes, a string of a document that owns its text, and an edited string must not be passed to
|
||||
[`read()`](../basic_json_document/read.md) of the document it came from: `read()` releases them before it parses its
|
||||
input. Copy the string first. (A string read unchanged from a borrowed text is not affected.)
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -74,7 +70,7 @@ input. Copy the string first. (A string read unchanged from a borrowed text is n
|
||||
- [`get`](get.md) - convert the value to a given type (`#!cpp get<string_view_t>()` is equivalent to this function)
|
||||
- [`number_token`](number_token.md) - a number's token text, without a copy
|
||||
- [`BasicJsonType::get_ref`](../basic_json/get_ref.md) - the closest counterpart of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#getting-values-out-without-copying) - borrowing strings instead of copying them
|
||||
- [Zero-copy JSON views](../../features/json_view.md#getting-values-out-without-copying) - borrowing strings instead of copying them
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ them with those of a default-constructed `T`.
|
||||
|
||||
- [`get`](get.md) - convert the value to a given type
|
||||
- [`BasicJsonType::get_to`](../basic_json/get_to.md) - the corresponding function of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#getting-values-out-without-copying) - which conversions avoid building a basic_json value
|
||||
- [Zero-copy JSON views](../../features/json_view.md#getting-values-out-without-copying) - which conversions avoid building a basic_json value
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ still refers to it — including ones taken before the change — reads the new
|
||||
|
||||
## See also
|
||||
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md) - guide to documents and views
|
||||
- [Zero-copy JSON views](../../features/json_view.md) - guide to documents and views
|
||||
- [`basic_json_document`](../basic_json_document/index.md) - the document that owns the parsed data
|
||||
- [`json_view`](../json_view.md) - and [`json_editable_view`](../json_editable_view.md) - the default specializations
|
||||
- [`materialize`](materialize.md) - build a `basic_json` value from a view
|
||||
|
||||
@@ -54,7 +54,7 @@ A `basic_json_view` is not convertible to `#!cpp bool`: such a conversion would
|
||||
- [`(constructor)`](basic_json_view.md) - the default constructor creates a discarded view
|
||||
- [`basic_json_document::is_discarded`](../basic_json_document/is_discarded.md) - return whether the last parse failed
|
||||
- [`BasicJsonType::is_discarded`](../basic_json/is_discarded.md) - the corresponding function of `basic_json`
|
||||
- [Zero-copy JSON views](../../features/json_view/differences.md) - how views differ from basic_json
|
||||
- [Zero-copy JSON views](../../features/json_view.md#what-is-different) - how views differ from basic_json
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ never caches the result.
|
||||
- [`root`](../basic_json_document/root.md) - the view of a document's root value
|
||||
- [`BasicJsonType::parse`](../basic_json/parse.md) - build a `BasicJsonType` value directly from a JSON text
|
||||
- [`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) - source positions on parsed values
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#getting-values-out-without-copying) - when to build a basic_json value from a view
|
||||
- [Zero-copy JSON views](../../features/json_view.md#getting-values-out-without-copying) - when to build a basic_json value from a view
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ source
|
||||
- [`number_token`](number_token.md) - get a single number's token text without dumping the whole value
|
||||
- [`BasicJsonType::error_handler_t`](../basic_json/error_handler_t.md) - the analogous enumeration for
|
||||
`BasicJsonType::dump`'s decoding-error behavior
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#writing-a-view-back) - writing numbers as they appeared in the source
|
||||
- [Zero-copy JSON views](../../features/json_view.md#writing-a-view-back) - writing numbers as they appeared in the source
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -38,14 +38,9 @@ by the grammar; trailing zeros in the fraction; the case and sign of the exponen
|
||||
useful precisely where that form must survive — a price or an identifier that must be reproduced exactly, or a
|
||||
number too large for any of `BasicJsonType`'s number types to hold without loss.
|
||||
|
||||
The returned [`string_view_t`](index.md#member-types) points into the document's
|
||||
[`source()`](../basic_json_document/source.md) text or, for a number written by an
|
||||
[edit](../basic_json_document/index.md#edits), into storage owned by the document (the token of an edited `NaN` is
|
||||
`nan`). It is valid exactly as long as that text or storage is, see the [validity rules](index.md) of
|
||||
`basic_json_view`. Numbers are never decoded into the document's separate string buffer.
|
||||
|
||||
For the same reason, the token must not be passed to [`read()`](../basic_json_document/read.md) of the document it came
|
||||
from if that document owns its text or the number was written by an edit: `read()` releases both before it parses.
|
||||
The returned [`string_view_t`](index.md#member-types) always points into the document's
|
||||
[`source()`](../basic_json_document/source.md) text — numbers are never decoded into the document's separate string
|
||||
buffer — and is valid exactly as long as that text is, see the [validity rules](index.md) of `basic_json_view`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -73,7 +68,7 @@ from if that document owns its text or the number was written by an edit: `read(
|
||||
- [`BasicJsonType::number_integer_t`](../basic_json/number_integer_t.md),
|
||||
[`number_unsigned_t`](../basic_json/number_unsigned_t.md), [`number_float_t`](../basic_json/number_float_t.md) - the
|
||||
number types `#!cpp get<T>()` and `materialize()` convert into
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#getting-values-out-without-copying) - reading a number exactly as written
|
||||
- [Zero-copy JSON views](../../features/json_view.md#getting-values-out-without-copying) - reading a number exactly as written
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ document.
|
||||
[`materialize()`](materialize.md) or iterate the members with [`items()`](items.md) and keep the last match.
|
||||
The key hash index of a larger object (128 members or more) leads to the first member of a key as well.
|
||||
[`begin()`](begin.md)/[`end()`](end.md) and [`items()`](items.md) iterate over *all* members, including
|
||||
duplicates, in document order. See [Duplicate keys](../../features/json_view/differences.md#duplicate-keys) and
|
||||
duplicates, in document order. See [Duplicate keys](../../features/json_view.md#duplicate-keys) and
|
||||
[`size()`](size.md#notes).
|
||||
|
||||
!!! info "JSON pointer resolution"
|
||||
|
||||
@@ -19,7 +19,7 @@ Neither overload builds a `BasicJsonType` value for a view to do the comparison
|
||||
compare by value across their types (`#!cpp 1 == 1.0`), and an object compares by its members, with duplicate keys
|
||||
resolved exactly as `parse()` resolves them — the last value, at the position of the first occurrence of the key.
|
||||
This is not what [`operator[]`](operator[].md) and the other lookups return for a duplicate key: they find the *first*
|
||||
member (see [Duplicate keys](../../features/json_view/differences.md#duplicate-keys)).
|
||||
member (see [Duplicate keys](../../features/json_view.md#duplicate-keys)).
|
||||
|
||||
## Parameters
|
||||
|
||||
@@ -57,9 +57,7 @@ compared. Two arrays of different [`size()`](size.md) are rejected without visit
|
||||
Only a single number, boolean, or `#!cpp null` value is ever materialized into a `BasicJsonType`, to reuse its
|
||||
`operator==` — for numbers, so that values written differently in the source text but equal in value (e.g. an
|
||||
integer and a floating-point literal) still compare equal, following the same rules `BasicJsonType` does for special
|
||||
values such as `#!cpp NaN`: a `#!cpp NaN` that an [edit](../basic_json_document/set.md) wrote is not equal to itself, so
|
||||
a view of it is not equal to itself either, nor is a view of an array or object that contains one, as for
|
||||
`BasicJsonType`. Constructing one of these scalars never allocates. Strings are compared directly, without
|
||||
values such as `#!cpp NaN`. Constructing one of these scalars never allocates. Strings are compared directly, without
|
||||
allocating, either from the source text on both sides or, for overload 2, against `BasicJsonType`'s own string.
|
||||
Arrays and objects are never materialized at all; only their elements or members are visited, one pair at a time.
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ Linear, as [`dump`](dump.md#complexity).
|
||||
- [`dump`](dump.md) - serialize to a JSON-formatted string
|
||||
- [`operator<<(std::ostream&)`](../operator_ltlt.md) - the corresponding operator for `basic_json`
|
||||
- [`JSON_NO_IO`](../macros/json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||
- [Zero-copy JSON views](../../features/json_view/reading.md#writing-a-view-back) - writing a view back without building a tree
|
||||
- [Zero-copy JSON views](../../features/json_view.md#writing-a-view-back) - writing a view back without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ string, whose token length is not the same as its decoded [`size()`](size.md).
|
||||
|
||||
- [`source`](../basic_json_document/source.md) - the parsed text
|
||||
- [`is_string`](is_string.md) - return whether the value is a string
|
||||
- [Zero-copy JSON views](../../features/json_view/images.md) - images and the source text
|
||||
- [Zero-copy JSON views](../../features/json_view.md#images) - images and the source text
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ Pointer path of the value within the document, and with
|
||||
|
||||
If the source text repeats a key, this resolves to the *first* member with it, not to the last one that
|
||||
[`materialize()`](materialize.md) and `parse()` keep. See the [Notes on duplicate keys](operator[].md#notes) of
|
||||
`operator[]` and [Duplicate keys](../../features/json_view/differences.md#duplicate-keys) for the reasons and for how to get
|
||||
`operator[]` and [Duplicate keys](../../features/json_view.md#duplicate-keys) for the reasons and for how to get
|
||||
the last value.
|
||||
|
||||
!!! info "Differences to `at` and `operator[]`"
|
||||
|
||||
@@ -49,7 +49,7 @@ view class.
|
||||
- [basic_json_view](basic_json_view/index.md) - a handle to one value of a document
|
||||
- [get](basic_json_view/get.md) - which conversions read the view directly
|
||||
- [view_mode](view_mode.md) - read-only or editable
|
||||
- [Writing generic code](../features/json_view/generic_code.md) - functions and `from_json()` for views
|
||||
- [Writing generic code](../features/json_view.md#writing-generic-code) - functions and `from_json()` for views
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ specialization.
|
||||
|
||||
- [`json_view`](json_view.md) - a view of a value of a `json_document`
|
||||
- [`ordered_json_document`](ordered_json_document.md) - the corresponding document for `ordered_json`
|
||||
- [Zero-copy JSON views](../features/json_view/index.md) - how to parse, inspect and edit a document without building a tree
|
||||
- [Zero-copy JSON views](../features/json_view.md) - how to parse, inspect and edit a document without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ This type is an **editable** [`basic_json_document`](basic_json_document/index.m
|
||||
[`json`](json.md) specialization: in addition to everything [`json_document`](json_document.md) offers,
|
||||
[`set`](basic_json_document/set.md) and [`push_back`](basic_json_document/push_back.md) change values after
|
||||
parsing, without ever rewriting the source text — see [Edits](basic_json_document/index.md#edits) and
|
||||
[Editing a document](../features/json_view/editing.md).
|
||||
[Editing a document](../features/json_view.md#editing-a-document).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ still referring to it seeing the change, see [Edits](basic_json_document/index.m
|
||||
- [`json_view`](json_view.md) - the corresponding read-only view
|
||||
- [`ordered_json_editable_view`](ordered_json_editable_view.md) - the corresponding view for
|
||||
`ordered_json_editable_document`
|
||||
- [Zero-copy JSON views](../features/json_view/editing.md) - editing a document in place and writing it back
|
||||
- [Zero-copy JSON views](../features/json_view.md#editing-a-document) - editing a document in place and writing it back
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of a [`j
|
||||
|
||||
- [`json_document`](json_document.md) - the document type this view refers into
|
||||
- [`ordered_json_view`](ordered_json_view.md) - the corresponding view for `ordered_json_document`
|
||||
- [Zero-copy JSON views](../features/json_view/index.md) - how to parse, inspect and edit a document without building a tree
|
||||
- [Zero-copy JSON views](../features/json_view.md) - how to parse, inspect and edit a document without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ header. See also the [macro overview page](../../features/macros.md).
|
||||
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||
- [**JSON_NO_SIMD**](json_no_simd.md) - use only portable code instead of vector instructions (SSE2, SSSE3, NEON)
|
||||
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||
- [**JSON_RECURSION_DEPTH_LIMIT**](json_recursion_depth_limit.md) - set how many nesting levels the operations on a value
|
||||
recurse into on the call stack (default 128)
|
||||
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
||||
- [**JSON_USE_GLOBAL_UDLS**](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||
- [**JSON_USE_SIMDUTF**](json_use_simdutf.md) - use the simdutf library to accelerate UTF-8 validation
|
||||
|
||||
@@ -27,13 +27,9 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
json j{obj};
|
||||
```
|
||||
|
||||
creates a single-element **array** `[{"key":"value"}]` instead of a copy of `obj`. For this constructor, the
|
||||
behavior was compiler-dependent for older compilers (GCC wrapped, Clang did not), but starting from Clang 20, both
|
||||
compilers behave the same way.
|
||||
|
||||
The calls `#!cpp arr.push_back({obj})` and `#!cpp arr += {obj}` are still compiler-dependent without the macro,
|
||||
even with Clang 20 and later: GCC converts `{obj}` to a single-element array and appends that array, whereas Clang
|
||||
appends a copy of `obj`. With the macro defined to `1`, both compilers append a copy of `obj`.
|
||||
creates a single-element **array** `[{"key":"value"}]` instead of a copy of `obj`. This behavior is
|
||||
compiler-dependent for older compilers (GCC wrapped, Clang did not), but starting from Clang 20, both compilers
|
||||
behave the same way.
|
||||
|
||||
Enabling this macro opts into copy/move semantics for this case
|
||||
(see [#5074](https://github.com/nlohmann/json/issues/5074)).
|
||||
|
||||
@@ -34,9 +34,6 @@ or quotes.
|
||||
Note that enabling this macro increases the size of every JSON value by two `std::size_t` fields and adds slight runtime
|
||||
overhead to parsing, copying JSON value objects, and the generation of error messages for exceptions. It also causes
|
||||
these values to be reported in those error messages.
|
||||
In addition, `parse()`, `accept()`, and `sax_parse()` no longer use the
|
||||
[faster path for input in one block of memory](../../features/parsing/index.md#input-sources-and-performance), so
|
||||
parsing a string or a buffer is slower than without the macro.
|
||||
|
||||
If [`JSON_DIAGNOSTICS`](json_diagnostics.md) is also set, the message contains the path and the byte range, such as
|
||||
`(/1) (bytes 4-8)`. An exception about the root value has no path and only the range, such as `(bytes 0-4)`.
|
||||
@@ -125,5 +122,3 @@ When the macro is not defined, the library will define it to its default value.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.0.
|
||||
- Fixed in version 3.13.0: in version 3.12.0, [`start_pos()`](../basic_json/start_pos.md) of a string that contains
|
||||
escape sequences was too large; it is now the position of the opening `"`.
|
||||
@@ -48,8 +48,8 @@ The default value is `0`: streams are scanned in bulk.
|
||||
!!! note "Performance"
|
||||
|
||||
Parsing from a `std::ifstream` or `std::istringstream` is typically 1.5 to 2 times as fast as before, and reading
|
||||
many small values from one stream with `operator>>` 1.4 to 4 times as fast. Parsing from a stream then takes about
|
||||
1.15 to 1.45 times as long as first reading the whole file into a `std::string` and parsing that.
|
||||
many small values from one stream with `operator>>` 1.4 to 4 times as fast. Parsing from a stream is then within
|
||||
about 10 to 20 % of first reading the whole file into a `std::string` and parsing that.
|
||||
|
||||
A stream buffer without a get area (one that only overrides `underflow()` and `uflow()` and hands out every
|
||||
character from there) offers nothing to scan in bulk, so it is read one character at a time as before.
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
```
|
||||
|
||||
When defined to `1`, parsing from a `#!cpp FILE*` reads every character with `std::fgetc`, as in version 3.12.0 and
|
||||
earlier, instead of locking the file once and reading it with the unlocked stdio functions. This also turns off the
|
||||
scan of the `FILE`'s buffer in bulk (see below), which [`JSON_DISABLE_STREAM_BULK_SCAN`](json_disable_stream_bulk_scan.md)
|
||||
does not affect.
|
||||
earlier, instead of locking the file once and reading it with the unlocked stdio functions.
|
||||
|
||||
It does not change any result: values, exceptions, and the position of the file after parsing are the same either way.
|
||||
Only the speed and the locking of the file differ (see the notes on locking below).
|
||||
@@ -39,17 +37,9 @@ The default value is `0`: the file is locked once and read with the unlocked std
|
||||
| Microsoft (MSVC, clang-cl) | `_lock_file`, `_fgetc_nolock`, `_unlock_file` |
|
||||
| others (e.g., musl, MinGW, newlib) | `std::fgetc`, as before |
|
||||
|
||||
With glibc and the Apple C library, the parser also scans the characters that the `FILE` already holds in its
|
||||
buffer in bulk, as it scans the get area of a stream (see
|
||||
[`JSON_DISABLE_STREAM_BULK_SCAN`](json_disable_stream_bulk_scan.md)): it reads the same fields of the `FILE` that
|
||||
the C library's own `getc_unlocked` reads, and it consumes exactly the characters that `getc_unlocked` would have
|
||||
returned, so the file is left where it was left before.
|
||||
|
||||
Locking the file once makes parsing from a `FILE*` 3 to 4 times as fast with the Apple C library and 1.1 to 1.3
|
||||
times as fast with glibc, whose locking is cheaper. Scanning the buffer in bulk makes `parse()` another 1.7 to 2.6
|
||||
times as fast (and `accept()` 2.9 to 4.4 times), about as fast as parsing from a `std::ifstream`. The binary
|
||||
formats ([`from_cbor`](../basic_json/from_cbor.md), [`from_msgpack`](../basic_json/from_msgpack.md), ...) read
|
||||
from a `FILE*` the same way.
|
||||
This makes parsing from a `FILE*` 3 to 4 times as fast with the Apple C library and 1.1 to 1.3 times as fast with
|
||||
glibc, whose locking is cheaper. The binary formats ([`from_cbor`](../basic_json/from_cbor.md),
|
||||
[`from_msgpack`](../basic_json/from_msgpack.md), ...) read from a `FILE*` the same way.
|
||||
|
||||
!!! note "Locking"
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ By default, `#!cpp JSON_NO_SIMD` is not defined, and vector instructions are use
|
||||
- [Parsing: input sources and performance](../../features/parsing/index.md#input-sources-and-performance) - how input
|
||||
sources affect parsing performance
|
||||
- [Serialization](../../features/serialization.md) - pretty-printing, UTF-8 handling, and number output
|
||||
- [Zero-copy JSON views](../../features/json_view/index.md) - the zero-copy view, whose parser the macro also affects
|
||||
- [Zero-copy JSON views](../../features/json_view.md) - the zero-copy view, whose parser the macro also affects
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ Copying and comparing fall back to working without the call stack there, as they
|
||||
|
||||
## See also
|
||||
|
||||
- [`JSON_RECURSION_DEPTH_LIMIT`](json_recursion_depth_limit.md) - set how many nesting levels the operations recurse into
|
||||
- [FAQ: Thread safety](../../home/faq.md#thread-safety) - thread-safety guarantees of the library
|
||||
- [Supported Macros](../../features/macros.md) - guide to all supported macros
|
||||
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
# JSON_RECURSION_DEPTH_LIMIT
|
||||
|
||||
```cpp
|
||||
#define JSON_RECURSION_DEPTH_LIMIT /* value */
|
||||
```
|
||||
|
||||
This macro sets how many nesting levels the operations that walk a value recurse into on the call stack. Beyond that,
|
||||
they continue with an explicit stack on the heap. The value is an integer constant from `0` to `254`; the default is
|
||||
`128`.
|
||||
|
||||
The operations are copying a value, comparing two values, serializing with [`dump`](../basic_json/dump.md) or
|
||||
[`operator<<`](../operator_ltlt.md), hashing with `std::hash`, [`merge_patch`](../basic_json/merge_patch.md),
|
||||
[`update`](../basic_json/update.md) with `merge_objects`, [`diff`](../basic_json/diff.md),
|
||||
[`merge_diff`](../basic_json/merge_diff.md), converting a value to another specialization of `basic_json`, destroying a
|
||||
value, and the binary writers [`to_cbor`](../basic_json/to_cbor.md),
|
||||
[`to_msgpack`](../basic_json/to_msgpack.md), [`to_ubjson`](../basic_json/to_ubjson.md),
|
||||
[`to_bjdata`](../basic_json/to_bjdata.md), and [`to_bon8`](../basic_json/to_bon8.md). They share this one limit; none
|
||||
has
|
||||
a limit of its own. Recursing is the fastest way to walk a value, but a value nested deeply enough would exhaust the
|
||||
call
|
||||
stack, so the library recurses only as far as the limit and finishes the levels below with an explicit stack. This is
|
||||
what makes all of them safe for untrusted input
|
||||
(see [Nesting depth](../../features/parsing/untrusted_input.md#nesting-depth)). Parsing, the binary readers,
|
||||
[`flatten`](../basic_json/flatten.md), [`unflatten`](../basic_json/unflatten.md), and
|
||||
[`to_bson`](../basic_json/to_bson.md) always use an explicit stack and do not depend on the macro. The lockstep
|
||||
comparison of two [`json_view`](../basic_json_view/index.md) documents has a fixed bound of its own, 48 levels,
|
||||
and does not depend on it either.
|
||||
|
||||
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the
|
||||
limit*, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build
|
||||
(see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few
|
||||
hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl
|
||||
C
|
||||
library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.
|
||||
|
||||
The macro changes only how much stack is used and how fast the operations are. It never changes a result: every
|
||||
operation returns the same value for every setting of the limit, for values nested less deeply than the limit as well as
|
||||
for values nested more deeply.
|
||||
|
||||
## Default definition
|
||||
|
||||
The default value is `128`.
|
||||
|
||||
```cpp
|
||||
#define JSON_RECURSION_DEPTH_LIMIT 128
|
||||
```
|
||||
|
||||
When the macro is not defined, the library defines it to its default value.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! note "Allowed values"
|
||||
|
||||
The value must be an integer constant expression from `0` to `254`; any other value (a negative number, a number
|
||||
above `254`, a floating-point number such as `254.0`, or `true` or `false`) is rejected at compile time with an
|
||||
error message that names the macro. A character of any character type (`'a'`, `L'a'`, `u8'a'`, ...) is rejected,
|
||||
too, although it is an integer.
|
||||
|
||||
- `0` is allowed, and means that every operation uses its explicit stack from the first level on and no operation
|
||||
recurses over the nesting of a value at all. That needs a constant amount of call stack (at most 16 KiB in the
|
||||
measurements below, for a value nested 20,000 levels deep) and is the setting for tiny stacks, at the price of
|
||||
speed (see [Speed](#speed)).
|
||||
- `254` is the largest allowed value. Copying a value and comparing two values (with `<=>`, or with the operators on
|
||||
objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the
|
||||
copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type
|
||||
`#!cpp std::uint8_t` that exists once per thread (see [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md)). Only
|
||||
the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a
|
||||
copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at
|
||||
most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be
|
||||
useful: `254` levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the
|
||||
default.)
|
||||
|
||||
### Stack needed
|
||||
|
||||
The tables show the smallest stack that an operation needs, in KiB, at several limits, on a value that is nested
|
||||
more deeply than the limit (limit + 10 levels). Each cell shows the result for Clang (Apple clang 21) and for
|
||||
GCC 16, separated by a slash; both measured on macOS with arm64, compiling in C++20 mode. The operations run in a
|
||||
thread whose stack has the size given, and are not given any stack that they do not need: the value is built, and
|
||||
the result destroyed, outside of that thread. Stacks can only be set in steps of 16 KiB (the page size), so `16`
|
||||
means "16 KiB or less". A row stands for all operations listed; the table shows the largest value among them.
|
||||
|
||||
Unoptimized (`-O0`):
|
||||
|
||||
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| `dump()` and `dump(indent)`, `operator<<` | 48 / 32 | 80 / 64 | 144 / 128 | 288 / 256 | 576 / 512 |
|
||||
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
|
||||
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
|
||||
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
|
||||
| `std::hash` | 16 / 16 | 16 / 16 | 32 / 32 | 80 / 64 | 160 / 128 |
|
||||
| `merge_patch`, `update(j, true)`, `patch` | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
|
||||
| `diff` | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 | 144 / 96 |
|
||||
| `merge_diff` | 16 / 16 | 48 / 32 | 80 / 48 | 176 / 112 | 352 / 224 |
|
||||
| `to_cbor`, `to_msgpack` | 16 / 16 | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 160 |
|
||||
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 | 176 / 112 |
|
||||
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 16 | 64 / 48 |
|
||||
| conversion to another `basic_json` type | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 144 | 448 / 304 |
|
||||
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
|
||||
|
||||
Optimized (`-O2`):
|
||||
|
||||
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| `dump()` and `dump(indent)`, `operator<<` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
|
||||
| copy construction and assignment | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 |
|
||||
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 16 |
|
||||
| `std::hash` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 48 | 80 / 80 |
|
||||
| `merge_patch`, `update(j, true)`, `patch` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 |
|
||||
| `diff` | 16 / 16 | 16 / 16 | 16 / 32 | 48 / 48 | 96 / 112 |
|
||||
| `merge_diff` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 |
|
||||
| `to_cbor`, `to_msgpack` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 |
|
||||
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 32 | 32 / 64 |
|
||||
| conversion to another `basic_json` type | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 48 | 64 / 96 |
|
||||
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
|
||||
With a limit of `0`, every operation in the tables ran in a 16 KiB stack at `-O0` (Clang and GCC), on a value nested
|
||||
20,000 levels deep. The operations that do not depend on the macro (`flatten`, `unflatten`, `to_bson`) needed
|
||||
16 KiB or less at every limit.
|
||||
|
||||
The rule of thumb is
|
||||
|
||||
> stack needed ≈ a few KiB + cost per level × limit
|
||||
|
||||
with a cost per level of up to 2.3 KiB (`dump` at `-O0` with Clang; 2.1 KiB with GCC), 1.7 KiB for copying and merging
|
||||
(1.3 KiB with GCC), and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers
|
||||
come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers,
|
||||
other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and
|
||||
sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables.
|
||||
The stack that your own code and the operating system need comes on top of these numbers.
|
||||
|
||||
Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured
|
||||
for which the slowest operation needs at most that much):
|
||||
|
||||
| Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) |
|
||||
|---|---:|---:|
|
||||
| 32 KiB | 64 | 0 |
|
||||
| 64 KiB | 128 | 16 |
|
||||
| 128 KiB (the default stack of threads on musl) | 254 | 32 |
|
||||
| 256 KiB | 254 | 64 |
|
||||
| 512 KiB | 254 | 128 |
|
||||
| 1 MiB or more | 254 | 254 |
|
||||
|
||||
### Speed
|
||||
|
||||
Operations are faster the more of a value they handle with plain recursion. The levels below the limit are handled with
|
||||
an explicit stack, which has to be kept on the heap and costs more per level. The macro therefore trades speed against
|
||||
stack.
|
||||
|
||||
The table shows the time of copying a value (including destroying the copy), of `==` on two equal values, of `dump`, and
|
||||
of `std::hash` for several limits, relative to the default of `128` (`1.00` means the same time; more is slower). It was
|
||||
measured with Clang 21 at `-O2` in C++17 mode on macOS with arm64, as the best of seven runs of each setting (two
|
||||
rounds, best of both). The documents are ordinary JSON files that are nested 7 (`canada.json`), 8
|
||||
(`citm_catalog.json`), 10 (`twitter.json`), and 2 levels deep (`jeopardy.json`); the other values are one array or object
|
||||
with one member per level, nested 1,000 and 100,000 levels deep. The absolute time at the limit `128` is given in the
|
||||
third column. Differences of up to about 0.1 are noise: a different limit changes the layout of the compiled code, and
|
||||
timings of the same binary vary by about as much. The slow columns (limits 0 and 1) vary more: repeating `std::hash` on
|
||||
`canada.json` gave 1.27 to 1.30 for limit 0 and 1.4 to 1.9 for limit 1, so read the cells of those two columns as
|
||||
accurate to about 0.3.
|
||||
|
||||
| Value | Operation | limit 128 (absolute) | limit 0 | limit 1 | limit 16 | limit 254 |
|
||||
|---|---|---:|---:|---:|---:|---:|
|
||||
| `canada.json` (2.1 MB) | copy | 3.5 ms | 1.80 | 1.80 | 0.99 | 1.00 |
|
||||
| `canada.json` (2.1 MB) | `==` | 350.5 µs | 2.36 | 2.38 | 1.00 | 0.99 |
|
||||
| `canada.json` (2.1 MB) | `dump` | 2.4 ms | 1.11 | 1.11 | 1.00 | 1.00 |
|
||||
| `canada.json` (2.1 MB) | `std::hash` | 920.2 µs | 1.33 | 1.59 | 1.00 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | copy | 1.8 ms | 1.38 | 1.36 | 1.00 | 0.99 |
|
||||
| `citm_catalog.json` (1.7 MB) | `==` | 275.5 µs | 1.31 | 1.31 | 0.99 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | `dump` | 314.6 µs | 1.24 | 1.23 | 1.00 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | `std::hash` | 309.1 µs | 1.77 | 1.42 | 1.06 | 1.05 |
|
||||
| `twitter.json` (0.6 MB) | copy | 865.7 µs | 1.45 | 1.47 | 1.01 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `==` | 135.8 µs | 1.26 | 1.23 | 1.00 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `dump` | 224.6 µs | 1.12 | 1.12 | 1.01 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `std::hash` | 132.9 µs | 1.28 | 1.27 | 1.03 | 1.04 |
|
||||
| `jeopardy.json` (53 MB) | copy | 111.1 ms | 1.22 | 1.25 | 1.00 | 1.00 |
|
||||
| `jeopardy.json` (53 MB) | `==` | 23.5 ms | 1.29 | 1.53 | 1.07 | 1.00 |
|
||||
| `jeopardy.json` (53 MB) | `dump` | 33.2 ms | 1.14 | 1.34 | 1.03 | 1.01 |
|
||||
| `jeopardy.json` (53 MB) | `std::hash` | 19.9 ms | 1.17 | 1.52 | 1.05 | 1.00 |
|
||||
| arrays, 1,000 levels | copy | 69.9 µs | 0.95 | 0.98 | 0.92 | 0.99 |
|
||||
| arrays, 1,000 levels | `==` | 10.4 µs | 1.02 | 1.01 | 0.96 | 1.00 |
|
||||
| arrays, 1,000 levels | `dump` | 9.6 µs | 0.97 | 0.96 | 0.97 | 1.06 |
|
||||
| arrays, 1,000 levels | `std::hash` | 16.9 µs | 1.00 | 1.01 | 1.01 | 0.98 |
|
||||
| objects, 1,000 levels | copy | 77.1 µs | 0.98 | 0.97 | 0.97 | 1.03 |
|
||||
| objects, 1,000 levels | `==` | 12.0 µs | 0.96 | 0.95 | 0.95 | 1.07 |
|
||||
| objects, 1,000 levels | `dump` | 12.6 µs | 0.97 | 0.95 | 0.98 | 1.01 |
|
||||
| objects, 1,000 levels | `std::hash` | 17.3 µs | 0.99 | 1.01 | 0.98 | 1.00 |
|
||||
| arrays, 100,000 levels | copy | 6.4 ms | 1.00 | 1.00 | 1.00 | 1.00 |
|
||||
| arrays, 100,000 levels | `==` | 1.1 ms | 1.01 | 1.03 | 1.00 | 1.06 |
|
||||
| arrays, 100,000 levels | `dump` | 917.9 µs | 1.01 | 1.01 | 1.02 | 1.01 |
|
||||
| arrays, 100,000 levels | `std::hash` | 1.7 ms | 1.04 | 1.05 | 0.99 | 0.99 |
|
||||
| objects, 100,000 levels | copy | 7.5 ms | 0.99 | 1.02 | 1.01 | 0.99 |
|
||||
| objects, 100,000 levels | `==` | 1.3 ms | 1.02 | 1.09 | 1.08 | 0.96 |
|
||||
| objects, 100,000 levels | `dump` | 1.2 ms | 1.06 | 0.99 | 1.01 | 0.99 |
|
||||
| objects, 100,000 levels | `std::hash` | 1.8 ms | 1.00 | 1.00 | 1.00 | 1.00 |
|
||||
|
||||
The results are as follows.
|
||||
|
||||
- A limit of `16` or more does not change the speed of ordinary documents (differences are within noise), because they
|
||||
are not nested more deeply than that anyway. A document nested more deeply than the limit is walked partly with the
|
||||
explicit stack.
|
||||
- A limit of `0` or `1` makes the operations on ordinary documents 1.1 to 2.4 times as slow, because even their first
|
||||
levels are handled with the explicit stack. The slowdown is largest for `==` on a document of many small containers
|
||||
(`canada.json`: 2.4 times) and for copying (up to 1.8 times).
|
||||
- For values that are nested far more deeply than any limit (1,000 and 100,000 levels deep), the limit makes no
|
||||
measurable difference: almost all of the levels are handled with the explicit stack for every setting.
|
||||
Raising the limit gains nothing for them, and lowering it costs nothing.
|
||||
|
||||
!!! note "Other macros"
|
||||
|
||||
- With [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md) defined (or for Clang targeting MinGW, where the library
|
||||
defines it by itself), copying and comparing never descend, so for them the limit does not matter. The other
|
||||
operations still recurse as many levels as the limit says. The range of the limit is the same.
|
||||
- The macro is not part of the [ABI tag](../../features/namespace.md), as `JSON_NO_THREAD_LOCAL` is not, and it is
|
||||
not undefined at the end of `json.hpp`.
|
||||
|
||||
!!! warning "Use the same value in every translation unit"
|
||||
|
||||
All translation units of a program that include the library must define the same value. Otherwise, the program
|
||||
violates the One Definition Rule: the function `nlohmann::detail::recursion_depth_limit()` and all the functions
|
||||
that use it are defined differently in different translation units. Which limit a call uses then depends on which
|
||||
functions the compiler inlined (an inlined copy uses the value of its own translation unit) and which out-of-line
|
||||
copy of each remaining function the linker kept, which is not specified. A function compiled with one value can
|
||||
call a function compiled with another, so a single operation can mix both limits.
|
||||
|
||||
Mixing values cannot corrupt the byte per thread that counts the levels of copying and comparing: each limit
|
||||
is at most `254`, and all of them stop counting at their own limit, so the count never exceeds `254`, whichever
|
||||
translation unit's definition runs. The counter exists once per thread and `basic_json` specialization, and is
|
||||
shared by all translation units. Nor can mixing values change any result, as no result depends on the limit. What
|
||||
changes is how much stack is used and how fast the operations are. Nevertheless, avoid it: the program has undefined
|
||||
behavior as far as the C++ standard is concerned.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: lower the limit"
|
||||
|
||||
The example nests an array 5,000 levels deep. With the limit set to 16, the library recurses over the first 16
|
||||
levels
|
||||
and over the rest uses an explicit stack. The results are those of the default limit.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_recursion_depth_limit.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_recursion_depth_limit.output"
|
||||
```
|
||||
|
||||
??? example "Example: find out how much stack an operation needs"
|
||||
|
||||
The program runs `dump()` on a value nested `depth` levels deep in a thread with a stack of `kib` KiB. Compile it
|
||||
with the options and the limit that you use, e.g. `-DJSON_RECURSION_DEPTH_LIMIT=64`, run it with `depth` set to the
|
||||
limit plus 10 and decreasing values of `kib` (the stack size must be a multiple of the page size, often 4 or 16
|
||||
KiB),
|
||||
and note the smallest stack with which it still finishes. That is how the tables above were measured.
|
||||
|
||||
```cpp
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <pthread.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
static nlohmann::json value;
|
||||
|
||||
static void* run(void*)
|
||||
{
|
||||
std::cout << "dump() ok, " << value.dump().size() << " bytes\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const int depth = std::atoi(argv[1]);
|
||||
const std::size_t kib = static_cast<std::size_t>(std::atoi(argv[2]));
|
||||
|
||||
// built on the main thread, without recursion
|
||||
value = 1;
|
||||
for (int i = 0; i < depth; ++i)
|
||||
{
|
||||
nlohmann::json outer = nlohmann::json::array();
|
||||
outer.push_back(std::move(value));
|
||||
value = std::move(outer);
|
||||
}
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, kib * 1024);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, &attr, run, nullptr);
|
||||
pthread_join(thread, nullptr);
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Nesting depth](../../features/parsing/untrusted_input.md#nesting-depth) - how the library handles deeply nested
|
||||
values
|
||||
- [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||
- [Supported Macros](../../features/macros.md) - guide to all supported macros
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -93,7 +93,7 @@ The default value is `0` (disabled, the behavior of version 3.12.0 and earlier i
|
||||
## See also
|
||||
|
||||
- [Binary formats](../../features/binary_formats/index.md) - overview of the supported binary formats
|
||||
- [`from_cbor`](../basic_json/from_cbor.md) - not affected by the macro; pass `error_handler` to validate CBOR strings
|
||||
- [`from_cbor`](../basic_json/from_cbor.md) - also affected when parsing CBOR strings
|
||||
- [`to_cbor`](../basic_json/to_cbor.md) - create a CBOR serialization of a JSON value
|
||||
- [`to_ubjson`](../basic_json/to_ubjson.md) - create a UBJSON serialization of a JSON value
|
||||
- [`to_bjdata`](../basic_json/to_bjdata.md) - create a BJData serialization of a JSON value
|
||||
|
||||
@@ -32,7 +32,7 @@ of object keys, instead of sorting them like [`json_document`](json_document.md)
|
||||
- [`ordered_json_view`](ordered_json_view.md) - a view of a value of an `ordered_json_document`
|
||||
- [`json_document`](json_document.md) - the corresponding document for the default `json` specialization
|
||||
- [Object Order](../features/object_order.md) - preserving the insertion order of object keys
|
||||
- [Zero-copy JSON views](../features/json_view/index.md) - how to parse, inspect and edit a document without building a tree
|
||||
- [Zero-copy JSON views](../features/json_view.md) - how to parse, inspect and edit a document without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ members [`set`](basic_json_document/set.md) added — instead of sorting them li
|
||||
specialization
|
||||
- [Object Order](../features/object_order.md) - preserving the insertion order of object keys
|
||||
- [Edits](basic_json_document/index.md#edits) - what an edit guarantees
|
||||
- [Zero-copy JSON views](../features/json_view/editing.md) - editing a document in place and writing it back
|
||||
- [Zero-copy JSON views](../features/json_view.md#editing-a-document) - editing a document in place and writing it back
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of an
|
||||
- [`ordered_json_editable_document`](ordered_json_editable_document.md) - the document type this view refers into
|
||||
- [`ordered_json_view`](ordered_json_view.md) - the corresponding read-only view
|
||||
- [`json_editable_view`](json_editable_view.md) - the corresponding view for `json_editable_document`
|
||||
- [Zero-copy JSON views](../features/json_view/editing.md) - editing a document in place and writing it back
|
||||
- [Zero-copy JSON views](../features/json_view.md#editing-a-document) - editing a document in place and writing it back
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ This type is a [`basic_json_view`](basic_json_view/index.md) of a value of an
|
||||
|
||||
- [`ordered_json_document`](ordered_json_document.md) - the document type this view refers into
|
||||
- [`json_view`](json_view.md) - the corresponding view for `json_document`
|
||||
- [Zero-copy JSON views](../features/json_view/index.md) - how to parse, inspect and edit a document without building a tree
|
||||
- [Zero-copy JSON views](../features/json_view.md) - how to parse, inspect and edit a document without building a tree
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ nor a [`json_editable_view`](json_editable_view.md). Views of the two modes comp
|
||||
- [basic_json_view](basic_json_view/index.md) - a handle to one value of a document
|
||||
- [json_editable_document](json_editable_document.md) - an editable document of `json`
|
||||
- [(constructor)](basic_json_view/basic_json_view.md) - the conversion from a read-only to an editable view
|
||||
- [Writing generic code](../features/json_view/generic_code.md) - functions that accept views
|
||||
- [Writing generic code](../features/json_view.md#writing-generic-code) - functions that accept views
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -53,15 +53,12 @@ flowchart LR
|
||||
only as bytes are actually read, arrays reserve at most a fixed number of elements up front, and sizes that no
|
||||
container can hold are rejected.
|
||||
- **Memory is owned by values.** Each `basic_json` value owns its content, and there is no manual memory management in
|
||||
user code. The destructor recurses only over a bounded number of nesting levels and then continues without the call
|
||||
stack, so destroying a deeply nested value does not exhaust the stack.
|
||||
user code. The destructor does not recurse, so destroying a deeply nested value does not exhaust the stack.
|
||||
- **Bounded recursion.** The JSON parser and the binary readers keep their state in explicit stacks instead of
|
||||
recursing per nesting level. Operations that walk a value, such as [`dump`](../api/basic_json/dump.md), copying,
|
||||
comparison, hashing, [`merge_patch`](../api/basic_json/merge_patch.md), [`diff`](../api/basic_json/diff.md),
|
||||
[`flatten`](../api/basic_json/flatten.md), and the binary writers, recurse only up to a fixed depth and continue with
|
||||
an explicit stack below it. The depth is 128 levels by default and can be changed with
|
||||
[`JSON_RECURSION_DEPTH_LIMIT`](../api/macros/json_recursion_depth_limit.md), for example to run on a small stack.
|
||||
Applications that process untrusted input can limit its nesting depth with a
|
||||
an explicit stack below it. Applications that process untrusted input can limit its nesting depth with a
|
||||
[parser callback](../features/parsing/parser_callbacks.md).
|
||||
- **Invariants are checked.** The class invariant (for instance, that the pointer for the stored type is never null) is
|
||||
checked with runtime assertions throughout the test suite.
|
||||
|
||||
@@ -759,14 +759,9 @@ body:has(.nj-hero) .md-content {
|
||||
}
|
||||
}
|
||||
|
||||
/* blog posts: author and date right below the title */
|
||||
.md-typeset .nj-byline { margin: -.8rem 0 1.6rem; font-size: .75rem; color: var(--md-default-fg-color--light); }
|
||||
.md-typeset .nj-byline a { color: inherit; }
|
||||
.md-typeset .nj-byline a:hover { color: var(--md-accent-fg-color); }
|
||||
|
||||
/* figure captions: "Figure N." in bold, close to the figure, set in from the text column; figures and tables are
|
||||
numbered per page, each with its own counter */
|
||||
.md-content__inner { counter-reset: nj-figure nj-table nj-listing; }
|
||||
.md-content__inner { counter-reset: nj-figure nj-table; }
|
||||
.md-typeset :is(.nj-caption, .nj-charts-caption) {
|
||||
max-width: none;
|
||||
margin: .3rem 2rem 1.5rem;
|
||||
@@ -787,25 +782,6 @@ body:has(.nj-hero) .md-content {
|
||||
.md-typeset :is(.nj-caption, .nj-charts-caption) { margin-inline: 1rem; }
|
||||
}
|
||||
|
||||
/* code captions: "Listing N." in bold, directly below the code block, in the figure caption style */
|
||||
.md-typeset .nj-code-caption {
|
||||
max-width: none;
|
||||
margin: -.4rem 2rem 1.5rem;
|
||||
font-size: .75rem;
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
color: var(--md-default-fg-color--light);
|
||||
}
|
||||
.md-typeset .nj-code-caption::before {
|
||||
counter-increment: nj-listing;
|
||||
content: "Listing " counter(nj-listing) ". ";
|
||||
font-weight: 700;
|
||||
color: var(--md-default-fg-color);
|
||||
}
|
||||
@media screen and (max-width: 44.9375em) {
|
||||
.md-typeset .nj-code-caption { margin-inline: 1rem; }
|
||||
}
|
||||
|
||||
/* table captions: "Table N." in bold, directly below the table, in the figure caption style */
|
||||
.md-typeset .nj-table-caption {
|
||||
max-width: none;
|
||||
|
||||
Loaded 100 of 262 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user