diff --git a/.clang-tidy b/.clang-tidy index 30886d7c8..4d4238a35 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -4,6 +4,7 @@ Checks: '*, -altera-unroll-loops, -android-cloexec-fopen, -bugprone-easily-swappable-parameters, + -cert-err58-cpp, -concurrency-mt-unsafe, -cppcoreguidelines-avoid-goto, -cppcoreguidelines-avoid-magic-numbers, @@ -42,6 +43,7 @@ Checks: '*, -readability-identifier-length, -readability-magic-numbers, -readability-redundant-access-specifiers, + -readability-simplify-boolean-expr, -readability-uppercase-literal-suffix' CheckOptions: diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md deleted file mode 100644 index d0fbbdda0..000000000 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: 'kind: bug' -assignees: '' - ---- - - - -#### What is the issue you have? - - - - -#### Please describe the steps to reproduce the issue. - - - - -1. -2. -3. - -#### Can you provide a small but working code example? - - - -#### What is the expected behavior? - - - -#### And what is the actual behavior instead? - - - -#### Which compiler and operating system are you using? - - - - -- Compiler: ___ -- Operating system: ___ - -#### Which version of the library did you use? - - - -- [ ] latest release version 3.10.5 -- [ ] other release - please state the version: ___ -- [ ] the `develop` branch - -#### If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)? - -- [ ] yes -- [ ] no - please copy/paste the error message below diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml new file mode 100644 index 000000000..762b08e9a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -0,0 +1,93 @@ +name: Bug Report +description: Create a bug report +labels: + - 'kind: bug' +body: + - type: markdown + attributes: + value: > + Thanks for taking the time to fill out this bug report! + + Make sure you give it a short and specific **title** so that the report + is searchable and uniquely identifiable. + + Note that this form is for bug reports only. Please + [open a discussion](https://github.com/nlohmann/json/discussions/new) + for questions, feature requests, or support requests + - type: textarea + id: summary + attributes: + label: Description + description: > + Please provide an abstract description of the issue to the developers, + and why you consider it to be a bug. Please include any specific links + to the documentation, JSON specification, or code. + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Reproduction steps + description: > + How do you trigger the bug? Please walk us through step by step. Be as + specific as possible. + validations: + required: true + - type: textarea + id: results + attributes: + label: Expected vs. actual results + description: > + Please describe what you expected to happen after the steps above and + what actually happened. + validations: + required: true + - type: textarea + id: code + attributes: + label: Minimal code example + description: > + If possible, provide a small and self-contained example that triggers + the bug. Please understand that we cannot analyze and debug large code + bases. Please do not paste screenshots here. + render: Shell + - type: textarea + id: output + attributes: + label: Error messages + description: > + Please provide any kind of error output (compilation errors, exception + messages, stack traces, etc.) which can help to diagnose the error. + render: Shell + - type: input + id: compiler + attributes: + label: Compiler and operating system + description: > + On which operating systems and compilers have you observed the issue? + Include as many relevant details about the environment you experienced + the bug in. Make sure you use a + [supported compiler](https://github.com/nlohmann/json#supported-compilers). + validations: + required: true + - type: input + id: version + attributes: + label: Library version + description: > + Which version of the library did you use? If it is a released version, + please enter the version number (e.g., 3.11.0). Otherwise, please enter + the commit hash. If you got the library from another source as the + GitHub repository (e.g., via a package manager), please also state + this. + validations: + required: true + - type: checkboxes + id: validation + attributes: + label: Validation + description: > + Please check these additional steps: + options: + - label: The bug also occurs if the latest version from the [`develop`](https://github.com/nlohmann/json/tree/develop) branch is used. + - label: I can successfully [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests). diff --git a/.drone.yml b/.github/external_ci/.drone.yml similarity index 97% rename from .drone.yml rename to .github/external_ci/.drone.yml index 3cdefe4b9..0d9e3d0be 100644 --- a/.drone.yml +++ b/.github/external_ci/.drone.yml @@ -18,5 +18,5 @@ steps: - cd build - ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON - make -j10 - - cd test + - cd tests - ../../cmake-3.20.2/bin/ctest -j10 diff --git a/appveyor.yml b/.github/external_ci/appveyor.yml similarity index 94% rename from appveyor.yml rename to .github/external_ci/appveyor.yml index b04ac24f2..0a7de686d 100644 --- a/appveyor.yml +++ b/.github/external_ci/appveyor.yml @@ -66,15 +66,15 @@ before_build: - cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%" build_script: - - cmake --build . --config "%configuration%" + - cmake --build . --config "%configuration%" --parallel 2 test_script: - - if "%configuration%"=="Release" ctest -C "%configuration%" -V -j + - if "%configuration%"=="Release" ctest -C "%configuration%" --parallel 2 --output-on-failure # On Debug builds, skip test-unicode_all # as it is extremely slow to run and cause # occasional timeouts on AppVeyor. # More info: https://github.com/nlohmann/json/pull/1570 - - if "%configuration%"=="Debug" ctest --exclude-regex "test-unicode" -C "%configuration%" -V -j + - if "%configuration%"=="Debug" ctest --exclude-regex "test-unicode" -C "%configuration%" --parallel 2 --output-on-failure # only build PRs and commits to develop branch # (see https://help.appveyor.com/discussions/questions/55079-two-builds-per-commit-to-pull-request) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 20275feac..1ba938cd6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,6 +9,11 @@ on: pull_request: schedule: - cron: '0 19 * * 1' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: CodeQL-Build: @@ -17,10 +22,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. + # a pull request then we can check out the head. fetch-depth: 2 # If this run was triggered by a pull request event, then checkout @@ -30,7 +35,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -38,7 +43,7 @@ jobs: # 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@v1 + uses: github/codeql-action/autobuild@v2 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -52,4 +57,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f653e2b6b..85b1b7052 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -7,9 +7,14 @@ on: - master - release/* pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: - xcode: + xcode_1: runs-on: macos-10.15 strategy: matrix: @@ -18,7 +23,24 @@ jobs: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON + - name: build + run: cmake --build build --parallel 10 + - name: test + run: cd build ; ctest -j 10 --output-on-failure + + xcode_2: + runs-on: macos-12 + strategy: + matrix: + xcode: [13.3.1, 13.3, 13.2.1, 13.2, 13.1] + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer + + steps: + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON - name: build @@ -27,7 +49,7 @@ jobs: run: cd build ; ctest -j 10 --output-on-failure xcode_standards: - runs-on: macos-10.15 + runs-on: macos-latest strategy: matrix: standard: [11, 14, 17, 20] @@ -35,9 +57,9 @@ jobs: DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake - run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=${{ matrix.standard }} -DCMAKE_CXX_STANDARD_REQUIRED=ON + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_TestStandards=${{ matrix.standard }} - name: build run: cmake --build build --parallel 10 - name: test diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index eb544007e..1b477c9e5 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -7,13 +7,18 @@ on: - master - release/* pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: ci_test_clang: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -21,9 +26,9 @@ jobs: ci_test_gcc: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -31,25 +36,35 @@ jobs: ci_static_analysis: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: target: [ci_clang_tidy, ci_cppcheck, ci_test_valgrind, ci_test_clang_sanitizer, ci_test_amalgamation, ci_clang_analyze, ci_cpplint, ci_cmake_flags, ci_single_binaries, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_infer] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build run: cmake --build build --target ${{ matrix.target }} + ci_test_single_header: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -DJSON_CI=On + - name: build + run: cmake --build build --target ci_test_single_header + ci_cmake_options: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: - target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions] + target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -57,15 +72,15 @@ jobs: ci_test_coverage: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build run: cmake --build build --target ci_test_coverage - name: archive coverage report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: code-coverage-report path: /__w/json/json/build/html @@ -77,12 +92,12 @@ jobs: ci_test_compilers: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: - compiler: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12, clang++-13] + compiler: [g++-4.8, g++-4.9, g++-5, g++-6, g++-7, g++-8, g++-9, g++-10, g++-11, clang++-3.5, clang++-3.6, clang++-3.7, clang++-3.8, clang++-3.9, clang++-4.0, clang++-5.0, clang++-6.0, clang++-7, clang++-8, clang++-9, clang++-10, clang++-11, clang++-12, clang++-13, clang++-14] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -90,19 +105,29 @@ jobs: ci_test_standards: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.4.0 strategy: matrix: standard: [11, 14, 17, 20] compiler: [gcc, clang] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build run: cmake --build build --target ci_test_${{ matrix.compiler }}_cxx${{ matrix.standard }} ci_cuda_example: + runs-on: ubuntu-latest + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -DJSON_CI=On + - name: build + run: cmake --build build --target ci_cuda_example + + ci_icpc: runs-on: ubuntu-latest container: ghcr.io/nlohmann/json-ci:v2.2.0 steps: @@ -110,4 +135,24 @@ jobs: - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build - run: cmake --build build --target ci_cuda_example + run: | + . /opt/intel/oneapi/setvars.sh + cmake --build build --target ci_icpc + ci_reuse_compliance: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - name: install REUSE tool + run: python -m pip install reuse + - name: REUSE lint + run: reuse lint + + ci_test_documentation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -DJSON_CI=On + - name: build + run: cmake --build build --target ci_test_documentation diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 597da4774..0fd723c84 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -7,6 +7,11 @@ on: - master - release/* pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true jobs: mingw: @@ -16,11 +21,32 @@ jobs: architecture: [x64, x86] steps: - - uses: actions/checkout@v2 - - name: Set up MinGW - uses: egor-tensin/setup-mingw@v2 - with: - platform: ${{ matrix.architecture }} + - uses: actions/checkout@v3 + - name: Download MinGW 8.1.0 + run: | + $headers = @{Authorization = 'Bearer ${{ secrets.GITHUB_TOKEN }}'} + $uri = 'https://nuget.pkg.github.com/falbrechtskirchinger/download/mingw/8.1.0/mingw.8.1.0.nupkg' + Invoke-WebRequest -Uri $uri -Headers $headers -OutFile mingw.8.1.0.nupkg + - name: Uninstall MinGW + continue-on-error: true + run: choco uninstall mingw + # Based on egor-tensin/setup-mingw + - name: Install MinGW 8.1.0 + run: | + choco install mingw.8.1.0.nupkg ${{ matrix.architecture == 'x86' && '--x86' || '' }} + $prefix = "${{ matrix.architecture == 'x64' && 'x86_64-w64-mingw32' || 'i686-w64-mingw32' }}" + $mingw = "${{ matrix.architecture == 'x64' && 'mingw64' || 'mingw32' }}" + $mingw_install = Join-Path C: ProgramData chocolatey lib mingw tools install + $mingw_root = Join-Path $mingw_install $mingw + $mingw_bin = Join-Path $mingw_root bin + $mingw_lib = Join-Path $mingw_root $prefix lib + echo $mingw_bin >> $env:GITHUB_PATH + Remove-Item (Join-Path $mingw_lib 'libpthread.dll.a') + Remove-Item (Join-Path $mingw_lib 'libwinpthread.dll.a') + #- name: Set up MinGW + # uses: egor-tensin/setup-mingw@v2 + # with: + # platform: ${{ matrix.architecture }} - name: cmake run: cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On - name: build @@ -28,50 +54,15 @@ jobs: - name: test run: cd build ; ctest -j 10 -C Debug --output-on-failure - msvc2017: - runs-on: windows-2016 - strategy: - matrix: - build_type: [Debug, Release] - architecture: [Win32, x64] - - steps: - - uses: actions/checkout@v2 - - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" - if: matrix.build_type == 'Release' && matrix.architecture == 'x64' - - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" - if: matrix.build_type == 'Release' && matrix.architecture != 'x64' - - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX" - if: matrix.build_type == 'Debug' - - name: build - run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure - - msvc2017_latest: - runs-on: windows-2016 - - steps: - - uses: actions/checkout@v2 - - name: cmake - run: cmake -S . -B build -G "Visual Studio 15 2017" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" - - name: build - run: cmake --build build --config Release --parallel 10 - - name: test - run: cd build ; ctest -j 10 -C Release --output-on-failure - msvc2019: - runs-on: windows-latest + runs-on: windows-2019 strategy: matrix: build_type: [Debug, Release] architecture: [Win32, x64] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" if: matrix.build_type == 'Release' @@ -84,10 +75,10 @@ jobs: run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure msvc2019_latest: - runs-on: windows-latest + runs-on: windows-2019 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" - name: build @@ -95,14 +86,46 @@ jobs: - name: test run: cd build ; ctest -j 10 -C Release --output-on-failure + msvc2022: + runs-on: windows-2022 + strategy: + matrix: + build_type: [Debug, Release] + architecture: [Win32, x64] + + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX" + if: matrix.build_type == 'Release' + - name: cmake + run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX" + if: matrix.build_type == 'Debug' + - name: build + run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure + + msvc2022_latest: + runs-on: windows-2022 + + steps: + - uses: actions/checkout@v3 + - name: cmake + run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" + - name: build + run: cmake --build build --config Release --parallel 10 + - name: test + run: cd build ; ctest -j 10 -C Release --output-on-failure + clang: - runs-on: windows-latest + runs-on: windows-2019 strategy: matrix: version: [11, 12] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install Clang run: curl -fsSL -o LLVM${{ matrix.version }}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.version }}.0.0/LLVM-${{ matrix.version }}.0.0-win64.exe ; 7z x LLVM${{ matrix.version }}.exe -y -o"C:/Program Files/LLVM" - name: cmake @@ -113,13 +136,13 @@ jobs: run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure clang-cl-11: - runs-on: windows-latest + runs-on: windows-2019 strategy: matrix: architecture: [Win32, x64] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On - name: build diff --git a/.gitignore b/.gitignore index a13ad89a5..30b62bfcf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,41 @@ -json_unit -json_benchmarks -json_benchmarks_simple -fuzz-testing - *.dSYM *.o *.gcno *.gcda - -build -build_coverage -clang_analyze_build - -benchmarks/files/numbers/*.json +.DS_Store .wsjcpp-logs/* .wsjcpp/* -.idea +/.idea /cmake-build-* -test/test-* -/.vs +# Visual Studio / Visual Studio Code +/.vs/ +/.vscode/ +/out/ -doc/html -doc/mkdocs/venv/ -doc/mkdocs/docs/examples -doc/mkdocs/site -doc/mkdocs/docs/__pycache__/ -/doc/docset/JSON_for_Modern_C++.docset/ -/doc/docset/JSON_for_Modern_C++.tgz +# clangd cache +/.cache/ + +# build directories (vscode-cmake-tools, user-defined, ...) +/build*/ + +# fuzzers +/tests/corpus_* +/tests/parse_*_fuzzer + +# documentation +/docs/docset/docSet.dsidx +/docs/docset/JSON_for_Modern_C++.docset/ +/docs/docset/JSON_for_Modern_C++.tgz +/docs/mkdocs/docs/__pycache__/ +/docs/mkdocs/docs/examples/ +/docs/mkdocs/docs/images/json.gif +/docs/mkdocs/site/ +/docs/mkdocs/venv/ + +# serve_header +/localhost.pem +/localhost-key.pem +/serve_header.yml diff --git a/.reuse/README.md b/.reuse/README.md new file mode 100644 index 000000000..29c2b67a1 --- /dev/null +++ b/.reuse/README.md @@ -0,0 +1,7 @@ +# REUSE Software + +This directory contains supporting files to make the project compliant with the REUSE specification. + +The root `Makefile` contains a target `reuse` that updates copyright headers and checks for compliance. + +See for more information. diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 000000000..610b8764b --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,36 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: json +Upstream-Contact: Niels Lohmann +Source: https://github.com/nlohmann/json + +Files: * +Copyright: 2013-2022 Niels Lohmann +License: MIT + +Files: tests/thirdparty/doctest/* +Copyright: 2016-2021 Viktor Kirilov +License: MIT + +Files: tests/thirdparty/fifo_map/* +Copyright: 2015-2017 Niels Lohmann +License: MIT + +Files: tests/thirdparty/Fuzzer/* +Copyright: 2003-2022, LLVM Project. +License: Apache-2.0 + +Files: tests/thirdparty/imapdl/* +Copyright: 2017 Georg Sauthoff +License: GPL-3.0-only + +Files: tools/amalgamate/* +Copyright: 2012 Erik Edlund +License: BSD-3-Clause + +Files: tools/cpplint/* +Copyright: 2009 Google Inc. All rights reserved. +License: BSD-3-Clause + +Files: tools/gdb_pretty_printer +Copyright: 2020 Hannes Domani +License: MIT diff --git a/.reuse/templates/json.jinja2 b/.reuse/templates/json.jinja2 new file mode 100644 index 000000000..4e85ec224 --- /dev/null +++ b/.reuse/templates/json.jinja2 @@ -0,0 +1,11 @@ + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.11.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +{% for copyright_line in copyright_lines %} +{{ copyright_line }} +{% endfor %} +{% for expression in spdx_expressions %} +SPDX-License-Identifier: {{ expression }} +{% endfor %} diff --git a/.reuse/templates/json_support.jinja2 b/.reuse/templates/json_support.jinja2 new file mode 100644 index 000000000..3df94354e --- /dev/null +++ b/.reuse/templates/json_support.jinja2 @@ -0,0 +1,11 @@ + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ (supporting code) +| | |__ | | | | | | version 3.11.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +{% for copyright_line in copyright_lines %} +{{ copyright_line }} +{% endfor %} +{% for expression in spdx_expressions %} +SPDX-License-Identifier: {{ expression }} +{% endfor %} diff --git a/CITATION.cff b/CITATION.cff index 7c28d04fd..7f3cff5d5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,14 +1,14 @@ -cff-version: 1.1.0 +cff-version: 1.2.0 message: "If you use this software, please cite it as below." -authors: +authors: - family-names: Lohmann given-names: Niels orcid: https://orcid.org/0000-0001-9037-795X email: mail@nlohmann.me website: https://nlohmann.me title: "JSON for Modern C++" -version: 3.10.5 -date-released: 2022 +version: 3.11.0 +date-released: 2022-01-03 license: MIT repository-code: "https://github.com/nlohmann" url: https://json.nlohmann.me diff --git a/CMakeLists.txt b/CMakeLists.txt index b93c6e47f..1945b2cd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1) ## PROJECT ## name and version ## -project(nlohmann_json VERSION 3.10.5 LANGUAGES CXX) +project(nlohmann_json VERSION 3.11.0 LANGUAGES CXX) ## ## MAIN_PROJECT CHECK @@ -19,6 +19,7 @@ endif() ## INCLUDE ## ## +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) include(ExternalProject) ## @@ -30,16 +31,25 @@ if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif () -option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${MAIN_PROJECT}) -option(JSON_CI "Enable CI build targets." OFF) -option(JSON_Diagnostics "Use extended diagnostic messages." OFF) -option(JSON_ImplicitConversions "Enable implicit conversions." ON) -option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT}) -option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) -option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) +# VERSION_GREATER_EQUAL is not available in CMake 3.1 +if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)) + set(JSON_BuildTests_INIT ON) +else() + set(JSON_BuildTests_INIT OFF) +endif() +option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${JSON_BuildTests_INIT}) +option(JSON_CI "Enable CI build targets." OFF) +option(JSON_Diagnostics "Use extended diagnostic messages." OFF) +option(JSON_GlobalUDLs "Place use-defined string literals in the global namespace." ON) +option(JSON_ImplicitConversions "Enable implicit conversions." ON) +option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF) +option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF) +option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT}) +option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON) +option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) if (JSON_CI) - include(cmake/ci.cmake) + include(ci) endif () ## @@ -48,7 +58,7 @@ endif () include(GNUInstallDirs) set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME}) -set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "") +set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "") set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in") @@ -56,7 +66,7 @@ set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}") set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake") set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake") set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake") -set(NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +set(NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/pkgconfig") if (JSON_MultipleHeaders) set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/") @@ -70,6 +80,14 @@ if (NOT JSON_ImplicitConversions) message(STATUS "Implicit conversions are disabled") endif() +if (JSON_DisableEnumSerialization) + message(STATUS "Enum integer serialization is disabled") +endif() + +if (JSON_LegacyDiscardedValueComparison) + message(STATUS "Legacy discarded value comparison enabled") +endif() + if (JSON_Diagnostics) message(STATUS "Diagnostics enabled") endif() @@ -93,8 +111,11 @@ endif() target_compile_definitions( ${NLOHMANN_JSON_TARGET_NAME} INTERFACE - JSON_USE_IMPLICIT_CONVERSIONS=$ - JSON_DIAGNOSTICS=$ + $<$>:JSON_USE_GLOBAL_UDLS=0> + $<$>:JSON_USE_IMPLICIT_CONVERSIONS=0> + $<$:JSON_DISABLE_ENUM_SERIALIZATION=1> + $<$:JSON_DIAGNOSTICS=1> + $<$:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1> ) target_include_directories( @@ -129,7 +150,7 @@ CONFIGURE_FILE( if (JSON_BuildTests) include(CTest) enable_testing() - add_subdirectory(test) + add_subdirectory(tests) endif() ## diff --git a/ChangeLog.md b/ChangeLog.md index 9a92b9f1f..1d7f8cabd 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,9 +1,228 @@ # Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [3.10.5](https://github.com/nlohmann/json/releases/tag/3.10.5) (2022-01-02) +## [3.11.0](https://github.com/nlohmann/json/releases/tag/3.11.0) (2022-07-31) -[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.4...3.10.5) +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.5...3.11.0) + +- ICPC: warning \#1098: the qualifier on this friend declaration is ignored [\#3632](https://github.com/nlohmann/json/issues/3632) +- Starting with 3.10.4, just adding `\#include json.hpp` causes compile error: `overload resolution selected deleted operator '=' [\#3620](https://github.com/nlohmann/json/issues/3620) +- xwidgets doesn't compile with version \>3.10.3 [\#3602](https://github.com/nlohmann/json/issues/3602) +- json\_pointer\_\_pop\_back.cpp example does not compile [\#3600](https://github.com/nlohmann/json/issues/3600) +- nlohmann::json::array 'push\_back' is ambiguous [\#3589](https://github.com/nlohmann/json/issues/3589) +- Multiple versions causing conflict [\#3588](https://github.com/nlohmann/json/issues/3588) +- ERROR: ThreadSanitizer: SEGV on unknown address [\#3584](https://github.com/nlohmann/json/issues/3584) +- unicode4 test consistently fails on RISC-V hardware [\#3579](https://github.com/nlohmann/json/issues/3579) +- sax\_parse\(iterator, json\_sax\_t \*\) string callback clobbers spaces [\#3574](https://github.com/nlohmann/json/issues/3574) +- Nlohmann JSON Parse crash with raylib-cpp [\#3570](https://github.com/nlohmann/json/issues/3570) +- ordered\_json doesn't accept keys of types other than string\_t \(e.g., string\_view\) [\#3558](https://github.com/nlohmann/json/issues/3558) +- turning an object into an array [\#3547](https://github.com/nlohmann/json/issues/3547) +- json:parse\_bjdata\_fuzzer: ASSERT: ref\_stack.back\(\)-\>is\_array\(\) [\#3541](https://github.com/nlohmann/json/issues/3541) +- Warning about potential null dereference in GCC 12.1 \(Fedora 36\) [\#3525](https://github.com/nlohmann/json/issues/3525) +- Enable 32bit unit test in CI [\#3524](https://github.com/nlohmann/json/issues/3524) +- Error when roundtripping BJData [\#3519](https://github.com/nlohmann/json/issues/3519) +- ASSERT error while parsing BJData [\#3513](https://github.com/nlohmann/json/issues/3513) +- An exception occurred when sending a string with double quotes [\#3504](https://github.com/nlohmann/json/issues/3504) +- Binary reader for BJData creates incorrect SAX events [\#3503](https://github.com/nlohmann/json/issues/3503) +- It can't support "nan", "inf", "-inf" for float type [\#3494](https://github.com/nlohmann/json/issues/3494) +- ASAN error while parsing BJData \(Heap-buffer-overflow READ 1\) [\#3492](https://github.com/nlohmann/json/issues/3492) +- UBSAN error while parsing BJData \(Null-dereference\) [\#3491](https://github.com/nlohmann/json/issues/3491) +- UBSAN error while parsing BJData \(Invalid-bool-value\) [\#3490](https://github.com/nlohmann/json/issues/3490) +- json:parse\_bjdata\_fuzzer reaches assertion [\#3475](https://github.com/nlohmann/json/issues/3475) +- Compilation with -fmodules-ts and use inside of a module [\#3472](https://github.com/nlohmann/json/issues/3472) +- json.exception.parse\_error.101 only occurs outside of IDE [\#3467](https://github.com/nlohmann/json/issues/3467) +- json:parse\_bjdata\_fuzzer reaches assertion [\#3461](https://github.com/nlohmann/json/issues/3461) +- NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE\_WITH\_DEFAULT can not parse { "key" : null} [\#3458](https://github.com/nlohmann/json/issues/3458) +- Unable to compile when using Microsoft's \_CRTDBG [\#3457](https://github.com/nlohmann/json/issues/3457) +- Compilation errors when including `` and using `--std=c++17` or above \(MinGW/Win10\) [\#3449](https://github.com/nlohmann/json/issues/3449) +- Weird things on for statement [\#3447](https://github.com/nlohmann/json/issues/3447) +- Parsing error when there is a json string within a Json [\#3445](https://github.com/nlohmann/json/issues/3445) +- ordered\_json vs json types comparison [\#3443](https://github.com/nlohmann/json/issues/3443) +- Error occurred when converting nlohmann::json to std::any [\#3428](https://github.com/nlohmann/json/issues/3428) +- I was forced to report an assertion error when copying an array of strings [\#3419](https://github.com/nlohmann/json/issues/3419) +- About Serialization Error invalid UTF-8 byte at index [\#3414](https://github.com/nlohmann/json/issues/3414) +- Comparison of NaN differs between json and float [\#3409](https://github.com/nlohmann/json/issues/3409) +- when i use it in C++ sserver,it it constantly show that fatal error: adl\_serializer.hpp: No such file or directory [\#3404](https://github.com/nlohmann/json/issues/3404) +- parse error [\#3403](https://github.com/nlohmann/json/issues/3403) +- CMake script MAIN\_PROJECT always OFF [\#3390](https://github.com/nlohmann/json/issues/3390) +- Parser unable to handle large floating point numbers [\#3389](https://github.com/nlohmann/json/issues/3389) +- Compilation error if json\_pointer is used with alternative string type [\#3388](https://github.com/nlohmann/json/issues/3388) +- Unit tests conversions & items fail to build \(Clang \<4.0/C++14 only\) [\#3384](https://github.com/nlohmann/json/issues/3384) +- Regression test for \#3070 is not being run and fails when enabled [\#3377](https://github.com/nlohmann/json/issues/3377) +- Refactor unit tests to use more convenient doctest assertion macros [\#3365](https://github.com/nlohmann/json/issues/3365) +- An json.h issue reported in a static code analyzer [\#3361](https://github.com/nlohmann/json/issues/3361) +- Mixing different JSON\_DIAGNOSTICS settings in separately compiled units leads to core [\#3360](https://github.com/nlohmann/json/issues/3360) +- json::out\_of\_range exception matches against lot of others while testing [\#3352](https://github.com/nlohmann/json/issues/3352) +- use mipsel-openwrt-linux-g++ -std=c++11 to compile, it has some errors "error: 'snprintf' is not a member of 'std'" [\#3349](https://github.com/nlohmann/json/issues/3349) +- Add proper issue templates [\#3348](https://github.com/nlohmann/json/issues/3348) +- switch from json to ordered\_json [\#3343](https://github.com/nlohmann/json/issues/3343) +- Json dump use to compilation errors [\#3339](https://github.com/nlohmann/json/issues/3339) +- Ambiguous conversion from nlohmann::basic\_json\<\> to custom class. [\#3333](https://github.com/nlohmann/json/issues/3333) +- Iterator doesn't satisfy std::incrementable because post-increment may change constness [\#3331](https://github.com/nlohmann/json/issues/3331) +- Inconsistent handling of floating point numbers after parse\(\) [\#3329](https://github.com/nlohmann/json/issues/3329) +- Documentation for `ordered_json` should show proper use of the `parse()` function. [\#3325](https://github.com/nlohmann/json/issues/3325) +- "type must be boolean, but is object" error thrown on non-boolean object [\#3319](https://github.com/nlohmann/json/issues/3319) +- Incomplete Type in request parms [\#3318](https://github.com/nlohmann/json/issues/3318) +- 小įąŗ MIX4 MIUI13 bug [\#3316](https://github.com/nlohmann/json/issues/3316) +- json.exception.parse\_error.101 when parsing data received over a socket [\#3313](https://github.com/nlohmann/json/issues/3313) +- Parse to custom class from unordered\_json breaks on G++11.2.0 with C++20 [\#3312](https://github.com/nlohmann/json/issues/3312) +- try to assign dumped string to a class member varible [\#3300](https://github.com/nlohmann/json/issues/3300) +- includedir in pkgconfig is error if install\_headers\(\) has subdir argument. [\#3284](https://github.com/nlohmann/json/issues/3284) +- SHA-256 sum of json-3.10.5.tar.xz changes over time \(but not the content itself\) [\#3281](https://github.com/nlohmann/json/issues/3281) +- items\(\) method does not follow order of json message [\#3278](https://github.com/nlohmann/json/issues/3278) +- Perplexing template deduction failure serialising a 3rd party type using base class [\#3267](https://github.com/nlohmann/json/issues/3267) +- json.hpp 'isfinite' is not a member of 'std' also isinf; snprintf; stoull and to\_string members of std [\#3263](https://github.com/nlohmann/json/issues/3263) +- JSON build fails for C++ cmake [\#3256](https://github.com/nlohmann/json/issues/3256) +- Unexpected implicit conversion [\#3254](https://github.com/nlohmann/json/issues/3254) +- Add a function that checks for valid json in a C++ string [\#3245](https://github.com/nlohmann/json/issues/3245) +- Replace use of standard IO from error handling [\#3239](https://github.com/nlohmann/json/issues/3239) +- Use Catch for unit tests [\#3232](https://github.com/nlohmann/json/issues/3232) +- Exception thrown during initialization causes a memory leak [\#3215](https://github.com/nlohmann/json/issues/3215) +- Tests failing when compiling with c++20 [\#3207](https://github.com/nlohmann/json/issues/3207) +- ambiguous regression [\#3204](https://github.com/nlohmann/json/issues/3204) +- Deserialization: if class is\_constructible from std::string wrong from\_json overload is being selected, compilation failed [\#3171](https://github.com/nlohmann/json/issues/3171) +- 'clang++ ./json.hpp' with no usage: Compiler syntax problem in clang 3.7.0 \(tizen :/ \) [\#3153](https://github.com/nlohmann/json/issues/3153) +- build failure on upcoming gcc-12: test/src/unit-regression1.cpp:392:22: error: ambiguous overload for 'operator=' [\#3138](https://github.com/nlohmann/json/issues/3138) +- Applying JSON patch creates parent object [\#3134](https://github.com/nlohmann/json/issues/3134) +- Iterators cannot be used with range-v3 [\#3130](https://github.com/nlohmann/json/issues/3130) +- std::shared\_ptr\ == nlohmann::json compiles, which seem undesirable [\#3026](https://github.com/nlohmann/json/issues/3026) +- Error in test\download\_test\_data.vcxproj custom build step when compiling with Visual Studio 2019 16.7.7 msbuild on Windows 10 [\#2593](https://github.com/nlohmann/json/issues/2593) +- Consider putting the user-defined literals in a namespace [\#1682](https://github.com/nlohmann/json/issues/1682) +- Using versioned namespaces [\#1539](https://github.com/nlohmann/json/issues/1539) +- How can I use std::string\_view as the json\_key to "operator \[\]" ? [\#1529](https://github.com/nlohmann/json/issues/1529) +- serialize std::variant\<...\> [\#1261](https://github.com/nlohmann/json/issues/1261) + +- Prepare 3.11.0 release [\#3635](https://github.com/nlohmann/json/pull/3635) ([nlohmann](https://github.com/nlohmann)) +- Fix warning [\#3634](https://github.com/nlohmann/json/pull/3634) ([nlohmann](https://github.com/nlohmann)) +- Add license header to new files [\#3633](https://github.com/nlohmann/json/pull/3633) ([nlohmann](https://github.com/nlohmann)) +- Add a unit test including windows.h [\#3631](https://github.com/nlohmann/json/pull/3631) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fixed latest build error in msvc platform [\#3630](https://github.com/nlohmann/json/pull/3630) ([KsaNL](https://github.com/KsaNL)) +- Add regression tests for \#3204 and \#3333 [\#3629](https://github.com/nlohmann/json/pull/3629) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix patch::add creating nonexistent parents [\#3628](https://github.com/nlohmann/json/pull/3628) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Adjust JSON Pointer examples [\#3622](https://github.com/nlohmann/json/pull/3622) ([nlohmann](https://github.com/nlohmann)) +- Disable exceptions on ICPC [\#3621](https://github.com/nlohmann/json/pull/3621) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- build: install .pc and .cmake files to share/ [\#3619](https://github.com/nlohmann/json/pull/3619) ([Tachi107](https://github.com/Tachi107)) +- Fix MinGW CI failures [\#3618](https://github.com/nlohmann/json/pull/3618) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix Unicode test timeout \(for real this time!\) [\#3614](https://github.com/nlohmann/json/pull/3614) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Use 'concurrency' in GitHub workflows [\#3610](https://github.com/nlohmann/json/pull/3610) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Use swap\(\) by ADL [\#3609](https://github.com/nlohmann/json/pull/3609) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Move UDLs out of the global namespace [\#3605](https://github.com/nlohmann/json/pull/3605) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Re-add value\_type detection to distinguish string types [\#3604](https://github.com/nlohmann/json/pull/3604) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add operator\<\<\(json\_pointer\) [\#3601](https://github.com/nlohmann/json/pull/3601) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add documentation for comparing json and ordered\_json [\#3599](https://github.com/nlohmann/json/pull/3599) ([nlohmann](https://github.com/nlohmann)) +- Clean up after \#3581 [\#3596](https://github.com/nlohmann/json/pull/3596) ([nlohmann](https://github.com/nlohmann)) +- Add assertion if nullptr is passed to parse function [\#3593](https://github.com/nlohmann/json/pull/3593) ([nlohmann](https://github.com/nlohmann)) +- Minor documentation fixes [\#3592](https://github.com/nlohmann/json/pull/3592) ([nlohmann](https://github.com/nlohmann)) +- Add versioned, ABI-tagged inline namespace and namespace macros [\#3590](https://github.com/nlohmann/json/pull/3590) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add badge for https://repology.org/project/nlohmann-json/versions [\#3586](https://github.com/nlohmann/json/pull/3586) ([nlohmann](https://github.com/nlohmann)) +- Add error message if test suite cannot be found [\#3585](https://github.com/nlohmann/json/pull/3585) ([nlohmann](https://github.com/nlohmann)) +- add patch\_inplace function [\#3581](https://github.com/nlohmann/json/pull/3581) ([wolfv](https://github.com/wolfv)) +- Enable overriding test properties and set Unicode test timeouts [\#3580](https://github.com/nlohmann/json/pull/3580) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Ignore output directory [\#3572](https://github.com/nlohmann/json/pull/3572) ([NN---](https://github.com/NN---)) +- Optimize output vector adapter write [\#3569](https://github.com/nlohmann/json/pull/3569) ([romainreignier](https://github.com/romainreignier)) +- Add overloads for more key types to ordered\_map and fix ordered\_map::erase\(first, last\) with first == last [\#3564](https://github.com/nlohmann/json/pull/3564) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Make certain usage patterns more prominent in the README [\#3557](https://github.com/nlohmann/json/pull/3557) ([jez](https://github.com/jez)) +- CI: fix "JSON\_MultipleHeaders" option spelling [\#3555](https://github.com/nlohmann/json/pull/3555) ([karzhenkov](https://github.com/karzhenkov)) +- More documentation updates for 3.11.0 [\#3553](https://github.com/nlohmann/json/pull/3553) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Use DOCTEST\_\* compiler macros and suppress pragmas warning [\#3550](https://github.com/nlohmann/json/pull/3550) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add unit test to make sure iterator\_input\_adapter advances iterators correctly [\#3548](https://github.com/nlohmann/json/pull/3548) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Use REUSE framework [\#3546](https://github.com/nlohmann/json/pull/3546) ([nlohmann](https://github.com/nlohmann)) +- Use `std::iterator_traits` to extract `iterator_category` [\#3544](https://github.com/nlohmann/json/pull/3544) ([Mike-Leo-Smith](https://github.com/Mike-Leo-Smith)) +- BJData dimension length can not be string\_t::npos, fix \#3541 [\#3543](https://github.com/nlohmann/json/pull/3543) ([fangq](https://github.com/fangq)) +- Allow disabling default enum conversions [\#3536](https://github.com/nlohmann/json/pull/3536) ([zxey](https://github.com/zxey)) +- Add to\_json\(\) for std::vector\::reference [\#3534](https://github.com/nlohmann/json/pull/3534) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- CI: Enable 32bit unit test \(3\) [\#3532](https://github.com/nlohmann/json/pull/3532) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Use new CI image [\#3528](https://github.com/nlohmann/json/pull/3528) ([nlohmann](https://github.com/nlohmann)) +- Fix ndarray dimension signedness, fix ndarray length overflow \(2\); add 32bit unit test [\#3523](https://github.com/nlohmann/json/pull/3523) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Small documentation fixes [\#3520](https://github.com/nlohmann/json/pull/3520) ([nlohmann](https://github.com/nlohmann)) +- Add assertion to converting constructor [\#3517](https://github.com/nlohmann/json/pull/3517) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- CI: Remove -Wstrict-overflow [\#3516](https://github.com/nlohmann/json/pull/3516) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix nlohmann/json\#3513, explain is\_ndarray flag [\#3514](https://github.com/nlohmann/json/pull/3514) ([fangq](https://github.com/fangq)) +- Prevent ndarray size vector from recursive use, fix nlohmann/json\#3503 [\#3505](https://github.com/nlohmann/json/pull/3505) ([fangq](https://github.com/fangq)) +- prevent ndarray dimension vector from recusive array, nlohmann/json\#3500 [\#3502](https://github.com/nlohmann/json/pull/3502) ([fangq](https://github.com/fangq)) +- Discard optimized containers with negative counts in UBJSON/BJData \(\#3491,\#3492,\#3490\) [\#3500](https://github.com/nlohmann/json/pull/3500) ([fangq](https://github.com/fangq)) +- Update json.hpp [\#3499](https://github.com/nlohmann/json/pull/3499) ([ivanovmp](https://github.com/ivanovmp)) +- Add assertion for invariant in SAX-DOM parser [\#3498](https://github.com/nlohmann/json/pull/3498) ([nlohmann](https://github.com/nlohmann)) +- Add more macOS builders [\#3485](https://github.com/nlohmann/json/pull/3485) ([nlohmann](https://github.com/nlohmann)) +- change bjdata ndarray flag to detect negative size, as part of \#3475 [\#3479](https://github.com/nlohmann/json/pull/3479) ([fangq](https://github.com/fangq)) +- Document fuzzer usage [\#3478](https://github.com/nlohmann/json/pull/3478) ([nlohmann](https://github.com/nlohmann)) +- Add build step for ICPC \(with fixes\) [\#3465](https://github.com/nlohmann/json/pull/3465) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Complete documentation for 3.11.0 [\#3464](https://github.com/nlohmann/json/pull/3464) ([nlohmann](https://github.com/nlohmann)) +- Handle invalid BJData optimized type, fix \#3461 [\#3463](https://github.com/nlohmann/json/pull/3463) ([fangq](https://github.com/fangq)) +- Reorganize directories [\#3462](https://github.com/nlohmann/json/pull/3462) ([nlohmann](https://github.com/nlohmann)) +- Enable rapid testing and development on Compiler Explorer [\#3456](https://github.com/nlohmann/json/pull/3456) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- cpplint 1.6.0 [\#3454](https://github.com/nlohmann/json/pull/3454) ([nlohmann](https://github.com/nlohmann)) +- Disable regression test for \#3070 on GCC \<8.4 [\#3451](https://github.com/nlohmann/json/pull/3451) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix C++20/gcc-12 issues \(Part 2\) [\#3446](https://github.com/nlohmann/json/pull/3446) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Overwork documentation [\#3444](https://github.com/nlohmann/json/pull/3444) ([nlohmann](https://github.com/nlohmann)) +- Fix typo in basic\_json documentation [\#3439](https://github.com/nlohmann/json/pull/3439) ([jhnlee](https://github.com/jhnlee)) +- Exclude std::any from implicit conversion \(fixes \#3428\) [\#3437](https://github.com/nlohmann/json/pull/3437) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Document which version introduced the macros [\#3431](https://github.com/nlohmann/json/pull/3431) ([nlohmann](https://github.com/nlohmann)) +- Fix constraints on from\_json\(\) for strings \(fixes \#3171, \#3267, \#3312, \#3384\) [\#3427](https://github.com/nlohmann/json/pull/3427) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- at.md: fix typo [\#3426](https://github.com/nlohmann/json/pull/3426) ([heinemml](https://github.com/heinemml)) +- Implement support for string\_view \(attempt no. 3\) [\#3423](https://github.com/nlohmann/json/pull/3423) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- CI: speedup AppVeyor builds by ~30% [\#3422](https://github.com/nlohmann/json/pull/3422) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Restore disabled check for \#3070 \(except on MSVC\) [\#3421](https://github.com/nlohmann/json/pull/3421) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Update CI image [\#3420](https://github.com/nlohmann/json/pull/3420) ([nlohmann](https://github.com/nlohmann)) +- Add check if different version is also included [\#3418](https://github.com/nlohmann/json/pull/3418) ([nlohmann](https://github.com/nlohmann)) +- Report the right \_\_cplusplus value for MSVC in basic\_json meta\(\) [\#3417](https://github.com/nlohmann/json/pull/3417) ([flagarde](https://github.com/flagarde)) +- CI: windows-2016 has been deprecated; remove jobs [\#3416](https://github.com/nlohmann/json/pull/3416) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Re-template json\_pointer on string type [\#3415](https://github.com/nlohmann/json/pull/3415) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Refactor unit tests to use more convenient doctest assertion macros \(Part 2\) [\#3405](https://github.com/nlohmann/json/pull/3405) ([kkarbowiak](https://github.com/kkarbowiak)) +- Refactor unit tests to use more convenient doctest assertion macros [\#3393](https://github.com/nlohmann/json/pull/3393) ([kkarbowiak](https://github.com/kkarbowiak)) +- Improve unit testing \(Part 1\) [\#3380](https://github.com/nlohmann/json/pull/3380) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix C++20/gcc-12 issues \(Part 1\) [\#3379](https://github.com/nlohmann/json/pull/3379) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add clarification to avoid misunderstanding that cause \#3360 [\#3378](https://github.com/nlohmann/json/pull/3378) ([puffetto](https://github.com/puffetto)) +- Fix ordered\_map ctor with initializer\_list \(fixes \#3343\) [\#3370](https://github.com/nlohmann/json/pull/3370) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Fix and update CI [\#3368](https://github.com/nlohmann/json/pull/3368) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- FetchContent\_MakeAvailable [\#3351](https://github.com/nlohmann/json/pull/3351) ([nlohmann](https://github.com/nlohmann)) +- Avoid clash with Arduino defines [\#3338](https://github.com/nlohmann/json/pull/3338) ([DarkZeros](https://github.com/DarkZeros)) +- Support UBJSON-derived Binary JData \(BJData\) format [\#3336](https://github.com/nlohmann/json/pull/3336) ([fangq](https://github.com/fangq)) +- Make iterator operator++/--\(int\) equality-preserving [\#3332](https://github.com/nlohmann/json/pull/3332) ([falbrechtskirchinger](https://github.com/falbrechtskirchinger)) +- Add note on parsing ordered\_json [\#3326](https://github.com/nlohmann/json/pull/3326) ([nlohmann](https://github.com/nlohmann)) +- Fix CITATION.cff and add automatic validation of your citation metadata [\#3320](https://github.com/nlohmann/json/pull/3320) ([fdiblen](https://github.com/fdiblen)) +- .github/workflows/windows.yml: Add support for Visual Studio 2022 [\#3295](https://github.com/nlohmann/json/pull/3295) ([t-b](https://github.com/t-b)) +- Add maintainer targets to create source archive [\#3289](https://github.com/nlohmann/json/pull/3289) ([nlohmann](https://github.com/nlohmann)) +- Fix a typo [\#3265](https://github.com/nlohmann/json/pull/3265) ([fhuberts](https://github.com/fhuberts)) +- Fix typo [\#3249](https://github.com/nlohmann/json/pull/3249) ([rex4539](https://github.com/rex4539)) +- Add documentation for JSON Lines [\#3247](https://github.com/nlohmann/json/pull/3247) ([nlohmann](https://github.com/nlohmann)) +- Improve documentation InputType and IteratorType [\#3246](https://github.com/nlohmann/json/pull/3246) ([nlohmann](https://github.com/nlohmann)) +- Remove stringstream [\#3244](https://github.com/nlohmann/json/pull/3244) ([nlohmann](https://github.com/nlohmann)) +- fix \_MSC\_VER version to check for std::filesystem [\#3240](https://github.com/nlohmann/json/pull/3240) ([gcerretani](https://github.com/gcerretani)) +- Fix compilation error with NVCC [\#3234](https://github.com/nlohmann/json/pull/3234) ([nlohmann](https://github.com/nlohmann)) +- Remove Travis CI [\#3233](https://github.com/nlohmann/json/pull/3233) ([nlohmann](https://github.com/nlohmann)) +- Add build step for NVCC and fix a warning [\#3227](https://github.com/nlohmann/json/pull/3227) ([nlohmann](https://github.com/nlohmann)) +- Update cpplint [\#3225](https://github.com/nlohmann/json/pull/3225) ([nlohmann](https://github.com/nlohmann)) +- Fix: Warning for shadowed variables \(\#3188\) [\#3193](https://github.com/nlohmann/json/pull/3193) ([kernie](https://github.com/kernie)) +- Fix FAQ hyperlink typo in readme [\#3148](https://github.com/nlohmann/json/pull/3148) ([Prince-Mendiratta](https://github.com/Prince-Mendiratta)) +- Docs: Update `skip_comments` to `ignore_comments` [\#3145](https://github.com/nlohmann/json/pull/3145) ([daniel-kun](https://github.com/daniel-kun)) +- Add macros NLOHMANN\_DEFINE\_TYPE\_INTRUSIVE\_WITH\_DEFAULT and ...\_NON\_INTRUSIVE\_WITH\_DEFAULT [\#3143](https://github.com/nlohmann/json/pull/3143) ([pketelsen](https://github.com/pketelsen)) +- fix typos in documentation [\#3140](https://github.com/nlohmann/json/pull/3140) ([striezel](https://github.com/striezel)) +- Fix spelling [\#3125](https://github.com/nlohmann/json/pull/3125) ([axic](https://github.com/axic)) +- Extend std specializations [\#3121](https://github.com/nlohmann/json/pull/3121) ([nlohmann](https://github.com/nlohmann)) +- Add missing erase\(first, last\) function to ordered\_map [\#3109](https://github.com/nlohmann/json/pull/3109) ([nlohmann](https://github.com/nlohmann)) +- Fix typos in operator\[\] documentation [\#3102](https://github.com/nlohmann/json/pull/3102) ([axnsan12](https://github.com/axnsan12)) +- Add C++17 copies of the test binaries [\#3101](https://github.com/nlohmann/json/pull/3101) ([nlohmann](https://github.com/nlohmann)) +- Add examples for parsing from iterator pair [\#3100](https://github.com/nlohmann/json/pull/3100) ([nlohmann](https://github.com/nlohmann)) +- Update CI [\#3088](https://github.com/nlohmann/json/pull/3088) ([nlohmann](https://github.com/nlohmann)) +- Revert invalid fix [\#3082](https://github.com/nlohmann/json/pull/3082) ([nlohmann](https://github.com/nlohmann)) +- Allow to use get with explicit constructor [\#3079](https://github.com/nlohmann/json/pull/3079) ([nlohmann](https://github.com/nlohmann)) +- fix std::filesystem::path regression [\#3073](https://github.com/nlohmann/json/pull/3073) ([theodelrieu](https://github.com/theodelrieu)) +- Consolidate documentation [\#3071](https://github.com/nlohmann/json/pull/3071) ([nlohmann](https://github.com/nlohmann)) +- Add recursive update function [\#3069](https://github.com/nlohmann/json/pull/3069) ([nlohmann](https://github.com/nlohmann)) +- Fix Clang version [\#3040](https://github.com/nlohmann/json/pull/3040) ([nlohmann](https://github.com/nlohmann)) +- Fix assertion failure for JSON\_DIAGNOSTICS [\#3037](https://github.com/nlohmann/json/pull/3037) ([carlsmedstad](https://github.com/carlsmedstad)) +- meta: fix is\_compatible/constructible traits [\#3020](https://github.com/nlohmann/json/pull/3020) ([theodelrieu](https://github.com/theodelrieu)) +- Set parent pointers for values inserted via update\(\) \(fixes \#3007\). [\#3008](https://github.com/nlohmann/json/pull/3008) ([AnthonyVH](https://github.com/AnthonyVH)) +- Allow allocators for output\_vector\_adapter [\#2989](https://github.com/nlohmann/json/pull/2989) ([nlohmann](https://github.com/nlohmann)) +- Re-add Clang 12 [\#2986](https://github.com/nlohmann/json/pull/2986) ([nlohmann](https://github.com/nlohmann)) +- Use new Docker image [\#2981](https://github.com/nlohmann/json/pull/2981) ([nlohmann](https://github.com/nlohmann)) +- Fix -Wunused warnings on JSON\_DIAGNOSTICS [\#2976](https://github.com/nlohmann/json/pull/2976) ([gcerretani](https://github.com/gcerretani)) +- Update docset generation script [\#2967](https://github.com/nlohmann/json/pull/2967) ([nlohmann](https://github.com/nlohmann)) + +## [v3.10.5](https://github.com/nlohmann/json/releases/tag/v3.10.5) (2022-01-03) + +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.4...v3.10.5) - \#include \ doesn't work with gcc-7 when `-std=c++17` is specified. [\#3203](https://github.com/nlohmann/json/issues/3203) - Not able to use nlohmann json with c++ code built using emscripten to wasm [\#3200](https://github.com/nlohmann/json/issues/3200) @@ -30,36 +249,6 @@ All notable changes to this project will be documented in this file. This projec - some static analysis warning at line 11317 [\#1390](https://github.com/nlohmann/json/issues/1390) - Compiling with icpc [\#755](https://github.com/nlohmann/json/issues/755) -- Fix compilation error with NVCC [\#3234](https://github.com/nlohmann/json/pull/3234) ([nlohmann](https://github.com/nlohmann)) -- Remove Travis CI [\#3233](https://github.com/nlohmann/json/pull/3233) ([nlohmann](https://github.com/nlohmann)) -- Add build step for NVCC and fix a warning [\#3227](https://github.com/nlohmann/json/pull/3227) ([nlohmann](https://github.com/nlohmann)) -- Update cpplint [\#3225](https://github.com/nlohmann/json/pull/3225) ([nlohmann](https://github.com/nlohmann)) -- Fix: Warning for shadowed variables \(\#3188\) [\#3193](https://github.com/nlohmann/json/pull/3193) ([kernie](https://github.com/kernie)) -- Fix FAQ hyperlink typo in readme [\#3148](https://github.com/nlohmann/json/pull/3148) ([Prince-Mendiratta](https://github.com/Prince-Mendiratta)) -- Docs: Update `skip_comments` to `ignore_comments` [\#3145](https://github.com/nlohmann/json/pull/3145) ([daniel-kun](https://github.com/daniel-kun)) -- fix typos in documentation [\#3140](https://github.com/nlohmann/json/pull/3140) ([striezel](https://github.com/striezel)) -- Fix spelling [\#3125](https://github.com/nlohmann/json/pull/3125) ([axic](https://github.com/axic)) -- Extend std specializations [\#3121](https://github.com/nlohmann/json/pull/3121) ([nlohmann](https://github.com/nlohmann)) -- Add missing erase\(first, last\) function to ordered\_map [\#3109](https://github.com/nlohmann/json/pull/3109) ([nlohmann](https://github.com/nlohmann)) -- Fix typos in operator\[\] documentation [\#3102](https://github.com/nlohmann/json/pull/3102) ([axnsan12](https://github.com/axnsan12)) -- Add C++17 copies of the test binaries [\#3101](https://github.com/nlohmann/json/pull/3101) ([nlohmann](https://github.com/nlohmann)) -- Add examples for parsing from iterator pair [\#3100](https://github.com/nlohmann/json/pull/3100) ([nlohmann](https://github.com/nlohmann)) -- Update CI [\#3088](https://github.com/nlohmann/json/pull/3088) ([nlohmann](https://github.com/nlohmann)) -- Revert invalid fix [\#3082](https://github.com/nlohmann/json/pull/3082) ([nlohmann](https://github.com/nlohmann)) -- Allow to use get with explicit constructor [\#3079](https://github.com/nlohmann/json/pull/3079) ([nlohmann](https://github.com/nlohmann)) -- fix std::filesystem::path regression [\#3073](https://github.com/nlohmann/json/pull/3073) ([theodelrieu](https://github.com/theodelrieu)) -- Consolidate documentation [\#3071](https://github.com/nlohmann/json/pull/3071) ([nlohmann](https://github.com/nlohmann)) -- Add recursive update function [\#3069](https://github.com/nlohmann/json/pull/3069) ([nlohmann](https://github.com/nlohmann)) -- Fix Clang version [\#3040](https://github.com/nlohmann/json/pull/3040) ([nlohmann](https://github.com/nlohmann)) -- Fix assertion failure for JSON\_DIAGNOSTICS [\#3037](https://github.com/nlohmann/json/pull/3037) ([carlsmedstad](https://github.com/carlsmedstad)) -- meta: fix is\_compatible/constructible traits [\#3020](https://github.com/nlohmann/json/pull/3020) ([theodelrieu](https://github.com/theodelrieu)) -- Set parent pointers for values inserted via update\(\) \(fixes \#3007\). [\#3008](https://github.com/nlohmann/json/pull/3008) ([AnthonyVH](https://github.com/AnthonyVH)) -- Allow allocators for output\_vector\_adapter [\#2989](https://github.com/nlohmann/json/pull/2989) ([nlohmann](https://github.com/nlohmann)) -- Re-add Clang 12 [\#2986](https://github.com/nlohmann/json/pull/2986) ([nlohmann](https://github.com/nlohmann)) -- Use new Docker image [\#2981](https://github.com/nlohmann/json/pull/2981) ([nlohmann](https://github.com/nlohmann)) -- Fix -Wunused warnings on JSON\_DIAGNOSTICS [\#2976](https://github.com/nlohmann/json/pull/2976) ([gcerretani](https://github.com/gcerretani)) -- Update docset generation script [\#2967](https://github.com/nlohmann/json/pull/2967) ([nlohmann](https://github.com/nlohmann)) - ## [v3.10.4](https://github.com/nlohmann/json/releases/tag/v3.10.4) (2021-10-16) [Full Changelog](https://github.com/nlohmann/json/compare/v3.10.3...v3.10.4) @@ -118,7 +307,7 @@ All notable changes to this project will be documented in this file. This projec - Linker error LNK2005 when compiling \(x64\) json-3.10.0.zip with Visual Studio 2019 16.11.1 [\#2941](https://github.com/nlohmann/json/issues/2941) - Move Travis jobs to travis-ci.com [\#2938](https://github.com/nlohmann/json/issues/2938) -- Fixed typo in docs/api/basic\_json/parse.md [\#2968](https://github.com/nlohmann/json/pull/2968) ([mb0202](https://github.com/mb0202)) +- Fixed typo in docs/api/basic\_json/parse.md [\#2968](https://github.com/nlohmann/json/pull/2968) ([mbadhan](https://github.com/mbadhan)) - Add link to Homebrew package [\#2966](https://github.com/nlohmann/json/pull/2966) ([nlohmann](https://github.com/nlohmann)) - Fix parent update for diagnostics with ordered\_json [\#2963](https://github.com/nlohmann/json/pull/2963) ([nlohmann](https://github.com/nlohmann)) - Set stack size for some unit tests when using MSVC [\#2961](https://github.com/nlohmann/json/pull/2961) ([nlohmann](https://github.com/nlohmann)) @@ -240,7 +429,6 @@ All notable changes to this project will be documented in this file. This projec - from\_\*\(ptr, len\) deprecation [\#2426](https://github.com/nlohmann/json/issues/2426) - Error ONLY in release mode [\#2425](https://github.com/nlohmann/json/issues/2425) - "Custom data source" exemple make no sense [\#2423](https://github.com/nlohmann/json/issues/2423) -- Compile errors [\#2421](https://github.com/nlohmann/json/issues/2421) - Refuses to compile in project [\#2419](https://github.com/nlohmann/json/issues/2419) - Compilation failure of tests with C++20 standard \(caused by change of u8 literals\) [\#2413](https://github.com/nlohmann/json/issues/2413) - No matching function for call to 'input\_adapter' under Xcode of with nlohmann version 3.9.1 [\#2412](https://github.com/nlohmann/json/issues/2412) @@ -860,7 +1048,7 @@ All notable changes to this project will be documented in this file. This projec - Segmentation fault \(stack overflow\) due to unbounded recursion [\#1419](https://github.com/nlohmann/json/issues/1419) - Stack-overflow \(OSS-Fuzz 4234\) [\#832](https://github.com/nlohmann/json/issues/832) -- Configure WhiteSource Bolt for GitHub [\#1830](https://github.com/nlohmann/json/pull/1830) ([whitesource-bolt-for-github[bot]](https://github.com/apps/whitesource-bolt-for-github)) +- Configure WhiteSource Bolt for GitHub [\#1830](https://github.com/nlohmann/json/pull/1830) ([mend-bolt-for-github[bot]](https://github.com/apps/mend-bolt-for-github)) - Prevent stackoverflow caused by recursive deconstruction [\#1436](https://github.com/nlohmann/json/pull/1436) ([nickaein](https://github.com/nickaein)) ## [v3.7.1](https://github.com/nlohmann/json/releases/tag/v3.7.1) (2019-11-06) @@ -951,7 +1139,6 @@ All notable changes to this project will be documented in this file. This projec - Information: My project uses this awesome library [\#1691](https://github.com/nlohmann/json/issues/1691) - Consider listing files explicitly instead of using GLOB [\#1686](https://github.com/nlohmann/json/issues/1686) - Failing tests on MSVC with VS2019 15.9.13 x64 [\#1685](https://github.com/nlohmann/json/issues/1685) -- Consider putting the user-defined literals in a namespace [\#1682](https://github.com/nlohmann/json/issues/1682) - Change from v2 to v3. Encoding with cp1252 [\#1680](https://github.com/nlohmann/json/issues/1680) - How to add Fifo\_map into json using Cmake [\#1679](https://github.com/nlohmann/json/issues/1679) - include.zip should contain meson.build [\#1672](https://github.com/nlohmann/json/issues/1672) @@ -1103,7 +1290,6 @@ All notable changes to this project will be documented in this file. This projec - \[Help Needed!\] Season of Docs [\#1542](https://github.com/nlohmann/json/issues/1542) - program still abort\(\) or exit\(\) with try catch [\#1541](https://github.com/nlohmann/json/issues/1541) - Have a json::type\_error exception because of JSON object [\#1540](https://github.com/nlohmann/json/issues/1540) -- Using versioned namespaces [\#1539](https://github.com/nlohmann/json/issues/1539) - Quoted numbers [\#1538](https://github.com/nlohmann/json/issues/1538) - Reading a JSON file into an object [\#1537](https://github.com/nlohmann/json/issues/1537) - Releases 3.6.0 and 3.6.1 don't build on conda / windows [\#1536](https://github.com/nlohmann/json/issues/1536) @@ -1370,7 +1556,6 @@ All notable changes to this project will be documented in this file. This projec - syntax error on right json string [\#1276](https://github.com/nlohmann/json/issues/1276) - Parsing JSON Array where members have no key, using custom types [\#1267](https://github.com/nlohmann/json/issues/1267) - I get a json exception periodically from json::parse for the same json [\#1263](https://github.com/nlohmann/json/issues/1263) -- serialize std::variant\<...\> [\#1261](https://github.com/nlohmann/json/issues/1261) - GCC 8.2.1. Compilation error: invalid conversion from... [\#1246](https://github.com/nlohmann/json/issues/1246) - BSON support [\#1244](https://github.com/nlohmann/json/issues/1244) - enum to json mapping [\#1208](https://github.com/nlohmann/json/issues/1208) @@ -1856,7 +2041,7 @@ All notable changes to this project will be documented in this file. This projec - Add Visual Studio 17 image to appveyor build matrix [\#536](https://github.com/nlohmann/json/pull/536) ([vpetrigo](https://github.com/vpetrigo)) - UTF8 encoding enhancement [\#534](https://github.com/nlohmann/json/pull/534) ([TedLyngmo](https://github.com/TedLyngmo)) - Fix typo [\#530](https://github.com/nlohmann/json/pull/530) ([berkus](https://github.com/berkus)) -- Make exception base class visible in basic\_json [\#526](https://github.com/nlohmann/json/pull/526) ([krzysztofwos](https://github.com/krzysztofwos)) +- Make exception base class visible in basic\_json [\#526](https://github.com/nlohmann/json/pull/526) ([ghost](https://github.com/ghost)) - :art: Namespace `uint8_t` from the C++ stdlib [\#510](https://github.com/nlohmann/json/pull/510) ([alexweej](https://github.com/alexweej)) - add to\_json method for C arrays [\#508](https://github.com/nlohmann/json/pull/508) ([theodelrieu](https://github.com/theodelrieu)) - Fix -Weffc++ warnings \(GNU 6.3.1\) [\#496](https://github.com/nlohmann/json/pull/496) ([TedLyngmo](https://github.com/TedLyngmo)) diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 000000000..137069b82 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/BSD-3-Clause.txt b/LICENSES/BSD-3-Clause.txt new file mode 100644 index 000000000..ea890afbc --- /dev/null +++ b/LICENSES/BSD-3-Clause.txt @@ -0,0 +1,11 @@ +Copyright (c) . + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSES/GPL-3.0-only.txt b/LICENSES/GPL-3.0-only.txt new file mode 100644 index 000000000..d41c0bd98 --- /dev/null +++ b/LICENSES/GPL-3.0-only.txt @@ -0,0 +1,232 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright Š 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on the Program. + +To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”. + + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +7. Additional Terms. +“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +11. Patents. +A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”. + +You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 000000000..2071b23b0 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 43db74d85..1f220b261 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,6 @@ # configuration ########################################################################## -# directory to recent compiler binaries -COMPILER_DIR=/usr/local/opt/llvm/bin - # find GNU sed to use `-i` parameter SED:=$(shell command -v gsed || which sed) @@ -18,6 +15,9 @@ SED:=$(shell command -v gsed || which sed) # the list of sources in the include folder SRCS=$(shell find include -type f | sort) +# the list of sources in the tests folder +TESTS_SRCS=$(shell find tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) + # the single header (amalgamated from the source files) AMALGAMATED_FILE=single_include/nlohmann/json.hpp @@ -48,7 +48,7 @@ all: # compile example files and check output doctest: - $(MAKE) check_output -C doc + $(MAKE) check_output -C docs ########################################################################## @@ -58,10 +58,11 @@ doctest: run_benchmarks: rm -fr cmake-build-benchmarks mkdir cmake-build-benchmarks - cd cmake-build-benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On + cd cmake-build-benchmarks ; cmake ../tests/benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release cd cmake-build-benchmarks ; ninja cd cmake-build-benchmarks ; ./json_benchmarks + ########################################################################## # fuzzing ########################################################################## @@ -70,41 +71,41 @@ run_benchmarks: fuzz_testing: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_afl_fuzzer -C test CXX=afl-clang++ - mv test/parse_afl_fuzzer fuzz-testing/fuzzer - find test/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_afl_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_afl_fuzzer fuzz-testing/fuzzer + find tests/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_bson: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_bson_fuzzer -C test CXX=afl-clang++ - mv test/parse_bson_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_bson_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_bson_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_cbor: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_cbor_fuzzer -C test CXX=afl-clang++ - mv test/parse_cbor_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_cbor_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_cbor_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_msgpack: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_msgpack_fuzzer -C test CXX=afl-clang++ - mv test/parse_msgpack_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_msgpack_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_msgpack_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzz_testing_ubjson: rm -fr fuzz-testing mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out - $(MAKE) parse_ubjson_fuzzer -C test CXX=afl-clang++ - mv test/parse_ubjson_fuzzer fuzz-testing/fuzzer - find test/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases + $(MAKE) parse_ubjson_fuzzer -C tests CXX=afl-clang++ + mv tests/parse_ubjson_fuzzer fuzz-testing/fuzzer + find tests/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases @echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer" fuzzing-start: @@ -135,6 +136,7 @@ pvs_studio: cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs open cmake-build-pvs-studio/pvs/index.html + ########################################################################## # Code format and source amalgamation ########################################################################## @@ -160,18 +162,18 @@ pretty: --preserve-date \ --suffix=none \ --formatted \ - $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp + $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp # call the Clang-Format on all source files pretty_format: - for FILE in $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done + for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done # create single header file amalgamate: $(AMALGAMATED_FILE) # call the amalgamation tool and pretty print $(AMALGAMATED_FILE): $(SRCS) - third_party/amalgamate/amalgamate.py -c third_party/amalgamate/config.json -s . --verbose=yes + tools/amalgamate/amalgamate.py -c tools/amalgamate/config.json -s . --verbose=yes $(MAKE) pretty # check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources @@ -203,20 +205,29 @@ ChangeLog.md: # Release files ########################################################################## -# Create the files for a release and add signatures and hashes. We use `-X` to make the resulting ZIP file -# reproducible, see . +# Create a tar.gz archive that contains sufficient files to be used as CMake project (e.g., using FetchContent). The +# archive is created according to the advices of . +json.tar.xz: + mkdir json + rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include -type f) json + gtar --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz + rm -fr json -release: +# We use `-X` to make the resulting ZIP file reproducible, see +# . +include.zip: + zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build LICENSE.MIT + +# Create the files for a release and add signatures and hashes. +release: include.zip json.tar.xz rm -fr release_files mkdir release_files - zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build LICENSE.MIT gpg --armor --detach-sig include.zip - mv include.zip include.zip.asc release_files gpg --armor --detach-sig $(AMALGAMATED_FILE) + gpg --armor --detach-sig json.tar.xz cp $(AMALGAMATED_FILE) release_files - mv $(AMALGAMATED_FILE).asc release_files - cd release_files ; shasum -a 256 json.hpp > hashes.txt - cd release_files ; shasum -a 256 include.zip >> hashes.txt + mv $(AMALGAMATED_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files + cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt ########################################################################## @@ -225,11 +236,11 @@ release: # clean up clean: - rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html + rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM rm -fr benchmarks/files/numbers/*.json - rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64 - rm -fr cmake-build-benchmarks cmake-build-pedantic fuzz-testing cmake-build-clang-analyze cmake-build-pvs-studio cmake-build-infer cmake_build - $(MAKE) clean -Cdoc + rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files + $(MAKE) clean -Cdocs + ########################################################################## # Thirdparty code @@ -243,3 +254,19 @@ update_hedley: $(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley.hpp $(SED) -i '1s/^/#pragma once\n\n/' include/nlohmann/thirdparty/hedley/hedley_undef.hpp $(MAKE) amalgamate + +########################################################################## +# serve_header.py +########################################################################## + +serve_header: + ./tools/serve_header/serve_header.py --make $(MAKE) + +########################################################################## +# REUSE +########################################################################## + +reuse: + pipx run reuse addheader --recursive single_include include -tjson --license MIT --copyright "Niels Lohmann " --year "2013-2022" + pipx run reuse addheader $(TESTS_SRCS) --style=c -tjson_support --license MIT --copyright "Niels Lohmann " --year "2013-2022" + pipx run reuse lint diff --git a/README.md b/README.md index 313296323..de8b5242c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![JSON for Modern C++](https://raw.githubusercontent.com/nlohmann/json/master/doc/json.gif)](https://github.com/nlohmann/json/releases) +[![JSON for Modern C++](docs/json.gif)](https://github.com/nlohmann/json/releases) [![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?svg=true)](https://ci.appveyor.com/project/nlohmann/json) [![Ubuntu](https://github.com/nlohmann/json/workflows/Ubuntu/badge.svg)](https://github.com/nlohmann/json/actions?query=workflow%3AUbuntu) @@ -10,19 +10,23 @@ [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/nlohmann/json.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nlohmann/json/context:cpp) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/json.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json) [![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/1mp10JbaANo6FUc7) -[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](https://nlohmann.github.io/json/doxygen/index.html) +[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://json.nlohmann.me) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT) [![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases) +[![Packaging status](https://repology.org/badge/tiny-repos/nlohmann-json.svg)](https://repology.org/project/nlohmann-json/versions) [![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases) [![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](https://github.com/nlohmann/json/issues) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/nlohmann/json.svg)](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue") [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Sponsors-ff69b4)](https://github.com/sponsors/nlohmann) +[![REUSE status](https://api.reuse.software/badge/github.com/nlohmann/json)](https://api.reuse.software/info/github.com/nlohmann/json) - [Design goals](#design-goals) - [Sponsors](#sponsors) - [Support](#support) ([documentation](https://json.nlohmann.me), [FAQ](https://json.nlohmann.me/home/faq/), [discussions](https://github.com/nlohmann/json/discussions), [API](https://json.nlohmann.me/api/basic_json/), [bug issues](https://github.com/nlohmann/json/issues)) - [Examples](#examples) + - [Read JSON from a file](#read-json-from-a-file) + - [Creating `json` objects from JSON literals](#creating-json-objects-from-json-literals) - [JSON as first-class data type](#json-as-first-class-data-type) - [Serialization / Deserialization](#serialization--deserialization) - [STL-like access](#stl-like-access) @@ -32,7 +36,7 @@ - [Implicit conversions](#implicit-conversions) - [Conversions to/from arbitrary types](#arbitrary-types-conversions) - [Specializing enum conversion](#specializing-enum-conversion) - - [Binary formats (BSON, CBOR, MessagePack, and UBJSON)](#binary-formats-bson-cbor-messagepack-and-ubjson) + - [Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData)](#binary-formats-bson-cbor-messagepack-ubjson-and-bjdata) - [Supported compilers](#supported-compilers) - [Integration](#integration) - [CMake](#cmake) @@ -54,7 +58,7 @@ There are myriads of [JSON](https://json.org) libraries out there, and each may - **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings. -- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/test/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). +- **Serious testing**. Our code is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/tests/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). Other aspects were not so important to us: @@ -69,6 +73,10 @@ See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/. You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). +### :office: Corporate Sponsor + +[![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Codacy-logo-black.svg/320px-Codacy-logo-black.svg.png)](https://github.com/codacy) + ### :label: Named Sponsors - [Michael Hartmann](https://github.com/reFX-Mike) @@ -83,9 +91,9 @@ Thanks everyone! :question: If you have a **question**, please check if it is already answered in the [**FAQ**](https://json.nlohmann.me/home/faq/) or the [**Q&A**](https://github.com/nlohmann/json/discussions/categories/q-a) section. If not, please [**ask a new question**](https://github.com/nlohmann/json/discussions/new) there. -:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/doc/examples), or browse through the [**help pages**](https://json.nlohmann.me). +:books: If you want to **learn more** about how to use the library, check out the rest of the [**README**](#examples), have a look at [**code examples**](https://github.com/nlohmann/json/tree/develop/docs/examples), or browse through the [**help pages**](https://json.nlohmann.me). -:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/) or the [**Doxygen documentation**](https://json.nlohmann.me/doxygen/index.html). +:construction: If you want to understand the **API** better, check out the [**API Reference**](https://json.nlohmann.me/api/basic_json/). :bug: If you found a **bug**, please check the [**FAQ**](https://json.nlohmann.me/home/faq/) if it is a known issue or the result of a design decision. Please also have a look at the [**issue list**](https://github.com/nlohmann/json/issues) before you [**create a new issue**](https://github.com/nlohmann/json/issues/new/choose). Please provide as much information as possible to help us understand and reproduce your issue. @@ -93,7 +101,67 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t ## Examples -Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)). +Here are some examples to give you an idea how to use the class. + +Beside the examples below, you may want to: + +→ Check the [documentation](https://json.nlohmann.me/)\ +→ Browse the [standalone example files](https://github.com/nlohmann/json/tree/develop/docs/examples) + +Every API function (documented in the [API Documentation](https://json.nlohmann.me/api/basic_json/)) has a corresponding standalone example file. For example, the [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/) function has a matching [emplace.cpp](https://github.com/nlohmann/json/blob/develop/docs/examples/emplace.cpp) example file. + +### Read JSON from a file + +The `json` class provides an API for manipulating a JSON value. To create a `json` object by reading a JSON file: + +```cpp +#include +#include +using json = nlohmann::json; + +// ... + +std::ifstream f("example.json"); +json data = json::parse(f); +``` + +### Creating `json` objects from JSON literals + +Assume you want to create hard-code this literal JSON value in a file, as a `json` object: + +```json +{ + "pi": 3.141, + "happy": true +} +``` + +There are various options: + +```cpp +// Using (raw) string literals and json::parse +json ex1 = json::parse(R"( + { + "pi": 3.141, + "happy": true + } +)"); + +// Using user-defined (raw) string literals +using namespace nlohmann::literals; +json ex2 = R"( + { + "pi": 3.141, + "happy": true + } +)"_json; + +// Using initializer lists +json ex3 = { + {"happy", true}, + {"pi", 3.141}, +}; +``` ### JSON as first-class data type @@ -162,7 +230,7 @@ json j2 = { }; ``` -Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help: +Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://json.nlohmann.me/api/basic_json/array/) and [`json::object()`](https://json.nlohmann.me/api/basic_json/object/) will help: ```cpp // a way to express the empty array [] @@ -195,9 +263,14 @@ auto j2 = R"( )"_json; ``` -Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. +Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string +value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string +`"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object. -The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/): +The string literal should be brought into scope with with `using namespace nlohmann::literals;` +(see [`json::parse()`](https://json.nlohmann.me/api/operator_literal_json/)). + +The above example can also be expressed explicitly using [`json::parse()`](https://json.nlohmann.me/api/basic_json/parse/): ```cpp // parse explicitly @@ -240,9 +313,9 @@ std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) -* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. +* In function `from_json`, use function [`at()`](https://json.nlohmann.me/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. #### Simplify your life with macros @@ -857,7 +930,7 @@ namespace nlohmann { #### Can I write my own serializer? (Advanced use) -Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. +Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-udt.cpp) in the test suite, to see a few examples. If you write your own serializer, you'll need to do a few things: @@ -961,9 +1034,9 @@ Other Important points: - When using `get()`, undefined JSON values will default to the first pair specified in your map. Select this default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. -### Binary formats (BSON, CBOR, MessagePack, and UBJSON) +### Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData) -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), and [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) to efficiently encode JSON values to byte vectors and to decode such vectors. +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [BSON](https://bsonspec.org) (Binary JSON), [CBOR](https://cbor.io) (Concise Binary Object Representation), [MessagePack](https://msgpack.org), [UBJSON](https://ubjson.org) (Universal Binary JSON Specification) and [BJData](https://neurojson.org/bjdata) (Binary JData) to efficiently encode JSON values to byte vectors and to decode such vectors. ```cpp // create a JSON value @@ -1037,14 +1110,15 @@ auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE Though it's 2022 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- GCC 4.8 - 11.0 (and possibly later) -- Clang 3.4 - 13.0 (and possibly later) -- Apple Clang 9.1 - 13.0 (and possibly later) +- GCC 4.8 - 12.0 (and possibly later) +- Clang 3.4 - 15.0 (and possibly later) +- Apple Clang 9.1 - 13.1 (and possibly later) - Intel C++ Compiler 17.0.2 (and possibly later) - Nvidia CUDA Compiler 11.0.221 (and possibly later) - Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) - Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later) - Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later) +- Microsoft Visual C++ 2022 / Build Tools 19.30.30709.0 (and possibly later) I would be happy to learn about other compilers/versions. @@ -1082,18 +1156,11 @@ The following compilers are currently used in continuous integration at [AppVeyo | Apple Clang 12.0.0 (clang-1200.0.32.27); Xcode 12.2 | macOS 10.15.7 | GitHub Actions | | Apple Clang 12.0.0 (clang-1200.0.32.28); Xcode 12.3 | macOS 10.15.7 | GitHub Actions | | Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 10.15.7 | GitHub Actions | -| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | -| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | -| GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 11.0.1 20210321 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | +| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.1 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2.1 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.1.6 (clang-1316.0.21.2); Xcode 13.3 | macOS 12.3.1 | GitHub Actions | +| Apple Clang 13.1.6 (clang-1316.0.21.2.3); Xcode 13.3.1 | macOS 12.3.1 | GitHub Actions | | Clang 3.5.2 (3.5.2-3ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 3.6.2 (3.6.2-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 3.7.1 (3.7.1-2ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | @@ -1112,13 +1179,28 @@ The following compilers are currently used in continuous integration at [AppVeyo | Clang 11.0.0 (11.0.0-2~ubuntu20.04.1) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 12.0.0 (12.0.0-3ubuntu1~20.04.3) | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 13.0.1 (13.0.1-++20211015123032+cf15ccdeb6d5-1exp120211015003613.5) | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 14.0.0 (14.0.0-++20211221052852+55c71c9eac9b-1exp120211221172954.95) | Ubuntu 20.04.3 LTS | GitHub Actions | +| Clang 14.0.5-++20220603124341+2f0a69c32a4c-1~exp1~20220603124352.149 | Ubuntu 20.04.3 LTS | GitHub Actions | +| Clang 15.0.0 (15.0.0-++20220530052901+b7d2b160c3ba-1~exp1~20220530172952.268) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.12) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 7.5.0 (Ubuntu 7.5.0-6ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | +| GCC 8.4.0 (Ubuntu 8.4.0-3ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 11.1.0 | Ubuntu (aarch64) | Drone CI | +| GCC 11.1.0 (Ubuntu 11.1.0-1ubuntu1~20.04) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 13.0.0 13.0.0 20220605 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions | +| Intel C++ Compiler 2021.5.0.20211109 | Ubuntu 20.04.3 LTS | GitHub Actions | | NVCC 11.0.221 | Ubuntu 20.04.3 LTS | GitHub Actions | | Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor | | Visual Studio 15 2017 MSVC 19.16.27035.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor | -| Visual Studio 15 2017 MSVC 19.16.27045.0 (Build Engine version 15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | GitHub Actions | | Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | GitHub Actions | | Visual Studio 16 2019 MSVC 19.28.29912.0 (Build Engine version 16.9.0+57a23d249 for .NET Framework) | Windows-10.0.17763 | AppVeyor | +| Visual Studio 17 2022 MSVC 19.30.30709.0 (Build Engine version 17.0.31804.368 for .NET Framework) | Windows-10.0.20348 | GitHub Actions | ## Integration @@ -1183,29 +1265,20 @@ target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) Since CMake v3.11, [FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can -be used to automatically download the repository as a dependency at configure time. +be used to automatically download a release as a dependency at configure time. Example: ```cmake include(FetchContent) -FetchContent_Declare(json - GIT_REPOSITORY https://github.com/nlohmann/json.git - GIT_TAG v3.7.3) - -FetchContent_GetProperties(json) -if(NOT json_POPULATED) - FetchContent_Populate(json) - add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() +FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.0/json.tar.xz) +FetchContent_MakeAvailable(json) target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) ``` -**Note**: The repository https://github.com/nlohmann/json download size is huge. -It contains all the dataset used for the benchmarks. You might want to depend on -a smaller repository. For instance, you might want to replace the URL above by -https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent +**Note**: It is recommended to use the URL approach described above which is supported as of version 3.10.0. See + for more information. #### Supporting Both @@ -1336,7 +1409,7 @@ Only if your request would contain confidential information, please [send me an I deeply appreciate the help of the following people. - + - [Teemperor](https://github.com/Teemperor) implemented CMake support and lcov integration, realized escape and Unicode handling in the string parser, and fixed the JSON serialization. - [elliotgoodrich](https://github.com/elliotgoodrich) fixed an issue with double deletion in the iterator classes. @@ -1605,6 +1678,21 @@ I deeply appreciate the help of the following people. - [Dirk Stolle](https://github.com/striezel) fixed typos in documentation. - [Daniel Albuschat](https://github.com/daniel-kun) corrected the parameter name in the `parse` documentation. - [Prince Mendiratta](https://github.com/Prince-Mendiratta) fixed a link to the FAQ. +- [Florian Albrechtskirchinger](https://github.com/falbrechtskirchinger) implemented `std::string_view` support for object keys and made dozens of other improvements. +- [Qianqian Fang](https://github.com/fangq) implemented the Binary JData (BJData) format. +- [pketelsen](https://github.com/pketelsen) added macros `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`. +- [DarkZeros](https://github.com/DarkZeros) adjusted to code to not clash with Arduino defines. +- [flagarde](https://github.com/flagarde) fixed the output of `meta()` for MSVC. +- [Giovanni Cerretani](https://github.com/gcerretani) fixed a check for `std::filesystem`. +- [Dimitris Apostolou](https://github.com/rex4539) fixed a typo. +- [Ferry Huberts](https://github.com/fhuberts) fixed a typo. +- [Michael Nosthoff](https://github.com/heinemml) fixed a typo. +- [JungHoon Lee](https://github.com/jhnlee) fixed a typo. +- [Faruk D.](https://github.com/fdiblen) fixed the CITATION.CFF file. +- [Andrea Cocito](https://github.com/puffetto) added a clarification on macro usage to the documentation. +- [Krzysiek Karbowiak](https://github.com/kkarbowiak) refactored the tests to use `CHECK_THROWS_WITH_AS`. +- [Chaoqi Zhang](https://github.com/prncoprs) fixed a typo. +- [ivanovmp](https://github.com/ivanovmp) fixed a whitespace error. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -1619,18 +1707,19 @@ The library itself consists of a single header file licensed under the MIT licen - [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code indentation - [**Clang**](https://clang.llvm.org) for compilation with code sanitizers - [**CMake**](https://cmake.org) for build automation -- [**Codacity**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) +- [**Codacy**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json) - [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json) - [**Coverity Scan**](https://scan.coverity.com) for [static analysis](https://scan.coverity.com/projects/nlohmann-json) - [**cppcheck**](http://cppcheck.sourceforge.net) for static analysis - [**doctest**](https://github.com/onqtam/doctest) for the unit tests -- [**Doxygen**](https://www.doxygen.nl/index.html) to generate [documentation](https://nlohmann.github.io/json/doxygen/index.html) - [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages - [**GitHub Changelog Generator**](https://github.com/skywinder/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 - [**lcov**](http://ltp.sourceforge.net/coverage/lcov.php) to process coverage information and create an HTML view - [**libFuzzer**](https://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz +- [**Material for MkDocs**](https://squidfunk.github.io/mkdocs-material/) for the style of the documentation site +- [**MkDocs**](https://www.mkdocs.org) for the documentation site - [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library ([project repository](https://github.com/google/oss-fuzz/tree/master/projects/json)) - [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. - [**Valgrind**](https://valgrind.org) to check for correct memory management @@ -1638,7 +1727,7 @@ The library itself consists of a single header file licensed under the MIT licen ## Projects using JSON for Modern C++ -The library is currently used in Apple macOS Sierra and iOS 10. I am not sure what they are using the library for, but I am happy that it runs on so many devices. +The library is currently used in Apple macOS Sierra-Monterey and iOS 10-15. I am not sure what they are using the library for, but I am happy that it runs on so many devices. ## Notes @@ -1653,7 +1742,7 @@ The library supports **Unicode input** as follows: - [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library. - Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors. - The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs. -- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. +- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers. - To store wide strings (e.g., `std::wstring`), you need to convert them to a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling). ### Comments in JSON @@ -1688,7 +1777,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924). ### Further notes -- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. +- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://json.nlohmann.me/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://json.nlohmann.me/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`. - As the exact number type is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions. - The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag. - **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). @@ -1707,6 +1796,22 @@ $ ctest --output-on-failure Note that during the `ctest` stage, several JSON test files are downloaded from an [external repository](https://github.com/nlohmann/json_test_data). If policies forbid downloading artifacts during testing, you can download the files yourself and pass the directory with the test files via `-DJSON_TestDataDirectory=path` to CMake. Then, no Internet connectivity is required. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. +If the test suite is not found, several test suites will fail like this: + +``` +=============================================================================== +json/tests/src/make_test_data_available.hpp:21: +TEST CASE: check test suite is downloaded + +json/tests/src/make_test_data_available.hpp:23: FATAL ERROR: REQUIRE( utils::check_testsuite_downloaded() ) is NOT correct! + values: REQUIRE( false ) + logged: Test data not found in 'json/cmake-build-debug/json_test_data'. + Please execute target 'download_test_data' before running this test suite. + See for more information. + +=============================================================================== +``` + In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. diff --git a/cmake/ci.cmake b/cmake/ci.cmake index d0b989c80..5ccd4c4a4 100644 --- a/cmake/ci.cmake +++ b/cmake/ci.cmake @@ -13,12 +13,12 @@ execute_process(COMMAND ${ASTYLE_TOOL} --version OUTPUT_VARIABLE ASTYLE_TOOL_VER string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" ASTYLE_TOOL_VERSION "${ASTYLE_TOOL_VERSION}") message(STATUS "🔖 Artistic Style ${ASTYLE_TOOL_VERSION} (${ASTYLE_TOOL})") -find_program(CLANG_TOOL NAMES clang++-HEAD clang++-14 clang++-13 clang++-12 clang++-11 clang++) +find_program(CLANG_TOOL NAMES clang++-HEAD clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++) execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION) string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}") message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})") -find_program(CLANG_TIDY_TOOL NAMES clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy) +find_program(CLANG_TIDY_TOOL NAMES clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy) execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION) string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}") message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})") @@ -30,7 +30,7 @@ execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CPPCHECK_TOOL_VERSION "${CPPCHECK_TOOL_VERSION}") message(STATUS "🔖 Cppcheck ${CPPCHECK_TOOL_VERSION} (${CPPCHECK_TOOL})") -find_program(GCC_TOOL NAMES g++-HEAD g++-11 g++-latest) +find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++-11 g++-10) execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION) string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}") message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})") @@ -79,7 +79,7 @@ message(STATUS "🔖 Valgrind ${VALGRIND_TOOL_VERSION} (${VALGRIND_TOOL})") find_program(GENHTML_TOOL NAMES genhtml) find_program(PLOG_CONVERTER_TOOL NAMES plog-converter) find_program(PVS_STUDIO_ANALYZER_TOOL NAMES pvs-studio-analyzer) -find_program(SCAN_BUILD_TOOL NAMES scan-build-14 scan-build-13 scan-build-12 scan-build-11 scan-build) +find_program(SCAN_BUILD_TOOL NAMES scan-build-15 scan-build-14 scan-build-13 scan-build-12 scan-build-11 scan-build) # the individual source files file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp) @@ -98,19 +98,20 @@ file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp) # -Wno-weak-vtables The library is header-only. # -Wreserved-identifier See https://github.com/onqtam/doctest/issues/536. -set(CLANG_CXXFLAGS "-std=c++11 \ - -Werror \ - -Weverything \ - -Wno-c++98-compat \ - -Wno-c++98-compat-pedantic \ - -Wno-deprecated-declarations \ - -Wno-extra-semi-stmt \ - -Wno-padded \ - -Wno-covered-switch-default \ - -Wno-weak-vtables \ - -Wno-reserved-identifier \ -") +set(CLANG_CXXFLAGS + -Werror + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-deprecated-declarations + -Wno-extra-semi-stmt + -Wno-padded + -Wno-covered-switch-default + -Wno-weak-vtables + -Wno-reserved-identifier +) +# Warning flags determined for GCC 13.0 (experimental) with https://github.com/nlohmann/gcc_flags: # Ignored GCC warnings: # -Wno-abi-tag We do not care about ABI tags. # -Wno-aggregate-return The library uses aggregate returns. @@ -120,285 +121,302 @@ set(CLANG_CXXFLAGS "-std=c++11 \ # -Wno-system-headers We do not care about warnings in system headers. # -Wno-templates The library uses templates. -set(GCC_CXXFLAGS "-std=c++11 \ - -pedantic \ - -Werror \ - --all-warnings \ - --extra-warnings \ - -W \ - -WNSObject-attribute \ - -Wno-abi-tag \ - -Waddress \ - -Waddress-of-packed-member \ - -Wno-aggregate-return \ - -Waggressive-loop-optimizations \ - -Waligned-new=all \ - -Wall \ - -Walloc-zero \ - -Walloca \ - -Wanalyzer-double-fclose \ - -Wanalyzer-double-free \ - -Wanalyzer-exposure-through-output-file \ - -Wanalyzer-file-leak \ - -Wanalyzer-free-of-non-heap \ - -Wanalyzer-malloc-leak \ - -Wanalyzer-mismatching-deallocation \ - -Wanalyzer-null-argument \ - -Wanalyzer-null-dereference \ - -Wanalyzer-possible-null-argument \ - -Wanalyzer-possible-null-dereference \ - -Wanalyzer-shift-count-negative \ - -Wanalyzer-shift-count-overflow \ - -Wanalyzer-stale-setjmp-buffer \ - -Wanalyzer-tainted-array-index \ - -Wanalyzer-too-complex \ - -Wanalyzer-unsafe-call-within-signal-handler \ - -Wanalyzer-use-after-free \ - -Wanalyzer-use-of-pointer-in-stale-stack-frame \ - -Wanalyzer-write-to-const \ - -Wanalyzer-write-to-string-literal \ - -Warith-conversion \ - -Warray-bounds \ - -Warray-bounds=2 \ - -Warray-parameter=2 \ - -Wattribute-alias=2 \ - -Wattribute-warning \ - -Wattributes \ - -Wbool-compare \ - -Wbool-operation \ - -Wbuiltin-declaration-mismatch \ - -Wbuiltin-macro-redefined \ - -Wc++0x-compat \ - -Wc++11-compat \ - -Wc++14-compat \ - -Wc++17-compat \ - -Wc++1z-compat \ - -Wc++20-compat \ - -Wc++2a-compat \ - -Wcannot-profile \ - -Wcast-align \ - -Wcast-align=strict \ - -Wcast-function-type \ - -Wcast-qual \ - -Wcatch-value=3 \ - -Wchar-subscripts \ - -Wclass-conversion \ - -Wclass-memaccess \ - -Wclobbered \ - -Wcomma-subscript \ - -Wcomment \ - -Wcomments \ - -Wconditionally-supported \ - -Wconversion \ - -Wconversion-null \ - -Wcoverage-mismatch \ - -Wcpp \ - -Wctad-maybe-unsupported \ - -Wctor-dtor-privacy \ - -Wdangling-else \ - -Wdate-time \ - -Wdelete-incomplete \ - -Wdelete-non-virtual-dtor \ - -Wdeprecated \ - -Wdeprecated-copy \ - -Wdeprecated-copy-dtor \ - -Wdeprecated-declarations \ - -Wdeprecated-enum-enum-conversion \ - -Wdeprecated-enum-float-conversion \ - -Wdisabled-optimization \ - -Wdiv-by-zero \ - -Wdouble-promotion \ - -Wduplicated-branches \ - -Wduplicated-cond \ - -Weffc++ \ - -Wempty-body \ - -Wendif-labels \ - -Wenum-compare \ - -Wenum-conversion \ - -Wexpansion-to-defined \ - -Wextra \ - -Wextra-semi \ - -Wfloat-conversion \ - -Wfloat-equal \ - -Wformat-contains-nul \ - -Wformat-diag \ - -Wformat-extra-args \ - -Wformat-nonliteral \ - -Wformat-overflow=2 \ - -Wformat-security \ - -Wformat-signedness \ - -Wformat-truncation=2 \ - -Wformat-y2k \ - -Wformat-zero-length \ - -Wformat=2 \ - -Wframe-address \ - -Wfree-nonheap-object \ - -Whsa \ - -Wif-not-aligned \ - -Wignored-attributes \ - -Wignored-qualifiers \ - -Wimplicit-fallthrough=5 \ - -Winaccessible-base \ - -Winherited-variadic-ctor \ - -Winit-list-lifetime \ - -Winit-self \ - -Winline \ - -Wint-in-bool-context \ - -Wint-to-pointer-cast \ - -Winvalid-memory-model \ - -Winvalid-offsetof \ - -Winvalid-pch \ - -Wliteral-suffix \ - -Wlogical-not-parentheses \ - -Wlogical-op \ - -Wno-long-long \ - -Wlto-type-mismatch \ - -Wmain \ - -Wmaybe-uninitialized \ - -Wmemset-elt-size \ - -Wmemset-transposed-args \ - -Wmisleading-indentation \ - -Wmismatched-dealloc \ - -Wmismatched-new-delete \ - -Wmismatched-tags \ - -Wmissing-attributes \ - -Wmissing-braces \ - -Wmissing-declarations \ - -Wmissing-field-initializers \ - -Wmissing-include-dirs \ - -Wmissing-profile \ - -Wmultichar \ - -Wmultiple-inheritance \ - -Wmultistatement-macros \ - -Wno-namespaces \ - -Wnarrowing \ - -Wnoexcept \ - -Wnoexcept-type \ - -Wnon-template-friend \ - -Wnon-virtual-dtor \ - -Wnonnull \ - -Wnonnull-compare \ - -Wnormalized=nfkc \ - -Wnull-dereference \ - -Wodr \ - -Wold-style-cast \ - -Wopenmp-simd \ - -Woverflow \ - -Woverlength-strings \ - -Woverloaded-virtual \ - -Wpacked \ - -Wpacked-bitfield-compat \ - -Wpacked-not-aligned \ - -Wno-padded \ - -Wparentheses \ - -Wpedantic \ - -Wpessimizing-move \ - -Wplacement-new=2 \ - -Wpmf-conversions \ - -Wpointer-arith \ - -Wpointer-compare \ - -Wpragmas \ - -Wprio-ctor-dtor \ - -Wpsabi \ - -Wrange-loop-construct \ - -Wredundant-decls \ - -Wredundant-move \ - -Wredundant-tags \ - -Wregister \ - -Wreorder \ - -Wrestrict \ - -Wreturn-local-addr \ - -Wreturn-type \ - -Wscalar-storage-order \ - -Wsequence-point \ - -Wshadow=compatible-local \ - -Wshadow=global \ - -Wshadow=local \ - -Wshift-count-negative \ - -Wshift-count-overflow \ - -Wshift-negative-value \ - -Wshift-overflow=2 \ - -Wsign-compare \ - -Wsign-conversion \ - -Wsign-promo \ - -Wsized-deallocation \ - -Wsizeof-array-argument \ - -Wsizeof-array-div \ - -Wsizeof-pointer-div \ - -Wsizeof-pointer-memaccess \ - -Wstack-protector \ - -Wstrict-aliasing \ - -Wstrict-aliasing=3 \ - -Wstrict-null-sentinel \ - -Wstrict-overflow \ - -Wstrict-overflow=5 \ - -Wstring-compare \ - -Wstringop-overflow=4 \ - -Wstringop-overread \ - -Wstringop-truncation \ - -Wsubobject-linkage \ - -Wsuggest-attribute=cold \ - -Wsuggest-attribute=const \ - -Wsuggest-attribute=format \ - -Wsuggest-attribute=malloc \ - -Wsuggest-attribute=noreturn \ - -Wsuggest-attribute=pure \ - -Wsuggest-final-methods \ - -Wsuggest-final-types \ - -Wsuggest-override \ - -Wswitch \ - -Wswitch-bool \ - -Wswitch-default \ - -Wswitch-enum \ - -Wswitch-outside-range \ - -Wswitch-unreachable \ - -Wsync-nand \ - -Wsynth \ - -Wno-system-headers \ - -Wtautological-compare \ - -Wno-templates \ - -Wterminate \ - -Wtrampolines \ - -Wtrigraphs \ - -Wtsan \ - -Wtype-limits \ - -Wundef \ - -Wuninitialized \ - -Wunknown-pragmas \ - -Wunreachable-code \ - -Wunsafe-loop-optimizations \ - -Wunused \ - -Wunused-but-set-parameter \ - -Wunused-but-set-variable \ - -Wunused-const-variable=2 \ - -Wunused-function \ - -Wunused-label \ - -Wunused-local-typedefs \ - -Wunused-macros \ - -Wunused-parameter \ - -Wunused-result \ - -Wunused-value \ - -Wunused-variable \ - -Wuseless-cast \ - -Wvarargs \ - -Wvariadic-macros \ - -Wvector-operation-performance \ - -Wvexing-parse \ - -Wvirtual-inheritance \ - -Wvirtual-move-assign \ - -Wvla \ - -Wvla-parameter \ - -Wvolatile \ - -Wvolatile-register-var \ - -Wwrite-strings \ - -Wzero-as-null-pointer-constant \ - -Wzero-length-bounds \ -") +set(GCC_CXXFLAGS + -pedantic + -Werror + --all-warnings + --extra-warnings + -W + -WNSObject-attribute + -Wno-abi-tag + -Waddress + -Waddress-of-packed-member + -Wno-aggregate-return + -Waggressive-loop-optimizations + -Waligned-new=all + -Wall + -Walloc-zero + -Walloca + -Wanalyzer-double-fclose + -Wanalyzer-double-free + -Wanalyzer-exposure-through-output-file + -Wanalyzer-file-leak + -Wanalyzer-free-of-non-heap + -Wanalyzer-malloc-leak + -Wanalyzer-mismatching-deallocation + -Wanalyzer-null-argument + -Wanalyzer-null-dereference + -Wanalyzer-possible-null-argument + -Wanalyzer-possible-null-dereference + -Wanalyzer-shift-count-negative + -Wanalyzer-shift-count-overflow + -Wanalyzer-stale-setjmp-buffer + -Wanalyzer-tainted-allocation-size + -Wanalyzer-tainted-array-index + -Wanalyzer-tainted-divisor + -Wanalyzer-tainted-offset + -Wanalyzer-tainted-size + -Wanalyzer-too-complex + -Wanalyzer-unsafe-call-within-signal-handler + -Wanalyzer-use-after-free + -Wanalyzer-use-of-pointer-in-stale-stack-frame + -Wanalyzer-use-of-uninitialized-value + -Wanalyzer-va-arg-type-mismatch + -Wanalyzer-va-list-exhausted + -Wanalyzer-va-list-leak + -Wanalyzer-va-list-use-after-va-end + -Wanalyzer-write-to-const + -Wanalyzer-write-to-string-literal + -Warith-conversion + -Warray-bounds=2 + -Warray-compare + -Warray-parameter=2 + -Wattribute-alias=2 + -Wattribute-warning + -Wattributes + -Wbool-compare + -Wbool-operation + -Wbuiltin-declaration-mismatch + -Wbuiltin-macro-redefined + -Wc++0x-compat + -Wc++11-compat + -Wc++11-extensions + -Wc++14-compat + -Wc++14-extensions + -Wc++17-compat + -Wc++17-extensions + -Wc++1z-compat + -Wc++20-compat + -Wc++20-extensions + -Wc++23-extensions + -Wc++2a-compat + -Wcannot-profile + -Wcast-align + -Wcast-align=strict + -Wcast-function-type + -Wcast-qual + -Wcatch-value=3 + -Wchar-subscripts + -Wclass-conversion + -Wclass-memaccess + -Wclobbered + -Wcomma-subscript + -Wcomment + -Wcomments + -Wconditionally-supported + -Wconversion + -Wconversion-null + -Wcoverage-invalid-line-number + -Wcoverage-mismatch + -Wcpp + -Wctad-maybe-unsupported + -Wctor-dtor-privacy + -Wdangling-else + -Wdangling-pointer=2 + -Wdate-time + -Wdelete-incomplete + -Wdelete-non-virtual-dtor + -Wdeprecated + -Wdeprecated-copy + -Wdeprecated-copy-dtor + -Wdeprecated-declarations + -Wdeprecated-enum-enum-conversion + -Wdeprecated-enum-float-conversion + -Wdisabled-optimization + -Wdiv-by-zero + -Wdouble-promotion + -Wduplicated-branches + -Wduplicated-cond + -Weffc++ + -Wempty-body + -Wendif-labels + -Wenum-compare + -Wenum-conversion + -Wexceptions + -Wexpansion-to-defined + -Wextra + -Wextra-semi + -Wfloat-conversion + -Wfloat-equal + -Wformat-diag + -Wformat-overflow=2 + -Wformat-signedness + -Wformat-truncation=2 + -Wformat=2 + -Wframe-address + -Wfree-nonheap-object + -Whsa + -Wif-not-aligned + -Wignored-attributes + -Wignored-qualifiers + -Wimplicit-fallthrough=5 + -Winaccessible-base + -Winfinite-recursion + -Winherited-variadic-ctor + -Winit-list-lifetime + -Winit-self + -Winline + -Wint-in-bool-context + -Wint-to-pointer-cast + -Winterference-size + -Winvalid-imported-macros + -Winvalid-memory-model + -Winvalid-offsetof + -Winvalid-pch + -Wliteral-suffix + -Wlogical-not-parentheses + -Wlogical-op + -Wno-long-long + -Wlto-type-mismatch + -Wmain + -Wmaybe-uninitialized + -Wmemset-elt-size + -Wmemset-transposed-args + -Wmisleading-indentation + -Wmismatched-dealloc + -Wmismatched-new-delete + -Wmismatched-tags + -Wmissing-attributes + -Wmissing-braces + -Wmissing-declarations + -Wmissing-field-initializers + -Wmissing-include-dirs + -Wmissing-profile + -Wmissing-requires + -Wmissing-template-keyword + -Wmultichar + -Wmultiple-inheritance + -Wmultistatement-macros + -Wno-namespaces + -Wnarrowing + -Wnoexcept + -Wnoexcept-type + -Wnon-template-friend + -Wnon-virtual-dtor + -Wnonnull + -Wnonnull-compare + -Wnormalized=nfkc + -Wnull-dereference + -Wodr + -Wold-style-cast + -Wopenacc-parallelism + -Wopenmp-simd + -Woverflow + -Woverlength-strings + -Woverloaded-virtual + -Wpacked + -Wpacked-bitfield-compat + -Wpacked-not-aligned + -Wno-padded + -Wparentheses + -Wpedantic + -Wpessimizing-move + -Wplacement-new=2 + -Wpmf-conversions + -Wpointer-arith + -Wpointer-compare + -Wpragmas + -Wprio-ctor-dtor + -Wpsabi + -Wrange-loop-construct + -Wredundant-decls + -Wredundant-move + -Wredundant-tags + -Wregister + -Wreorder + -Wrestrict + -Wreturn-local-addr + -Wreturn-type + -Wscalar-storage-order + -Wsequence-point + -Wshadow=compatible-local + -Wshadow=global + -Wshadow=local + -Wshift-count-negative + -Wshift-count-overflow + -Wshift-negative-value + -Wshift-overflow=2 + -Wsign-compare + -Wsign-conversion + -Wsign-promo + -Wsized-deallocation + -Wsizeof-array-argument + -Wsizeof-array-div + -Wsizeof-pointer-div + -Wsizeof-pointer-memaccess + -Wstack-protector + -Wstrict-aliasing=3 + -Wstrict-null-sentinel + -Wno-strict-overflow + -Wstring-compare + -Wstringop-overflow=4 + -Wstringop-overread + -Wstringop-truncation + -Wsubobject-linkage + -Wsuggest-attribute=cold + -Wsuggest-attribute=const + -Wsuggest-attribute=format + -Wsuggest-attribute=malloc + -Wsuggest-attribute=noreturn + -Wsuggest-attribute=pure + -Wsuggest-final-methods + -Wsuggest-final-types + -Wsuggest-override + -Wswitch + -Wswitch-bool + -Wswitch-default + -Wswitch-enum + -Wswitch-outside-range + -Wswitch-unreachable + -Wsync-nand + -Wsynth + -Wno-system-headers + -Wtautological-compare + -Wno-templates + -Wterminate + -Wtrampolines + -Wtrigraphs + -Wtrivial-auto-var-init + -Wtsan + -Wtype-limits + -Wundef + -Wuninitialized + -Wunknown-pragmas + -Wunreachable-code + -Wunsafe-loop-optimizations + -Wunused + -Wunused-but-set-parameter + -Wunused-but-set-variable + -Wunused-const-variable=2 + -Wunused-function + -Wunused-label + -Wunused-local-typedefs + -Wunused-macros + -Wunused-parameter + -Wunused-result + -Wunused-value + -Wunused-variable + -Wuse-after-free=3 + -Wuseless-cast + -Wvarargs + -Wvariadic-macros + -Wvector-operation-performance + -Wvexing-parse + -Wvirtual-inheritance + -Wvirtual-move-assign + -Wvla + -Wvla-parameter + -Wvolatile + -Wvolatile-register-var + -Wwrite-strings + -Wzero-as-null-pointer-constant + -Wzero-length-bounds +) add_custom_target(ci_test_gcc - COMMAND CXX=${GCC_TOOL} CXXFLAGS=${GCC_CXXFLAGS} ${CMAKE_COMMAND} + COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -406,9 +424,9 @@ add_custom_target(ci_test_gcc ) add_custom_target(ci_test_clang - COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXXFLAGS} ${CMAKE_COMMAND} + COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang COMMAND cd ${PROJECT_BINARY_DIR}/build_clang && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -421,10 +439,10 @@ add_custom_target(ci_test_clang foreach(CXX_STANDARD 11 14 17 20) add_custom_target(ci_test_gcc_cxx${CXX_STANDARD} - COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND} + COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON -DJSON_BuildTests=ON -DJSON_FastTests=ON + -DJSON_TestStandards=${CXX_STANDARD} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} COMMAND cd ${PROJECT_BINARY_DIR}/build_gcc_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -432,10 +450,10 @@ foreach(CXX_STANDARD 11 14 17 20) ) add_custom_target(ci_test_clang_cxx${CXX_STANDARD} - COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} + COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DCMAKE_CXX_STANDARD=${CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON - -DJSON_BuildTests=ON + -DJSON_BuildTests=ON -DJSON_FastTests=ON + -DJSON_TestStandards=${CXX_STANDARD} -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -450,7 +468,7 @@ endforeach() add_custom_target(ci_test_noexceptions COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw + -DJSON_BuildTests=ON -DCMAKE_CXX_FLAGS=-DJSON_NOEXCEPTION -DDOCTEST_TEST_FILTER=--no-throw -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noexceptions COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noexceptions COMMAND cd ${PROJECT_BINARY_DIR}/build_noexceptions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -464,7 +482,7 @@ add_custom_target(ci_test_noexceptions add_custom_target(ci_test_noimplicitconversions COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_ImplicitConversions=OFF + -DJSON_BuildTests=ON -DJSON_ImplicitConversions=OFF -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noimplicitconversions COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noimplicitconversions COMMAND cd ${PROJECT_BINARY_DIR}/build_noimplicitconversions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure @@ -478,13 +496,41 @@ add_custom_target(ci_test_noimplicitconversions add_custom_target(ci_test_diagnostics COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON -DJSON_Diagnostics=ON + -DJSON_BuildTests=ON -DJSON_Diagnostics=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostics COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostics COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostics && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMENT "Compile and test with improved diagnostics enabled" ) +############################################################################### +# Enable legacy discarded value comparison. +############################################################################### + +add_custom_target(ci_test_legacycomparison + COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_LegacyDiscardedValueComparison=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_legacycomparison + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_legacycomparison + COMMAND cd ${PROJECT_BINARY_DIR}/build_legacycomparison && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test with legacy discarded value comparison enabled" +) + +############################################################################### +# Disable global UDLs. +############################################################################### + +add_custom_target(ci_test_noglobaludls + COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_UseGlobalUDLs=OFF + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_noglobaludls + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_noglobaludls + COMMAND cd ${PROJECT_BINARY_DIR}/build_noglobaludls && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test with global UDLs disabled" +) + ############################################################################### # Coverage. ############################################################################### @@ -492,14 +538,21 @@ add_custom_target(ci_test_diagnostics add_custom_target(ci_test_coverage COMMAND CXX=g++ ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="--coverage;-fprofile-arcs;-ftest-coverage" - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMAND CXX=g++ ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CXX_FLAGS="-m32;--coverage;-fprofile-arcs;-ftest-coverage" + -DJSON_BuildTests=ON -DJSON_32bitTest=ONLY + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_coverage32 + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_coverage32 + COMMAND cd ${PROJECT_BINARY_DIR}/build_coverage32 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMAND ${LCOV_TOOL} --directory . --capture --output-file json.info --rc lcov_branch_coverage=1 COMMAND ${LCOV_TOOL} -e json.info ${SRC_FILES} --output-file json.info.filtered --rc lcov_branch_coverage=1 - COMMAND ${CMAKE_SOURCE_DIR}/test/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept + COMMAND ${CMAKE_SOURCE_DIR}/tests/thirdparty/imapdl/filterbr.py json.info.filtered > json.info.filtered.noexcept COMMAND genhtml --title "JSON for Modern C++" --legend --demangle-cpp --output-directory html --show-details --branch-coverage json.info.filtered.noexcept COMMENT "Compile and test with coverage" @@ -529,16 +582,16 @@ set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-sw file(GLOB_RECURSE INDENT_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp - ${PROJECT_SOURCE_DIR}/test/src/*.cpp - ${PROJECT_SOURCE_DIR}/test/src/*.hpp - ${PROJECT_SOURCE_DIR}/benchmarks/src/benchmarks.cpp - ${PROJECT_SOURCE_DIR}/doc/examples/*.cpp + ${PROJECT_SOURCE_DIR}/tests/src/*.cpp + ${PROJECT_SOURCE_DIR}/tests/src/*.hpp + ${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp + ${PROJECT_SOURCE_DIR}/docs/examples/*.cpp ) add_custom_target(ci_test_amalgamation COMMAND rm -fr ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ COMMAND cp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ - COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/third_party/amalgamate/amalgamate.py -c ${PROJECT_SOURCE_DIR}/third_party/amalgamate/config.json -s . + COMMAND ${Python3_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/amalgamate/amalgamate.py -c ${PROJECT_SOURCE_DIR}/tools/amalgamate/config.json -s . COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp COMMAND diff ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp~ ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp @@ -546,7 +599,21 @@ add_custom_target(ci_test_amalgamation COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `find . -name '*.orig'`\; do false \; done WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMENT "Check amalagamation and indentation" + COMMENT "Check amalgamation and indentation" +) + +############################################################################### +# Build and test using the amalgamated header +############################################################################### + +add_custom_target(ci_test_single_header + COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_MultipleHeaders=OFF -DJSON_FastTests=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_single_header + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_single_header + COMMAND cd ${PROJECT_BINARY_DIR}/build_single_header && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test single-header version" ) ############################################################################### @@ -592,7 +659,7 @@ add_custom_target(ci_cppcheck ############################################################################### add_custom_target(ci_cpplint - COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/third_party/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES} + COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/cpplint/cpplint.py --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES} COMMENT "Check code with cpplint" ) @@ -632,7 +699,7 @@ add_custom_target(ci_clang_tidy COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=${CLANG_TIDY_TOOL} - -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + -DJSON_BuildTests=ON -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_tidy COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_tidy COMMENT "Check code with Clang-Tidy" @@ -659,7 +726,7 @@ add_custom_target(ci_pvs_studio add_custom_target(ci_infer COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer - COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON -DJSON_MultipleHeaders=ON + COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make COMMENT "Check code with Infer" ) @@ -670,7 +737,7 @@ add_custom_target(ci_infer add_custom_target(ci_offline_testdata COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data - COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.0.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1 + COMMAND cd ${PROJECT_BINARY_DIR}/build_offline_testdata/test_data && ${GIT_TOOL} clone -c advice.detachedHead=false --branch v3.1.0 https://github.com/nlohmann/json_test_data.git --quiet --depth 1 COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_TestDataDirectory=${PROJECT_BINARY_DIR}/build_offline_testdata/test_data/json_test_data @@ -685,6 +752,7 @@ add_custom_target(ci_offline_testdata ############################################################################### add_custom_target(ci_non_git_tests + COMMAND git config --global --add safe.directory ${PROJECT_SOURCE_DIR} COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_non_git_tests/sources COMMAND cd ${PROJECT_SOURCE_DIR} && for FILE in `${GIT_TOOL} ls-tree --name-only HEAD`\; do cp -r $$FILE ${PROJECT_BINARY_DIR}/build_non_git_tests/sources \; done COMMAND ${CMAKE_COMMAND} @@ -756,50 +824,68 @@ add_custom_target(ci_benchmarks # CMake flags ############################################################################### -if (APPLE) - set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Darwin64/CMake.app/Contents/bin/cmake) - add_custom_command( - OUTPUT ${CMAKE_310_BINARY} - COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Darwin64.tar.gz - COMMAND tar xfz cmake-3.1.0-Darwin64.tar.gz - COMMAND rm cmake-3.1.0-Darwin64.tar.gz - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - COMMENT "Download CMake 3.1.0" - ) -else() - set(CMAKE_310_BINARY ${PROJECT_BINARY_DIR}/cmake-3.1.0-Linux-x86_64/bin/cmake) - add_custom_command( - OUTPUT ${CMAKE_310_BINARY} - COMMAND wget https://github.com/Kitware/CMake/releases/download/v3.1.0/cmake-3.1.0-Linux-x86_64.tar.gz - COMMAND tar xfz cmake-3.1.0-Linux-x86_64.tar.gz - COMMAND rm cmake-3.1.0-Linux-x86_64.tar.gz - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - COMMENT "Download CMake 3.1.0" - ) -endif() +function(ci_get_cmake version var) + if (APPLE) + set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Darwin64/CMake.app/Contents/bin/cmake) + add_custom_command( + OUTPUT ${${var}} + COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Darwin64.tar.gz + COMMAND tar xfz cmake-${version}-Darwin64.tar.gz + COMMAND rm cmake-${version}-Darwin64.tar.gz + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Download CMake ${version}" + ) + else() + set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}-Linux-x86_64/bin/cmake) + add_custom_command( + OUTPUT ${${var}} + COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-Linux-x86_64.tar.gz + COMMAND tar xfz cmake-${version}-Linux-x86_64.tar.gz + COMMAND rm cmake-${version}-Linux-x86_64.tar.gz + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Download CMake ${version}" + ) + endif() + set(${var} ${${var}} PARENT_SCOPE) +endfunction() -set(JSON_CMAKE_FLAGS "JSON_BuildTests;JSON_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude") +ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY) +ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY) -foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS}) - string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" JSON_CMAKE_FLAG_TARGET) - add_custom_target("${JSON_CMAKE_FLAG_TARGET}" - COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})" +set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization + JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind) +set(JSON_CMAKE_FLAGS_3_13_0 JSON_BuildTests) + +function(ci_add_cmake_flags_targets flag min_version) + string(TOLOWER "ci_cmake_flag_${flag}" flag_target) + string(REPLACE . _ min_version_var ${min_version}) + set(cmake_binary ${CMAKE_${min_version_var}_BINARY}) + add_custom_target(${flag_target} + COMMENT "Check CMake flag ${flag} (CMake ${CMAKE_VERSION})" COMMAND ${CMAKE_COMMAND} -Werror=dev - -D${JSON_CMAKE_FLAG}=ON - -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET} + -D${flag}=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target} ) - add_custom_target("${JSON_CMAKE_FLAG_TARGET}_31" - COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake 3.1)" - COMMAND mkdir ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31 - COMMAND cd ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31 && ${CMAKE_310_BINARY} - -Werror=dev ${PROJECT_SOURCE_DIR} - -D${JSON_CMAKE_FLAG}=ON - -DCMAKE_CXX_COMPILE_FEATURES="cxx_range_for" -DCMAKE_CXX_FLAGS="-std=gnu++11" - DEPENDS ${CMAKE_310_BINARY} + add_custom_target(${flag_target}_${min_version_var} + COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${min_version})" + COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var} + COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var} + && ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON + DEPENDS ${cmake_binary} ) - list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${JSON_CMAKE_FLAG_TARGET}_31) - list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET} ${PROJECT_BINARY_DIR}/build_${JSON_CMAKE_FLAG_TARGET}_31) + list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${flag_target}_${min_version_var}) + list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target} ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}) + set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE) + set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE) +endfunction() + +foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_1_0}) + ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.1.0) +endforeach() + +foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_3_13_0}) + ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 3.13.0) endforeach() add_custom_target(ci_cmake_flags @@ -811,7 +897,7 @@ add_custom_target(ci_cmake_flags # Use more installed compilers. ############################################################################### -foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13) +foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14) find_program(COMPILER_TOOL NAMES ${COMPILER}) if (COMPILER_TOOL) if ("${COMPILER}" STREQUAL "clang++-9") @@ -843,10 +929,35 @@ add_custom_target(ci_cuda_example COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug -GNinja -DCMAKE_CUDA_HOST_COMPILER=g++-8 - -S${PROJECT_SOURCE_DIR}/test/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example + -S${PROJECT_SOURCE_DIR}/tests/cuda_example -B${PROJECT_BINARY_DIR}/build_cuda_example COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_cuda_example ) +############################################################################### +# Intel C++ Compiler +############################################################################### + +add_custom_target(ci_icpc + COMMAND ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc + -DJSON_BuildTests=ON -DJSON_FastTests=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpc + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpc + COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure + COMMENT "Compile and test with ICPC" +) + +############################################################################### +# test documentation +############################################################################### + +add_custom_target(ci_test_documentation + COMMAND make CXX="${GCC_TOOL}" check_output_portable -j8 + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs + COMMENT "Check that all examples compile and create the desired output" +) + ############################################################################### # Clean up all generated files. ############################################################################### diff --git a/cmake/download_test_data.cmake b/cmake/download_test_data.cmake index f516a7c3b..1bb998dae 100644 --- a/cmake/download_test_data.cmake +++ b/cmake/download_test_data.cmake @@ -1,5 +1,5 @@ set(JSON_TEST_DATA_URL https://github.com/nlohmann/json_test_data) -set(JSON_TEST_DATA_VERSION 3.0.0) +set(JSON_TEST_DATA_VERSION 3.1.0) # if variable is set, use test data from given directory rather than downloading them if(JSON_TestDataDirectory) diff --git a/cmake/test.cmake b/cmake/test.cmake new file mode 100644 index 000000000..bb840c6c0 --- /dev/null +++ b/cmake/test.cmake @@ -0,0 +1,273 @@ +set(_json_test_cmake_list_file ${CMAKE_CURRENT_LIST_FILE}) + +############################################################################# +# download test data +############################################################################# + +include(download_test_data) + +# test fixture to download test data +add_test(NAME "download_test_data" COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} + --target download_test_data +) +set_tests_properties(download_test_data PROPERTIES FIXTURES_SETUP TEST_DATA) + +if(JSON_Valgrind) + find_program(CMAKE_MEMORYCHECK_COMMAND valgrind) + message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})") + set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full") + separate_arguments(memcheck_command) +endif() + +############################################################################# +# detect standard support +############################################################################# + +# C++11 is the minimum required +set(compiler_supports_cpp_11 TRUE) + +foreach(feature ${CMAKE_CXX_COMPILE_FEATURES}) + if (${feature} STREQUAL cxx_std_14) + set(compiler_supports_cpp_14 TRUE) + elseif (${feature} STREQUAL cxx_std_17) + set(compiler_supports_cpp_17 TRUE) + elseif (${feature} STREQUAL cxx_std_20) + set(compiler_supports_cpp_20 TRUE) + elseif (${feature} STREQUAL cxx_std_23) + set(compiler_supports_cpp_23 TRUE) + endif() +endforeach() + +############################################################################# +# test functions +############################################################################# + +############################################################################# +# json_test_set_test_options( +# all| +# [CXX_STANDARDS all|...] +# [COMPILE_DEFINITIONS ...] +# [COMPILE_FEATURES ...] +# [COMPILE_OPTIONS ...] +# [LINK_LIBRARIES ...] +# [LINK_OPTIONS ...] +# [TEST_PROPERTIES ...]) +# +# Supply test- and standard-specific build settings and/or test properties. +# Specify multiple tests using a list e.g., "test-foo;test-bar". +# +# Must be called BEFORE the test is created. +############################################################################# + +function(json_test_set_test_options tests) + cmake_parse_arguments(args "" "" + "CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES" + ${ARGN}) + + if(NOT args_CXX_STANDARDS) + set(args_CXX_STANDARDS "all") + endif() + + foreach(test ${tests}) + if("${test}" STREQUAL "all") + set(test "") + endif() + + foreach(cxx_standard ${args_CXX_STANDARDS}) + if("${cxx_standard}" STREQUAL "all") + if("${test}" STREQUAL "") + message(FATAL_ERROR "Not supported. Change defaults in: ${_json_test_cmake_list_file}") + endif() + set(test_interface _json_test_interface_${test}) + else() + set(test_interface _json_test_interface_${test}_cpp_${cxx_standard}) + endif() + + if(NOT TARGET ${test_interface}) + add_library(${test_interface} INTERFACE) + endif() + + target_compile_definitions(${test_interface} INTERFACE ${args_COMPILE_DEFINITIONS}) + target_compile_features(${test_interface} INTERFACE ${args_COMPILE_FEATURES}) + target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS}) + target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES}) + target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS}) + #set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}") + set_property(DIRECTORY PROPERTY + ${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}" + ) + endforeach() + endforeach() +endfunction() + +# for internal use by _json_test_add_test() +function(_json_test_apply_test_properties test_target properties_target) + #get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES) + get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES) + if(test_properties) + set_tests_properties(${test_target} PROPERTIES ${test_properties}) + endif() +endfunction() + +# for internal use by json_test_add_test_for() +function(_json_test_add_test test_name file main cxx_standard) + set(test_target ${test_name}_cpp${cxx_standard}) + + if(TARGET ${test_target}) + message(FATAL_ERROR "Target ${test_target} has already been added.") + endif() + + add_executable(${test_target} ${file}) + target_link_libraries(${test_target} PRIVATE ${main}) + + # set and require C++ standard + set_target_properties(${test_target} PROPERTIES + CXX_STANDARD ${cxx_standard} + CXX_STANDARD_REQUIRED ON + ) + + # apply standard-specific build settings + if(TARGET _json_test_interface__cpp_${cxx_standard}) + target_link_libraries(${test_target} PRIVATE _json_test_interface__cpp_${cxx_standard}) + endif() + + # apply test-specific build settings + if(TARGET _json_test_interface_${test_name}) + target_link_libraries(${test_target} PRIVATE _json_test_interface_${test_name}) + endif() + + # apply test- and standard-specific build settings + if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard}) + target_link_libraries(${test_target} PRIVATE + _json_test_interface_${test_name}_cpp_${cxx_standard} + ) + endif() + + if (JSON_FastTests) + add_test(NAME ${test_target} + COMMAND ${test_target} ${DOCTEST_TEST_FILTER} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + else() + add_test(NAME ${test_target} + COMMAND ${test_target} ${DOCTEST_TEST_FILTER} --no-skip + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + endif() + set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA) + + # apply standard-specific test properties + if(TARGET _json_test_interface__cpp_${cxx_standard}) + _json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard}) + endif() + + # apply test-specific test properties + if(TARGET _json_test_interface_${test_name}) + _json_test_apply_test_properties(${test_target} _json_test_interface_${test_name}) + endif() + + # apply test- and standard-specific test properties + if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard}) + _json_test_apply_test_properties(${test_target} + _json_test_interface_${test_name}_cpp_${cxx_standard} + ) + endif() + + if(JSON_Valgrind) + add_test(NAME ${test_target}_valgrind + COMMAND ${memcheck_command} $ ${DOCTEST_TEST_FILTER} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + ) + set_tests_properties(${test_target}_valgrind PROPERTIES + LABELS "valgrind" FIXTURES_REQUIRED TEST_DATA + ) + endif() +endfunction() + +############################################################################# +# json_test_add_test_for( +# +# [NAME ] +# MAIN
+# [CXX_STANDARDS ...] [FORCE]) +# +# Given a unit-foo.cpp, produces +# +# test-foo_cpp +# +# if C++ standard is supported by the compiler and the +# source file contains JSON_HAS_CPP_. +# Use NAME to override the filename-derived test name. +# Use FORCE to create the test regardless of the file containing +# JSON_HAS_CPP_. +# Test targets are linked against
. +# CXX_STANDARDS defaults to "11". +############################################################################# + +function(json_test_add_test_for file) + cmake_parse_arguments(args "FORCE" "MAIN;NAME" "CXX_STANDARDS" ${ARGN}) + + if("${args_MAIN}" STREQUAL "") + message(FATAL_ERROR "Required argument MAIN
missing.") + endif() + + if("${args_NAME}" STREQUAL "") + get_filename_component(file_basename ${file} NAME_WE) + string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) + else() + set(test_name ${args_NAME}) + if(NOT test_name MATCHES "test-[^$]+") + message(FATAL_ERROR "Test name must start with 'test-'.") + endif() + endif() + + if("${args_CXX_STANDARDS}" STREQUAL "") + set(args_CXX_STANDARDS 11) + endif() + + file(READ ${file} file_content) + foreach(cxx_standard ${args_CXX_STANDARDS}) + if(NOT compiler_supports_cpp_${cxx_standard}) + continue() + endif() + + # add unconditionally if C++11 (default) or forced + if(NOT ("${cxx_standard}" STREQUAL 11 OR args_FORCE)) + string(FIND "${file_content}" JSON_HAS_CPP_${cxx_standard} has_cpp_found) + if(${has_cpp_found} EQUAL -1) + continue() + endif() + endif() + + _json_test_add_test(${test_name} ${file} ${args_MAIN} ${cxx_standard}) + endforeach() +endfunction() + +############################################################################# +# json_test_should_build_32bit_test( +# ) +# +# Check if the 32bit unit test should be built based on the value of +# and store the result in the variables and +# . +############################################################################# + +function(json_test_should_build_32bit_test build_32bit_var build_32bit_only_var input) + set(${build_32bit_only_var} OFF PARENT_SCOPE) + string(TOUPPER "${input}" ${build_32bit_var}) + if("${${build_32bit_var}}" STREQUAL AUTO) + # check if compiler is targeting 32bit by default + include(CheckTypeSize) + check_type_size("size_t" sizeof_size_t LANGUAGE CXX) + if(sizeof_size_t AND ${sizeof_size_t} EQUAL 4) + message(STATUS "Auto-enabling 32bit unit test.") + set(${build_32bit_var} ON) + else() + set(${build_32bit_var} OFF) + endif() + elseif("${${build_32bit_var}}" STREQUAL ONLY) + set(${build_32bit_only_var} ON PARENT_SCOPE) + endif() + + set(${build_32bit_var} "${${build_32bit_var}}" PARENT_SCOPE) +endfunction() diff --git a/doc/avatars.png b/doc/avatars.png deleted file mode 100644 index 51243580d..000000000 Binary files a/doc/avatars.png and /dev/null differ diff --git a/doc/docset/Makefile b/doc/docset/Makefile deleted file mode 100644 index e538661ec..000000000 --- a/doc/docset/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -JSON_for_Modern_C++.docset: Info.plist docSet.sql - $(MAKE) clean - mkdir -p JSON_for_Modern_C++.docset/Contents/Resources/Documents/ - cp icon*.png JSON_for_Modern_C++.docset - cp Info.plist JSON_for_Modern_C++.docset/Contents - # build and copy documentation - $(MAKE) build -C ../mkdocs - cp -r ../mkdocs/site/* JSON_for_Modern_C++.docset/Contents/Resources/Documents - # patch CSS to hide navigation items - echo "\n\nheader, footer, navi, div.md-sidebar--primary, nav.md-tabs--active, a.md-content__button { display: none; }" >> "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)" - # fix spacing - echo "\n\ndiv.md-sidebar div.md-sidebar--secondary, div.md-main__inner { top: 0; margin-top: 0 }" >> "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)" - # remove "JSON for Modern C++" from page titles - find JSON_for_Modern_C++.docset/Contents/Resources/Documents -type f -exec gsed -i 's| - JSON for Modern C++||' {} + - # clean up - rm JSON_for_Modern_C++.docset/Contents/Resources/Documents/hooks.py - rm JSON_for_Modern_C++.docset/Contents/Resources/Documents/sitemap.* - # generate index - sqlite3 JSON_for_Modern_C++.docset/Contents/Resources/docSet.dsidx < docSet.sql - -JSON_for_Modern_C++.tgz: JSON_for_Modern_C++.docset - tar --exclude='.DS_Store' -cvzf JSON_for_Modern_C++.tgz JSON_for_Modern_C++.docset - -clean: - rm -fr JSON_for_Modern_C++.docset JSON_for_Modern_C++.tgz diff --git a/doc/docset/docSet.sql b/doc/docset/docSet.sql deleted file mode 100644 index 8bd4e0678..000000000 --- a/doc/docset/docSet.sql +++ /dev/null @@ -1,155 +0,0 @@ -DROP TABLE IF EXISTS searchIndex; -CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT); -CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path); - --- API -INSERT INTO searchIndex(name, type, path) VALUES ('accept', 'Function', 'api/basic_json/accept/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer', 'Class', 'api/adl_serializer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('array', 'Function', 'api/basic_json/array/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('array_t', 'Type', 'api/basic_json/array_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('at', 'Method', 'api/basic_json/at/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('back', 'Method', 'api/basic_json/back/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/basic_json/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Constructor', 'api/basic_json/basic_json/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('begin', 'Method', 'api/basic_json/begin/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('binary', 'Function', 'api/basic_json/binary/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('binary_t', 'Type', 'api/basic_json/binary_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('boolean_t', 'Type', 'api/basic_json/boolean_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('cbegin', 'Method', 'api/basic_json/cbegin/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('cbor_tag_handler_t', 'Enum', 'api/basic_json/cbor_tag_handler_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('cend', 'Method', 'api/basic_json/cend/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('clear', 'Method', 'api/basic_json/clear/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('contains', 'Method', 'api/basic_json/contains/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('count', 'Method', 'api/basic_json/count/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('crbegin', 'Method', 'api/basic_json/crbegin/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('crend', 'Method', 'api/basic_json/crend/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('diff', 'Function', 'api/basic_json/diff/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('dump', 'Method', 'api/basic_json/dump/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('emplace', 'Method', 'api/basic_json/emplace/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('emplace_back', 'Method', 'api/basic_json/emplace_back/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('empty', 'Method', 'api/basic_json/empty/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('end', 'Method', 'api/basic_json/end/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('erase', 'Method', 'api/basic_json/erase/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('error_handler_t', 'Enum', 'api/basic_json/error_handler_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('exception', 'Class', 'api/basic_json/exception/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('find', 'Method', 'api/basic_json/find/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('flatten', 'Method', 'api/basic_json/flatten/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('from_bson', 'Function', 'api/basic_json/from_bson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('from_cbor', 'Function', 'api/basic_json/from_cbor/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('from_msgpack', 'Function', 'api/basic_json/from_msgpack/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('from_ubjson', 'Function', 'api/basic_json/from_ubjson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('front', 'Method', 'api/basic_json/front/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get', 'Method', 'api/basic_json/get/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get_allocator', 'Function', 'api/basic_json/get_allocator/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get_binary', 'Method', 'api/basic_json/get_binary/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get_ptr', 'Method', 'api/basic_json/get_ptr/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get_ref', 'Method', 'api/basic_json/get_ref/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('get_to', 'Method', 'api/basic_json/get_to/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('input_format_t', 'Enum', 'api/basic_json/input_format_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('insert', 'Method', 'api/basic_json/insert/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('invalid_iterator', 'Class', 'api/basic_json/invalid_iterator/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_array', 'Method', 'api/basic_json/is_array/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_binary', 'Method', 'api/basic_json/is_binary/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_boolean', 'Method', 'api/basic_json/is_boolean/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_discarded', 'Method', 'api/basic_json/is_discarded/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_null', 'Method', 'api/basic_json/is_null/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_number', 'Method', 'api/basic_json/is_number/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_number_float', 'Method', 'api/basic_json/is_number_float/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_number_integer', 'Method', 'api/basic_json/is_number_integer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_number_unsigned', 'Method', 'api/basic_json/is_number_unsigned/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_object', 'Method', 'api/basic_json/is_object/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_primitive', 'Method', 'api/basic_json/is_primitive/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_string', 'Method', 'api/basic_json/is_string/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('is_structured', 'Method', 'api/basic_json/is_structured/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('items', 'Method', 'api/basic_json/items/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('json', 'Class', 'api/json/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer', 'Class', 'api/json_pointer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('json_serializer', 'Type', 'api/basic_json/json_serializer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('max_size', 'Method', 'api/basic_json/max_size/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('merge_patch', 'Method', 'api/basic_json/merge_patch/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('meta', 'Function', 'api/basic_json/meta/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('number_float_t', 'Type', 'api/basic_json/number_float_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('number_integer_t', 'Type', 'api/basic_json/number_integer_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('number_unsigned_t', 'Type', 'api/basic_json/number_unsigned_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('object', 'Function', 'api/basic_json/object/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('object_comparator_t', 'Type', 'api/basic_json/object_comparator_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('object_t', 'Type', 'api/basic_json/object_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator!=', 'Operator', 'api/basic_json/operator_ne/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator+=', 'Operator', 'api/basic_json/operator+=/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator=', 'Operator', 'api/basic_json/operator=/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator==', 'Operator', 'api/basic_json/operator_eq/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator<', 'Operator', 'api/basic_json/operator_lt/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator<=', 'Operator', 'api/basic_json/operator_le/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator>', 'Operator', 'api/basic_json/operator_gt/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator>=', 'Operator', 'api/basic_json/operator_ge/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator[]', 'Operator', 'api/basic_json/operator[]/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json', 'Literal', 'api/basic_json/operator_literal_json/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json_pointer', 'Literal', 'api/basic_json/operator_literal_json_pointer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator ValueType', 'Operator', 'api/basic_json/operator_ValueType/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('operator value_t', 'Operator', 'api/basic_json/operator_value_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('ordered_json', 'Class', 'api/ordered_json/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map', 'Class', 'api/ordered_map/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('out_of_range', 'Class', 'api/basic_json/out_of_range/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('other_error', 'Class', 'api/basic_json/other_error/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('parse', 'Function', 'api/basic_json/parse/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('parse_error', 'Class', 'api/basic_json/parse_error/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('parse_event_t', 'Enum', 'api/basic_json/parse_event_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('parser_callback_t', 'Type', 'api/basic_json/parser_callback_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('patch', 'Method', 'api/basic_json/patch/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('push_back', 'Method', 'api/basic_json/push_back/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('rbegin', 'Method', 'api/basic_json/rbegin/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('rend', 'Method', 'api/basic_json/rend/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('sax_parse', 'Function', 'api/basic_json/sax_parse/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('size', 'Method', 'api/basic_json/size/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('string_t', 'Type', 'api/basic_json/string_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('type', 'Method', 'api/basic_json/type/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('type_error', 'Class', 'api/basic_json/type_error/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('type_name', 'Method', 'api/basic_json/type_name/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('unflatten', 'Method', 'api/basic_json/unflatten/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('update', 'Method', 'api/basic_json/update/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('to_bson', 'Function', 'api/basic_json/to_bson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('to_cbor', 'Function', 'api/basic_json/to_cbor/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('to_msgpack', 'Function', 'api/basic_json/to_msgpack/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('to_ubjson', 'Function', 'api/basic_json/to_ubjson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('value', 'Method', 'api/basic_json/value/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('value_t', 'Enum', 'api/basic_json/value_t/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('~basic_json', 'Method', 'api/basic_json/~basic_json/index.html'); - --- Features -INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats', 'Guide', 'features/binary_formats/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('BSON', 'Guide', 'features/binary_formats/bson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('CBOR', 'Guide', 'features/binary_formats/cbor/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('MessagePack', 'Guide', 'features/binary_formats/messagepack/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('UBJSON', 'Guide', 'features/binary_formats/ubjson/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Supported Macros', 'Guide', 'features/macros/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Binary Values', 'Guide', 'features/binary_values/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Comments', 'Guide', 'features/comments/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Iterators', 'Guide', 'features/iterators/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Types', 'Guide', 'features/types/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Number Handling', 'Guide', 'features/types/number_handling/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Element Access', 'Guide', 'features/element_access/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON Pointer', 'Guide', 'features/json_pointer/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON Patch and Diff', 'Guide', 'features/json_patch/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON Merge Patch', 'Guide', 'features/merge_patch/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Object Order', 'Guide', 'features/object_order/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Parsing and Exceptions', 'Guide', 'features/parsing/parse_exceptions/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('Parser Callbacks', 'Guide', 'features/parsing/parser_callbacks/index.html'); -INSERT INTO searchIndex(name, type, path) VALUES ('SAX Interface', 'Guide', 'features/parsing/sax_interface/index.html'); - --- Macros -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'features/macros/index.html#json_assertx'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'features/macros/index.html#json_catch_userexception'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'features/macros/index.html#json_diagnostics'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_20', 'Macro', 'features/macros/index.html#json_has_cpp_11-json_has_cpp_14-json_has_cpp_17-json_has_cpp_20'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NOEXCEPTION', 'Macro', 'features/macros/index.html#json_noexception'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_IO', 'Macro', 'features/macros/index.html#json_no_io'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_UNSUPPORTED_COMPILER_CHECK', 'Macro', 'features/macros/index.html#json_skip_unsupported_compiler_check'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_THROW_USER', 'Macro', 'features/macros/index.html#json_throw_userexception'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_TRY_USER', 'Macro', 'features/macros/index.html#json_try_user'); -INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_IMPLICIT_CONVERSIONS', 'Macro', 'features/macros/index.html#json_use_implicit_conversions'); -INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE', 'Macro', 'features/macros/index.html#nlohmann_define_type_intrusivetype-member'); -INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE', 'Macro', 'features/macros/index.html#nlohmann_define_type_non_intrusivetype-member'); -INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM', 'Macro', 'features/macros/index.html#nlohmann_json_serialize_enumtype'); diff --git a/doc/examples/iterator_wrapper.cpp b/doc/examples/iterator_wrapper.cpp deleted file mode 100644 index 84d37254b..000000000 --- a/doc/examples/iterator_wrapper.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -using json = nlohmann::json; - -int main() -{ - // create JSON values - json j_object = {{"one", 1}, {"two", 2}}; - json j_array = {1, 2, 4, 8, 16}; - - ////////////////////////////////////////////////////////////////////////// - // The static function iterator_wrapper was deprecated in version 3.1.0 - // and will be removed in version 4.0.0. Please replace all occurrences - // of iterator_wrapper(j) with j.items(). - ////////////////////////////////////////////////////////////////////////// - - // example for an object - for (auto& x : json::iterator_wrapper(j_object)) - { - std::cout << "key: " << x.key() << ", value: " << x.value() << '\n'; - } - - // example for an array - for (auto& x : json::iterator_wrapper(j_array)) - { - std::cout << "key: " << x.key() << ", value: " << x.value() << '\n'; - } -} diff --git a/doc/examples/iterator_wrapper.output b/doc/examples/iterator_wrapper.output deleted file mode 100644 index 89b09f524..000000000 --- a/doc/examples/iterator_wrapper.output +++ /dev/null @@ -1,7 +0,0 @@ -key: one, value: 1 -key: two, value: 2 -key: 0, value: 1 -key: 1, value: 2 -key: 2, value: 4 -key: 3, value: 8 -key: 4, value: 16 diff --git a/doc/examples/json_pointer__back.output b/doc/examples/json_pointer__back.output deleted file mode 100644 index da4d02794..000000000 --- a/doc/examples/json_pointer__back.output +++ /dev/null @@ -1,2 +0,0 @@ -last reference token of "/foo" is foo -last reference token of "/foo/0" is 0 diff --git a/doc/examples/json_pointer__to_string.cpp b/doc/examples/json_pointer__to_string.cpp deleted file mode 100644 index da397cdf4..000000000 --- a/doc/examples/json_pointer__to_string.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -using json = nlohmann::json; - -int main() -{ - // different JSON Pointers - json::json_pointer ptr1(""); - json::json_pointer ptr2("/foo"); - json::json_pointer ptr3("/foo/0"); - json::json_pointer ptr4("/"); - json::json_pointer ptr5("/a~1b"); - json::json_pointer ptr6("/c%d"); - json::json_pointer ptr7("/e^f"); - json::json_pointer ptr8("/g|h"); - json::json_pointer ptr9("/i\\j"); - json::json_pointer ptr10("/k\"l"); - json::json_pointer ptr11("/ "); - json::json_pointer ptr12("/m~0n"); - - - std::cout << ptr1.to_string() << '\n' - << ptr2.to_string() << '\n' - << ptr3.to_string() << '\n' - << ptr4.to_string() << '\n' - << ptr5.to_string() << '\n' - << ptr6.to_string() << '\n' - << ptr7.to_string() << '\n' - << ptr8.to_string() << '\n' - << ptr9.to_string() << '\n' - << ptr10.to_string() << '\n' - << ptr11.to_string() << '\n' - << ptr12.to_string() << std::endl; -} diff --git a/doc/examples/json_pointer__to_string.output b/doc/examples/json_pointer__to_string.output deleted file mode 100644 index c4b5ea8fa..000000000 --- a/doc/examples/json_pointer__to_string.output +++ /dev/null @@ -1,12 +0,0 @@ - -/foo -/foo/0 -/ -/a~1b -/c%d -/e^f -/g|h -/i\j -/k"l -/ -/m~0n diff --git a/doc/examples/max_size.output b/doc/examples/max_size.output deleted file mode 100644 index 8c79995ba..000000000 --- a/doc/examples/max_size.output +++ /dev/null @@ -1,7 +0,0 @@ -0 -1 -1 -1 -256204778801521550 -1152921504606846975 -1 diff --git a/doc/examples/sax_parse.output b/doc/examples/sax_parse.output deleted file mode 100644 index e16c2c4de..000000000 --- a/doc/examples/sax_parse.output +++ /dev/null @@ -1,2 +0,0 @@ -(start: object) (key: Image) (start: object) (key: Width) (value: 800) (key: Height) (value: 600) (key: Title) (value: View from 15th Floor) (key: Thumbnail) (start: object) (key: Url) (value: http://www.example.com/image/481989943) (key: Height) (value: 125) (key: Width) (value: 100) (end: object) (key: Animated) (value: false) (key: IDs) (start: array) (value: 116) (value: 943) (value: 234) (value: 38793) (end: array) (key: Distance) (value: 12.723374634) (end: object) (end: object) -result: true diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index cb782e7d3..000000000 --- a/doc/index.md +++ /dev/null @@ -1,335 +0,0 @@ -# JSON for Modern C++ - -These pages contain the API documentation of JSON for Modern C++, a C++11 header-only JSON class. - -# Contents - -- Classes - - @link nlohmann::basic_json `basic_json`@endlink -- class template for JSON values - - @link nlohmann::json `json`@endlink -- the default specialization of `basic_json`, defined as `basic_json<>` -- [Functions](functions_func.html) - - object inspection - - @link nlohmann::basic_json::dump dump @endlink -- value serialization - - @link nlohmann::basic_json::type type @endlink -- type of the value - - @link nlohmann::basic_json::is_primitive is_primitive @endlink, - @link nlohmann::basic_json::is_structured is_structured @endlink, - @link nlohmann::basic_json::is_null is_null @endlink, - @link nlohmann::basic_json::is_boolean is_boolean @endlink, - @link nlohmann::basic_json::is_number is_number @endlink, - @link nlohmann::basic_json::is_number_integer is_number_integer @endlink, - @link nlohmann::basic_json::is_number_unsigned is_number_unsigned @endlink, - @link nlohmann::basic_json::is_number_float is_number_float @endlink, - @link nlohmann::basic_json::is_object is_object @endlink, - @link nlohmann::basic_json::is_array is_array @endlink, - @link nlohmann::basic_json::is_string is_string @endlink, - @link nlohmann::basic_json::is_discarded is_discarded @endlink, - @link nlohmann::basic_json::is_binary is_binary @endlink -- check for value type - - @link nlohmann::basic_json::operator value_t() const operator value_t @endlink -- type of the value (implicit conversion) - - value access - - @link nlohmann::basic_json::get get @endlink -- get a value - - @link nlohmann::basic_json::get_ptr get_ptr @endlink -- get a value pointer - - @link nlohmann::basic_json::get_ref get_ref @endlink -- get a value reference - - @link nlohmann::basic_json::get_binary get_binary @endlink -- get a binary value - - @link nlohmann::basic_json::operator ValueType() const operator ValueType @endlink -- get a value (implicit conversion) - - @link nlohmann::basic_json::value value @endlink -- get a value from an object and return default value if key is not present - - exceptions - - @link nlohmann::basic_json::parse_error parse_error @endlink for exceptions indicating a parse error - - @link nlohmann::basic_json::invalid_iterator invalid_iterator @endlink for exceptions indicating errors with iterators - - @link nlohmann::basic_json::type_error type_error @endlink for exceptions indicating executing a member function with a wrong type - - @link nlohmann::basic_json::out_of_range out_of_range @endlink for exceptions indicating access out of the defined range - - @link nlohmann::basic_json::other_error other_error @endlink for exceptions indicating other library errors - - lexicographical comparison operators - - @link nlohmann::basic_json::operator== operator== @endlink - - @link nlohmann::basic_json::operator!= operator!= @endlink - - @link nlohmann::basic_json::operator< operator<= @endlink - - @link nlohmann::basic_json::operator<= operator< @endlink - - @link nlohmann::basic_json::operator> operator> @endlink - - @link nlohmann::basic_json::operator>= operator>= @endlink - - serialization - - @link nlohmann::basic_json::dump dump @endlink serialize to string - - @link nlohmann::basic_json::operator<<(std::ostream&, const basic_json &) operator<< @endlink serialize to stream - - deserialization / parsing - - @link nlohmann::basic_json::parse parse @endlink parse from input (string, file, etc.) and return JSON value - - @link nlohmann::basic_json::sax_parse sax_parse @endlink parse from input (string, file, etc.) and generate SAX events - - @link nlohmann::basic_json::operator>>(std::istream&, basic_json&) operator>> @endlink parse from stream - - @link nlohmann::basic_json::accept accept @endlink check for syntax errors without parsing - - @link nlohmann::json_sax SAX interface @endlink define a user-defined SAX event consumer - - @link nlohmann::basic_json::parser_callback_t callback interface @endlink register a callback to the parse function - - [binary formats](binary_formats.md): - - CBOR: @link nlohmann::basic_json::from_cbor from_cbor @endlink / @link nlohmann::basic_json::to_cbor to_cbor @endlink - - MessagePack: @link nlohmann::basic_json::from_msgpack from_msgpack @endlink / @link nlohmann::basic_json::to_msgpack to_msgpack @endlink - - UBJSON: @link nlohmann::basic_json::from_ubjson from_ubjson @endlink / @link nlohmann::basic_json::to_ubjson to_ubjson @endlink - - BSON: @link nlohmann::basic_json::from_bson from_bson @endlink / @link nlohmann::basic_json::to_bson to_bson @endlink -- Types - - @link nlohmann::basic_json::array_t arrays @endlink - - @link nlohmann::basic_json::object_t objects @endlink - - @link nlohmann::basic_json::string_t strings @endlink - - @link nlohmann::basic_json::boolean_t booleans @endlink - - numbers - - @link nlohmann::basic_json::number_integer_t signed integers @endlink - - @link nlohmann::basic_json::number_unsigned_t unsigned integers @endlink - - @link nlohmann::basic_json::number_float_t floating-point @endlink - - @link nlohmann::basic_json::binary_t binary values @endlink -- further JSON standards - - @link nlohmann::json_pointer JSON Pointer @endlink (RFC 6901) - - @link nlohmann::basic_json::patch JSON Patch @endlink (RFC 6902) - - @link nlohmann::basic_json::merge_patch JSON Merge Patch @endlink (RFC 7396) - -# Container function overview - -The container functions known from STL have been extended to support the different value types from JSON. However, not all functions can be applied to all value types. Note that the signature of some functions differ between the types; for instance, `at` may be called with either a string to address a key in an object or with an integer to address a value in an array. - -Note that this table only lists those exceptions thrown due to the type. For instance, the @link nlohmann::basic_json::at(const typename object_t::key_type & key) `at` @endlink function will always throw a @link nlohmann::basic_json::type_error `json::type_error` @endlink exception when called for a string type. When called for an array, it *may* throw an @link nlohmann::basic_json::out_of_range `json::out_of_range` @endlink exception if the passed index is invalid. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
groupfunctionJSON value type
objectarraystringnumberbooleannull
iterators`begin`@link nlohmann::basic_json::begin `begin` @endlink@link nlohmann::basic_json::begin `begin` @endlink@link nlohmann::basic_json::begin `begin` @endlink@link nlohmann::basic_json::begin `begin` @endlink@link nlohmann::basic_json::begin `begin` @endlink@link nlohmann::basic_json::begin `begin` @endlink (returns `end()`)
`cbegin`@link nlohmann::basic_json::cbegin `cbegin` @endlink@link nlohmann::basic_json::cbegin `cbegin` @endlink@link nlohmann::basic_json::cbegin `cbegin` @endlink@link nlohmann::basic_json::cbegin `cbegin` @endlink@link nlohmann::basic_json::cbegin `cbegin` @endlink@link nlohmann::basic_json::cbegin `cbegin` @endlink (returns `cend()`)
`end`@link nlohmann::basic_json::end `end` @endlink@link nlohmann::basic_json::end `end` @endlink@link nlohmann::basic_json::end `end` @endlink@link nlohmann::basic_json::end `end` @endlink@link nlohmann::basic_json::end `end` @endlink@link nlohmann::basic_json::end `end` @endlink
`cend`@link nlohmann::basic_json::cend `cend` @endlink@link nlohmann::basic_json::cend `cend` @endlink@link nlohmann::basic_json::cend `cend` @endlink@link nlohmann::basic_json::cend `cend` @endlink@link nlohmann::basic_json::cend `cend` @endlink@link nlohmann::basic_json::cend `cend` @endlink
`rbegin`@link nlohmann::basic_json::rbegin `rbegin` @endlink@link nlohmann::basic_json::rbegin `rbegin` @endlink@link nlohmann::basic_json::rbegin `rbegin` @endlink@link nlohmann::basic_json::rbegin `rbegin` @endlink@link nlohmann::basic_json::rbegin `rbegin` @endlink@link nlohmann::basic_json::rbegin `rbegin` @endlink
`crbegin`@link nlohmann::basic_json::crbegin `crbegin` @endlink@link nlohmann::basic_json::crbegin `crbegin` @endlink@link nlohmann::basic_json::crbegin `crbegin` @endlink@link nlohmann::basic_json::crbegin `crbegin` @endlink@link nlohmann::basic_json::crbegin `crbegin` @endlink@link nlohmann::basic_json::crbegin `crbegin` @endlink
`rend`@link nlohmann::basic_json::rend `rend` @endlink@link nlohmann::basic_json::rend `rend` @endlink@link nlohmann::basic_json::rend `rend` @endlink@link nlohmann::basic_json::rend `rend` @endlink@link nlohmann::basic_json::rend `rend` @endlink@link nlohmann::basic_json::rend `rend` @endlink
`crend`@link nlohmann::basic_json::crend `crend` @endlink@link nlohmann::basic_json::crend `crend` @endlink@link nlohmann::basic_json::crend `crend` @endlink@link nlohmann::basic_json::crend `crend` @endlink@link nlohmann::basic_json::crend `crend` @endlink@link nlohmann::basic_json::crend `crend` @endlink
element
access
`at`@link nlohmann::basic_json::at(const typename object_t::key_type & key) `at` @endlink@link nlohmann::basic_json::at(size_type) `at` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (304)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (304)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (304)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (304)
`operator[]`@link nlohmann::basic_json::operator[](const typename object_t::key_type &key) `operator[]` @endlink@link nlohmann::basic_json::operator[](size_type) `operator[]` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (305)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (305)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (305)@link nlohmann::basic_json::operator[](const typename object_t::key_type & key) `operator[]` @endlink (creates object)
@link nlohmann::basic_json::operator[](size_type) `operator[]` @endlink (creates array)
`front`@link nlohmann::basic_json::front `front` @endlink@link nlohmann::basic_json::front `front` @endlink@link nlohmann::basic_json::front `front` @endlink@link nlohmann::basic_json::front `front` @endlink@link nlohmann::basic_json::front `front` @endlinkthrows @link nlohmann::basic_json::invalid_iterator `json::invalid_iterator` @endlink (214)
`back`@link nlohmann::basic_json::back `back` @endlink@link nlohmann::basic_json::back `back` @endlink@link nlohmann::basic_json::back `back` @endlink@link nlohmann::basic_json::back `back` @endlink@link nlohmann::basic_json::back `back` @endlinkthrows @link nlohmann::basic_json::invalid_iterator `json::invalid_iterator` @endlink (214)
capacity`empty`@link nlohmann::basic_json::empty `empty` @endlink@link nlohmann::basic_json::empty `empty` @endlink@link nlohmann::basic_json::empty `empty` @endlink (returns `false`)@link nlohmann::basic_json::empty `empty` @endlink (returns `false`)@link nlohmann::basic_json::empty `empty` @endlink (returns `false`)@link nlohmann::basic_json::empty `empty` @endlink (returns `true`)
`size`@link nlohmann::basic_json::size `size` @endlink@link nlohmann::basic_json::size `size` @endlink@link nlohmann::basic_json::size `size` @endlink (returns `1`)@link nlohmann::basic_json::size `size` @endlink (returns `1`)@link nlohmann::basic_json::size `size` @endlink (returns `1`)@link nlohmann::basic_json::size `size` @endlink (returns `0`)
`max_size_`@link nlohmann::basic_json::max_size `max_size` @endlink@link nlohmann::basic_json::max_size `max_size` @endlink@link nlohmann::basic_json::max_size `max_size` @endlink (returns `1`)@link nlohmann::basic_json::max_size `max_size` @endlink (returns `1`)@link nlohmann::basic_json::max_size `max_size` @endlink (returns `1`)@link nlohmann::basic_json::max_size `max_size` @endlink (returns `0`)
modifiers`clear`@link nlohmann::basic_json::clear `clear` @endlink@link nlohmann::basic_json::clear `clear` @endlink@link nlohmann::basic_json::clear `clear` @endlink@link nlohmann::basic_json::clear `clear` @endlink@link nlohmann::basic_json::clear `clear` @endlink@link nlohmann::basic_json::clear `clear` @endlink
`insert`throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (309)@link nlohmann::basic_json::insert `insert` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (309)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (309)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (309)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (309)
`erase`@link nlohmann::basic_json::erase `erase` @endlink@link nlohmann::basic_json::erase `erase` @endlink@link nlohmann::basic_json::erase `erase` @endlink (converts to null)@link nlohmann::basic_json::erase `erase` @endlink (converts to null)@link nlohmann::basic_json::erase `erase` @endlink (converts to null)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (307)
`push_back`@link nlohmann::basic_json::push_back(const typename object_t::value_type & val) `push_back` @endlink@link nlohmann::basic_json::push_back(const nlohmann::basic_json &) `push_back` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (308)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (308)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (308)@link nlohmann::basic_json::push_back(const typename object_t::value_type & val) `push_back` @endlink (creates object)
@link nlohmann::basic_json::push_back(const nlohmann::basic_json &) `push_back` @endlink (creates array)
`emplace` / `emplace_back`@link nlohmann::basic_json::emplace() `emplace` @endlink@link nlohmann::basic_json::emplace_back() `emplace_back` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (311)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (311)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (311)@link nlohmann::basic_json::emplace() `emplace` @endlink (creates object)
@link nlohmann::basic_json::emplace_back() `emplace_back` @endlink (creates array)
`update`@link nlohmann::basic_json::update() `update` @endlinkthrows @link nlohmann::basic_json::type_error `json::type_error` @endlink (312)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (312)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (312)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (312)throws @link nlohmann::basic_json::type_error `json::type_error` @endlink (312)
`swap`@link nlohmann::basic_json::swap `swap` @endlink@link nlohmann::basic_json::swap `swap` @endlink@link nlohmann::basic_json::swap `swap` @endlink@link nlohmann::basic_json::swap `swap` @endlink@link nlohmann::basic_json::swap `swap` @endlink@link nlohmann::basic_json::swap `swap` @endlink
lookup`find`@link nlohmann::basic_json::find `find` @endlink@link nlohmann::basic_json::find `find` @endlink (returns `end()`)@link nlohmann::basic_json::find `find` @endlink (returns `end()`)@link nlohmann::basic_json::find `find` @endlink (returns `end()`)@link nlohmann::basic_json::find `find` @endlink (returns `end()`)@link nlohmann::basic_json::find `find` @endlink (returns `end()`)
`count`@link nlohmann::basic_json::count `count` @endlink@link nlohmann::basic_json::count `count` @endlink (returns `0`)@link nlohmann::basic_json::count `count` @endlink (returns `0`)@link nlohmann::basic_json::count `count` @endlink (returns `0`)@link nlohmann::basic_json::count `count` @endlink (returns `0`)@link nlohmann::basic_json::count `count` @endlink (returns `0`)
`contains`@link nlohmann::basic_json::contains `contains` @endlink@link nlohmann::basic_json::contains `contains` @endlink (returns `false`)@link nlohmann::basic_json::contains `contains` @endlink (returns `false`)@link nlohmann::basic_json::contains `contains` @endlink (returns `false`)@link nlohmann::basic_json::contains `contains` @endlink (returns `false`)@link nlohmann::basic_json::contains `contains` @endlink (returns `false`)
- -@copyright Copyright © 2013-2022 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT). - -@author [Niels Lohmann](http://nlohmann.me) -@see https://github.com/nlohmann/json to download the source code - -@version 3.10.5 diff --git a/doc/mkdocs/docs/api/basic_json/contains.md b/doc/mkdocs/docs/api/basic_json/contains.md deleted file mode 100644 index 8463f4ea9..000000000 --- a/doc/mkdocs/docs/api/basic_json/contains.md +++ /dev/null @@ -1,94 +0,0 @@ -# nlohmann::basic_json::contains - -```cpp -// (1) -template -bool contains(KeyT && key) const; - -// (2) -bool contains(const json_pointer& ptr) const; -``` - -1. Check whether an element exists in a JSON object with key equivalent to `key`. If the element is not found or the - JSON value is not an object, `#!cpp false` is returned. -2. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value. - -## Template parameters - -`KeyT` -: A type for an object key other than `basic_json::json_pointer`. - -## Parameters - -`key` (in) -: key value to check its existence. - -`ptr` (in) -: JSON pointer to check its existence. - -## Return value - -1. `#!cpp true` if an element with specified `key` exists. If no such element with such key is found or the JSON value - is not an object, `#!cpp false` is returned. -2. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. - -## Exception safety - -Strong exception safety: if an exception occurs, the original value stays intact. - -## Exceptions - -1. The function does not throw exceptions. -2. The function can throw the following exceptions: - - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index begins with - `0`. - - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index was not a - number. - -## Complexity - -Logarithmic in the size of the JSON object. - -## Notes - -1. This method always returns `#!cpp false` when executed on a JSON type that is not an object. -2. This method can be executed on any JSON value type. - -!!! info "Postconditions" - - If `#!cpp j.contains(x)` returns `#!c true` for a key or JSON pointer `x`, then it is safe to call `j[x]`. - -## Examples - -??? example "Example (1) check with key" - - The example shows how `contains()` is used. - - ```cpp - --8<-- "examples/contains.cpp" - ``` - - Output: - - ```json - --8<-- "examples/contains.output" - ``` - -??? example "Example (1) check with JSON pointer" - - The example shows how `contains()` is used. - - ```cpp - --8<-- "examples/contains_json_pointer.cpp" - ``` - - Output: - - ```json - --8<-- "examples/contains_json_pointer.output" - ``` - -## Version history - -1. Added in version 3.6.0. -2. Added in version 3.7.0. diff --git a/doc/mkdocs/docs/api/basic_json/count.md b/doc/mkdocs/docs/api/basic_json/count.md deleted file mode 100644 index fcfef8673..000000000 --- a/doc/mkdocs/docs/api/basic_json/count.md +++ /dev/null @@ -1,55 +0,0 @@ -# nlohmann::basic_json::count - -```cpp -template -size_type count(KeyT&& key) const; -``` - -Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will -always be `0` (`key` was not found) or `1` (`key` was found). - -## Template parameters - -`KeyT` -: A type for an object key. - -## Parameters - -`key` (in) -: key value of the element to count. - -## Return value - -Number of elements with key `key`. If the JSON value is not an object, the return value will be `0`. - -## Exception safety - -Strong exception safety: if an exception occurs, the original value stays intact. - -## Complexity - -Logarithmic in the size of the JSON object. - -## Notes - -This method always returns `0` when executed on a JSON type that is not an object. - -## Examples - -??? example - - The example shows how `count()` is used. - - ```cpp - --8<-- "examples/count.cpp" - ``` - - Output: - - ```json - --8<-- "examples/count.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/find.md b/doc/mkdocs/docs/api/basic_json/find.md deleted file mode 100644 index af4cb2972..000000000 --- a/doc/mkdocs/docs/api/basic_json/find.md +++ /dev/null @@ -1,63 +0,0 @@ -# nlohmann::basic_json::find - -```cpp -template -iterator find(KeyT&& key); - -template -const_iterator find(KeyT&& key) const; -``` - -Finds an element in a JSON object with key equivalent to `key`. If the element is not found or the JSON value is not an -object, `end()` is returned. - -## Template parameters - -`KeyT` -: A type for an object key. - -## Parameters - -`key` (in) -: key value of the element to search for. - -## Return value - -Iterator to an element with key equivalent to `key`. If no such element is found or the JSON value is not an object, -past-the-end (see `end()`) iterator is returned. - -## Exception safety - -Strong exception safety: if an exception occurs, the original value stays intact. - -## Complexity - -Logarithmic in the size of the JSON object. - -## Notes - -This method always returns `end()` when executed on a JSON type that is not an object. - -## Examples - -??? example - - The example shows how `find()` is used. - - ```cpp - --8<-- "examples/find__key_type.cpp" - ``` - - Output: - - ```json - --8<-- "examples/find__key_type.output" - ``` - -## See also - -- [contains](contains.md) checks whether a key exists - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/get_allocator.md b/doc/mkdocs/docs/api/basic_json/get_allocator.md deleted file mode 100644 index 1b7700c77..000000000 --- a/doc/mkdocs/docs/api/basic_json/get_allocator.md +++ /dev/null @@ -1,19 +0,0 @@ -# nlohmann::basic_json::get_allocator - -```cpp -static allocator_type get_allocator(); -``` - -Returns the allocator associated with the container. - -## Return value - -associated allocator - -## Version history - -- Unknown. - -!!! note - - This documentation page is a stub. diff --git a/doc/mkdocs/docs/api/basic_json/object_comparator_t.md b/doc/mkdocs/docs/api/basic_json/object_comparator_t.md deleted file mode 100644 index 44509a94b..000000000 --- a/doc/mkdocs/docs/api/basic_json/object_comparator_t.md +++ /dev/null @@ -1,16 +0,0 @@ -# nlohmann::basic_json::object_comparator_t - -```cpp -using object_comparator_t = std::less; // until C++14 - -using object_comparator_t = std::less<>; // since C++14 -``` - -The comparator used in [`object_t`](object_t.md). - -When C++14 is detected, a transparent com parator is used which, when combined with perfect forwarding on find() and -count() calls, prevents unnecessary string construction. - -## Version history - -- Unknown. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ValueType.md b/doc/mkdocs/docs/api/basic_json/operator_ValueType.md deleted file mode 100644 index 1eec13553..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ValueType.md +++ /dev/null @@ -1,72 +0,0 @@ -# nlohmann::basic_json::operator ValueType - -```cpp -template -JSON_EXPLICIT operator ValueType() const; -``` - -Implicit type conversion between the JSON value and a compatible value. The call is realized by calling -[`get()`](get.md). See [Notes](#notes) for the meaning of `JSON_EXPLICIT`. - -## Template parameters - -`ValueType` -: the value type to return - -## Return value - -copy of the JSON value, converted to `ValueType` - -## Exceptions - -Depends on what `json_serializer` `from_json()` method throws - -## Complexity - -Linear in the size of the JSON value. - -## Notes - -By default `JSON_EXPLICIT` defined to the empty string, so the signature is: - -```cpp -template -operator ValueType() const; -``` - -If [`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) is set to `0`, -`JSON_EXPLICIT` is defined to `#!cpp explicit`: - -```cpp -template -explicit operator ValueType() const; -``` - -That is, implicit conversions can be switched off by defining -[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) to `0`. - -## Examples - -??? example - - The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers, (2) A JSON array can be converted to a standard - `std::vector`, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`. - - ```cpp - --8<-- "examples/operator__ValueType.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__ValueType.output" - ``` - -## Version history - -- Since version 1.0.0. -- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../../features/macros.md#json_use_implicit_conversions) added - in version 3.9.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ge.md b/doc/mkdocs/docs/api/basic_json/operator_ge.md deleted file mode 100644 index 68aac6557..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ge.md +++ /dev/null @@ -1,59 +0,0 @@ -# nlohmann::basic_json::operator>= - -```cpp -bool operator>=(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator>=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator>=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is greater than or equal to another JSON value `rhs` by calculating -`#!cpp !(lhs < rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than or equal to `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__greaterequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__greaterequal.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_gt.md b/doc/mkdocs/docs/api/basic_json/operator_gt.md deleted file mode 100644 index 92ec30594..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_gt.md +++ /dev/null @@ -1,58 +0,0 @@ -# nlohmann::basic_json::operator> - -```cpp -bool operator>(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator>(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator>(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is greater than another JSON value `rhs` by calculating `#!cpp !(lhs <= rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is greater than `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__greater.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__greater.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_le.md b/doc/mkdocs/docs/api/basic_json/operator_le.md deleted file mode 100644 index 54f9a2809..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_le.md +++ /dev/null @@ -1,59 +0,0 @@ -# nlohmann::basic_json::operator<= - -```cpp -bool operator<=(const_reference lhs, const_reference rhs) noexcept, - -template -bool operator<=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is less than or equal to another JSON value `rhs` by calculating -`#cpp !(rhs < lhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than or equal to `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__lessequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__lessequal.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json.md b/doc/mkdocs/docs/api/basic_json/operator_literal_json.md deleted file mode 100644 index 8e0c65df0..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_literal_json.md +++ /dev/null @@ -1,48 +0,0 @@ -# nlohmann::basic_json::operator""_json - -```cpp -json operator "" _json(const char* s, std::size_t n); -``` - -This operator implements a user-defined string literal for JSON objects. It can be used by adding `#!cpp _json` to a -string literal and returns a [`json`](../json.md) object if no parse error occurred. - -## Parameters - -`s` (in) -: a string representation of a JSON object - -`n` (in) -: length of string `s` - -## Return value - -[`json`](../json.md) value parsed from `s` - -## Exceptions - -The function can throw anything that [`parse(s, s+n)`](parse.md) would throw. - -## Complexity - -Linear. - -## Examples - -??? example - - The following code shows how to create JSON values from string literals. - - ```cpp - --8<-- "examples/operator_literal_json.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator_literal_json.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md b/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md deleted file mode 100644 index 38c957e61..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md +++ /dev/null @@ -1,48 +0,0 @@ -# nlohmann::basic_json::operator""_json_pointer - -```cpp -json_pointer operator "" _json_pointer(const char* s, std::size_t n); -``` - -This operator implements a user-defined string literal for JSON Pointers. It can be used by adding `#!cpp _json_pointer` -to a string literal and returns a [`json_pointer`](../json_pointer/index.md) object if no parse error occurred. - -## Parameters - -`s` (in) -: a string representation of a JSON Pointer - -`n` (in) -: length of string `s` - -## Return value - -[`json_pointer`](../json_pointer/index.md) value parsed from `s` - -## Exceptions - -The function can throw anything that [`json_pointer::json_pointer`](../json_pointer/index.md) would throw. - -## Complexity - -Linear. - -## Examples - -??? example - - The following code shows how to create JSON Pointers from string literals. - - ```cpp - --8<-- "examples/operator_literal_json_pointer.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator_literal_json_pointer.output" - ``` - -## Version history - -- Added in version 2.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_lt.md b/doc/mkdocs/docs/api/basic_json/operator_lt.md deleted file mode 100644 index d1a4999b4..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_lt.md +++ /dev/null @@ -1,73 +0,0 @@ -# nlohmann::basic_json::operator< - -```cpp -bool operator<(const_reference lhs, const_reference rhs) noexcept; - -template -bool operator<(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator<(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares whether one JSON value `lhs` is less than another JSON value `rhs` according to the following rules: - -- If `lhs` and `rhs` have the same type, the values are compared using the default `<` operator. -- Integer and floating-point numbers are automatically converted before comparison -- Discarded values a -- In case `lhs` and `rhs` have different types, the values are ignored and the order of the types is considered, which - is: - 1. null - 2. boolean - 3. number (all types) - 4. object - 5. array - 6. string - 7. binary - - For instance, any boolean value is considered less than any string. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether `lhs` is less than `rhs` - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__less.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__less.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ltlt.md b/doc/mkdocs/docs/api/basic_json/operator_ltlt.md deleted file mode 100644 index 0cba5ea3c..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ltlt.md +++ /dev/null @@ -1,62 +0,0 @@ -# operator<<(basic_json) - -```cpp -std::ostream& operator<<(std::ostream& o, const basic_json& j); -``` - -Serialize the given JSON value `j` to the output stream `o`. The JSON value will be serialized using the -[`dump`](dump.md) member function. - -- The indentation of the output can be controlled with the member variable `width` of the output stream `o`. For - instance, using the manipulator `std::setw(4)` on `o` sets the indentation level to `4` and the serialization result - is the same as calling `dump(4)`. -- The indentation character can be controlled with the member variable `fill` of the output stream `o`. For instance, - the manipulator `std::setfill('\\t')` sets indentation to use a tab character rather than the default space character. - -## Parameters - -`o` (in, out) -: stream to serialize to - -`j` (in) -: JSON value to serialize - -## Return value - -the stream `o` - -## Exceptions - -Throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316) if a string stored inside the JSON value -is not UTF-8 encoded. Note that unlike the [`dump`](dump.md) member functions, no `error_handler` can be set. - -## Complexity - -Linear. - -## Examples - -??? example - - The example below shows the serialization with different parameters to `width` to adjust the indentation level. - - ```cpp - --8<-- "examples/operator_serialize.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator_serialize.output" - ``` - -## Version history - -- Added in version 1.0.0 -- Support for indentation character added in version 3.0.0. - -!!! warning "Deprecation" - - This function replaces function `#!cpp std::ostream& operator>>(const basic_json& j, std::ostream& o)` which has - been deprecated in version 3.0.0. It will be removed in version 4.0.0. Please replace calls like `#!cpp j >> o;` - with `#!cpp o << j;`. diff --git a/doc/mkdocs/docs/api/basic_json/operator_ne.md b/doc/mkdocs/docs/api/basic_json/operator_ne.md deleted file mode 100644 index e94da9b76..000000000 --- a/doc/mkdocs/docs/api/basic_json/operator_ne.md +++ /dev/null @@ -1,72 +0,0 @@ -# nlohmann::basic_json::operator!= - -```cpp -bool operator!=(const_reference lhs, const_reference rhs) noexcept; - -template -bool operator!=(const_reference lhs, const ScalarType rhs) noexcept; - -template -bool operator!=(ScalarType lhs, const const_reference rhs) noexcept; -``` - -Compares two JSON values for inequality by calculating `#!cpp !(lhs == rhs)`. - -## Template parameters - -`ScalarType` -: a scalar type according to `std::is_scalar::value` - -## Parameters - -`lhs` (in) -: first value to consider - -`rhs` (in) -: second value to consider - -## Return value - -whether the values `lhs` and `rhs` are not equal - -## Exception safety - -No-throw guarantee: this function never throws exceptions. - -## Complexity - -Linear. - -## Examples - -??? example - - The example demonstrates comparing several JSON types. - - ```cpp - --8<-- "examples/operator__notequal.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__notequal.output" - ``` - -??? example - - The example demonstrates comparing several JSON types against the null pointer (JSON `#!json null`). - - ```cpp - --8<-- "examples/operator__notequal__nullptr_t.cpp" - ``` - - Output: - - ```json - --8<-- "examples/operator__notequal__nullptr_t.output" - ``` - -## Version history - -- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/value_t.md b/doc/mkdocs/docs/api/basic_json/value_t.md deleted file mode 100644 index 768b13ca1..000000000 --- a/doc/mkdocs/docs/api/basic_json/value_t.md +++ /dev/null @@ -1,36 +0,0 @@ -# nlohmann::basic_json::value_t - -```cpp -enum class value_t : std::uint8_t { - null, - object, - array, - string, - boolean, - number_integer, - number_unsigned, - number_float, - binary, - discarded -}; -``` - -This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the -functions [`is_null`](is_null.md), [`is_object`](is_object.md), [`is_array`](is_array.md), [`is_string`](is_string.md), -[`is_boolean`](is_boolean.md), [`is_number`](is_number.md) (with [`is_number_integer`](is_number_integer.md), -[`is_number_unsigned`](is_number_unsigned.md), and [`is_number_float`](is_number_float.md)), -[`is_discarded`](is_discarded.md), [`is_binary`](is_binary.md), [`is_primitive`](is_primitive.md), and -[`is_structured`](is_structured.md) rely on it. - -## Notes - -There are three enumeration entries (number_integer, number_unsigned, and number_float), because the library -distinguishes these three types for numbers: [`number_unsigned_t`](number_unsigned_t.md) is used for unsigned integers, -[`number_integer_t`](number_integer_t.md) is used for signed integers, and [`number_float_t`](number_float_t.md) is used -for floating-point numbers or to approximate integers which do not fit in the limits of their respective type. - -## Version history - -- Added in version 1.0.0. -- Added unsigned integer type in version 2.0.0. -- Added binary type in version 3.8.0. diff --git a/doc/mkdocs/docs/api/json_pointer/operator_string.md b/doc/mkdocs/docs/api/json_pointer/operator_string.md deleted file mode 100644 index 56d8eebeb..000000000 --- a/doc/mkdocs/docs/api/json_pointer/operator_string.md +++ /dev/null @@ -1,24 +0,0 @@ -# nlohmann::json_pointer::operator std::string - -```cpp -operator std::string() const -``` - -Return a string representation of the JSON pointer. - -## Return value - -A string representation of the JSON pointer - -## Possible implementation - -```cpp -operator std::string() const -{ - return to_string(); -} -``` - -## Version history - -Since version 2.0.0. diff --git a/doc/mkdocs/docs/api/json_sax/end_array.md b/doc/mkdocs/docs/api/json_sax/end_array.md deleted file mode 100644 index 245cf974c..000000000 --- a/doc/mkdocs/docs/api/json_sax/end_array.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::end_array - -```cpp -virtual bool end_array() = 0; -``` - -The end of an array was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/end_object.md b/doc/mkdocs/docs/api/json_sax/end_object.md deleted file mode 100644 index 5654e262e..000000000 --- a/doc/mkdocs/docs/api/json_sax/end_object.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::end_object - -```cpp -virtual bool end_object() = 0; -``` - -The end of an object was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/null.md b/doc/mkdocs/docs/api/json_sax/null.md deleted file mode 100644 index bcbb4a348..000000000 --- a/doc/mkdocs/docs/api/json_sax/null.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::json_sax::null - -```cpp -virtual bool null() = 0; -``` - -A null value was read. - -## Return value - -Whether parsing should proceed. - -## Version history - -- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/macros/index.md b/doc/mkdocs/docs/api/macros/index.md deleted file mode 100644 index 9c390d55e..000000000 --- a/doc/mkdocs/docs/api/macros/index.md +++ /dev/null @@ -1,18 +0,0 @@ -# Macros - -Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. - -- [`JSON_ASSERT(x)`](json_assert.md) -- `JSON_CATCH_USER(exception)` -- `JSON_DIAGNOSTICS` -- `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20` -- `JSON_NOEXCEPTION` -- `JSON_NO_IO` -- `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK` -- `JSON_THROW_USER(exception)` -- `JSON_TRY_USER` -- `JSON_USE_IMPLICIT_CONVERSIONS` -- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` -- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` -- `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` -- `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` diff --git a/doc/mkdocs/docs/api/macros/json_assert.md b/doc/mkdocs/docs/api/macros/json_assert.md deleted file mode 100644 index 63d4ae076..000000000 --- a/doc/mkdocs/docs/api/macros/json_assert.md +++ /dev/null @@ -1,11 +0,0 @@ -# JSON_ASSERT(x) - -```cpp -JSON_ASSERT(x) -``` - -## Default implementation - -```cpp -assert(x); -``` diff --git a/doc/mkdocs/docs/api/ordered_json.md b/doc/mkdocs/docs/api/ordered_json.md deleted file mode 100644 index 8b122f90b..000000000 --- a/doc/mkdocs/docs/api/ordered_json.md +++ /dev/null @@ -1,15 +0,0 @@ -# nlohmann::ordered_json - -```cpp -using ordered_json = basic_json; -``` - -This type preserves the insertion order of object keys. - -## See also - -- [ordered_map](ordered_map.md) - -## Version history - -Since version 3.9.0. diff --git a/doc/mkdocs/docs/features/element_access/checked_access.md b/doc/mkdocs/docs/features/element_access/checked_access.md deleted file mode 100644 index fd444bebe..000000000 --- a/doc/mkdocs/docs/features/element_access/checked_access.md +++ /dev/null @@ -1,77 +0,0 @@ -# Checked access: at - -## Overview - -The `#!cpp at()` member function performs checked access; that is, it returns a reference to the desired value if it exists and throws a [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) otherwise. - -??? example - - Consider the following JSON value: - - ```json - { - "name": "Mary Smith", - "age": 42, - "hobbies": ["hiking", "reading"] - } - ``` - - Assume the value is parsed to a `json` variable `j`. - - | expression | value | - | ---------- | ----- | - | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | - | `#!cpp j.at("name")` | `#!json "Mary Smith"` | - | `#!cpp j.at("age")` | `#!json 42` | - | `#!cpp j.at("hobbies")` | `#!json ["hiking", "reading"]` | - | `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` | - | `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` | - -The return value is a reference, so it can be modified by the original value. - -??? example - - ```cpp - j.at("name") = "John Smith"; - ``` - - This code produces the following JSON value: - - ```json - { - "name": "John Smith", - "age": 42, - "hobbies": ["hiking", "reading"] - } - ``` - -When accessing an invalid index (i.e., an index greater than or equal to the array size) or the passed object key is non-existing, an exception is thrown. - -??? example - - ```cpp - j.at("hobbies").at(3) = "cooking"; - ``` - - This code produces the following exception: - - ``` - [json.exception.out_of_range.401] array index 3 is out of range - ``` - -## Notes - - -!!! failure "Exceptions" - - - `at` can only be used with objects (with a string argument) or with arrays (with a numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error304) is thrown. - - [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) exceptions are thrown if the provided key is not found in an object or the provided index is invalid. - -## Summary - -| scenario | non-const value | const value | -|-----------------------------------|------------------------------------------------|------------------------------------------------| -| access to existing object key | reference to existing value is returned | const reference to existing value is returned | -| access to valid array index | reference to existing value is returned | const reference to existing value is returned | -| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | -| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | diff --git a/doc/mkdocs/docs/features/json_pointer.md b/doc/mkdocs/docs/features/json_pointer.md deleted file mode 100644 index 8f5d60ec7..000000000 --- a/doc/mkdocs/docs/features/json_pointer.md +++ /dev/null @@ -1,19 +0,0 @@ -# JSON Pointer - -The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. - -```cpp -// a JSON value -json j_original = R"({ - "baz": ["one", "two", "three"], - "foo": "bar" -})"_json; - -// access members with a JSON pointer (RFC 6901) -j_original["/baz/1"_json_pointer]; -// "two" -``` - -## See also - -- Class [`json_pointer`](../api/json_pointer/index.md) diff --git a/doc/mkdocs/docs/integration/cmake.md b/doc/mkdocs/docs/integration/cmake.md deleted file mode 100644 index 9f1ecc95a..000000000 --- a/doc/mkdocs/docs/integration/cmake.md +++ /dev/null @@ -1,138 +0,0 @@ -# CMake - -## Integration - -You can also use the `nlohmann_json::nlohmann_json` interface target in CMake. This target populates the appropriate usage requirements for `INTERFACE_INCLUDE_DIRECTORIES` to point to the appropriate include directories and `INTERFACE_COMPILE_FEATURES` for the necessary C++11 flags. - -### External - -To use this library from a CMake project, you can locate it directly with `find_package()` and use the namespaced imported target from the generated package configuration: - -```cmake -# CMakeLists.txt -find_package(nlohmann_json 3.2.0 REQUIRED) -... -add_library(foo ...) -... -target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) -``` - -The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of the build tree. - -### Embedded - -To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call `add_subdirectory()` in your `CMakeLists.txt` file: - -```cmake -# If you only include this third party in PRIVATE source files, you do not -# need to install it when your main project gets installed. -# set(JSON_Install OFF CACHE INTERNAL "") - -# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it -# unintended consequences that will break the build. It's generally -# discouraged (although not necessarily well documented as such) to use -# include(...) for pulling in other CMake projects anyways. -add_subdirectory(nlohmann_json) -... -add_library(foo ...) -... -target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) -``` - -### Embedded (FetchContent) - -Since CMake v3.11, -[FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can -be used to automatically download the repository as a dependency at configure type. - -Example: -```cmake -include(FetchContent) - -FetchContent_Declare(json - GIT_REPOSITORY https://github.com/nlohmann/json - GIT_TAG v3.7.3) - -FetchContent_GetProperties(json) -if(NOT json_POPULATED) - FetchContent_Populate(json) - add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() - -target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) -``` - -!!! Note - The repository download size is quite large. - You might want to depend on a smaller repository. For instance, you might want to replace the URL above by - . - -### Supporting Both - -To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin to the following: - -``` cmake -# Top level CMakeLists.txt -project(FOO) -... -option(FOO_USE_EXTERNAL_JSON "Use an external JSON library" OFF) -... -add_subdirectory(thirdparty) -... -add_library(foo ...) -... -# Note that the namespaced target will always be available regardless of the -# import method -target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json) -``` -```cmake -# thirdparty/CMakeLists.txt -... -if(FOO_USE_EXTERNAL_JSON) - find_package(nlohmann_json 3.2.0 REQUIRED) -else() - set(JSON_BuildTests OFF CACHE INTERNAL "") - add_subdirectory(nlohmann_json) -endif() -... -``` - -`thirdparty/nlohmann_json` is then a complete copy of this source tree. - -## CMake Options - -### `JSON_BuildTests` - -Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option. - -### `JSON_CI` - -Enable CI build targets. The exact targets are used during the several CI steps and are subject to change without notice. This option is `OFF` by default. - -### `JSON_Diagnostics` - -Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../features/macros.md#json_diagnostics). This option is `OFF` by default. - -### `JSON_FastTests` - -Skip expensive/slow test suites. This option is `OFF` by default. Depends on `JSON_BuildTests`. - -### `JSON_ImplicitConversions` - -Enable implicit conversions by defining macro [`JSON_USE_IMPLICIT_CONVERSIONS`](../features/macros.md#json_use_implicit_conversions). This option is `ON` by default. - -### `JSON_Install` - -Install CMake targets during install step. This option is `ON` by default if the library's CMake project is the top project. - -### `JSON_MultipleHeaders` - -Use non-amalgamated version of the library. This option is `OFF` by default. - -### `JSON_SystemInclude` - -Treat the library headers like system headers (i.e., adding `SYSTEM` to the [`target_include_directories`](https://cmake.org/cmake/help/latest/command/target_include_directories.html) call) to checks for this library by tools like Clang-Tidy. This option is `OFF` by default. - -### `JSON_Valgrind` - -Execute test suite with [Valgrind](https://valgrind.org). This option is `OFF` by default. Depends on `JSON_BuildTests`. diff --git a/doc/mkdocs/docs/integration/index.md b/doc/mkdocs/docs/integration/index.md deleted file mode 100644 index 5ee4ff721..000000000 --- a/doc/mkdocs/docs/integration/index.md +++ /dev/null @@ -1,14 +0,0 @@ -# Header only - -[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add - -```cpp -#include - -// for convenience -using json = nlohmann::json; -``` - -to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang). - -You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) for forward-declarations. The installation of `json_fwd.hpp` (as part of CMake's install step), can be achieved by setting `-DJSON_MultipleHeaders=ON`. diff --git a/doc/mkdocs/requirements.txt b/doc/mkdocs/requirements.txt deleted file mode 100644 index b64e9b873..000000000 --- a/doc/mkdocs/requirements.txt +++ /dev/null @@ -1,29 +0,0 @@ -click>=7.1.2 -future>=0.18.2 -htmlmin>=0.1.12 -httplib2>=0.18.1 -importlib-metadata>=1.6.0 -Jinja2>=2.11.2 -joblib>=0.15.1 -jsmin>=2.2.2 -livereload>=2.6.1 -lunr>=0.5.8 -Markdown>=3.2.2 -markdown-include>=0.5.1 -MarkupSafe>=1.1.1 -mkdocs>=1.1.2 -mkdocs-material>=5.2.1 -mkdocs-material-extensions>=1.0 -mkdocs-minify-plugin>=0.3.0 -mkdocs-simple-hooks>=0.1.1 -nltk>=3.5 -plantuml>=0.3.0 -plantuml-markdown>=3.2.2 -Pygments>=2.6.1 -pymdown-extensions>=7.1 -PyYAML>=5.3.1 -regex>=2020.5.14 -six>=1.15.0 -tornado>=6.0.4 -tqdm>=4.46.0 -zipp>=3.1.0 diff --git a/doc/mkdocs/scripts/check_structure.py b/doc/mkdocs/scripts/check_structure.py deleted file mode 100644 index cacc51cb4..000000000 --- a/doc/mkdocs/scripts/check_structure.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python - -import glob -import os.path - - -def check_structure(): - expected_headers = [ - 'Template parameters', - 'Specializations', - 'Iterator invalidation', - 'Requirements', - 'Member types', - 'Member functions', - 'Member variables', - 'Static functions', - 'Non-member functions', - 'Literals', - 'Helper classes', - 'Parameters', - 'Return value', - 'Exception safety', - 'Exceptions', - 'Complexity', - 'Possible implementation', - 'Notes', - 'Examples', - 'See also', - 'Version history' - ] - - required_headers = [ - 'Examples', - 'Version history' - ] - - files = sorted(glob.glob('api/**/*.md', recursive=True)) - for file in files: - with open(file) as file_content: - header_idx = -1 - existing_headers = [] - in_initial_code_example = False - previous_line = None - h1sections = 0 - - for lineno, line in enumerate(file_content.readlines()): - line = line.strip() - - if line.startswith('# '): - h1sections += 1 - - # there should only be one top-level title - if h1sections > 1: - print(f'{file}:{lineno+1}: Error: unexpected top-level title "{line}"!') - h1sections = 1 - - # Overview pages should have a better title - if line == '# Overview': - print(f'{file}:{lineno+1}: Error: overview pages should have a better title!') - - # lines longer than 160 characters are bad (unless they are tables) - if len(line) > 160 and '|' not in line: - print(f'{file}:{lineno+1}: Error: line is too long ({len(line)} vs. 160 chars)!') - - # check if headers are correct - if line.startswith('## '): - header = line.strip('## ') - existing_headers.append(header) - - if header in expected_headers: - idx = expected_headers.index(header) - if idx <= header_idx: - print(f'{file}:{lineno+1}: Error: header "{header}" is in an unexpected order (should be before "{expected_headers[header_idx]}")!') - header_idx = idx - else: - print(f'{file}:{lineno+1}: Error: header "{header}" is not part of the expected headers!') - - # code example - if line == '```cpp' and header_idx == -1: - in_initial_code_example = True - - if in_initial_code_example and line.startswith('//'): - if any(map(str.isdigit, line)) and '(' not in line: - print(f'{file}:{lineno+1}: Number should be in parentheses: {line}') - - if line == '```' and in_initial_code_example: - in_initial_code_example = False - - # consecutive blank lines are bad - if line == '' and previous_line == '': - print(f'{file}:{lineno}-{lineno+1}: Error: Consecutive blank lines!') - - previous_line = line - - for required_header in required_headers: - if required_header not in existing_headers: - print(f'{file}:{lineno+1}: Error: required header "{required_header}" was not found!') - - -def check_examples(): - example_files = sorted(glob.glob('../../examples/*.cpp')) - markdown_files = sorted(glob.glob('**/*.md', recursive=True)) - - # check if every example file is used in at least one markdown file - for example_file in example_files: - example_file = os.path.join('examples', os.path.basename(example_file)) - - found = False - for markdown_file in markdown_files: - content = ' '.join(open(markdown_file).readlines()) - if example_file in content: - found = True - break - - if not found: - print(f'{example_file}: Error: example file is not used in any documentation file!') - - -if __name__ == '__main__': - check_structure() - check_examples() diff --git a/doc/Makefile b/docs/Makefile similarity index 51% rename from doc/Makefile rename to docs/Makefile index 0de57e00f..35c30daef 100644 --- a/doc/Makefile +++ b/docs/Makefile @@ -9,15 +9,22 @@ all: create_output # where are the example cpp files EXAMPLES = $(wildcard examples/*.cpp) +cxx_standard = $(lastword c++11 $(filter c++%, $(subst ., ,$1))) + # create output from a stand-alone example file %.output: %.cpp - make $(<:.cpp=) CPPFLAGS="-I $(SRCDIR)" CXXFLAGS="-std=c++11" + @echo "standard $(call cxx_standard $(<:.cpp=))" + $(MAKE) $(<:.cpp=) \ + CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \ + CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations" ./$(<:.cpp=) > $@ rm $(<:.cpp=) # compare created output with current output of the example files %.test: %.cpp - make $(<:.cpp=) CPPFLAGS="-I $(SRCDIR)" CXXFLAGS="-std=c++11" + $(MAKE) $(<:.cpp=) \ + CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \ + CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations" ./$(<:.cpp=) > $@ diff $@ $(<:.cpp=.output) rm $(<:.cpp=) $@ @@ -28,6 +35,10 @@ create_output: $(EXAMPLES:.cpp=.output) # check output of all stand-alone example files check_output: $(EXAMPLES:.cpp=.test) +# check output of all stand-alone example files (exclude files with platform-dependent output.) +# This target is used in the CI (ci_test_documentation). +check_output_portable: $(filter-out examples/meta.test examples/max_size.test examples/std_hash.test examples/basic_json__CompatibleType.test,$(EXAMPLES:.cpp=.test)) + clean: rm -fr $(EXAMPLES:.cpp=) $(MAKE) clean -C docset diff --git a/doc/README.md b/docs/README.md similarity index 95% rename from doc/README.md rename to docs/README.md index ec5c25d49..b39d54e05 100644 --- a/doc/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ If you want to see the documentation for a specific tag or commit hash, you can git clone https://github.com/nlohmann/json.git cd json git checkout v3.10.2 -make install_venv serve -C doc/mkdocs +make install_venv serve -C docs/mkdocs ``` Open URL in your browser. Replace from any URL from the source code `https://json.nlohmann.me` diff --git a/docs/avatars.png b/docs/avatars.png new file mode 100644 index 000000000..69e7da318 Binary files /dev/null and b/docs/avatars.png differ diff --git a/doc/docset/Info.plist b/docs/docset/Info.plist similarity index 100% rename from doc/docset/Info.plist rename to docs/docset/Info.plist diff --git a/docs/docset/Makefile b/docs/docset/Makefile new file mode 100644 index 000000000..6cdca4a03 --- /dev/null +++ b/docs/docset/Makefile @@ -0,0 +1,86 @@ +SED ?= $(shell which gsed 2>/dev/null || which sed) + +MKDOCS_PAGES=$(shell cd ../mkdocs/docs/ && find * -type f -name '*.md' | sort) + +.PHONY: all +all: JSON_for_Modern_C++.tgz + +docSet.dsidx: docSet.sql + # generate index + sqlite3 docSet.dsidx > "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)" + # fix spacing + echo -e "\n\ndiv.md-sidebar div.md-sidebar--secondary, div.md-main__inner { top: 0; margin-top: 0 }" >> "$$(ls JSON_for_Modern_C++.docset/Contents/Resources/Documents/assets/stylesheets/main.*.min.css)" + # remove "JSON for Modern C++" from page titles (fallback) + find JSON_for_Modern_C++.docset/Contents/Resources/Documents -type f -exec $(SED) -i 's| - JSON for Modern C++||' {} + + # replace page titles with name from index, if available + for page in $(MKDOCS_PAGES); do \ + case "$$page" in \ + */index.md) path=$${page/\/index.md/} ;; \ + *) path=$${page/.md/} ;; \ + esac; \ + title=$$(sqlite3 docSet.dsidx "SELECT name FROM searchIndex WHERE path='$$path/index.html'" | tr '\n' ',' | $(SED) -e 's/,/, /g' -e 's/, $$/\n/'); \ + if [ "x$$title" != "x" ]; then \ + $(SED) -i "s%.*%$$title%" "JSON_for_Modern_C++.docset/Contents/Resources/Documents/$$path/index.html"; \ + fi \ + done + # clean up + rm JSON_for_Modern_C++.docset/Contents/Resources/Documents/sitemap.* + # copy index + cp docSet.dsidx JSON_for_Modern_C++.docset/Contents/Resources/ + +JSON_for_Modern_C++.tgz: JSON_for_Modern_C++.docset + tar --exclude='.DS_Store' -cvzf JSON_for_Modern_C++.tgz JSON_for_Modern_C++.docset + +# install docset for Zeal documentation browser (https://zealdocs.org/) +.PHONY: install_docset_zeal +install_docset_zeal: JSON_for_Modern_C++.docset + docset_root=$${XDG_DATA_HOME:-$$HOME/.local/share}/Zeal/Zeal/docsets; \ + rm -rf $$docset_root/JSON_for_Modern_C++.docset; \ + mkdir -p $$docset_root; \ + cp -r JSON_for_Modern_C++.docset $$docset_root/ + +# list mkdocs pages missing from the docset index +.PHONY: list_missing_pages +list_missing_pages: docSet.dsidx + @for page in $(MKDOCS_PAGES); do \ + case "$$page" in \ + */index.md) path=$${page/\/index.md/} ;; \ + *) path=$${page/.md/} ;; \ + esac; \ + if [ "x$$page" != "xindex.md" -a "x$$(sqlite3 docSet.dsidx "SELECT COUNT(*) FROM searchIndex WHERE path='$$path/index.html'")" = "x0" ]; then \ + echo $$page; \ + fi \ + done + +# list paths in the docset index without a corresponding mkdocs page +.PHONY: list_removed_paths +list_removed_paths: docSet.dsidx + @for path in $$(sqlite3 docSet.dsidx "SELECT path FROM searchIndex"); do \ + page=$${path/\/index.html/.md}; \ + page_index=$${path/index.html/index.md}; \ + page_found=0; \ + for p in $(MKDOCS_PAGES); do \ + if [ "x$$p" = "x$$page" -o "x$$p" = "x$$page_index" ]; then \ + page_found=1; \ + fi \ + done; \ + if [ "x$$page_found" = "x0" ]; then \ + echo $$path; \ + fi \ + done + +.PHONY: clean +clean: + rm -f docSet.dsidx + rm -fr JSON_for_Modern_C++.docset JSON_for_Modern_C++.tgz diff --git a/doc/docset/README.md b/docs/docset/README.md similarity index 100% rename from doc/docset/README.md rename to docs/docset/README.md diff --git a/docs/docset/docSet.sql b/docs/docset/docSet.sql new file mode 100644 index 000000000..e076ea575 --- /dev/null +++ b/docs/docset/docSet.sql @@ -0,0 +1,229 @@ +DROP TABLE IF EXISTS searchIndex; +CREATE TABLE searchIndex(id INTEGER PRIMARY KEY, name TEXT, type TEXT, path TEXT); +CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path); + +-- API +INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer', 'Class', 'api/adl_serializer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer::from_json', 'Function', 'api/adl_serializer/from_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('adl_serializer::to_json', 'Function', 'api/adl_serializer/to_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype', 'Class', 'api/byte_container_with_subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::byte_container_with_subtype', 'Constructor', 'api/byte_container_with_subtype/byte_container_with_subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::clear_subtype', 'Method', 'api/byte_container_with_subtype/clear_subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::has_subtype', 'Method', 'api/byte_container_with_subtype/has_subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::set_subtype', 'Method', 'api/byte_container_with_subtype/set_subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('byte_container_with_subtype::subtype', 'Method', 'api/byte_container_with_subtype/subtype/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/basic_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::accept', 'Function', 'api/basic_json/accept/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array', 'Function', 'api/basic_json/array/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array_t', 'Type', 'api/basic_json/array_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::at', 'Method', 'api/basic_json/at/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::back', 'Method', 'api/basic_json/back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::basic_json', 'Constructor', 'api/basic_json/basic_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::begin', 'Method', 'api/basic_json/begin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary', 'Function', 'api/basic_json/binary/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::binary_t', 'Type', 'api/basic_json/binary_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::boolean_t', 'Type', 'api/basic_json/boolean_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbegin', 'Method', 'api/basic_json/cbegin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cbor_tag_handler_t', 'Enum', 'api/basic_json/cbor_tag_handler_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::cend', 'Method', 'api/basic_json/cend/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::clear', 'Method', 'api/basic_json/clear/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::contains', 'Method', 'api/basic_json/contains/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::count', 'Method', 'api/basic_json/count/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::crbegin', 'Method', 'api/basic_json/crbegin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::crend', 'Method', 'api/basic_json/crend/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::default_object_comparator_t', 'Type', 'api/basic_json/default_object_comparator_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::diff', 'Function', 'api/basic_json/diff/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::dump', 'Method', 'api/basic_json/dump/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::emplace', 'Method', 'api/basic_json/emplace/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::emplace_back', 'Method', 'api/basic_json/emplace_back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::empty', 'Method', 'api/basic_json/empty/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::end', 'Method', 'api/basic_json/end/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::erase', 'Method', 'api/basic_json/erase/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::error_handler_t', 'Enum', 'api/basic_json/error_handler_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::exception', 'Class', 'api/basic_json/exception/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::find', 'Method', 'api/basic_json/find/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::flatten', 'Method', 'api/basic_json/flatten/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_bjdata', 'Function', 'api/basic_json/from_bjdata/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_bson', 'Function', 'api/basic_json/from_bson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_cbor', 'Function', 'api/basic_json/from_cbor/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_msgpack', 'Function', 'api/basic_json/from_msgpack/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::from_ubjson', 'Function', 'api/basic_json/from_ubjson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::front', 'Method', 'api/basic_json/front/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get', 'Method', 'api/basic_json/get/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_allocator', 'Function', 'api/basic_json/get_allocator/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_binary', 'Method', 'api/basic_json/get_binary/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ptr', 'Method', 'api/basic_json/get_ptr/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_ref', 'Method', 'api/basic_json/get_ref/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::get_to', 'Method', 'api/basic_json/get_to/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::input_format_t', 'Enum', 'api/basic_json/input_format_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::insert', 'Method', 'api/basic_json/insert/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::invalid_iterator', 'Class', 'api/basic_json/invalid_iterator/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_array', 'Method', 'api/basic_json/is_array/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_binary', 'Method', 'api/basic_json/is_binary/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_boolean', 'Method', 'api/basic_json/is_boolean/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_discarded', 'Method', 'api/basic_json/is_discarded/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_null', 'Method', 'api/basic_json/is_null/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number', 'Method', 'api/basic_json/is_number/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_float', 'Method', 'api/basic_json/is_number_float/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_integer', 'Method', 'api/basic_json/is_number_integer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_number_unsigned', 'Method', 'api/basic_json/is_number_unsigned/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_object', 'Method', 'api/basic_json/is_object/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_primitive', 'Method', 'api/basic_json/is_primitive/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_string', 'Method', 'api/basic_json/is_string/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::is_structured', 'Method', 'api/basic_json/is_structured/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::items', 'Method', 'api/basic_json/items/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::json_serializer', 'Class', 'api/basic_json/json_serializer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::max_size', 'Method', 'api/basic_json/max_size/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::merge_patch', 'Method', 'api/basic_json/merge_patch/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::meta', 'Function', 'api/basic_json/meta/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_float_t', 'Type', 'api/basic_json/number_float_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_integer_t', 'Type', 'api/basic_json/number_integer_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::number_unsigned_t', 'Type', 'api/basic_json/number_unsigned_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object', 'Function', 'api/basic_json/object/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object_comparator_t', 'Type', 'api/basic_json/object_comparator_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::object_t', 'Type', 'api/basic_json/object_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator ValueType', 'Operator', 'api/basic_json/operator_ValueType/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator value_t', 'Operator', 'api/basic_json/operator_value_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator[]', 'Operator', 'api/basic_json/operator[]/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator=', 'Operator', 'api/basic_json/operator=/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator+=', 'Operator', 'api/basic_json/operator+=/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator==', 'Operator', 'api/basic_json/operator_eq/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator!=', 'Operator', 'api/basic_json/operator_ne/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<', 'Operator', 'api/basic_json/operator_lt/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<=', 'Operator', 'api/basic_json/operator_le/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator>', 'Operator', 'api/basic_json/operator_gt/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator>=', 'Operator', 'api/basic_json/operator_ge/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::operator<=>', 'Operator', 'api/basic_json/operator_spaceship/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::out_of_range', 'Class', 'api/basic_json/out_of_range/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::other_error', 'Class', 'api/basic_json/other_error/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse', 'Function', 'api/basic_json/parse/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse_error', 'Class', 'api/basic_json/parse_error/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parse_event_t', 'Enum', 'api/basic_json/parse_event_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::parser_callback_t', 'Type', 'api/basic_json/parser_callback_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::patch', 'Method', 'api/basic_json/patch/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::patch_inplace', 'Method', 'api/basic_json/patch_inplace/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::push_back', 'Method', 'api/basic_json/push_back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::rbegin', 'Method', 'api/basic_json/rbegin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::rend', 'Method', 'api/basic_json/rend/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::sax_parse', 'Function', 'api/basic_json/sax_parse/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::size', 'Method', 'api/basic_json/size/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::string_t', 'Type', 'api/basic_json/string_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::swap', 'Method', 'api/basic_json/swap/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type', 'Method', 'api/basic_json/type/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type_error', 'Class', 'api/basic_json/type_error/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::type_name', 'Method', 'api/basic_json/type_name/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::unflatten', 'Method', 'api/basic_json/unflatten/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::update', 'Method', 'api/basic_json/update/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_bjdata', 'Function', 'api/basic_json/to_bjdata/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_bson', 'Function', 'api/basic_json/to_bson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_cbor', 'Function', 'api/basic_json/to_cbor/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_msgpack', 'Function', 'api/basic_json/to_msgpack/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_string', 'Method', 'api/basic_json/to_string/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_ubjson', 'Function', 'api/basic_json/to_ubjson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value', 'Method', 'api/basic_json/value/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value_t', 'Enum', 'api/basic_json/value_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::~basic_json', 'Method', 'api/basic_json/~basic_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json', 'Class', 'api/json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer', 'Class', 'api/json_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::back', 'Method', 'api/json_pointer/back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::empty', 'Method', 'api/json_pointer/empty/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::json_pointer', 'Constructor', 'api/json_pointer/json_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator/', 'Operator', 'api/json_pointer/operator_slash/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator/=', 'Operator', 'api/json_pointer/operator_slasheq/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::operator string_t', 'Operator', 'api/json_pointer/operator_string_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::parent_pointer', 'Method', 'api/json_pointer/parent_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::pop_back', 'Method', 'api/json_pointer/pop_back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::push_back', 'Method', 'api/json_pointer/push_back/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::string_t', 'Type', 'api/json_pointer/string_t/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer::to_string', 'Method', 'api/json_pointer/to_string/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax', 'Class', 'api/json_sax/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::binary', 'Method', 'api/json_sax/binary/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::boolean', 'Method', 'api/json_sax/boolean/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_array', 'Method', 'api/json_sax/end_array/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::end_object', 'Method', 'api/json_sax/end_object/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::key', 'Method', 'api/json_sax/key/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::null', 'Method', 'api/json_sax/null/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_float', 'Method', 'api/json_sax/number_float/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_integer', 'Method', 'api/json_sax/number_integer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::number_unsigned', 'Method', 'api/json_sax/number_unsigned/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::parse_error', 'Method', 'api/json_sax/parse_error/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_array', 'Method', 'api/json_sax/start_array/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::start_object', 'Method', 'api/json_sax/start_object/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('json_sax::string', 'Method', 'api/json_sax/string/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json', 'Literal', 'api/operator_literal_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('operator""_json_pointer', 'Literal', 'api/operator_literal_json_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('operator<<', 'Operator', 'api/operator_ltlt/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('operator>>', 'Operator', 'api/operator_gtgt/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('ordered_json', 'Class', 'api/ordered_json/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('ordered_map', 'Class', 'api/ordered_map/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('std::hash', 'Class', 'api/basic_json/std_hash/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('std::swap', 'Function', 'api/basic_json/std_swap/index.html'); + +-- Features +INSERT INTO searchIndex(name, type, path) VALUES ('Arbitrary Type Conversions', 'Guide', 'features/arbitrary_types/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats', 'Guide', 'features/binary_formats/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: BJData', 'Guide', 'features/binary_formats/bjdata/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: BSON', 'Guide', 'features/binary_formats/bson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: CBOR', 'Guide', 'features/binary_formats/cbor/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: MessagePack', 'Guide', 'features/binary_formats/messagepack/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Formats: UBJSON', 'Guide', 'features/binary_formats/ubjson/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Binary Values', 'Guide', 'features/binary_values/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Comments', 'Guide', 'features/comments/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Element Access', 'Guide', 'features/element_access/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Access with default value: value', 'Guide', 'features/element_access/default_value/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Checked access: at', 'Guide', 'features/element_access/checked_access/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Element Access: Unchecked access: operator[]', 'Guide', 'features/element_access/unchecked_access/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Integration: CMake', 'Guide', 'integration/cmake/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Header only', 'Guide', 'integration/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Package Managers', 'Guide', 'integration/package_managers/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Integration: Pkg-config', 'Guide', 'integration/pkg-config/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Iterators', 'Guide', 'features/iterators/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON Merge Patch', 'Guide', 'features/merge_patch/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON Patch and Diff', 'Guide', 'features/json_patch/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON Pointer', 'Guide', 'features/json_pointer/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Types', 'Guide', 'features/types/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Types: Number Handling', 'Guide', 'features/types/number_handling/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Object Order', 'Guide', 'features/object_order/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Parsing', 'Guide', 'features/parsing/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: JSON Lines', 'Guide', 'features/parsing/json_lines/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: Parser Callbacks', 'Guide', 'features/parsing/parser_callbacks/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: Parsing and Exceptions', 'Guide', 'features/parsing/parse_exceptions/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Parsing: SAX Interface', 'Guide', 'features/parsing/sax_interface/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Runtime Assertions', 'Guide', 'features/assertions/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Specializing enum conversion', 'Guide', 'features/enum_conversion/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Supported Macros', 'Guide', 'features/macros/index.html'); + +-- Macros +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'api/macros/json_assert/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'api/macros/json_throw_user/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'api/macros/json_has_cpp_11/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'api/macros/json_has_cpp_11/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'api/macros/json_has_cpp_11/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_20', 'Macro', 'api/macros/json_has_cpp_11/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_EXPERIMENTAL_FILESYSTEM', 'Macro', 'api/macros/json_has_filesystem/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_FILESYSTEM', 'Macro', 'api/macros/json_has_filesystem/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_RANGES', 'Macro', 'api/macros/json_has_ranges/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_THREE_WAY_COMPARISON', 'Macro', 'api/macros/json_has_three_way_comparison/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NOEXCEPTION', 'Macro', 'api/macros/json_noexception/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_NO_IO', 'Macro', 'api/macros/json_no_io/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_LIBRARY_VERSION_CHECK', 'Macro', 'api/macros/json_skip_library_version_check/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_SKIP_UNSUPPORTED_COMPILER_CHECK', 'Macro', 'api/macros/json_skip_unsupported_compiler_check/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_THROW_USER', 'Macro', 'api/macros/json_throw_user/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_TRY_USER', 'Macro', 'api/macros/json_throw_user/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_GLOBAL_UDLS', 'Macro', 'api/macros/json_use_global_udls/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_IMPLICIT_CONVERSIONS', 'Macro', 'api/macros/json_use_implicit_conversions/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON', 'Macro', 'api/macros/json_use_legacy_discarded_value_comparison/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('Macros', 'Macro', 'api/macros/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_type_intrusive/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_type_intrusive/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_type_non_intrusive/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT', 'Macro', 'api/macros/nlohmann_define_type_non_intrusive/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE', 'Macro', 'api/macros/nlohmann_json_namespace/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_BEGIN', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_NAMESPACE_END', 'Macro', 'api/macros/nlohmann_json_namespace_begin/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_SERIALIZE_ENUM', 'Macro', 'api/macros/nlohmann_json_serialize_enum/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MAJOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_MINOR', 'Macro', 'api/macros/nlohmann_json_version_major/index.html'); +INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_JSON_VERSION_PATCH', 'Macro', 'api/macros/nlohmann_json_version_major/index.html'); diff --git a/doc/docset/docset.json b/docs/docset/docset.json similarity index 89% rename from doc/docset/docset.json rename to docs/docset/docset.json index f8d478302..c252636a0 100644 --- a/doc/docset/docset.json +++ b/docs/docset/docset.json @@ -1,6 +1,6 @@ { "name": "JSON for Modern C++", - "version": "3.10.0", + "version": "3.11.0", "archive": "JSON_for_Modern_C++.tgz", "author": { "name": "Niels Lohmann", diff --git a/doc/docset/icon.png b/docs/docset/icon.png similarity index 100% rename from doc/docset/icon.png rename to docs/docset/icon.png diff --git a/doc/docset/icon@2x.png b/docs/docset/icon@2x.png similarity index 100% rename from doc/docset/icon@2x.png rename to docs/docset/icon@2x.png diff --git a/doc/examples/README.cpp b/docs/examples/README.cpp similarity index 100% rename from doc/examples/README.cpp rename to docs/examples/README.cpp diff --git a/doc/examples/README.output b/docs/examples/README.output similarity index 100% rename from doc/examples/README.output rename to docs/examples/README.output diff --git a/doc/examples/accept__string.cpp b/docs/examples/accept__string.cpp similarity index 100% rename from doc/examples/accept__string.cpp rename to docs/examples/accept__string.cpp diff --git a/doc/examples/accept__string.output b/docs/examples/accept__string.output similarity index 100% rename from doc/examples/accept__string.output rename to docs/examples/accept__string.output diff --git a/doc/examples/array.cpp b/docs/examples/array.cpp similarity index 100% rename from doc/examples/array.cpp rename to docs/examples/array.cpp diff --git a/doc/examples/array.output b/docs/examples/array.output similarity index 100% rename from doc/examples/array.output rename to docs/examples/array.output diff --git a/doc/examples/array_t.cpp b/docs/examples/array_t.cpp similarity index 100% rename from doc/examples/array_t.cpp rename to docs/examples/array_t.cpp diff --git a/doc/examples/array_t.output b/docs/examples/array_t.output similarity index 100% rename from doc/examples/array_t.output rename to docs/examples/array_t.output diff --git a/doc/examples/at_json_pointer.cpp b/docs/examples/at__json_pointer.cpp similarity index 98% rename from doc/examples/at_json_pointer.cpp rename to docs/examples/at__json_pointer.cpp index f554d8533..26dfd8edd 100644 --- a/doc/examples/at_json_pointer.cpp +++ b/docs/examples/at__json_pointer.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/at_json_pointer.output b/docs/examples/at__json_pointer.output similarity index 100% rename from doc/examples/at_json_pointer.output rename to docs/examples/at__json_pointer.output diff --git a/doc/examples/at_json_pointer_const.cpp b/docs/examples/at__json_pointer_const.cpp similarity index 98% rename from doc/examples/at_json_pointer_const.cpp rename to docs/examples/at__json_pointer_const.cpp index 3ac232b9f..f049bd8d9 100644 --- a/doc/examples/at_json_pointer_const.cpp +++ b/docs/examples/at__json_pointer_const.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/at_json_pointer_const.output b/docs/examples/at__json_pointer_const.output similarity index 100% rename from doc/examples/at_json_pointer_const.output rename to docs/examples/at__json_pointer_const.output diff --git a/docs/examples/at__keytype.c++17.cpp b/docs/examples/at__keytype.c++17.cpp new file mode 100644 index 000000000..3491cb9f7 --- /dev/null +++ b/docs/examples/at__keytype.c++17.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create JSON object + json object = + { + {"the good", "il buono"}, + {"the bad", "il cattivo"}, + {"the ugly", "il brutto"} + }; + + // output element with key "the ugly" using string_view + std::cout << object.at("the ugly"sv) << '\n'; + + // change element with key "the bad" using string_view + object.at("the bad"sv) = "il cattivo"; + + // output changed array + std::cout << object << '\n'; + + + // exception type_error.304 + try + { + // use at() with string_view on a non-object type + json str = "I am a string"; + str.at("the good"sv) = "Another string"; + } + catch (json::type_error& e) + { + std::cout << e.what() << '\n'; + } + + // exception out_of_range.401 + try + { + // try to write at a nonexisting key using string_view + object.at("the fast"sv) = "il rapido"; + } + catch (json::out_of_range& e) + { + std::cout << e.what() << '\n'; + } +} diff --git a/doc/examples/at__object_t_key_type.output b/docs/examples/at__keytype.c++17.output similarity index 100% rename from doc/examples/at__object_t_key_type.output rename to docs/examples/at__keytype.c++17.output diff --git a/docs/examples/at__keytype_const.c++17.cpp b/docs/examples/at__keytype_const.c++17.cpp new file mode 100644 index 000000000..ec93c7059 --- /dev/null +++ b/docs/examples/at__keytype_const.c++17.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create JSON object + const json object = + { + {"the good", "il buono"}, + {"the bad", "il cattivo"}, + {"the ugly", "il brutto"} + }; + + // output element with key "the ugly" using string_view + std::cout << object.at("the ugly"sv) << '\n'; + + + // exception type_error.304 + try + { + // use at() with string_view on a non-object type + const json str = "I am a string"; + std::cout << str.at("the good"sv) << '\n'; + } + catch (json::type_error& e) + { + std::cout << e.what() << '\n'; + } + + // exception out_of_range.401 + try + { + // try to read from a nonexisting key using string_view + std::cout << object.at("the fast"sv) << '\n'; + } + catch (json::out_of_range) + { + std::cout << "out of range" << '\n'; + } +} diff --git a/doc/examples/at__object_t_key_type_const.output b/docs/examples/at__keytype_const.c++17.output similarity index 100% rename from doc/examples/at__object_t_key_type_const.output rename to docs/examples/at__keytype_const.c++17.output diff --git a/doc/examples/at__object_t_key_type.cpp b/docs/examples/at__object_t_key_type.cpp similarity index 100% rename from doc/examples/at__object_t_key_type.cpp rename to docs/examples/at__object_t_key_type.cpp diff --git a/docs/examples/at__object_t_key_type.output b/docs/examples/at__object_t_key_type.output new file mode 100644 index 000000000..b544b7299 --- /dev/null +++ b/docs/examples/at__object_t_key_type.output @@ -0,0 +1,4 @@ +"il brutto" +{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"} +[json.exception.type_error.304] cannot use at() with string +[json.exception.out_of_range.403] key 'the fast' not found diff --git a/doc/examples/at__object_t_key_type_const.cpp b/docs/examples/at__object_t_key_type_const.cpp similarity index 100% rename from doc/examples/at__object_t_key_type_const.cpp rename to docs/examples/at__object_t_key_type_const.cpp diff --git a/docs/examples/at__object_t_key_type_const.output b/docs/examples/at__object_t_key_type_const.output new file mode 100644 index 000000000..40ca3f09f --- /dev/null +++ b/docs/examples/at__object_t_key_type_const.output @@ -0,0 +1,3 @@ +"il brutto" +[json.exception.type_error.304] cannot use at() with string +out of range diff --git a/doc/examples/at__size_type.cpp b/docs/examples/at__size_type.cpp similarity index 100% rename from doc/examples/at__size_type.cpp rename to docs/examples/at__size_type.cpp diff --git a/doc/examples/at__size_type.output b/docs/examples/at__size_type.output similarity index 100% rename from doc/examples/at__size_type.output rename to docs/examples/at__size_type.output diff --git a/doc/examples/at__size_type_const.cpp b/docs/examples/at__size_type_const.cpp similarity index 100% rename from doc/examples/at__size_type_const.cpp rename to docs/examples/at__size_type_const.cpp diff --git a/doc/examples/at__size_type_const.output b/docs/examples/at__size_type_const.output similarity index 100% rename from doc/examples/at__size_type_const.output rename to docs/examples/at__size_type_const.output diff --git a/doc/examples/back.cpp b/docs/examples/back.cpp similarity index 100% rename from doc/examples/back.cpp rename to docs/examples/back.cpp diff --git a/doc/examples/back.output b/docs/examples/back.output similarity index 100% rename from doc/examples/back.output rename to docs/examples/back.output diff --git a/doc/examples/basic_json__CompatibleType.cpp b/docs/examples/basic_json__CompatibleType.cpp similarity index 100% rename from doc/examples/basic_json__CompatibleType.cpp rename to docs/examples/basic_json__CompatibleType.cpp diff --git a/doc/examples/basic_json__CompatibleType.output b/docs/examples/basic_json__CompatibleType.output similarity index 94% rename from doc/examples/basic_json__CompatibleType.output rename to docs/examples/basic_json__CompatibleType.output index 2337e81fb..10c4ed3fe 100644 --- a/doc/examples/basic_json__CompatibleType.output +++ b/docs/examples/basic_json__CompatibleType.output @@ -2,7 +2,7 @@ {"one":1,"three":3,"two":2} {"one":1.2,"three":3.4,"two":2.3} {"one":true,"three":false,"two":true} -{"one":true,"three":false,"two":true} +{"one":true,"three":true,"two":true} ["one","two",3,4.5,false] [1,2,3,4] diff --git a/doc/examples/basic_json__InputIt_InputIt.cpp b/docs/examples/basic_json__InputIt_InputIt.cpp similarity index 100% rename from doc/examples/basic_json__InputIt_InputIt.cpp rename to docs/examples/basic_json__InputIt_InputIt.cpp diff --git a/doc/examples/basic_json__InputIt_InputIt.output b/docs/examples/basic_json__InputIt_InputIt.output similarity index 100% rename from doc/examples/basic_json__InputIt_InputIt.output rename to docs/examples/basic_json__InputIt_InputIt.output diff --git a/doc/examples/basic_json__basic_json.cpp b/docs/examples/basic_json__basic_json.cpp similarity index 100% rename from doc/examples/basic_json__basic_json.cpp rename to docs/examples/basic_json__basic_json.cpp diff --git a/doc/examples/basic_json__basic_json.output b/docs/examples/basic_json__basic_json.output similarity index 100% rename from doc/examples/basic_json__basic_json.output rename to docs/examples/basic_json__basic_json.output diff --git a/doc/examples/basic_json__copyassignment.cpp b/docs/examples/basic_json__copyassignment.cpp similarity index 100% rename from doc/examples/basic_json__copyassignment.cpp rename to docs/examples/basic_json__copyassignment.cpp diff --git a/doc/examples/basic_json__copyassignment.output b/docs/examples/basic_json__copyassignment.output similarity index 100% rename from doc/examples/basic_json__copyassignment.output rename to docs/examples/basic_json__copyassignment.output diff --git a/doc/examples/basic_json__list_init_t.cpp b/docs/examples/basic_json__list_init_t.cpp similarity index 100% rename from doc/examples/basic_json__list_init_t.cpp rename to docs/examples/basic_json__list_init_t.cpp diff --git a/doc/examples/basic_json__list_init_t.output b/docs/examples/basic_json__list_init_t.output similarity index 100% rename from doc/examples/basic_json__list_init_t.output rename to docs/examples/basic_json__list_init_t.output diff --git a/doc/examples/basic_json__moveconstructor.cpp b/docs/examples/basic_json__moveconstructor.cpp similarity index 100% rename from doc/examples/basic_json__moveconstructor.cpp rename to docs/examples/basic_json__moveconstructor.cpp diff --git a/doc/examples/basic_json__moveconstructor.output b/docs/examples/basic_json__moveconstructor.output similarity index 100% rename from doc/examples/basic_json__moveconstructor.output rename to docs/examples/basic_json__moveconstructor.output diff --git a/doc/examples/basic_json__nullptr_t.cpp b/docs/examples/basic_json__nullptr_t.cpp similarity index 100% rename from doc/examples/basic_json__nullptr_t.cpp rename to docs/examples/basic_json__nullptr_t.cpp diff --git a/doc/examples/basic_json__nullptr_t.output b/docs/examples/basic_json__nullptr_t.output similarity index 100% rename from doc/examples/basic_json__nullptr_t.output rename to docs/examples/basic_json__nullptr_t.output diff --git a/doc/examples/basic_json__size_type_basic_json.cpp b/docs/examples/basic_json__size_type_basic_json.cpp similarity index 100% rename from doc/examples/basic_json__size_type_basic_json.cpp rename to docs/examples/basic_json__size_type_basic_json.cpp diff --git a/doc/examples/basic_json__size_type_basic_json.output b/docs/examples/basic_json__size_type_basic_json.output similarity index 100% rename from doc/examples/basic_json__size_type_basic_json.output rename to docs/examples/basic_json__size_type_basic_json.output diff --git a/doc/examples/basic_json__value_t.cpp b/docs/examples/basic_json__value_t.cpp similarity index 100% rename from doc/examples/basic_json__value_t.cpp rename to docs/examples/basic_json__value_t.cpp diff --git a/doc/examples/basic_json__value_t.output b/docs/examples/basic_json__value_t.output similarity index 100% rename from doc/examples/basic_json__value_t.output rename to docs/examples/basic_json__value_t.output diff --git a/doc/examples/begin.cpp b/docs/examples/begin.cpp similarity index 100% rename from doc/examples/begin.cpp rename to docs/examples/begin.cpp diff --git a/doc/examples/begin.output b/docs/examples/begin.output similarity index 100% rename from doc/examples/begin.output rename to docs/examples/begin.output diff --git a/doc/examples/binary.cpp b/docs/examples/binary.cpp similarity index 100% rename from doc/examples/binary.cpp rename to docs/examples/binary.cpp diff --git a/doc/examples/binary.output b/docs/examples/binary.output similarity index 100% rename from doc/examples/binary.output rename to docs/examples/binary.output diff --git a/doc/examples/binary_t.cpp b/docs/examples/binary_t.cpp similarity index 100% rename from doc/examples/binary_t.cpp rename to docs/examples/binary_t.cpp diff --git a/doc/examples/binary_t.output b/docs/examples/binary_t.output similarity index 100% rename from doc/examples/binary_t.output rename to docs/examples/binary_t.output diff --git a/doc/examples/boolean_t.cpp b/docs/examples/boolean_t.cpp similarity index 100% rename from doc/examples/boolean_t.cpp rename to docs/examples/boolean_t.cpp diff --git a/doc/examples/boolean_t.output b/docs/examples/boolean_t.output similarity index 100% rename from doc/examples/boolean_t.output rename to docs/examples/boolean_t.output diff --git a/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp new file mode 100644 index 000000000..1c10be5c2 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.cpp @@ -0,0 +1,23 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + // (1) create empty container + auto c1 = byte_container_with_subtype(); + + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // (2) create container + auto c2 = byte_container_with_subtype(bytes); + + // (3) create container with subtype + auto c3 = byte_container_with_subtype(bytes, 42); + + std::cout << json(c1) << "\n" << json(c2) << "\n" << json(c3) << std::endl; +} diff --git a/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output new file mode 100644 index 000000000..67ac1b2ef --- /dev/null +++ b/docs/examples/byte_container_with_subtype__byte_container_with_subtype.output @@ -0,0 +1,3 @@ +{"bytes":[],"subtype":null} +{"bytes":[202,254,186,190],"subtype":null} +{"bytes":[202,254,186,190],"subtype":42} diff --git a/docs/examples/byte_container_with_subtype__clear_subtype.cpp b/docs/examples/byte_container_with_subtype__clear_subtype.cpp new file mode 100644 index 000000000..f9ce6842b --- /dev/null +++ b/docs/examples/byte_container_with_subtype__clear_subtype.cpp @@ -0,0 +1,21 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container with subtype + auto c1 = byte_container_with_subtype(bytes, 42); + + std::cout << "before calling clear_subtype(): " << json(c1) << '\n'; + + c1.clear_subtype(); + + std::cout << "after calling clear_subtype(): " << json(c1) << '\n'; +} diff --git a/docs/examples/byte_container_with_subtype__clear_subtype.output b/docs/examples/byte_container_with_subtype__clear_subtype.output new file mode 100644 index 000000000..9d8212946 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__clear_subtype.output @@ -0,0 +1,2 @@ +before calling clear_subtype(): {"bytes":[202,254,186,190],"subtype":42} +after calling clear_subtype(): {"bytes":[202,254,186,190],"subtype":null} diff --git a/docs/examples/byte_container_with_subtype__has_subtype.cpp b/docs/examples/byte_container_with_subtype__has_subtype.cpp new file mode 100644 index 000000000..61c21eaae --- /dev/null +++ b/docs/examples/byte_container_with_subtype__has_subtype.cpp @@ -0,0 +1,19 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container + auto c1 = byte_container_with_subtype(bytes); + + // create container with subtype + auto c2 = byte_container_with_subtype(bytes, 42); + + std::cout << std::boolalpha << "c1.has_subtype() = " << c1.has_subtype() + << "\nc2.has_subtype() = " << c2.has_subtype() << std::endl; +} diff --git a/docs/examples/byte_container_with_subtype__has_subtype.output b/docs/examples/byte_container_with_subtype__has_subtype.output new file mode 100644 index 000000000..f4aade2a1 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__has_subtype.output @@ -0,0 +1,2 @@ +c1.has_subtype() = false +c2.has_subtype() = true diff --git a/docs/examples/byte_container_with_subtype__set_subtype.cpp b/docs/examples/byte_container_with_subtype__set_subtype.cpp new file mode 100644 index 000000000..b2694c54d --- /dev/null +++ b/docs/examples/byte_container_with_subtype__set_subtype.cpp @@ -0,0 +1,22 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +using json = nlohmann::json; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container without subtype + auto c = byte_container_with_subtype(bytes); + + std::cout << "before calling set_subtype(42): " << json(c) << '\n'; + + // set the subtype + c.set_subtype(42); + + std::cout << "after calling set_subtype(42): " << json(c) << '\n'; +} diff --git a/docs/examples/byte_container_with_subtype__set_subtype.output b/docs/examples/byte_container_with_subtype__set_subtype.output new file mode 100644 index 000000000..648b3ef24 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__set_subtype.output @@ -0,0 +1,2 @@ +before calling set_subtype(42): {"bytes":[202,254,186,190],"subtype":null} +after calling set_subtype(42): {"bytes":[202,254,186,190],"subtype":42} diff --git a/docs/examples/byte_container_with_subtype__subtype.cpp b/docs/examples/byte_container_with_subtype__subtype.cpp new file mode 100644 index 000000000..cd230ade1 --- /dev/null +++ b/docs/examples/byte_container_with_subtype__subtype.cpp @@ -0,0 +1,22 @@ +#include +#include + +// define a byte container based on std::vector +using byte_container_with_subtype = nlohmann::byte_container_with_subtype>; + +int main() +{ + std::vector bytes = {{0xca, 0xfe, 0xba, 0xbe}}; + + // create container + auto c1 = byte_container_with_subtype(bytes); + + // create container with subtype + auto c2 = byte_container_with_subtype(bytes, 42); + + std::cout << "c1.subtype() = " << c1.subtype() + << "\nc2.subtype() = " << c2.subtype() << std::endl; + + // in case no subtype is set, return special value + assert(c1.subtype() == static_cast(-1)); +} diff --git a/docs/examples/byte_container_with_subtype__subtype.output b/docs/examples/byte_container_with_subtype__subtype.output new file mode 100644 index 000000000..47955277b --- /dev/null +++ b/docs/examples/byte_container_with_subtype__subtype.output @@ -0,0 +1,2 @@ +c1.subtype() = 18446744073709551615 +c2.subtype() = 42 diff --git a/doc/examples/cbegin.cpp b/docs/examples/cbegin.cpp similarity index 100% rename from doc/examples/cbegin.cpp rename to docs/examples/cbegin.cpp diff --git a/doc/examples/cbegin.output b/docs/examples/cbegin.output similarity index 100% rename from doc/examples/cbegin.output rename to docs/examples/cbegin.output diff --git a/docs/examples/cbor_tag_handler_t.cpp b/docs/examples/cbor_tag_handler_t.cpp new file mode 100644 index 000000000..79052c7a0 --- /dev/null +++ b/docs/examples/cbor_tag_handler_t.cpp @@ -0,0 +1,28 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // tagged byte string + std::vector vec = {{0xd8, 0x42, 0x44, 0xcA, 0xfe, 0xba, 0xbe}}; + + // cbor_tag_handler_t::error throws + try + { + auto b_throw_on_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::error); + } + catch (json::parse_error& e) + { + std::cout << e.what() << std::endl; + } + + // cbor_tag_handler_t::ignore ignores the tag + auto b_ignore_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::ignore); + std::cout << b_ignore_tag << std::endl; + + // cbor_tag_handler_t::store stores the tag as binary subtype + auto b_store_tag = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::store); + std::cout << b_store_tag << std::endl; +} diff --git a/docs/examples/cbor_tag_handler_t.output b/docs/examples/cbor_tag_handler_t.output new file mode 100644 index 000000000..18920b137 --- /dev/null +++ b/docs/examples/cbor_tag_handler_t.output @@ -0,0 +1,3 @@ +[json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0xD8 +{"bytes":[202,254,186,190],"subtype":null} +{"bytes":[202,254,186,190],"subtype":66} diff --git a/doc/examples/cend.cpp b/docs/examples/cend.cpp similarity index 100% rename from doc/examples/cend.cpp rename to docs/examples/cend.cpp diff --git a/doc/examples/cend.output b/docs/examples/cend.output similarity index 100% rename from doc/examples/cend.output rename to docs/examples/cend.output diff --git a/doc/examples/clear.cpp b/docs/examples/clear.cpp similarity index 100% rename from doc/examples/clear.cpp rename to docs/examples/clear.cpp diff --git a/doc/examples/clear.output b/docs/examples/clear.output similarity index 100% rename from doc/examples/clear.output rename to docs/examples/clear.output diff --git a/doc/examples/contains_json_pointer.cpp b/docs/examples/contains__json_pointer.cpp similarity index 96% rename from doc/examples/contains_json_pointer.cpp rename to docs/examples/contains__json_pointer.cpp index 54bcaa9e4..f9de546b5 100644 --- a/doc/examples/contains_json_pointer.cpp +++ b/docs/examples/contains__json_pointer.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/contains_json_pointer.output b/docs/examples/contains__json_pointer.output similarity index 100% rename from doc/examples/contains_json_pointer.output rename to docs/examples/contains__json_pointer.output diff --git a/docs/examples/contains__keytype.c++17.cpp b/docs/examples/contains__keytype.c++17.cpp new file mode 100644 index 000000000..43b62fab1 --- /dev/null +++ b/docs/examples/contains__keytype.c++17.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; +using namespace nlohmann::literals; + +int main() +{ + // create some JSON values + json j_object = R"( {"key": "value"} )"_json; + json j_array = R"( [1, 2, 3] )"_json; + + // call contains + std::cout << std::boolalpha << + "j_object contains 'key': " << j_object.contains("key"sv) << '\n' << + "j_object contains 'another': " << j_object.contains("another"sv) << '\n' << + "j_array contains 'key': " << j_array.contains("key"sv) << std::endl; +} diff --git a/doc/examples/contains.output b/docs/examples/contains__keytype.c++17.output similarity index 100% rename from doc/examples/contains.output rename to docs/examples/contains__keytype.c++17.output diff --git a/doc/examples/contains.cpp b/docs/examples/contains__object_t_key_type.cpp similarity index 93% rename from doc/examples/contains.cpp rename to docs/examples/contains__object_t_key_type.cpp index df8201c33..a8bc8143d 100644 --- a/doc/examples/contains.cpp +++ b/docs/examples/contains__object_t_key_type.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/docs/examples/contains__object_t_key_type.output b/docs/examples/contains__object_t_key_type.output new file mode 100644 index 000000000..14ad177b1 --- /dev/null +++ b/docs/examples/contains__object_t_key_type.output @@ -0,0 +1,3 @@ +j_object contains 'key': true +j_object contains 'another': false +j_array contains 'key': false diff --git a/docs/examples/count__keytype.c++17.cpp b/docs/examples/count__keytype.c++17.cpp new file mode 100644 index 000000000..ec6de0607 --- /dev/null +++ b/docs/examples/count__keytype.c++17.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object + json j_object = {{"one", 1}, {"two", 2}}; + + // call count() + auto count_two = j_object.count("two"sv); + auto count_three = j_object.count("three"sv); + + // print values + std::cout << "number of elements with key \"two\": " << count_two << '\n'; + std::cout << "number of elements with key \"three\": " << count_three << '\n'; +} diff --git a/doc/examples/count.output b/docs/examples/count__keytype.c++17.output similarity index 100% rename from doc/examples/count.output rename to docs/examples/count__keytype.c++17.output diff --git a/doc/examples/count.cpp b/docs/examples/count__object_t_key_type.cpp similarity index 100% rename from doc/examples/count.cpp rename to docs/examples/count__object_t_key_type.cpp diff --git a/docs/examples/count__object_t_key_type.output b/docs/examples/count__object_t_key_type.output new file mode 100644 index 000000000..d816fcb24 --- /dev/null +++ b/docs/examples/count__object_t_key_type.output @@ -0,0 +1,2 @@ +number of elements with key "two": 1 +number of elements with key "three": 0 diff --git a/doc/examples/crbegin.cpp b/docs/examples/crbegin.cpp similarity index 100% rename from doc/examples/crbegin.cpp rename to docs/examples/crbegin.cpp diff --git a/doc/examples/crbegin.output b/docs/examples/crbegin.output similarity index 100% rename from doc/examples/crbegin.output rename to docs/examples/crbegin.output diff --git a/doc/examples/crend.cpp b/docs/examples/crend.cpp similarity index 100% rename from doc/examples/crend.cpp rename to docs/examples/crend.cpp diff --git a/doc/examples/crend.output b/docs/examples/crend.output similarity index 100% rename from doc/examples/crend.output rename to docs/examples/crend.output diff --git a/docs/examples/default_object_comparator_t.cpp b/docs/examples/default_object_comparator_t.cpp new file mode 100644 index 000000000..9f200fe6b --- /dev/null +++ b/docs/examples/default_object_comparator_t.cpp @@ -0,0 +1,11 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::boolalpha + << "one < two : " << json::default_object_comparator_t{}("one", "two") << "\n" + << "three < four : " << json::default_object_comparator_t{}("three", "four") << std::endl; +} diff --git a/docs/examples/default_object_comparator_t.output b/docs/examples/default_object_comparator_t.output new file mode 100644 index 000000000..b1daf3b96 --- /dev/null +++ b/docs/examples/default_object_comparator_t.output @@ -0,0 +1,2 @@ +one < two : true +three < four : false diff --git a/doc/examples/diagnostics_extended.cpp b/docs/examples/diagnostics_extended.cpp similarity index 100% rename from doc/examples/diagnostics_extended.cpp rename to docs/examples/diagnostics_extended.cpp diff --git a/doc/examples/diagnostics_extended.output b/docs/examples/diagnostics_extended.output similarity index 100% rename from doc/examples/diagnostics_extended.output rename to docs/examples/diagnostics_extended.output diff --git a/doc/examples/diagnostics_standard.cpp b/docs/examples/diagnostics_standard.cpp similarity index 100% rename from doc/examples/diagnostics_standard.cpp rename to docs/examples/diagnostics_standard.cpp diff --git a/doc/examples/diagnostics_standard.output b/docs/examples/diagnostics_standard.output similarity index 100% rename from doc/examples/diagnostics_standard.output rename to docs/examples/diagnostics_standard.output diff --git a/doc/examples/diff.cpp b/docs/examples/diff.cpp similarity index 95% rename from doc/examples/diff.cpp rename to docs/examples/diff.cpp index 71b19be66..ef01332a1 100644 --- a/doc/examples/diff.cpp +++ b/docs/examples/diff.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/diff.output b/docs/examples/diff.output similarity index 100% rename from doc/examples/diff.output rename to docs/examples/diff.output diff --git a/doc/examples/dump.cpp b/docs/examples/dump.cpp similarity index 100% rename from doc/examples/dump.cpp rename to docs/examples/dump.cpp diff --git a/doc/examples/dump.output b/docs/examples/dump.output similarity index 100% rename from doc/examples/dump.output rename to docs/examples/dump.output diff --git a/doc/examples/emplace.cpp b/docs/examples/emplace.cpp similarity index 100% rename from doc/examples/emplace.cpp rename to docs/examples/emplace.cpp diff --git a/doc/examples/emplace.output b/docs/examples/emplace.output similarity index 100% rename from doc/examples/emplace.output rename to docs/examples/emplace.output diff --git a/doc/examples/emplace_back.cpp b/docs/examples/emplace_back.cpp similarity index 100% rename from doc/examples/emplace_back.cpp rename to docs/examples/emplace_back.cpp diff --git a/doc/examples/emplace_back.output b/docs/examples/emplace_back.output similarity index 100% rename from doc/examples/emplace_back.output rename to docs/examples/emplace_back.output diff --git a/doc/examples/empty.cpp b/docs/examples/empty.cpp similarity index 100% rename from doc/examples/empty.cpp rename to docs/examples/empty.cpp diff --git a/doc/examples/empty.output b/docs/examples/empty.output similarity index 100% rename from doc/examples/empty.output rename to docs/examples/empty.output diff --git a/doc/examples/end.cpp b/docs/examples/end.cpp similarity index 100% rename from doc/examples/end.cpp rename to docs/examples/end.cpp diff --git a/doc/examples/end.output b/docs/examples/end.output similarity index 100% rename from doc/examples/end.output rename to docs/examples/end.output diff --git a/doc/examples/erase__IteratorType.cpp b/docs/examples/erase__IteratorType.cpp similarity index 100% rename from doc/examples/erase__IteratorType.cpp rename to docs/examples/erase__IteratorType.cpp diff --git a/doc/examples/erase__IteratorType.output b/docs/examples/erase__IteratorType.output similarity index 100% rename from doc/examples/erase__IteratorType.output rename to docs/examples/erase__IteratorType.output diff --git a/doc/examples/erase__IteratorType_IteratorType.cpp b/docs/examples/erase__IteratorType_IteratorType.cpp similarity index 100% rename from doc/examples/erase__IteratorType_IteratorType.cpp rename to docs/examples/erase__IteratorType_IteratorType.cpp diff --git a/doc/examples/erase__IteratorType_IteratorType.output b/docs/examples/erase__IteratorType_IteratorType.output similarity index 100% rename from doc/examples/erase__IteratorType_IteratorType.output rename to docs/examples/erase__IteratorType_IteratorType.output diff --git a/docs/examples/erase__keytype.c++17.cpp b/docs/examples/erase__keytype.c++17.cpp new file mode 100644 index 000000000..c5e4bed5d --- /dev/null +++ b/docs/examples/erase__keytype.c++17.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object + json j_object = {{"one", 1}, {"two", 2}}; + + // call erase() + auto count_one = j_object.erase("one"sv); + auto count_three = j_object.erase("three"sv); + + // print values + std::cout << j_object << '\n'; + std::cout << count_one << " " << count_three << '\n'; +} diff --git a/doc/examples/erase__key_type.output b/docs/examples/erase__keytype.c++17.output similarity index 100% rename from doc/examples/erase__key_type.output rename to docs/examples/erase__keytype.c++17.output diff --git a/doc/examples/erase__key_type.cpp b/docs/examples/erase__object_t_key_type.cpp similarity index 100% rename from doc/examples/erase__key_type.cpp rename to docs/examples/erase__object_t_key_type.cpp diff --git a/docs/examples/erase__object_t_key_type.output b/docs/examples/erase__object_t_key_type.output new file mode 100644 index 000000000..28d79391a --- /dev/null +++ b/docs/examples/erase__object_t_key_type.output @@ -0,0 +1,2 @@ +{"two":2} +1 0 diff --git a/doc/examples/erase__size_type.cpp b/docs/examples/erase__size_type.cpp similarity index 100% rename from doc/examples/erase__size_type.cpp rename to docs/examples/erase__size_type.cpp diff --git a/doc/examples/erase__size_type.output b/docs/examples/erase__size_type.output similarity index 100% rename from doc/examples/erase__size_type.output rename to docs/examples/erase__size_type.output diff --git a/docs/examples/error_handler_t.cpp b/docs/examples/error_handler_t.cpp new file mode 100644 index 000000000..add3f3b2d --- /dev/null +++ b/docs/examples/error_handler_t.cpp @@ -0,0 +1,24 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create JSON value with invalid UTF-8 byte sequence + json j_invalid = "ä\xA9Ãŧ"; + try + { + std::cout << j_invalid.dump() << std::endl; + } + catch (json::type_error& e) + { + std::cout << e.what() << std::endl; + } + + std::cout << "string with replaced invalid characters: " + << j_invalid.dump(-1, ' ', false, json::error_handler_t::replace) + << "\nstring with ignored invalid characters: " + << j_invalid.dump(-1, ' ', false, json::error_handler_t::ignore) + << '\n'; +} diff --git a/docs/examples/error_handler_t.output b/docs/examples/error_handler_t.output new file mode 100644 index 000000000..718d62bee --- /dev/null +++ b/docs/examples/error_handler_t.output @@ -0,0 +1,3 @@ +[json.exception.type_error.316] invalid UTF-8 byte at index 2: 0xA9 +string with replaced invalid characters: "äīŋŊÃŧ" +string with ignored invalid characters: "äÃŧ" diff --git a/doc/examples/exception.cpp b/docs/examples/exception.cpp similarity index 100% rename from doc/examples/exception.cpp rename to docs/examples/exception.cpp diff --git a/doc/examples/exception.output b/docs/examples/exception.output similarity index 100% rename from doc/examples/exception.output rename to docs/examples/exception.output diff --git a/docs/examples/find__keytype.c++17.cpp b/docs/examples/find__keytype.c++17.cpp new file mode 100644 index 000000000..da94cf0ad --- /dev/null +++ b/docs/examples/find__keytype.c++17.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object + json j_object = {{"one", 1}, {"two", 2}}; + + // call find + auto it_two = j_object.find("two"sv); + auto it_three = j_object.find("three"sv); + + // print values + std::cout << std::boolalpha; + std::cout << "\"two\" was found: " << (it_two != j_object.end()) << '\n'; + std::cout << "value at key \"two\": " << *it_two << '\n'; + std::cout << "\"three\" was found: " << (it_three != j_object.end()) << '\n'; +} diff --git a/doc/examples/find__key_type.output b/docs/examples/find__keytype.c++17.output similarity index 100% rename from doc/examples/find__key_type.output rename to docs/examples/find__keytype.c++17.output diff --git a/doc/examples/find__key_type.cpp b/docs/examples/find__object_t_key_type.cpp similarity index 100% rename from doc/examples/find__key_type.cpp rename to docs/examples/find__object_t_key_type.cpp diff --git a/docs/examples/find__object_t_key_type.output b/docs/examples/find__object_t_key_type.output new file mode 100644 index 000000000..509bb42d5 --- /dev/null +++ b/docs/examples/find__object_t_key_type.output @@ -0,0 +1,3 @@ +"two" was found: true +value at key "two": 2 +"three" was found: false diff --git a/doc/examples/flatten.cpp b/docs/examples/flatten.cpp similarity index 100% rename from doc/examples/flatten.cpp rename to docs/examples/flatten.cpp diff --git a/doc/examples/flatten.output b/docs/examples/flatten.output similarity index 100% rename from doc/examples/flatten.output rename to docs/examples/flatten.output diff --git a/docs/examples/from_bjdata.cpp b/docs/examples/from_bjdata.cpp new file mode 100644 index 000000000..961164c29 --- /dev/null +++ b/docs/examples/from_bjdata.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create byte vector + std::vector v = {0x7B, 0x69, 0x07, 0x63, 0x6F, 0x6D, 0x70, 0x61, + 0x63, 0x74, 0x54, 0x69, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6D, 0x61, 0x69, 0x00, 0x7D + }; + + // deserialize it with BJData + json j = json::from_bjdata(v); + + // print the deserialized JSON value + std::cout << std::setw(2) << j << std::endl; +} diff --git a/doc/examples/from_bson.output b/docs/examples/from_bjdata.output similarity index 100% rename from doc/examples/from_bson.output rename to docs/examples/from_bjdata.output diff --git a/doc/examples/from_bson.cpp b/docs/examples/from_bson.cpp similarity index 100% rename from doc/examples/from_bson.cpp rename to docs/examples/from_bson.cpp diff --git a/doc/examples/from_cbor.output b/docs/examples/from_bson.output similarity index 100% rename from doc/examples/from_cbor.output rename to docs/examples/from_bson.output diff --git a/doc/examples/from_cbor.cpp b/docs/examples/from_cbor.cpp similarity index 100% rename from doc/examples/from_cbor.cpp rename to docs/examples/from_cbor.cpp diff --git a/doc/examples/from_msgpack.output b/docs/examples/from_cbor.output similarity index 100% rename from doc/examples/from_msgpack.output rename to docs/examples/from_cbor.output diff --git a/doc/examples/from_msgpack.cpp b/docs/examples/from_msgpack.cpp similarity index 100% rename from doc/examples/from_msgpack.cpp rename to docs/examples/from_msgpack.cpp diff --git a/doc/examples/from_ubjson.output b/docs/examples/from_msgpack.output similarity index 100% rename from doc/examples/from_ubjson.output rename to docs/examples/from_msgpack.output diff --git a/doc/examples/from_ubjson.cpp b/docs/examples/from_ubjson.cpp similarity index 100% rename from doc/examples/from_ubjson.cpp rename to docs/examples/from_ubjson.cpp diff --git a/docs/examples/from_ubjson.output b/docs/examples/from_ubjson.output new file mode 100644 index 000000000..259f63bd4 --- /dev/null +++ b/docs/examples/from_ubjson.output @@ -0,0 +1,4 @@ +{ + "compact": true, + "schema": 0 +} diff --git a/doc/examples/front.cpp b/docs/examples/front.cpp similarity index 100% rename from doc/examples/front.cpp rename to docs/examples/front.cpp diff --git a/doc/examples/front.output b/docs/examples/front.output similarity index 100% rename from doc/examples/front.output rename to docs/examples/front.output diff --git a/doc/examples/get__PointerType.cpp b/docs/examples/get__PointerType.cpp similarity index 100% rename from doc/examples/get__PointerType.cpp rename to docs/examples/get__PointerType.cpp diff --git a/doc/examples/get__PointerType.output b/docs/examples/get__PointerType.output similarity index 100% rename from doc/examples/get__PointerType.output rename to docs/examples/get__PointerType.output diff --git a/doc/examples/get__ValueType_const.cpp b/docs/examples/get__ValueType_const.cpp similarity index 100% rename from doc/examples/get__ValueType_const.cpp rename to docs/examples/get__ValueType_const.cpp diff --git a/doc/examples/get__ValueType_const.output b/docs/examples/get__ValueType_const.output similarity index 100% rename from doc/examples/get__ValueType_const.output rename to docs/examples/get__ValueType_const.output diff --git a/docs/examples/get_allocator.cpp b/docs/examples/get_allocator.cpp new file mode 100644 index 000000000..35079a10c --- /dev/null +++ b/docs/examples/get_allocator.cpp @@ -0,0 +1,18 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + auto alloc = json::get_allocator(); + using traits_t = std::allocator_traits; + + json* j = traits_t::allocate(alloc, 1); + traits_t::construct(alloc, j, "Hello, world!"); + + std::cout << *j << std::endl; + + traits_t::destroy(alloc, j); + traits_t::deallocate(alloc, j, 1); +} diff --git a/docs/examples/get_allocator.output b/docs/examples/get_allocator.output new file mode 100644 index 000000000..8effb3e8c --- /dev/null +++ b/docs/examples/get_allocator.output @@ -0,0 +1 @@ +"Hello, world!" diff --git a/doc/examples/get_binary.cpp b/docs/examples/get_binary.cpp similarity index 100% rename from doc/examples/get_binary.cpp rename to docs/examples/get_binary.cpp diff --git a/doc/examples/get_binary.output b/docs/examples/get_binary.output similarity index 100% rename from doc/examples/get_binary.output rename to docs/examples/get_binary.output diff --git a/doc/examples/get_ptr.cpp b/docs/examples/get_ptr.cpp similarity index 100% rename from doc/examples/get_ptr.cpp rename to docs/examples/get_ptr.cpp diff --git a/doc/examples/get_ptr.output b/docs/examples/get_ptr.output similarity index 100% rename from doc/examples/get_ptr.output rename to docs/examples/get_ptr.output diff --git a/doc/examples/get_ref.cpp b/docs/examples/get_ref.cpp similarity index 100% rename from doc/examples/get_ref.cpp rename to docs/examples/get_ref.cpp diff --git a/doc/examples/get_ref.output b/docs/examples/get_ref.output similarity index 100% rename from doc/examples/get_ref.output rename to docs/examples/get_ref.output diff --git a/doc/examples/get_to.cpp b/docs/examples/get_to.cpp similarity index 100% rename from doc/examples/get_to.cpp rename to docs/examples/get_to.cpp diff --git a/doc/examples/get_to.output b/docs/examples/get_to.output similarity index 100% rename from doc/examples/get_to.output rename to docs/examples/get_to.output diff --git a/doc/examples/insert.cpp b/docs/examples/insert.cpp similarity index 100% rename from doc/examples/insert.cpp rename to docs/examples/insert.cpp diff --git a/doc/examples/insert.output b/docs/examples/insert.output similarity index 100% rename from doc/examples/insert.output rename to docs/examples/insert.output diff --git a/doc/examples/insert__count.cpp b/docs/examples/insert__count.cpp similarity index 100% rename from doc/examples/insert__count.cpp rename to docs/examples/insert__count.cpp diff --git a/doc/examples/insert__count.output b/docs/examples/insert__count.output similarity index 100% rename from doc/examples/insert__count.output rename to docs/examples/insert__count.output diff --git a/doc/examples/insert__ilist.cpp b/docs/examples/insert__ilist.cpp similarity index 100% rename from doc/examples/insert__ilist.cpp rename to docs/examples/insert__ilist.cpp diff --git a/doc/examples/insert__ilist.output b/docs/examples/insert__ilist.output similarity index 100% rename from doc/examples/insert__ilist.output rename to docs/examples/insert__ilist.output diff --git a/doc/examples/insert__range.cpp b/docs/examples/insert__range.cpp similarity index 100% rename from doc/examples/insert__range.cpp rename to docs/examples/insert__range.cpp diff --git a/doc/examples/insert__range.output b/docs/examples/insert__range.output similarity index 100% rename from doc/examples/insert__range.output rename to docs/examples/insert__range.output diff --git a/doc/examples/insert__range_object.cpp b/docs/examples/insert__range_object.cpp similarity index 100% rename from doc/examples/insert__range_object.cpp rename to docs/examples/insert__range_object.cpp diff --git a/doc/examples/insert__range_object.output b/docs/examples/insert__range_object.output similarity index 100% rename from doc/examples/insert__range_object.output rename to docs/examples/insert__range_object.output diff --git a/doc/examples/invalid_iterator.cpp b/docs/examples/invalid_iterator.cpp similarity index 100% rename from doc/examples/invalid_iterator.cpp rename to docs/examples/invalid_iterator.cpp diff --git a/doc/examples/invalid_iterator.output b/docs/examples/invalid_iterator.output similarity index 100% rename from doc/examples/invalid_iterator.output rename to docs/examples/invalid_iterator.output diff --git a/doc/examples/is_array.cpp b/docs/examples/is_array.cpp similarity index 100% rename from doc/examples/is_array.cpp rename to docs/examples/is_array.cpp diff --git a/doc/examples/is_array.output b/docs/examples/is_array.output similarity index 100% rename from doc/examples/is_array.output rename to docs/examples/is_array.output diff --git a/doc/examples/is_binary.cpp b/docs/examples/is_binary.cpp similarity index 100% rename from doc/examples/is_binary.cpp rename to docs/examples/is_binary.cpp diff --git a/doc/examples/is_binary.output b/docs/examples/is_binary.output similarity index 100% rename from doc/examples/is_binary.output rename to docs/examples/is_binary.output diff --git a/doc/examples/is_boolean.cpp b/docs/examples/is_boolean.cpp similarity index 100% rename from doc/examples/is_boolean.cpp rename to docs/examples/is_boolean.cpp diff --git a/doc/examples/is_boolean.output b/docs/examples/is_boolean.output similarity index 100% rename from doc/examples/is_boolean.output rename to docs/examples/is_boolean.output diff --git a/doc/examples/is_discarded.cpp b/docs/examples/is_discarded.cpp similarity index 100% rename from doc/examples/is_discarded.cpp rename to docs/examples/is_discarded.cpp diff --git a/doc/examples/is_discarded.output b/docs/examples/is_discarded.output similarity index 100% rename from doc/examples/is_discarded.output rename to docs/examples/is_discarded.output diff --git a/doc/examples/is_null.cpp b/docs/examples/is_null.cpp similarity index 100% rename from doc/examples/is_null.cpp rename to docs/examples/is_null.cpp diff --git a/doc/examples/is_null.output b/docs/examples/is_null.output similarity index 100% rename from doc/examples/is_null.output rename to docs/examples/is_null.output diff --git a/doc/examples/is_number.cpp b/docs/examples/is_number.cpp similarity index 100% rename from doc/examples/is_number.cpp rename to docs/examples/is_number.cpp diff --git a/doc/examples/is_number.output b/docs/examples/is_number.output similarity index 100% rename from doc/examples/is_number.output rename to docs/examples/is_number.output diff --git a/doc/examples/is_number_float.cpp b/docs/examples/is_number_float.cpp similarity index 100% rename from doc/examples/is_number_float.cpp rename to docs/examples/is_number_float.cpp diff --git a/doc/examples/is_number_float.output b/docs/examples/is_number_float.output similarity index 100% rename from doc/examples/is_number_float.output rename to docs/examples/is_number_float.output diff --git a/doc/examples/is_number_integer.cpp b/docs/examples/is_number_integer.cpp similarity index 100% rename from doc/examples/is_number_integer.cpp rename to docs/examples/is_number_integer.cpp diff --git a/doc/examples/is_number_integer.output b/docs/examples/is_number_integer.output similarity index 100% rename from doc/examples/is_number_integer.output rename to docs/examples/is_number_integer.output diff --git a/doc/examples/is_number_unsigned.cpp b/docs/examples/is_number_unsigned.cpp similarity index 100% rename from doc/examples/is_number_unsigned.cpp rename to docs/examples/is_number_unsigned.cpp diff --git a/doc/examples/is_number_unsigned.output b/docs/examples/is_number_unsigned.output similarity index 100% rename from doc/examples/is_number_unsigned.output rename to docs/examples/is_number_unsigned.output diff --git a/doc/examples/is_object.cpp b/docs/examples/is_object.cpp similarity index 100% rename from doc/examples/is_object.cpp rename to docs/examples/is_object.cpp diff --git a/doc/examples/is_object.output b/docs/examples/is_object.output similarity index 100% rename from doc/examples/is_object.output rename to docs/examples/is_object.output diff --git a/doc/examples/is_primitive.cpp b/docs/examples/is_primitive.cpp similarity index 100% rename from doc/examples/is_primitive.cpp rename to docs/examples/is_primitive.cpp diff --git a/doc/examples/is_primitive.output b/docs/examples/is_primitive.output similarity index 100% rename from doc/examples/is_primitive.output rename to docs/examples/is_primitive.output diff --git a/doc/examples/is_string.cpp b/docs/examples/is_string.cpp similarity index 100% rename from doc/examples/is_string.cpp rename to docs/examples/is_string.cpp diff --git a/doc/examples/is_string.output b/docs/examples/is_string.output similarity index 100% rename from doc/examples/is_string.output rename to docs/examples/is_string.output diff --git a/doc/examples/is_structured.cpp b/docs/examples/is_structured.cpp similarity index 100% rename from doc/examples/is_structured.cpp rename to docs/examples/is_structured.cpp diff --git a/doc/examples/is_structured.output b/docs/examples/is_structured.output similarity index 100% rename from doc/examples/is_structured.output rename to docs/examples/is_structured.output diff --git a/doc/examples/items.cpp b/docs/examples/items.cpp similarity index 100% rename from doc/examples/items.cpp rename to docs/examples/items.cpp diff --git a/doc/examples/items.output b/docs/examples/items.output similarity index 100% rename from doc/examples/items.output rename to docs/examples/items.output diff --git a/docs/examples/json_lines.cpp b/docs/examples/json_lines.cpp new file mode 100644 index 000000000..233c81a4a --- /dev/null +++ b/docs/examples/json_lines.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + // JSON Lines (see https://jsonlines.org) + std::stringstream input; + input << R"({"name": "Gilbert", "wins": [["straight", "7â™Ŗ"], ["one pair", "10â™Ĩ"]]} +{"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]} +{"name": "May", "wins": []} +{"name": "Deloise", "wins": [["three of a kind", "5â™Ŗ"]]} +)"; + + std::string line; + while (std::getline(input, line)) + { + std::cout << json::parse(line) << std::endl; + } +} diff --git a/docs/examples/json_lines.output b/docs/examples/json_lines.output new file mode 100644 index 000000000..1b4122480 --- /dev/null +++ b/docs/examples/json_lines.output @@ -0,0 +1,4 @@ +{"name":"Gilbert","wins":[["straight","7â™Ŗ"],["one pair","10â™Ĩ"]]} +{"name":"Alexa","wins":[["two pair","4♠"],["two pair","9♠"]]} +{"name":"May","wins":[]} +{"name":"Deloise","wins":[["three of a kind","5â™Ŗ"]]} diff --git a/doc/examples/json_pointer.cpp b/docs/examples/json_pointer.cpp similarity index 100% rename from doc/examples/json_pointer.cpp rename to docs/examples/json_pointer.cpp diff --git a/doc/examples/json_pointer.output b/docs/examples/json_pointer.output similarity index 100% rename from doc/examples/json_pointer.output rename to docs/examples/json_pointer.output diff --git a/doc/examples/json_pointer__back.cpp b/docs/examples/json_pointer__back.cpp similarity index 52% rename from doc/examples/json_pointer__back.cpp rename to docs/examples/json_pointer__back.cpp index 3d57c589a..dd3b210bf 100644 --- a/doc/examples/json_pointer__back.cpp +++ b/docs/examples/json_pointer__back.cpp @@ -10,6 +10,6 @@ int main() json::json_pointer ptr2("/foo/0"); // call empty() - std::cout << "last reference token of " << ptr1 << " is " << ptr1.back() << '\n' - << "last reference token of " << ptr2 << " is " << ptr2.back() << std::endl; + std::cout << "last reference token of \"" << ptr1 << "\" is \"" << ptr1.back() << "\"\n" + << "last reference token of \"" << ptr2 << "\" is \"" << ptr2.back() << "\"" << std::endl; } diff --git a/docs/examples/json_pointer__back.output b/docs/examples/json_pointer__back.output new file mode 100644 index 000000000..a89357b49 --- /dev/null +++ b/docs/examples/json_pointer__back.output @@ -0,0 +1,2 @@ +last reference token of "/foo" is "foo" +last reference token of "/foo/0" is "0" diff --git a/doc/examples/json_pointer__empty.cpp b/docs/examples/json_pointer__empty.cpp similarity index 54% rename from doc/examples/json_pointer__empty.cpp rename to docs/examples/json_pointer__empty.cpp index 5daaadc6c..57257e8b1 100644 --- a/doc/examples/json_pointer__empty.cpp +++ b/docs/examples/json_pointer__empty.cpp @@ -13,8 +13,8 @@ int main() // call empty() std::cout << std::boolalpha - << ptr0 << ": " << ptr0.empty() << '\n' - << ptr1 << ": " << ptr1.empty() << '\n' - << ptr2 << ": " << ptr2.empty() << '\n' - << ptr3 << ": " << ptr3.empty() << std::endl; + << "\"" << ptr0 << "\": " << ptr0.empty() << '\n' + << "\"" << ptr1 << "\": " << ptr1.empty() << '\n' + << "\"" << ptr2 << "\": " << ptr2.empty() << '\n' + << "\"" << ptr3 << "\": " << ptr3.empty() << std::endl; } diff --git a/doc/examples/json_pointer__empty.output b/docs/examples/json_pointer__empty.output similarity index 100% rename from doc/examples/json_pointer__empty.output rename to docs/examples/json_pointer__empty.output diff --git a/doc/examples/json_pointer__operator_add.cpp b/docs/examples/json_pointer__operator_add.cpp similarity index 65% rename from doc/examples/json_pointer__operator_add.cpp rename to docs/examples/json_pointer__operator_add.cpp index a2bbf59e8..14bd74561 100644 --- a/doc/examples/json_pointer__operator_add.cpp +++ b/docs/examples/json_pointer__operator_add.cpp @@ -7,17 +7,17 @@ int main() { // create a JSON pointer json::json_pointer ptr("/foo"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; // append a JSON Pointer ptr /= json::json_pointer("/bar/baz"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; // append a string ptr /= "fob"; - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; // append an array index ptr /= 42; - std::cout << ptr << std::endl; + std::cout << "\"" << ptr << "\"" << std::endl; } diff --git a/doc/examples/json_pointer__operator_add.output b/docs/examples/json_pointer__operator_add.output similarity index 100% rename from doc/examples/json_pointer__operator_add.output rename to docs/examples/json_pointer__operator_add.output diff --git a/doc/examples/json_pointer__operator_add_binary.cpp b/docs/examples/json_pointer__operator_add_binary.cpp similarity index 57% rename from doc/examples/json_pointer__operator_add_binary.cpp rename to docs/examples/json_pointer__operator_add_binary.cpp index 89e0a6a53..d26a0d171 100644 --- a/doc/examples/json_pointer__operator_add_binary.cpp +++ b/docs/examples/json_pointer__operator_add_binary.cpp @@ -9,11 +9,11 @@ int main() json::json_pointer ptr("/foo"); // append a JSON Pointer - std::cout << ptr / json::json_pointer("/bar/baz") << '\n'; + std::cout << "\"" << ptr / json::json_pointer("/bar/baz") << "\"\n"; // append a string - std::cout << ptr / "fob" << '\n'; + std::cout << "\"" << ptr / "fob" << "\"\n"; // append an array index - std::cout << ptr / 42 << std::endl; + std::cout << "\"" << ptr / 42 << "\"" << std::endl; } diff --git a/doc/examples/json_pointer__operator_add_binary.output b/docs/examples/json_pointer__operator_add_binary.output similarity index 100% rename from doc/examples/json_pointer__operator_add_binary.output rename to docs/examples/json_pointer__operator_add_binary.output diff --git a/docs/examples/json_pointer__operator_string_t.cpp b/docs/examples/json_pointer__operator_string_t.cpp new file mode 100644 index 000000000..56f213020 --- /dev/null +++ b/docs/examples/json_pointer__operator_string_t.cpp @@ -0,0 +1,19 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON Pointers + json::json_pointer ptr1("/foo/0"); + json::json_pointer ptr2("/a~1b"); + + // implicit conversion to string + std::string s; + s += ptr1; + s += "\n"; + s += ptr2; + + std::cout << s << std::endl; +} diff --git a/docs/examples/json_pointer__operator_string_t.output b/docs/examples/json_pointer__operator_string_t.output new file mode 100644 index 000000000..ec6aba2c2 --- /dev/null +++ b/docs/examples/json_pointer__operator_string_t.output @@ -0,0 +1,2 @@ +/foo/0 +/a~1b diff --git a/doc/examples/json_pointer__parent_pointer.cpp b/docs/examples/json_pointer__parent_pointer.cpp similarity index 51% rename from doc/examples/json_pointer__parent_pointer.cpp rename to docs/examples/json_pointer__parent_pointer.cpp index 6021463a1..ef9df4534 100644 --- a/doc/examples/json_pointer__parent_pointer.cpp +++ b/docs/examples/json_pointer__parent_pointer.cpp @@ -12,7 +12,7 @@ int main() // call parent_pointer() std::cout << std::boolalpha - << "parent of " << ptr1 << " is " << ptr1.parent_pointer() << '\n' - << "parent of " << ptr2 << " is " << ptr2.parent_pointer() << '\n' - << "parent of " << ptr3 << " is " << ptr3.parent_pointer() << std::endl; + << "parent of \"" << ptr1 << "\" is \"" << ptr1.parent_pointer() << "\"\n" + << "parent of \"" << ptr2 << "\" is \"" << ptr2.parent_pointer() << "\"\n" + << "parent of \"" << ptr3 << "\" is \"" << ptr3.parent_pointer() << "\"" << std::endl; } diff --git a/doc/examples/json_pointer__parent_pointer.output b/docs/examples/json_pointer__parent_pointer.output similarity index 100% rename from doc/examples/json_pointer__parent_pointer.output rename to docs/examples/json_pointer__parent_pointer.output diff --git a/doc/examples/json_pointer__pop_back.cpp b/docs/examples/json_pointer__pop_back.cpp similarity index 61% rename from doc/examples/json_pointer__pop_back.cpp rename to docs/examples/json_pointer__pop_back.cpp index ed3417ec1..fd077b7e9 100644 --- a/doc/examples/json_pointer__pop_back.cpp +++ b/docs/examples/json_pointer__pop_back.cpp @@ -7,15 +7,15 @@ int main() { // create empty JSON Pointer json::json_pointer ptr("/foo/bar/baz"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; // call pop_back() ptr.pop_back(); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; ptr.pop_back(); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; ptr.pop_back(); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; } diff --git a/doc/examples/json_pointer__pop_back.output b/docs/examples/json_pointer__pop_back.output similarity index 100% rename from doc/examples/json_pointer__pop_back.output rename to docs/examples/json_pointer__pop_back.output diff --git a/doc/examples/json_pointer__push_back.cpp b/docs/examples/json_pointer__push_back.cpp similarity index 61% rename from doc/examples/json_pointer__push_back.cpp rename to docs/examples/json_pointer__push_back.cpp index d6536b3f9..e6b59a125 100644 --- a/doc/examples/json_pointer__push_back.cpp +++ b/docs/examples/json_pointer__push_back.cpp @@ -7,15 +7,15 @@ int main() { // create empty JSON Pointer json::json_pointer ptr; - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; // call push_back() ptr.push_back("foo"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; ptr.push_back("0"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; ptr.push_back("bar"); - std::cout << ptr << '\n'; + std::cout << "\"" << ptr << "\"\n"; } diff --git a/doc/examples/json_pointer__push_back.output b/docs/examples/json_pointer__push_back.output similarity index 100% rename from doc/examples/json_pointer__push_back.output rename to docs/examples/json_pointer__push_back.output diff --git a/docs/examples/json_pointer__string_t.cpp b/docs/examples/json_pointer__string_t.cpp new file mode 100644 index 000000000..fbe0f179e --- /dev/null +++ b/docs/examples/json_pointer__string_t.cpp @@ -0,0 +1,13 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + json::json_pointer::string_t s = "This is a string."; + + std::cout << s << std::endl; + + std::cout << std::boolalpha << std::is_same::value << std::endl; +} diff --git a/docs/examples/json_pointer__string_t.output b/docs/examples/json_pointer__string_t.output new file mode 100644 index 000000000..d87113724 --- /dev/null +++ b/docs/examples/json_pointer__string_t.output @@ -0,0 +1,2 @@ +This is a string. +true diff --git a/docs/examples/json_pointer__to_string.cpp b/docs/examples/json_pointer__to_string.cpp new file mode 100644 index 000000000..31d35a724 --- /dev/null +++ b/docs/examples/json_pointer__to_string.cpp @@ -0,0 +1,34 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // different JSON Pointers + json::json_pointer ptr1(""); + json::json_pointer ptr2("/foo"); + json::json_pointer ptr3("/foo/0"); + json::json_pointer ptr4("/"); + json::json_pointer ptr5("/a~1b"); + json::json_pointer ptr6("/c%d"); + json::json_pointer ptr7("/e^f"); + json::json_pointer ptr8("/g|h"); + json::json_pointer ptr9("/i\\j"); + json::json_pointer ptr10("/k\"l"); + json::json_pointer ptr11("/ "); + json::json_pointer ptr12("/m~0n"); + + std::cout << "\"" << ptr1.to_string() << "\"\n" + << "\"" << ptr2.to_string() << "\"\n" + << "\"" << ptr3.to_string() << "\"\n" + << "\"" << ptr4.to_string() << "\"\n" + << "\"" << ptr5.to_string() << "\"\n" + << "\"" << ptr6.to_string() << "\"\n" + << "\"" << ptr7.to_string() << "\"\n" + << "\"" << ptr8.to_string() << "\"\n" + << "\"" << ptr9.to_string() << "\"\n" + << "\"" << ptr10.to_string() << "\"\n" + << "\"" << ptr11.to_string() << "\"\n" + << "\"" << ptr12.to_string() << "\"" << std::endl; +} diff --git a/docs/examples/json_pointer__to_string.output b/docs/examples/json_pointer__to_string.output new file mode 100644 index 000000000..3c441357e --- /dev/null +++ b/docs/examples/json_pointer__to_string.output @@ -0,0 +1,12 @@ +"" +"/foo" +"/foo/0" +"/" +"/a~1b" +"/c%d" +"/e^f" +"/g|h" +"/i\j" +"/k"l" +"/ " +"/m~0n" diff --git a/doc/examples/max_size.cpp b/docs/examples/max_size.cpp similarity index 100% rename from doc/examples/max_size.cpp rename to docs/examples/max_size.cpp diff --git a/docs/examples/max_size.output b/docs/examples/max_size.output new file mode 100644 index 000000000..b8dcb4d0c --- /dev/null +++ b/docs/examples/max_size.output @@ -0,0 +1,7 @@ +0 +1 +1 +1 +115292150460684697 +576460752303423487 +1 diff --git a/doc/examples/merge_patch.cpp b/docs/examples/merge_patch.cpp similarity index 96% rename from doc/examples/merge_patch.cpp rename to docs/examples/merge_patch.cpp index b8804d7c5..f3fee1ed1 100644 --- a/doc/examples/merge_patch.cpp +++ b/docs/examples/merge_patch.cpp @@ -3,6 +3,7 @@ #include // for std::setw using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/merge_patch.output b/docs/examples/merge_patch.output similarity index 100% rename from doc/examples/merge_patch.output rename to docs/examples/merge_patch.output diff --git a/doc/examples/meta.cpp b/docs/examples/meta.cpp similarity index 100% rename from doc/examples/meta.cpp rename to docs/examples/meta.cpp diff --git a/doc/examples/meta.output b/docs/examples/meta.output similarity index 63% rename from doc/examples/meta.output rename to docs/examples/meta.output index c35a3200a..53cf2660b 100644 --- a/doc/examples/meta.output +++ b/docs/examples/meta.output @@ -1,8 +1,8 @@ { "compiler": { "c++": "201103", - "family": "clang", - "version": "13.0.0 (clang-1300.0.29.30)" + "family": "gcc", + "version": "11.3.0" }, "copyright": "(C) 2013-2022 Niels Lohmann", "name": "JSON for Modern C++", @@ -10,8 +10,8 @@ "url": "https://github.com/nlohmann/json", "version": { "major": 3, - "minor": 10, - "patch": 5, - "string": "3.10.5" + "minor": 11, + "patch": 0, + "string": "3.11.0" } } diff --git a/docs/examples/nlohmann_define_type_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp new file mode 100644 index 000000000..7d2ba8aa1 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp @@ -0,0 +1,60 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) + { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) + { + nlohmann_json_t.name = nlohmann_json_j.at("name"); + nlohmann_json_t.address = nlohmann_json_j.at("address"); + nlohmann_json_t.age = nlohmann_json_j.at("age"); + } +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_intrusive_explicit.output b/docs/examples/nlohmann_define_type_intrusive_explicit.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_macro.cpp new file mode 100644 index 000000000..2977cd456 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_macro.cpp @@ -0,0 +1,48 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, address, age) +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_intrusive_macro.output b/docs/examples/nlohmann_define_type_intrusive_macro.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp new file mode 100644 index 000000000..7400c47a8 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp @@ -0,0 +1,55 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) + { + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; + } + + friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) + { + person nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address); + nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age); + } +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp new file mode 100644 index 000000000..851a3582f --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp @@ -0,0 +1,42 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +class person +{ + private: + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + public: + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} + + NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person, name, address, age) +}; +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp new file mode 100644 index 000000000..b71613d4f --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp @@ -0,0 +1,53 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) +{ + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; +} + +void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) +{ + nlohmann_json_t.name = nlohmann_json_j.at("name"); + nlohmann_json_t.address = nlohmann_json_j.at("address"); + nlohmann_json_t.age = nlohmann_json_j.at("age"); +} +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_explicit.output b/docs/examples/nlohmann_define_type_non_intrusive_explicit.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp new file mode 100644 index 000000000..be11a4576 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp @@ -0,0 +1,41 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name; + std::string address; + int age; +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age) +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + try + { + auto p3 = j3.get(); + } + catch (json::exception& e) + { + std::cout << "deserialization failed: " << e.what() << std::endl; + } +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_macro.output b/docs/examples/nlohmann_define_type_non_intrusive_macro.output new file mode 100644 index 000000000..37f4eb414 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +deserialization failed: [json.exception.out_of_range.403] key 'age' not found diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp new file mode 100644 index 000000000..6b538d18d --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp @@ -0,0 +1,53 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} +}; + +void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t) +{ + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["address"] = nlohmann_json_t.address; + nlohmann_json_j["age"] = nlohmann_json_t.age; +} + +void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t) +{ + person nlohmann_json_default_obj; + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address); + nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.age); +} +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp new file mode 100644 index 000000000..aa9bc53b4 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp @@ -0,0 +1,40 @@ +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +namespace ns +{ +struct person +{ + std::string name = "John Doe"; + std::string address = "123 Fake St"; + int age = -1; + + person() = default; + person(std::string name_, std::string address_, int age_) + : name(std::move(name_)), address(std::move(address_)), age(age_) + {} +}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person, name, address, age) +} // namespace ns + +int main() +{ + ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60}; + + // serialization: person -> json + json j = p; + std::cout << "serialization: " << j << std::endl; + + // deserialization: json -> person + json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json; + auto p2 = j2.get(); + + // incomplete deserialization: + json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json; + auto p3 = j3.get(); + std::cout << "roundtrip: " << json(p3) << std::endl; +} diff --git a/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output new file mode 100644 index 000000000..1a255f65c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.output @@ -0,0 +1,2 @@ +serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} +roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"} diff --git a/docs/examples/nlohmann_json_serialize_enum.cpp b/docs/examples/nlohmann_json_serialize_enum.cpp new file mode 100644 index 000000000..f9e472c64 --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum.cpp @@ -0,0 +1,59 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +enum TaskState +{ + TS_STOPPED, + TS_RUNNING, + TS_COMPLETED, + TS_INVALID = -1 +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, +{ + { TS_INVALID, nullptr }, + { TS_STOPPED, "stopped" }, + { TS_RUNNING, "running" }, + { TS_COMPLETED, "completed" } +}) + +enum class Color +{ + red, green, blue, unknown +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, +{ + { Color::unknown, "unknown" }, { Color::red, "red" }, + { Color::green, "green" }, { Color::blue, "blue" } +}) +} // namespace ns + +int main() +{ + // serialization + json j_stopped = ns::TS_STOPPED; + json j_red = ns::Color::red; + std::cout << "ns::TS_STOPPED -> " << j_stopped + << ", ns::Color::red -> " << j_red << std::endl; + + // deserialization + json j_running = "running"; + json j_blue = "blue"; + auto running = j_running.get(); + auto blue = j_blue.get(); + std::cout << j_running << " -> " << running + << ", " << j_blue << " -> " << static_cast(blue) << std::endl; + + // deserializing undefined JSON value to enum + // (where the first map entry above is the default) + json j_pi = 3.14; + auto invalid = j_pi.get(); + auto unknown = j_pi.get(); + std::cout << j_pi << " -> " << invalid << ", " + << j_pi << " -> " << static_cast(unknown) << std::endl; +} diff --git a/docs/examples/nlohmann_json_serialize_enum.output b/docs/examples/nlohmann_json_serialize_enum.output new file mode 100644 index 000000000..f512563dd --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum.output @@ -0,0 +1,3 @@ +ns::TS_STOPPED -> "stopped", ns::Color::red -> "red" +"running" -> 1, "blue" -> 2 +3.14 -> -1, 3.14 -> 3 diff --git a/docs/examples/nlohmann_json_serialize_enum_2.cpp b/docs/examples/nlohmann_json_serialize_enum_2.cpp new file mode 100644 index 000000000..fd27226ca --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum_2.cpp @@ -0,0 +1,33 @@ +#include +#include + +using json = nlohmann::json; + +namespace ns +{ +enum class Color +{ + red, green, blue, unknown +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(Color, +{ + { Color::unknown, "unknown" }, { Color::red, "red" }, + { Color::green, "green" }, { Color::blue, "blue" }, + { Color::red, "rot" } // a second conversion for Color::red +}) +} + +int main() +{ + // serialization + json j_red = ns::Color::red; + std::cout << static_cast(ns::Color::red) << " -> " << j_red << std::endl; + + // deserialization + json j_rot = "rot"; + auto rot = j_rot.get(); + auto red = j_red.get(); + std::cout << j_rot << " -> " << static_cast(rot) << std::endl; + std::cout << j_red << " -> " << static_cast(red) << std::endl; +} diff --git a/docs/examples/nlohmann_json_serialize_enum_2.output b/docs/examples/nlohmann_json_serialize_enum_2.output new file mode 100644 index 000000000..5dec31b4a --- /dev/null +++ b/docs/examples/nlohmann_json_serialize_enum_2.output @@ -0,0 +1,3 @@ +0 -> "red" +"rot" -> 0 +"red" -> 0 diff --git a/docs/examples/nlohmann_json_version.cpp b/docs/examples/nlohmann_json_version.cpp new file mode 100644 index 000000000..ca5f53728 --- /dev/null +++ b/docs/examples/nlohmann_json_version.cpp @@ -0,0 +1,12 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << "JSON for Modern C++ version " + << NLOHMANN_JSON_VERSION_MAJOR << "." + << NLOHMANN_JSON_VERSION_MINOR << "." + << NLOHMANN_JSON_VERSION_PATCH << std::endl; +} diff --git a/docs/examples/nlohmann_json_version.output b/docs/examples/nlohmann_json_version.output new file mode 100644 index 000000000..2809e3cb1 --- /dev/null +++ b/docs/examples/nlohmann_json_version.output @@ -0,0 +1 @@ +JSON for Modern C++ version 3.11.0 diff --git a/doc/examples/number_float_t.cpp b/docs/examples/number_float_t.cpp similarity index 100% rename from doc/examples/number_float_t.cpp rename to docs/examples/number_float_t.cpp diff --git a/doc/examples/number_float_t.output b/docs/examples/number_float_t.output similarity index 100% rename from doc/examples/number_float_t.output rename to docs/examples/number_float_t.output diff --git a/doc/examples/number_integer_t.cpp b/docs/examples/number_integer_t.cpp similarity index 100% rename from doc/examples/number_integer_t.cpp rename to docs/examples/number_integer_t.cpp diff --git a/doc/examples/number_integer_t.output b/docs/examples/number_integer_t.output similarity index 100% rename from doc/examples/number_integer_t.output rename to docs/examples/number_integer_t.output diff --git a/doc/examples/number_unsigned_t.cpp b/docs/examples/number_unsigned_t.cpp similarity index 100% rename from doc/examples/number_unsigned_t.cpp rename to docs/examples/number_unsigned_t.cpp diff --git a/doc/examples/number_unsigned_t.output b/docs/examples/number_unsigned_t.output similarity index 100% rename from doc/examples/number_unsigned_t.output rename to docs/examples/number_unsigned_t.output diff --git a/doc/examples/object.cpp b/docs/examples/object.cpp similarity index 100% rename from doc/examples/object.cpp rename to docs/examples/object.cpp diff --git a/doc/examples/object.output b/docs/examples/object.output similarity index 100% rename from doc/examples/object.output rename to docs/examples/object.output diff --git a/docs/examples/object_comparator_t.cpp b/docs/examples/object_comparator_t.cpp new file mode 100644 index 000000000..6b82c7ca6 --- /dev/null +++ b/docs/examples/object_comparator_t.cpp @@ -0,0 +1,11 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::boolalpha + << "json::object_comparator_t(\"one\", \"two\") = " << json::object_comparator_t{}("one", "two") << "\n" + << "json::object_comparator_t(\"three\", \"four\") = " << json::object_comparator_t{}("three", "four") << std::endl; +} diff --git a/docs/examples/object_comparator_t.output b/docs/examples/object_comparator_t.output new file mode 100644 index 000000000..63620edb4 --- /dev/null +++ b/docs/examples/object_comparator_t.output @@ -0,0 +1,2 @@ +json::object_comparator_t("one", "two") = true +json::object_comparator_t("three", "four") = false diff --git a/doc/examples/object_t.cpp b/docs/examples/object_t.cpp similarity index 100% rename from doc/examples/object_t.cpp rename to docs/examples/object_t.cpp diff --git a/doc/examples/object_t.output b/docs/examples/object_t.output similarity index 100% rename from doc/examples/object_t.output rename to docs/examples/object_t.output diff --git a/doc/examples/operator__ValueType.cpp b/docs/examples/operator__ValueType.cpp similarity index 100% rename from doc/examples/operator__ValueType.cpp rename to docs/examples/operator__ValueType.cpp diff --git a/doc/examples/operator__ValueType.output b/docs/examples/operator__ValueType.output similarity index 100% rename from doc/examples/operator__ValueType.output rename to docs/examples/operator__ValueType.output diff --git a/doc/examples/operator__equal.cpp b/docs/examples/operator__equal.cpp similarity index 100% rename from doc/examples/operator__equal.cpp rename to docs/examples/operator__equal.cpp diff --git a/doc/examples/operator__equal.output b/docs/examples/operator__equal.output similarity index 100% rename from doc/examples/operator__equal.output rename to docs/examples/operator__equal.output diff --git a/doc/examples/operator__equal__nullptr_t.cpp b/docs/examples/operator__equal__nullptr_t.cpp similarity index 100% rename from doc/examples/operator__equal__nullptr_t.cpp rename to docs/examples/operator__equal__nullptr_t.cpp diff --git a/doc/examples/operator__equal__nullptr_t.output b/docs/examples/operator__equal__nullptr_t.output similarity index 100% rename from doc/examples/operator__equal__nullptr_t.output rename to docs/examples/operator__equal__nullptr_t.output diff --git a/docs/examples/operator__equal__specializations.cpp b/docs/examples/operator__equal__specializations.cpp new file mode 100644 index 000000000..97d5ecead --- /dev/null +++ b/docs/examples/operator__equal__specializations.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + nlohmann::json uj1 = {{"version", 1}, {"type", "integer"}}; + nlohmann::json uj2 = {{"type", "integer"}, {"version", 1}}; + + nlohmann::ordered_json oj1 = {{"version", 1}, {"type", "integer"}}; + nlohmann::ordered_json oj2 = {{"type", "integer"}, {"version", 1}}; + + std::cout << std::boolalpha << (uj1 == uj2) << '\n' << (oj1 == oj2) << std::endl; +} diff --git a/docs/examples/operator__equal__specializations.output b/docs/examples/operator__equal__specializations.output new file mode 100644 index 000000000..da29283aa --- /dev/null +++ b/docs/examples/operator__equal__specializations.output @@ -0,0 +1,2 @@ +true +false diff --git a/doc/examples/operator__greater.cpp b/docs/examples/operator__greater.cpp similarity index 100% rename from doc/examples/operator__greater.cpp rename to docs/examples/operator__greater.cpp diff --git a/doc/examples/operator__greater.output b/docs/examples/operator__greater.output similarity index 100% rename from doc/examples/operator__greater.output rename to docs/examples/operator__greater.output diff --git a/doc/examples/operator__greaterequal.cpp b/docs/examples/operator__greaterequal.cpp similarity index 100% rename from doc/examples/operator__greaterequal.cpp rename to docs/examples/operator__greaterequal.cpp diff --git a/doc/examples/operator__greaterequal.output b/docs/examples/operator__greaterequal.output similarity index 100% rename from doc/examples/operator__greaterequal.output rename to docs/examples/operator__greaterequal.output diff --git a/doc/examples/operator__less.cpp b/docs/examples/operator__less.cpp similarity index 100% rename from doc/examples/operator__less.cpp rename to docs/examples/operator__less.cpp diff --git a/doc/examples/operator__less.output b/docs/examples/operator__less.output similarity index 100% rename from doc/examples/operator__less.output rename to docs/examples/operator__less.output diff --git a/doc/examples/operator__lessequal.cpp b/docs/examples/operator__lessequal.cpp similarity index 100% rename from doc/examples/operator__lessequal.cpp rename to docs/examples/operator__lessequal.cpp diff --git a/doc/examples/operator__lessequal.output b/docs/examples/operator__lessequal.output similarity index 100% rename from doc/examples/operator__lessequal.output rename to docs/examples/operator__lessequal.output diff --git a/doc/examples/operator__notequal.cpp b/docs/examples/operator__notequal.cpp similarity index 100% rename from doc/examples/operator__notequal.cpp rename to docs/examples/operator__notequal.cpp diff --git a/doc/examples/operator__notequal.output b/docs/examples/operator__notequal.output similarity index 100% rename from doc/examples/operator__notequal.output rename to docs/examples/operator__notequal.output diff --git a/doc/examples/operator__notequal__nullptr_t.cpp b/docs/examples/operator__notequal__nullptr_t.cpp similarity index 100% rename from doc/examples/operator__notequal__nullptr_t.cpp rename to docs/examples/operator__notequal__nullptr_t.cpp diff --git a/doc/examples/operator__notequal__nullptr_t.output b/docs/examples/operator__notequal__nullptr_t.output similarity index 100% rename from doc/examples/operator__notequal__nullptr_t.output rename to docs/examples/operator__notequal__nullptr_t.output diff --git a/doc/examples/operator__value_t.cpp b/docs/examples/operator__value_t.cpp similarity index 100% rename from doc/examples/operator__value_t.cpp rename to docs/examples/operator__value_t.cpp diff --git a/doc/examples/operator__value_t.output b/docs/examples/operator__value_t.output similarity index 100% rename from doc/examples/operator__value_t.output rename to docs/examples/operator__value_t.output diff --git a/doc/examples/operatorjson_pointer.cpp b/docs/examples/operator_array__json_pointer.cpp similarity index 97% rename from doc/examples/operatorjson_pointer.cpp rename to docs/examples/operator_array__json_pointer.cpp index 7a0353a1c..0fa207f02 100644 --- a/doc/examples/operatorjson_pointer.cpp +++ b/docs/examples/operator_array__json_pointer.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/operatorjson_pointer.output b/docs/examples/operator_array__json_pointer.output similarity index 100% rename from doc/examples/operatorjson_pointer.output rename to docs/examples/operator_array__json_pointer.output diff --git a/doc/examples/operatorjson_pointer_const.cpp b/docs/examples/operator_array__json_pointer_const.cpp similarity index 94% rename from doc/examples/operatorjson_pointer_const.cpp rename to docs/examples/operator_array__json_pointer_const.cpp index a5a437b44..f40e2494a 100644 --- a/doc/examples/operatorjson_pointer_const.cpp +++ b/docs/examples/operator_array__json_pointer_const.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/operatorjson_pointer_const.output b/docs/examples/operator_array__json_pointer_const.output similarity index 100% rename from doc/examples/operatorjson_pointer_const.output rename to docs/examples/operator_array__json_pointer_const.output diff --git a/docs/examples/operator_array__keytype.c++17.cpp b/docs/examples/operator_array__keytype.c++17.cpp new file mode 100644 index 000000000..7f2b41dd8 --- /dev/null +++ b/docs/examples/operator_array__keytype.c++17.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object + json object = + { + {"one", 1}, {"two", 2}, {"three", 2.9} + }; + + // output element with key "two" + std::cout << object["two"sv] << "\n\n"; + + // change element with key "three" + object["three"sv] = 3; + + // output changed array + std::cout << std::setw(4) << object << "\n\n"; + + // mention nonexisting key + object["four"sv]; + + // write to nonexisting key + object["five"sv]["really"sv]["nested"sv] = true; + + // output changed object + std::cout << std::setw(4) << object << '\n'; +} diff --git a/doc/examples/operatorarray__key_type.output b/docs/examples/operator_array__keytype.c++17.output similarity index 100% rename from doc/examples/operatorarray__key_type.output rename to docs/examples/operator_array__keytype.c++17.output diff --git a/docs/examples/operator_array__keytype_const.c++17.cpp b/docs/examples/operator_array__keytype_const.c++17.cpp new file mode 100644 index 000000000..2cf94f40f --- /dev/null +++ b/docs/examples/operator_array__keytype_const.c++17.cpp @@ -0,0 +1,18 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object + const json object = + { + {"one", 1}, {"two", 2}, {"three", 2.9} + }; + + // output element with key "two" + std::cout << object["two"sv] << '\n'; +} diff --git a/doc/examples/operatorarray__key_type_const.output b/docs/examples/operator_array__keytype_const.c++17.output similarity index 100% rename from doc/examples/operatorarray__key_type_const.output rename to docs/examples/operator_array__keytype_const.c++17.output diff --git a/doc/examples/operatorarray__key_type.cpp b/docs/examples/operator_array__object_t_key_type.cpp similarity index 100% rename from doc/examples/operatorarray__key_type.cpp rename to docs/examples/operator_array__object_t_key_type.cpp diff --git a/docs/examples/operator_array__object_t_key_type.output b/docs/examples/operator_array__object_t_key_type.output new file mode 100644 index 000000000..b643587f1 --- /dev/null +++ b/docs/examples/operator_array__object_t_key_type.output @@ -0,0 +1,19 @@ +2 + +{ + "one": 1, + "three": 3, + "two": 2 +} + +{ + "five": { + "really": { + "nested": true + } + }, + "four": null, + "one": 1, + "three": 3, + "two": 2 +} diff --git a/doc/examples/operatorarray__key_type_const.cpp b/docs/examples/operator_array__object_t_key_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__key_type_const.cpp rename to docs/examples/operator_array__object_t_key_type_const.cpp diff --git a/docs/examples/operator_array__object_t_key_type_const.output b/docs/examples/operator_array__object_t_key_type_const.output new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/docs/examples/operator_array__object_t_key_type_const.output @@ -0,0 +1 @@ +2 diff --git a/doc/examples/operatorarray__size_type.cpp b/docs/examples/operator_array__size_type.cpp similarity index 100% rename from doc/examples/operatorarray__size_type.cpp rename to docs/examples/operator_array__size_type.cpp diff --git a/doc/examples/operatorarray__size_type.output b/docs/examples/operator_array__size_type.output similarity index 100% rename from doc/examples/operatorarray__size_type.output rename to docs/examples/operator_array__size_type.output diff --git a/doc/examples/operatorarray__size_type_const.cpp b/docs/examples/operator_array__size_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__size_type_const.cpp rename to docs/examples/operator_array__size_type_const.cpp diff --git a/doc/examples/operatorarray__size_type_const.output b/docs/examples/operator_array__size_type_const.output similarity index 100% rename from doc/examples/operatorarray__size_type_const.output rename to docs/examples/operator_array__size_type_const.output diff --git a/doc/examples/operator_deserialize.cpp b/docs/examples/operator_deserialize.cpp similarity index 100% rename from doc/examples/operator_deserialize.cpp rename to docs/examples/operator_deserialize.cpp diff --git a/doc/examples/operator_deserialize.output b/docs/examples/operator_deserialize.output similarity index 100% rename from doc/examples/operator_deserialize.output rename to docs/examples/operator_deserialize.output diff --git a/doc/examples/operator_literal_json.cpp b/docs/examples/operator_literal_json.cpp similarity index 85% rename from doc/examples/operator_literal_json.cpp rename to docs/examples/operator_literal_json.cpp index 2ec008eb4..84ca6297d 100644 --- a/doc/examples/operator_literal_json.cpp +++ b/docs/examples/operator_literal_json.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/operator_literal_json.output b/docs/examples/operator_literal_json.output similarity index 100% rename from doc/examples/operator_literal_json.output rename to docs/examples/operator_literal_json.output diff --git a/doc/examples/operator_literal_json_pointer.cpp b/docs/examples/operator_literal_json_pointer.cpp similarity index 87% rename from doc/examples/operator_literal_json_pointer.cpp rename to docs/examples/operator_literal_json_pointer.cpp index bbdb974af..aba93e88e 100644 --- a/doc/examples/operator_literal_json_pointer.cpp +++ b/docs/examples/operator_literal_json_pointer.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/operator_literal_json_pointer.output b/docs/examples/operator_literal_json_pointer.output similarity index 100% rename from doc/examples/operator_literal_json_pointer.output rename to docs/examples/operator_literal_json_pointer.output diff --git a/doc/examples/operator_serialize.cpp b/docs/examples/operator_ltlt__basic_json.cpp similarity index 100% rename from doc/examples/operator_serialize.cpp rename to docs/examples/operator_ltlt__basic_json.cpp diff --git a/doc/examples/operator_serialize.output b/docs/examples/operator_ltlt__basic_json.output similarity index 100% rename from doc/examples/operator_serialize.output rename to docs/examples/operator_ltlt__basic_json.output diff --git a/docs/examples/operator_ltlt__json_pointer.cpp b/docs/examples/operator_ltlt__json_pointer.cpp new file mode 100644 index 000000000..f4fac886d --- /dev/null +++ b/docs/examples/operator_ltlt__json_pointer.cpp @@ -0,0 +1,13 @@ +#include +#include + +using json = nlohmann::json; + +int main() +{ + // create JSON poiner + json::json_pointer ptr("/foo/bar/baz"); + + // write string representation to stream + std::cout << ptr << std::endl; +} diff --git a/docs/examples/operator_ltlt__json_pointer.output b/docs/examples/operator_ltlt__json_pointer.output new file mode 100644 index 000000000..ed359432d --- /dev/null +++ b/docs/examples/operator_ltlt__json_pointer.output @@ -0,0 +1 @@ +/foo/bar/baz diff --git a/docs/examples/operator_spaceship__const_reference.c++20.cpp b/docs/examples/operator_spaceship__const_reference.c++20.cpp new file mode 100644 index 000000000..3c6c8b8c5 --- /dev/null +++ b/docs/examples/operator_spaceship__const_reference.c++20.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +using json = nlohmann::json; + +const char* to_string(const std::partial_ordering& po) +{ + if (std::is_lt(po)) + { + return "less"; + } + else if (std::is_gt(po)) + { + return "greater"; + } + else if (std::is_eq(po)) + { + return "equivalent"; + } + return "unordered"; +} + +int main() +{ + // create several JSON values + json array_1 = {1, 2, 3}; + json array_2 = {1, 2, 4}; + json object_1 = {{"A", "a"}, {"B", "b"}}; + json object_2 = {{"B", "b"}, {"A", "a"}}; + json number = 17; + json string = "foo"; + json discarded = json(json::value_t::discarded); + + + // output values and comparisons + std::cout << array_1 << " <=> " << array_2 << " := " << to_string(array_1 <=> array_2) << '\n'; // *NOPAD* + std::cout << object_1 << " <=> " << object_2 << " := " << to_string(object_1 <=> object_2) << '\n'; // *NOPAD* + std::cout << string << " <=> " << number << " := " << to_string(string <=> number) << '\n'; // *NOPAD* + std::cout << string << " <=> " << discarded << " := " << to_string(string <=> discarded) << '\n'; // *NOPAD* +} diff --git a/docs/examples/operator_spaceship__const_reference.c++20.output b/docs/examples/operator_spaceship__const_reference.c++20.output new file mode 100644 index 000000000..2e8bf9f64 --- /dev/null +++ b/docs/examples/operator_spaceship__const_reference.c++20.output @@ -0,0 +1,4 @@ +[1,2,3] <=> [1,2,4] := less +{"A":"a","B":"b"} <=> {"A":"a","B":"b"} := equivalent +"foo" <=> 17 := greater +"foo" <=> := unordered diff --git a/docs/examples/operator_spaceship__scalartype.c++20.cpp b/docs/examples/operator_spaceship__scalartype.c++20.cpp new file mode 100644 index 000000000..d9dc3ca49 --- /dev/null +++ b/docs/examples/operator_spaceship__scalartype.c++20.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +using json = nlohmann::json; + +const char* to_string(const std::partial_ordering& po) +{ + if (std::is_lt(po)) + { + return "less"; + } + else if (std::is_gt(po)) + { + return "greater"; + } + else if (std::is_eq(po)) + { + return "equivalent"; + } + return "unordered"; +} + +int main() +{ + using float_limits = std::numeric_limits; + constexpr auto nan = float_limits::quiet_NaN(); + + // create several JSON values + json boolean = false; + json number = 17; + json string = "17"; + + + // output values and comparisons + std::cout << std::boolalpha << std::fixed; + std::cout << boolean << " <=> " << true << " := " << to_string(boolean <=> true) << '\n'; // *NOPAD* + std::cout << number << " <=> " << 17.0 << " := " << to_string(number <=> 17.0) << '\n'; // *NOPAD* + std::cout << number << " <=> " << nan << " := " << to_string(number <=> nan) << '\n'; // *NOPAD* + std::cout << string << " <=> " << 17 << " := " << to_string(string <=> 17) << '\n'; // *NOPAD* +} diff --git a/docs/examples/operator_spaceship__scalartype.c++20.output b/docs/examples/operator_spaceship__scalartype.c++20.output new file mode 100644 index 000000000..b2939a5f5 --- /dev/null +++ b/docs/examples/operator_spaceship__scalartype.c++20.output @@ -0,0 +1,4 @@ +false <=> true := less +17 <=> 17.000000 := equivalent +17 <=> nan := unordered +"17" <=> 17 := greater diff --git a/docs/examples/ordered_json.cpp b/docs/examples/ordered_json.cpp new file mode 100644 index 000000000..effad530c --- /dev/null +++ b/docs/examples/ordered_json.cpp @@ -0,0 +1,14 @@ +#include +#include + +using ordered_json = nlohmann::ordered_json; + +int main() +{ + ordered_json j; + j["one"] = 1; + j["two"] = 2; + j["three"] = 3; + + std::cout << j.dump(2) << '\n'; +} diff --git a/docs/examples/ordered_json.output b/docs/examples/ordered_json.output new file mode 100644 index 000000000..120cbb284 --- /dev/null +++ b/docs/examples/ordered_json.output @@ -0,0 +1,5 @@ +{ + "one": 1, + "two": 2, + "three": 3 +} diff --git a/doc/examples/ordered_map.cpp b/docs/examples/ordered_map.cpp similarity index 100% rename from doc/examples/ordered_map.cpp rename to docs/examples/ordered_map.cpp diff --git a/doc/examples/ordered_map.output b/docs/examples/ordered_map.output similarity index 100% rename from doc/examples/ordered_map.output rename to docs/examples/ordered_map.output diff --git a/doc/examples/other_error.cpp b/docs/examples/other_error.cpp similarity index 94% rename from doc/examples/other_error.cpp rename to docs/examples/other_error.cpp index 2e7ccfbb8..99c4be70e 100644 --- a/doc/examples/other_error.cpp +++ b/docs/examples/other_error.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/other_error.output b/docs/examples/other_error.output similarity index 100% rename from doc/examples/other_error.output rename to docs/examples/other_error.output diff --git a/doc/examples/out_of_range.cpp b/docs/examples/out_of_range.cpp similarity index 100% rename from doc/examples/out_of_range.cpp rename to docs/examples/out_of_range.cpp diff --git a/doc/examples/out_of_range.output b/docs/examples/out_of_range.output similarity index 100% rename from doc/examples/out_of_range.output rename to docs/examples/out_of_range.output diff --git a/doc/examples/parse__allow_exceptions.cpp b/docs/examples/parse__allow_exceptions.cpp similarity index 100% rename from doc/examples/parse__allow_exceptions.cpp rename to docs/examples/parse__allow_exceptions.cpp diff --git a/doc/examples/parse__allow_exceptions.output b/docs/examples/parse__allow_exceptions.output similarity index 100% rename from doc/examples/parse__allow_exceptions.output rename to docs/examples/parse__allow_exceptions.output diff --git a/doc/examples/parse__array__parser_callback_t.cpp b/docs/examples/parse__array__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__array__parser_callback_t.cpp rename to docs/examples/parse__array__parser_callback_t.cpp diff --git a/doc/examples/parse__array__parser_callback_t.output b/docs/examples/parse__array__parser_callback_t.output similarity index 100% rename from doc/examples/parse__array__parser_callback_t.output rename to docs/examples/parse__array__parser_callback_t.output diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp b/docs/examples/parse__contiguouscontainer__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__contiguouscontainer__parser_callback_t.cpp rename to docs/examples/parse__contiguouscontainer__parser_callback_t.cpp diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.output b/docs/examples/parse__contiguouscontainer__parser_callback_t.output similarity index 100% rename from doc/examples/parse__contiguouscontainer__parser_callback_t.output rename to docs/examples/parse__contiguouscontainer__parser_callback_t.output diff --git a/doc/examples/parse__istream__parser_callback_t.cpp b/docs/examples/parse__istream__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__istream__parser_callback_t.cpp rename to docs/examples/parse__istream__parser_callback_t.cpp diff --git a/doc/examples/parse__istream__parser_callback_t.output b/docs/examples/parse__istream__parser_callback_t.output similarity index 100% rename from doc/examples/parse__istream__parser_callback_t.output rename to docs/examples/parse__istream__parser_callback_t.output diff --git a/doc/examples/parse__iterator_pair.cpp b/docs/examples/parse__iterator_pair.cpp similarity index 100% rename from doc/examples/parse__iterator_pair.cpp rename to docs/examples/parse__iterator_pair.cpp diff --git a/doc/examples/parse__iterator_pair.link b/docs/examples/parse__iterator_pair.link similarity index 100% rename from doc/examples/parse__iterator_pair.link rename to docs/examples/parse__iterator_pair.link diff --git a/doc/examples/parse__iterator_pair.output b/docs/examples/parse__iterator_pair.output similarity index 100% rename from doc/examples/parse__iterator_pair.output rename to docs/examples/parse__iterator_pair.output diff --git a/doc/examples/parse__pointers.cpp b/docs/examples/parse__pointers.cpp similarity index 100% rename from doc/examples/parse__pointers.cpp rename to docs/examples/parse__pointers.cpp diff --git a/doc/examples/parse__pointers.link b/docs/examples/parse__pointers.link similarity index 100% rename from doc/examples/parse__pointers.link rename to docs/examples/parse__pointers.link diff --git a/doc/examples/parse__pointers.output b/docs/examples/parse__pointers.output similarity index 100% rename from doc/examples/parse__pointers.output rename to docs/examples/parse__pointers.output diff --git a/doc/examples/parse__string__parser_callback_t.cpp b/docs/examples/parse__string__parser_callback_t.cpp similarity index 100% rename from doc/examples/parse__string__parser_callback_t.cpp rename to docs/examples/parse__string__parser_callback_t.cpp diff --git a/doc/examples/parse__string__parser_callback_t.output b/docs/examples/parse__string__parser_callback_t.output similarity index 100% rename from doc/examples/parse__string__parser_callback_t.output rename to docs/examples/parse__string__parser_callback_t.output diff --git a/doc/examples/parse_error.cpp b/docs/examples/parse_error.cpp similarity index 100% rename from doc/examples/parse_error.cpp rename to docs/examples/parse_error.cpp diff --git a/doc/examples/parse_error.output b/docs/examples/parse_error.output similarity index 100% rename from doc/examples/parse_error.output rename to docs/examples/parse_error.output diff --git a/doc/examples/patch.cpp b/docs/examples/patch.cpp similarity index 95% rename from doc/examples/patch.cpp rename to docs/examples/patch.cpp index b0896c794..b7ecb8eee 100644 --- a/doc/examples/patch.cpp +++ b/docs/examples/patch.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/patch.output b/docs/examples/patch.output similarity index 100% rename from doc/examples/patch.output rename to docs/examples/patch.output diff --git a/docs/examples/patch_inplace.cpp b/docs/examples/patch_inplace.cpp new file mode 100644 index 000000000..061708a2d --- /dev/null +++ b/docs/examples/patch_inplace.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +int main() +{ + // the original document + json doc = R"( + { + "baz": "qux", + "foo": "bar" + } + )"_json; + + // the patch + json patch = R"( + [ + { "op": "replace", "path": "/baz", "value": "boo" }, + { "op": "add", "path": "/hello", "value": ["world"] }, + { "op": "remove", "path": "/foo"} + ] + )"_json; + + // output original document + std::cout << "Before\n" << std::setw(4) << doc << std::endl; + + // apply the patch + doc.patch_inplace(patch); + + // output patched document + std::cout << "\nAfter\n" << std::setw(4) << doc << std::endl; +} diff --git a/docs/examples/patch_inplace.output b/docs/examples/patch_inplace.output new file mode 100644 index 000000000..9d31b8ba4 --- /dev/null +++ b/docs/examples/patch_inplace.output @@ -0,0 +1,13 @@ +Before +{ + "baz": "qux", + "foo": "bar" +} + +After +{ + "baz": "boo", + "hello": [ + "world" + ] +} diff --git a/doc/examples/push_back.cpp b/docs/examples/push_back.cpp similarity index 100% rename from doc/examples/push_back.cpp rename to docs/examples/push_back.cpp diff --git a/doc/examples/push_back.output b/docs/examples/push_back.output similarity index 100% rename from doc/examples/push_back.output rename to docs/examples/push_back.output diff --git a/doc/examples/push_back__initializer_list.cpp b/docs/examples/push_back__initializer_list.cpp similarity index 100% rename from doc/examples/push_back__initializer_list.cpp rename to docs/examples/push_back__initializer_list.cpp diff --git a/doc/examples/push_back__initializer_list.output b/docs/examples/push_back__initializer_list.output similarity index 100% rename from doc/examples/push_back__initializer_list.output rename to docs/examples/push_back__initializer_list.output diff --git a/doc/examples/push_back__object_t__value.cpp b/docs/examples/push_back__object_t__value.cpp similarity index 100% rename from doc/examples/push_back__object_t__value.cpp rename to docs/examples/push_back__object_t__value.cpp diff --git a/doc/examples/push_back__object_t__value.output b/docs/examples/push_back__object_t__value.output similarity index 100% rename from doc/examples/push_back__object_t__value.output rename to docs/examples/push_back__object_t__value.output diff --git a/doc/examples/rbegin.cpp b/docs/examples/rbegin.cpp similarity index 100% rename from doc/examples/rbegin.cpp rename to docs/examples/rbegin.cpp diff --git a/doc/examples/rbegin.output b/docs/examples/rbegin.output similarity index 100% rename from doc/examples/rbegin.output rename to docs/examples/rbegin.output diff --git a/doc/examples/rend.cpp b/docs/examples/rend.cpp similarity index 100% rename from doc/examples/rend.cpp rename to docs/examples/rend.cpp diff --git a/doc/examples/rend.output b/docs/examples/rend.output similarity index 100% rename from doc/examples/rend.output rename to docs/examples/rend.output diff --git a/doc/examples/sax_parse.cpp b/docs/examples/sax_parse.cpp similarity index 65% rename from doc/examples/sax_parse.cpp rename to docs/examples/sax_parse.cpp index 45273eb6c..8602687e3 100644 --- a/doc/examples/sax_parse.cpp +++ b/docs/examples/sax_parse.cpp @@ -6,7 +6,7 @@ using json = nlohmann::json; // a simple event consumer that collects string representations of the passed -// values; not inheriting from json::json_sax_t is not required, but can +// values; note inheriting from json::json_sax_t is not required, but can // help not to forget a required function class sax_event_consumer : public json::json_sax_t { @@ -15,79 +15,79 @@ class sax_event_consumer : public json::json_sax_t bool null() override { - events.push_back("value: null"); + events.push_back("null()"); return true; } bool boolean(bool val) override { - events.push_back("value: " + std::string(val ? "true" : "false")); + events.push_back("boolean(val=" + std::string(val ? "true" : "false") + ")"); return true; } bool number_integer(number_integer_t val) override { - events.push_back("value: " + std::to_string(val)); + events.push_back("number_integer(val=" + std::to_string(val) + ")"); return true; } bool number_unsigned(number_unsigned_t val) override { - events.push_back("value: " + std::to_string(val)); + events.push_back("number_unsigned(val=" + std::to_string(val) + ")"); return true; } bool number_float(number_float_t val, const string_t& s) override { - events.push_back("value: " + s); + events.push_back("number_float(val=" + std::to_string(val) + ", s=" + s + ")"); return true; } bool string(string_t& val) override { - events.push_back("value: " + val); + events.push_back("string(val=" + val + ")"); return true; } bool start_object(std::size_t elements) override { - events.push_back("start: object"); + events.push_back("start_object(elements=" + std::to_string(elements) + ")"); return true; } bool end_object() override { - events.push_back("end: object"); + events.push_back("end_object()"); return true; } bool start_array(std::size_t elements) override { - events.push_back("start: array"); + events.push_back("start_array(elements=" + std::to_string(elements) + ")"); return true; } bool end_array() override { - events.push_back("end: array"); + events.push_back("end_array()"); return true; } bool key(string_t& val) override { - events.push_back("key: " + val); + events.push_back("key(val=" + val + ")"); return true; } bool binary(json::binary_t& val) override { - events.push_back("binary"); + events.push_back("binary(val=[...])"); return true; } bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override { - events.push_back("error: " + std::string(ex.what())); + events.push_back("parse_error(position=" + std::to_string(position) + ", last_token=" + last_token + ",\n ex=" + std::string(ex.what()) + ")"); return false; } }; @@ -107,22 +107,23 @@ int main() "Width": 100 }, "Animated" : false, - "IDs": [116, 943, 234, 38793], + "IDs": [116, 943, 234, -38793], + "DeletionDate": null, "Distance": 12.723374634 } - } + }] )"; // create a SAX event consumer object sax_event_consumer sec; - // parse and serialize JSON + // parse JSON bool result = json::sax_parse(text, &sec); // output the recorded events for (auto& event : sec.events) { - std::cout << "(" << event << ") "; + std::cout << event << "\n"; } // output the result of sax_parse diff --git a/docs/examples/sax_parse.output b/docs/examples/sax_parse.output new file mode 100644 index 000000000..dd2fc2f05 --- /dev/null +++ b/docs/examples/sax_parse.output @@ -0,0 +1,37 @@ +start_object(elements=18446744073709551615) +key(val=Image) +start_object(elements=18446744073709551615) +key(val=Width) +number_unsigned(val=800) +key(val=Height) +number_unsigned(val=600) +key(val=Title) +string(val=View from 15th Floor) +key(val=Thumbnail) +start_object(elements=18446744073709551615) +key(val=Url) +string(val=http://www.example.com/image/481989943) +key(val=Height) +number_unsigned(val=125) +key(val=Width) +number_unsigned(val=100) +end_object() +key(val=Animated) +boolean(val=false) +key(val=IDs) +start_array(elements=18446744073709551615) +number_unsigned(val=116) +number_unsigned(val=943) +number_unsigned(val=234) +number_integer(val=-38793) +end_array() +key(val=DeletionDate) +null() +key(val=Distance) +number_float(val=12.723375, s=12.723374634) +end_object() +end_object() +parse_error(position=460, last_token=12.723374634 } }], + ex=[json.exception.parse_error.101] parse error at line 17, column 6: syntax error while parsing value - unexpected ']'; expected end of input) + +result: false diff --git a/docs/examples/sax_parse__binary.cpp b/docs/examples/sax_parse__binary.cpp new file mode 100644 index 000000000..08bc85df6 --- /dev/null +++ b/docs/examples/sax_parse__binary.cpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include + +using json = nlohmann::json; + +// a simple event consumer that collects string representations of the passed +// values; note inheriting from json::json_sax_t is not required, but can +// help not to forget a required function +class sax_event_consumer : public json::json_sax_t +{ + public: + std::vector events; + + bool null() override + { + events.push_back("null()"); + return true; + } + + bool boolean(bool val) override + { + events.push_back("boolean(val=" + std::string(val ? "true" : "false") + ")"); + return true; + } + + bool number_integer(number_integer_t val) override + { + events.push_back("number_integer(val=" + std::to_string(val) + ")"); + return true; + } + + bool number_unsigned(number_unsigned_t val) override + { + events.push_back("number_unsigned(val=" + std::to_string(val) + ")"); + return true; + } + + bool number_float(number_float_t val, const string_t& s) override + { + events.push_back("number_float(val=" + std::to_string(val) + ", s=" + s + ")"); + return true; + } + + bool string(string_t& val) override + { + events.push_back("string(val=" + val + ")"); + return true; + } + + bool start_object(std::size_t elements) override + { + events.push_back("start_object(elements=" + std::to_string(elements) + ")"); + return true; + } + + bool end_object() override + { + events.push_back("end_object()"); + return true; + } + + bool start_array(std::size_t elements) override + { + events.push_back("start_array(elements=" + std::to_string(elements) + ")"); + return true; + } + + bool end_array() override + { + events.push_back("end_array()"); + return true; + } + + bool key(string_t& val) override + { + events.push_back("key(val=" + val + ")"); + return true; + } + + bool binary(json::binary_t& val) override + { + events.push_back("binary(val=[...])"); + return true; + } + + bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override + { + events.push_back("parse_error(position=" + std::to_string(position) + ", last_token=" + last_token + ",\n ex=" + std::string(ex.what()) + ")"); + return false; + } +}; + +int main() +{ + // CBOR byte string + std::vector vec = {{0x44, 0xcA, 0xfe, 0xba, 0xbe}}; + + // create a SAX event consumer object + sax_event_consumer sec; + + // parse CBOR + bool result = json::sax_parse(vec, &sec, json::input_format_t::cbor); + + // output the recorded events + for (auto& event : sec.events) + { + std::cout << event << "\n"; + } + + // output the result of sax_parse + std::cout << "\nresult: " << std::boolalpha << result << std::endl; +} diff --git a/docs/examples/sax_parse__binary.output b/docs/examples/sax_parse__binary.output new file mode 100644 index 000000000..f88089610 --- /dev/null +++ b/docs/examples/sax_parse__binary.output @@ -0,0 +1,3 @@ +binary(val=[...]) + +result: true diff --git a/doc/examples/size.cpp b/docs/examples/size.cpp similarity index 100% rename from doc/examples/size.cpp rename to docs/examples/size.cpp diff --git a/doc/examples/size.output b/docs/examples/size.output similarity index 100% rename from doc/examples/size.output rename to docs/examples/size.output diff --git a/doc/examples/std_hash.cpp b/docs/examples/std_hash.cpp similarity index 95% rename from doc/examples/std_hash.cpp rename to docs/examples/std_hash.cpp index eee0fad0c..9721910eb 100644 --- a/doc/examples/std_hash.cpp +++ b/docs/examples/std_hash.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/std_hash.output b/docs/examples/std_hash.output similarity index 63% rename from doc/examples/std_hash.output rename to docs/examples/std_hash.output index d1b1b48b7..521d2b4b8 100644 --- a/doc/examples/std_hash.output +++ b/docs/examples/std_hash.output @@ -2,7 +2,7 @@ hash(null) = 2654435769 hash(false) = 2654436030 hash(0) = 2654436095 hash(0U) = 2654436156 -hash("") = 11160318156688833227 +hash("") = 6142509191626859748 hash({}) = 2654435832 hash([]) = 2654435899 -hash({"hello": "world"}) = 3701319991624763853 +hash({"hello": "world"}) = 4469488738203676328 diff --git a/doc/examples/std_swap.cpp b/docs/examples/std_swap.cpp similarity index 100% rename from doc/examples/std_swap.cpp rename to docs/examples/std_swap.cpp diff --git a/doc/examples/std_swap.output b/docs/examples/std_swap.output similarity index 100% rename from doc/examples/std_swap.output rename to docs/examples/std_swap.output diff --git a/doc/examples/string_t.cpp b/docs/examples/string_t.cpp similarity index 100% rename from doc/examples/string_t.cpp rename to docs/examples/string_t.cpp diff --git a/doc/examples/string_t.output b/docs/examples/string_t.output similarity index 100% rename from doc/examples/string_t.output rename to docs/examples/string_t.output diff --git a/doc/examples/swap__array_t.cpp b/docs/examples/swap__array_t.cpp similarity index 100% rename from doc/examples/swap__array_t.cpp rename to docs/examples/swap__array_t.cpp diff --git a/doc/examples/swap__array_t.output b/docs/examples/swap__array_t.output similarity index 100% rename from doc/examples/swap__array_t.output rename to docs/examples/swap__array_t.output diff --git a/doc/examples/swap__binary_t.cpp b/docs/examples/swap__binary_t.cpp similarity index 100% rename from doc/examples/swap__binary_t.cpp rename to docs/examples/swap__binary_t.cpp diff --git a/doc/examples/swap__binary_t.output b/docs/examples/swap__binary_t.output similarity index 100% rename from doc/examples/swap__binary_t.output rename to docs/examples/swap__binary_t.output diff --git a/doc/examples/swap__object_t.cpp b/docs/examples/swap__object_t.cpp similarity index 100% rename from doc/examples/swap__object_t.cpp rename to docs/examples/swap__object_t.cpp diff --git a/doc/examples/swap__object_t.output b/docs/examples/swap__object_t.output similarity index 100% rename from doc/examples/swap__object_t.output rename to docs/examples/swap__object_t.output diff --git a/doc/examples/swap__reference.cpp b/docs/examples/swap__reference.cpp similarity index 100% rename from doc/examples/swap__reference.cpp rename to docs/examples/swap__reference.cpp diff --git a/doc/examples/swap__reference.output b/docs/examples/swap__reference.output similarity index 100% rename from doc/examples/swap__reference.output rename to docs/examples/swap__reference.output diff --git a/doc/examples/swap__string_t.cpp b/docs/examples/swap__string_t.cpp similarity index 100% rename from doc/examples/swap__string_t.cpp rename to docs/examples/swap__string_t.cpp diff --git a/doc/examples/swap__string_t.output b/docs/examples/swap__string_t.output similarity index 100% rename from doc/examples/swap__string_t.output rename to docs/examples/swap__string_t.output diff --git a/docs/examples/to_bjdata.cpp b/docs/examples/to_bjdata.cpp new file mode 100644 index 000000000..9b7abac4e --- /dev/null +++ b/docs/examples/to_bjdata.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +using json = nlohmann::json; +using namespace nlohmann::literals; + +// function to print BJData's diagnostic format +void print_byte(uint8_t byte) +{ + if (32 < byte and byte < 128) + { + std::cout << (char)byte; + } + else + { + std::cout << (int)byte; + } +} + +int main() +{ + // create a JSON value + json j = R"({"compact": true, "schema": false})"_json; + + // serialize it to BJData + std::vector v = json::to_bjdata(j); + + // print the vector content + for (auto& byte : v) + { + print_byte(byte); + } + std::cout << std::endl; + + // create an array of numbers + json array = {1, 2, 3, 4, 5, 6, 7, 8}; + + // serialize it to BJData using default representation + std::vector v_array = json::to_bjdata(array); + // serialize it to BJData using size optimization + std::vector v_array_size = json::to_bjdata(array, true); + // serialize it to BJData using type optimization + std::vector v_array_size_and_type = json::to_bjdata(array, true, true); + + // print the vector contents + for (auto& byte : v_array) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size) + { + print_byte(byte); + } + std::cout << std::endl; + + for (auto& byte : v_array_size_and_type) + { + print_byte(byte); + } + std::cout << std::endl; +} diff --git a/doc/examples/to_ubjson.output b/docs/examples/to_bjdata.output similarity index 100% rename from doc/examples/to_ubjson.output rename to docs/examples/to_bjdata.output diff --git a/doc/examples/to_bson.cpp b/docs/examples/to_bson.cpp similarity index 92% rename from doc/examples/to_bson.cpp rename to docs/examples/to_bson.cpp index 2dd448768..3484b0b76 100644 --- a/doc/examples/to_bson.cpp +++ b/docs/examples/to_bson.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/to_bson.output b/docs/examples/to_bson.output similarity index 100% rename from doc/examples/to_bson.output rename to docs/examples/to_bson.output diff --git a/doc/examples/to_cbor.cpp b/docs/examples/to_cbor.cpp similarity index 92% rename from doc/examples/to_cbor.cpp rename to docs/examples/to_cbor.cpp index 3d85deb5a..3d5e04150 100644 --- a/doc/examples/to_cbor.cpp +++ b/docs/examples/to_cbor.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/to_cbor.output b/docs/examples/to_cbor.output similarity index 100% rename from doc/examples/to_cbor.output rename to docs/examples/to_cbor.output diff --git a/doc/examples/to_msgpack.cpp b/docs/examples/to_msgpack.cpp similarity index 93% rename from doc/examples/to_msgpack.cpp rename to docs/examples/to_msgpack.cpp index 76bb22f14..b29ae8c7c 100644 --- a/doc/examples/to_msgpack.cpp +++ b/docs/examples/to_msgpack.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/to_msgpack.output b/docs/examples/to_msgpack.output similarity index 100% rename from doc/examples/to_msgpack.output rename to docs/examples/to_msgpack.output diff --git a/doc/examples/to_string.cpp b/docs/examples/to_string.cpp similarity index 100% rename from doc/examples/to_string.cpp rename to docs/examples/to_string.cpp diff --git a/doc/examples/to_string.output b/docs/examples/to_string.output similarity index 100% rename from doc/examples/to_string.output rename to docs/examples/to_string.output diff --git a/doc/examples/to_ubjson.cpp b/docs/examples/to_ubjson.cpp similarity index 97% rename from doc/examples/to_ubjson.cpp rename to docs/examples/to_ubjson.cpp index 2329cdd05..fd267a85a 100644 --- a/doc/examples/to_ubjson.cpp +++ b/docs/examples/to_ubjson.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; // function to print UBJSON's diagnostic format void print_byte(uint8_t byte) diff --git a/docs/examples/to_ubjson.output b/docs/examples/to_ubjson.output new file mode 100644 index 000000000..087980cb9 --- /dev/null +++ b/docs/examples/to_ubjson.output @@ -0,0 +1,4 @@ +{i7compactTi6schemaF} +[i1i2i3i4i5i6i7i8] +[#i8i1i2i3i4i5i6i7i8 +[$i#i812345678 diff --git a/doc/examples/type.cpp b/docs/examples/type.cpp similarity index 100% rename from doc/examples/type.cpp rename to docs/examples/type.cpp diff --git a/doc/examples/type.output b/docs/examples/type.output similarity index 100% rename from doc/examples/type.output rename to docs/examples/type.output diff --git a/doc/examples/type_error.cpp b/docs/examples/type_error.cpp similarity index 100% rename from doc/examples/type_error.cpp rename to docs/examples/type_error.cpp diff --git a/doc/examples/type_error.output b/docs/examples/type_error.output similarity index 100% rename from doc/examples/type_error.output rename to docs/examples/type_error.output diff --git a/doc/examples/type_name.cpp b/docs/examples/type_name.cpp similarity index 100% rename from doc/examples/type_name.cpp rename to docs/examples/type_name.cpp diff --git a/doc/examples/type_name.output b/docs/examples/type_name.output similarity index 100% rename from doc/examples/type_name.output rename to docs/examples/type_name.output diff --git a/doc/examples/unflatten.cpp b/docs/examples/unflatten.cpp similarity index 100% rename from doc/examples/unflatten.cpp rename to docs/examples/unflatten.cpp diff --git a/doc/examples/unflatten.output b/docs/examples/unflatten.output similarity index 100% rename from doc/examples/unflatten.output rename to docs/examples/unflatten.output diff --git a/doc/examples/update.cpp b/docs/examples/update.cpp similarity index 94% rename from doc/examples/update.cpp rename to docs/examples/update.cpp index 8f8b3bf8e..ff94b67fa 100644 --- a/doc/examples/update.cpp +++ b/docs/examples/update.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/update.output b/docs/examples/update.output similarity index 100% rename from doc/examples/update.output rename to docs/examples/update.output diff --git a/doc/examples/update__range.cpp b/docs/examples/update__range.cpp similarity index 95% rename from doc/examples/update__range.cpp rename to docs/examples/update__range.cpp index 98a390429..5b4385046 100644 --- a/doc/examples/update__range.cpp +++ b/docs/examples/update__range.cpp @@ -3,6 +3,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/update__range.output b/docs/examples/update__range.output similarity index 100% rename from doc/examples/update__range.output rename to docs/examples/update__range.output diff --git a/doc/examples/basic_json__value_ptr.cpp b/docs/examples/value__json_ptr.cpp similarity index 96% rename from doc/examples/basic_json__value_ptr.cpp rename to docs/examples/value__json_ptr.cpp index f25b7736a..d866ef076 100644 --- a/doc/examples/basic_json__value_ptr.cpp +++ b/docs/examples/value__json_ptr.cpp @@ -2,6 +2,7 @@ #include using json = nlohmann::json; +using namespace nlohmann::literals; int main() { diff --git a/doc/examples/basic_json__value.output b/docs/examples/value__json_ptr.output similarity index 100% rename from doc/examples/basic_json__value.output rename to docs/examples/value__json_ptr.output diff --git a/docs/examples/value__keytype.c++17.cpp b/docs/examples/value__keytype.c++17.cpp new file mode 100644 index 000000000..1f6ff5c30 --- /dev/null +++ b/docs/examples/value__keytype.c++17.cpp @@ -0,0 +1,32 @@ +#include +#include +#include + +using namespace std::string_view_literals; +using json = nlohmann::json; + +int main() +{ + // create a JSON object with different entry types + json j = + { + {"integer", 1}, + {"floating", 42.23}, + {"string", "hello world"}, + {"boolean", true}, + {"object", {{"key1", 1}, {"key2", 2}}}, + {"array", {1, 2, 3}} + }; + + // access existing values + int v_integer = j.value("integer"sv, 0); + double v_floating = j.value("floating"sv, 47.11); + + // access nonexisting values and rely on default value + std::string v_string = j.value("nonexisting"sv, "oops"); + bool v_boolean = j.value("nonexisting"sv, false); + + // output values + std::cout << std::boolalpha << v_integer << " " << v_floating + << " " << v_string << " " << v_boolean << "\n"; +} diff --git a/doc/examples/basic_json__value_ptr.output b/docs/examples/value__keytype.c++17.output similarity index 100% rename from doc/examples/basic_json__value_ptr.output rename to docs/examples/value__keytype.c++17.output diff --git a/doc/examples/basic_json__value.cpp b/docs/examples/value__object_t_key_type.cpp similarity index 100% rename from doc/examples/basic_json__value.cpp rename to docs/examples/value__object_t_key_type.cpp diff --git a/docs/examples/value__object_t_key_type.output b/docs/examples/value__object_t_key_type.output new file mode 100644 index 000000000..dfc40e58c --- /dev/null +++ b/docs/examples/value__object_t_key_type.output @@ -0,0 +1 @@ +1 42.23 oops false diff --git a/doc/json.gif b/docs/json.gif similarity index 94% rename from doc/json.gif rename to docs/json.gif index 9f0d8a2f0..b34600b79 100644 Binary files a/doc/json.gif and b/docs/json.gif differ diff --git a/doc/mkdocs/Makefile b/docs/mkdocs/Makefile similarity index 57% rename from doc/mkdocs/Makefile rename to docs/mkdocs/Makefile index 3d3d5e7c6..3f894d098 100644 --- a/doc/mkdocs/Makefile +++ b/docs/mkdocs/Makefile @@ -1,18 +1,21 @@ # serve the site locally -serve: prepare_files +serve: prepare_files style_check venv/bin/mkdocs serve -build: prepare_files +serve_dirty: prepare_files style_check + venv/bin/mkdocs serve --dirtyreload + +build: prepare_files style_check venv/bin/mkdocs build -# create files that are not versioned inside the mkdocs folder +# create files that are not versioned inside the mkdocs folder (images, examples) prepare_files: clean - # create subfolders mkdir docs/examples - # copy images - cp -vr ../json.gif docs/images - # copy examples - cp -vr ../examples/*.cpp ../examples/*.output docs/examples + cp -r ../json.gif docs/images + cp -r ../examples/*.cpp ../examples/*.output docs/examples + +style_check: + @cd docs ; python3 ../scripts/check_structure.py # clean subfolders clean: diff --git a/doc/mkdocs/docs/api/adl_serializer/from_json.md b/docs/mkdocs/docs/api/adl_serializer/from_json.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/from_json.md rename to docs/mkdocs/docs/api/adl_serializer/from_json.md diff --git a/doc/mkdocs/docs/api/adl_serializer/index.md b/docs/mkdocs/docs/api/adl_serializer/index.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/index.md rename to docs/mkdocs/docs/api/adl_serializer/index.md diff --git a/doc/mkdocs/docs/api/adl_serializer/to_json.md b/docs/mkdocs/docs/api/adl_serializer/to_json.md similarity index 100% rename from doc/mkdocs/docs/api/adl_serializer/to_json.md rename to docs/mkdocs/docs/api/adl_serializer/to_json.md diff --git a/doc/mkdocs/docs/api/basic_json/accept.md b/docs/mkdocs/docs/api/basic_json/accept.md similarity index 84% rename from doc/mkdocs/docs/api/basic_json/accept.md rename to docs/mkdocs/docs/api/basic_json/accept.md index 8794c585d..1c806e82f 100644 --- a/doc/mkdocs/docs/api/basic_json/accept.md +++ b/docs/mkdocs/docs/api/basic_json/accept.md @@ -29,13 +29,17 @@ Unlike the [`parse`](parse.md) function, this function neither throws an excepti : A compatible input, for instance: - an `std::istream` object - - a `FILE` pointer + - a `FILE` pointer (must not be null) - a C-style array of characters - a pointer to a null-terminated string of single byte characters + - a `std::string` - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. `IteratorType` -: a compatible iterator type +: a compatible iterator type, for instance. + + - a pair of `std::string::iterator` or `std::vector::iterator` + - a pair of pointers such as `ptr` and `ptr + len` ## Parameters @@ -68,6 +72,11 @@ Linear in the length of the input. The parser is a predictive LL(1) parser. (1) A UTF-8 byte order mark is silently ignored. +!!! danger "Runtime assertion" + + The precondition that a passed `#!cpp FILE` pointer must not be null is enforced with a + [runtime assertion](../../features/assertions.md). + ## Examples ??? example @@ -87,7 +96,7 @@ Linear in the length of the input. The parser is a predictive LL(1) parser. ## See also - [parse](parse.md) - deserialize from a compatible input -- [operator>>](operator_gtgt.md) - deserialize from stream +- [operator>>](../operator_gtgt.md) - deserialize from stream ## Version history diff --git a/doc/mkdocs/docs/api/basic_json/array.md b/docs/mkdocs/docs/api/basic_json/array.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/array.md rename to docs/mkdocs/docs/api/basic_json/array.md diff --git a/doc/mkdocs/docs/api/basic_json/array_t.md b/docs/mkdocs/docs/api/basic_json/array_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/array_t.md rename to docs/mkdocs/docs/api/basic_json/array_t.md diff --git a/doc/mkdocs/docs/api/basic_json/at.md b/docs/mkdocs/docs/api/basic_json/at.md similarity index 67% rename from doc/mkdocs/docs/api/basic_json/at.md rename to docs/mkdocs/docs/api/basic_json/at.md index 1ad661322..5e9504508 100644 --- a/doc/mkdocs/docs/api/basic_json/at.md +++ b/docs/mkdocs/docs/api/basic_json/at.md @@ -10,13 +10,28 @@ reference at(const typename object_t::key_type& key); const_reference at(const typename object_t::key_type& key) const; // (3) +template +reference at(KeyType&& key); +template +const_reference at(KeyType&& key) const; + +// (4) reference at(const json_pointer& ptr); const_reference at(const json_pointer& ptr) const; ``` 1. Returns a reference to the array element at specified location `idx`, with bounds checking. -2. Returns a reference to the object element at with specified key `key`, with bounds checking. -3. Returns a reference to the element at with specified JSON pointer `ptr`, with bounds checking. +2. Returns a reference to the object element with specified key `key`, with bounds checking. +3. See 2. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +4. Returns a reference to the element at specified JSON pointer `ptr`, with bounds checking. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -24,16 +39,17 @@ const_reference at(const json_pointer& ptr) const; : index of the element to access `key` (in) -: object key of the elements to remove - +: object key of the elements to access + `ptr` (in) : JSON pointer to the desired element - + ## Return value 1. reference to the element at index `idx` 2. reference to the element at key `key` -3. reference to the element pointed to by `ptr` +3. reference to the element at key `key` +4. reference to the element pointed to by `ptr` ## Exception safety @@ -51,7 +67,8 @@ Strong exception safety: if an exception occurs, the original value stays intact in this case, calling `at` with a key makes no sense. See example below. - Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if the key `key` is not stored in the object; that is, `find(key) == end()`. See example below. -3. The function can throw the following exceptions: +3. See 2. +4. The function can throw the following exceptions: - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed JSON pointer `ptr` begins with '0'. See example below. - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed @@ -68,9 +85,10 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Complexity -1. Constant +1. Constant. 2. Logarithmic in the size of the container. -3. Constant +3. Logarithmic in the size of the container. +4. Logarithmic in the size of the container. ## Examples @@ -119,11 +137,11 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/at__object_t_key_type.output" ``` -??? example "Example (2) access specified object element with bounds checking" +??? example "Example: (2) access specified object element with bounds checking" The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions that can be thrown. - + ```cpp --8<-- "examples/at__object_t_key_type_const.cpp" ``` @@ -134,38 +152,69 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/at__object_t_key_type_const.output" ``` -??? example "Example (3) access specified element via JSON Pointer" +??? example "Example: (3) access specified object element using string_view with bounds checking" + + The example below shows how object elements can be read and written using `at()`. It also demonstrates the different + exceptions that can be thrown. + + ```cpp + --8<-- "examples/at__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/at__keytype.c++17.output" + ``` + +??? example "Example: (3) access specified object element using string_view with bounds checking" + + The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions + that can be thrown. + + ```cpp + --8<-- "examples/at__keytype_const.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/at__keytype_const.c++17.output" + ``` + +??? example "Example: (4) access specified element via JSON Pointer" The example below shows how object elements can be read and written using `at()`. It also demonstrates the different exceptions that can be thrown. ```cpp - --8<-- "examples/at_json_pointer.cpp" + --8<-- "examples/at__json_pointer.cpp" ``` Output: ```json - --8<-- "examples/at_json_pointer.output" + --8<-- "examples/at__json_pointer.output" ``` -??? example "Example (3) access specified element via JSON Pointer" +??? example "Example: (4) access specified element via JSON Pointer" The example below shows how object elements can be read using `at()`. It also demonstrates the different exceptions that can be thrown. ```cpp - --8<-- "examples/at_json_pointer_const.cpp" + --8<-- "examples/at__json_pointer_const.cpp" ``` Output: ```json - --8<-- "examples/at_json_pointer_const.output" + --8<-- "examples/at__json_pointer_const.output" ``` ## See also +- documentation on [checked access](../../features/element_access/checked_access.md) - see [`operator[]`](operator%5B%5D.md) for unchecked access by reference - see [`value`](value.md) for access with default value @@ -173,4 +222,5 @@ Strong exception safety: if an exception occurs, the original value stays intact 1. Added in version 1.0.0. 2. Added in version 1.0.0. -3. Added in version 2.0.0. +3. Added in version 3.11.0. +4. Added in version 2.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/back.md b/docs/mkdocs/docs/api/basic_json/back.md similarity index 89% rename from doc/mkdocs/docs/api/basic_json/back.md rename to docs/mkdocs/docs/api/basic_json/back.md index 96e1dec75..1a715284d 100644 --- a/doc/mkdocs/docs/api/basic_json/back.md +++ b/docs/mkdocs/docs/api/basic_json/back.md @@ -35,9 +35,9 @@ Constant. ## Notes -!!! danger +!!! info "Precondition" - Calling `back` on an empty array or object is undefined behavior and is **guarded by an assertion**! + The array or object must not be empty. Calling `back` on an empty array or object yields undefined behavior. ## Examples diff --git a/doc/mkdocs/docs/api/basic_json/basic_json.md b/docs/mkdocs/docs/api/basic_json/basic_json.md similarity index 96% rename from doc/mkdocs/docs/api/basic_json/basic_json.md rename to docs/mkdocs/docs/api/basic_json/basic_json.md index ab3fea470..e2e73612c 100644 --- a/doc/mkdocs/docs/api/basic_json/basic_json.md +++ b/docs/mkdocs/docs/api/basic_json/basic_json.md @@ -201,16 +201,16 @@ basic_json(basic_json&& other) noexcept; ## Exceptions -1. / +1. (none) 2. The function does not throw exceptions. -3. / -4. / +3. (none) +4. (none) 5. The function can throw the following exceptions: - Throws [`type_error.301`](../../home/exceptions.md#jsonexceptiontype_error301) if `type_deduction` is `#!cpp false`, `manual_type` is `value_t::object`, but `init` contains an element which is not a pair whose first element is a string. In this case, the constructor could not create an object. If `type_deduction` would have been `#!cpp true`, an array would have been created. See `object(initializer_list_t)` for an example. -6. / +6. (none) 7. The function can throw the following exceptions: - Throws [`invalid_iterator.201`](../../home/exceptions.md#jsonexceptioninvalid_iterator201) if iterators `first` and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range @@ -220,7 +220,7 @@ basic_json(basic_json&& other) noexcept; element anymore. In this case, the range `[first, last)` is undefined. See example code below. - Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first` and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined. -8. / +8. (none) 9. The function does not throw exceptions. ## Complexity @@ -241,7 +241,7 @@ basic_json(basic_json&& other) noexcept; - Overload 5: - !!! note + !!! note "Empty initializer list" When used without parentheses around an empty initializer list, `basic_json()` is called instead of this function, yielding the JSON `#!json null` value. @@ -250,17 +250,15 @@ basic_json(basic_json&& other) noexcept; !!! info "Preconditions" - - Iterators `first` and `last` must be initialized. **This precondition is enforced with an assertion (see - warning).** If assertions are switched off, a violation of this precondition yields undefined behavior. + - Iterators `first` and `last` must be initialized. **This precondition is enforced with a + [runtime assertion](../../features/assertions.md). - Range `[first, last)` is valid. Usually, this precondition cannot be checked efficiently. Only certain edge cases are detected; see the description of the exceptions above. A violation of this precondition yields undefined behavior. - !!! warning + !!! danger "Runtime assertion" - A precondition is enforced with a runtime assertion that will result in calling `std::abort` if this - precondition is not met. Assertions can be disabled by defining `NDEBUG` at compile time. See - for more information. + A precondition is enforced with a [runtime assertion](../../features/assertions.md). - Overload 8: @@ -319,6 +317,8 @@ basic_json(basic_json&& other) noexcept; --8<-- "examples/basic_json__CompatibleType.output" ``` + Note the output is platform-dependent. + ??? example "Example: (5) create a container (array or object) from an initializer list" The example below shows how JSON values are created from initializer lists. diff --git a/doc/mkdocs/docs/api/basic_json/begin.md b/docs/mkdocs/docs/api/basic_json/begin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/begin.md rename to docs/mkdocs/docs/api/basic_json/begin.md diff --git a/doc/mkdocs/docs/api/basic_json/binary.md b/docs/mkdocs/docs/api/basic_json/binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/binary.md rename to docs/mkdocs/docs/api/basic_json/binary.md diff --git a/doc/mkdocs/docs/api/basic_json/binary_t.md b/docs/mkdocs/docs/api/basic_json/binary_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/binary_t.md rename to docs/mkdocs/docs/api/basic_json/binary_t.md diff --git a/doc/mkdocs/docs/api/basic_json/boolean_t.md b/docs/mkdocs/docs/api/basic_json/boolean_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/boolean_t.md rename to docs/mkdocs/docs/api/basic_json/boolean_t.md diff --git a/doc/mkdocs/docs/api/basic_json/cbegin.md b/docs/mkdocs/docs/api/basic_json/cbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/cbegin.md rename to docs/mkdocs/docs/api/basic_json/cbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md similarity index 57% rename from doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md rename to docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md index 6622d8aca..e19c3edd9 100644 --- a/doc/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/cbor_tag_handler_t.md @@ -20,6 +20,23 @@ ignore store : store tagged values as binary container with subtype (for bytes 0xd8..0xdb) +## Examples + +??? example + + The example below shows how the different values of the `cbor_tag_handler_t` influence the behavior of + [`from_cbor`](from_cbor.md) when reading a tagged byte string. + + ```cpp + --8<-- "examples/cbor_tag_handler_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/cbor_tag_handler_t.output" + ``` + ## Version history - Added in version 3.9.0. Added value `store` in 3.10.0. diff --git a/doc/mkdocs/docs/api/basic_json/cend.md b/docs/mkdocs/docs/api/basic_json/cend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/cend.md rename to docs/mkdocs/docs/api/basic_json/cend.md diff --git a/doc/mkdocs/docs/api/basic_json/clear.md b/docs/mkdocs/docs/api/basic_json/clear.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/clear.md rename to docs/mkdocs/docs/api/basic_json/clear.md diff --git a/docs/mkdocs/docs/api/basic_json/contains.md b/docs/mkdocs/docs/api/basic_json/contains.md new file mode 100644 index 000000000..ba2c3df2d --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/contains.md @@ -0,0 +1,118 @@ +# nlohmann::basic_json::contains + +```cpp +// (1) +bool contains(const typename object_t::key_type& key) const; + +// (2) +template +bool contains(KeyType&& key) const; + +// (3) +bool contains(const json_pointer& ptr) const; +``` + +1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the + JSON value is not an object, `#!cpp false` is returned. +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +3. Check whether the given JSON pointer `ptr` can be resolved in the current JSON value. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). + +## Parameters + +`key` (in) +: key value to check its existence. + +`ptr` (in) +: JSON pointer to check its existence. + +## Return value + +1. `#!cpp true` if an element with specified `key` exists. If no such element with such key is found or the JSON value + is not an object, `#!cpp false` is returned. +2. See 1. +3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. + +## Exception safety + +Strong exception safety: if an exception occurs, the original value stays intact. + +## Exceptions + +1. The function does not throw exceptions. +2. The function does not throw exceptions. +3. The function can throw the following exceptions: + - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index begins with + `0`. + - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index was not a + number. + +## Complexity + +Logarithmic in the size of the JSON object. + +## Notes + +- This method always returns `#!cpp false` when executed on a JSON type that is not an object. +- This method can be executed on any JSON value type. + +!!! info "Postconditions" + + If `#!cpp j.contains(x)` returns `#!c true` for a key or JSON pointer `x`, then it is safe to call `j[x]`. + +## Examples + +??? example "Example: (1) check with key" + + The example shows how `contains()` is used. + + ```cpp + --8<-- "examples/contains__object_t_key_type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/contains__object_t_key_type.output" + ``` + +??? example "Example: (2) check with key using string_view" + + The example shows how `contains()` is used. + + ```cpp + --8<-- "examples/contains__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/contains__keytype.c++17.output" + ``` + +??? example "Example: (3) check with JSON pointer" + + The example shows how `contains()` is used. + + ```cpp + --8<-- "examples/contains__json_pointer.cpp" + ``` + + Output: + + ```json + --8<-- "examples/contains__json_pointer.output" + ``` + +## Version history + +1. Added in version 3.11.0. +2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0. +3. Added in version 3.7.0. diff --git a/docs/mkdocs/docs/api/basic_json/count.md b/docs/mkdocs/docs/api/basic_json/count.md new file mode 100644 index 000000000..4f3a31055 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/count.md @@ -0,0 +1,78 @@ +# nlohmann::basic_json::count + +```cpp +// (1) +size_type count(const typename object_t::key_type& key) const; + +// (2) +template +size_type count(KeyType&& key) const; +``` + +1. Returns the number of elements with key `key`. If `ObjectType` is the default `std::map` type, the return value will + always be `0` (`key` was not found) or `1` (`key` was found). +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). + +## Parameters + +`key` (in) +: key value of the element to count. + +## Return value + +Number of elements with key `key`. If the JSON value is not an object, the return value will be `0`. + +## Exception safety + +Strong exception safety: if an exception occurs, the original value stays intact. + +## Complexity + +Logarithmic in the size of the JSON object. + +## Notes + +This method always returns `0` when executed on a JSON type that is not an object. + +## Examples + +??? example "Example: (1) count number of elements" + + The example shows how `count()` is used. + + ```cpp + --8<-- "examples/count__object_t_key_type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/count__object_t_key_type.output" + ``` + +??? example "Example: (2) count number of elements using string_view" + + The example shows how `count()` is used. + + ```cpp + --8<-- "examples/count__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/count__keytype.c++17.output" + ``` + +## Version history + +1. Added in version 3.11.0. +2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/crbegin.md b/docs/mkdocs/docs/api/basic_json/crbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/crbegin.md rename to docs/mkdocs/docs/api/basic_json/crbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/crend.md b/docs/mkdocs/docs/api/basic_json/crend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/crend.md rename to docs/mkdocs/docs/api/basic_json/crend.md diff --git a/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md b/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md new file mode 100644 index 000000000..8a237f662 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md @@ -0,0 +1,35 @@ +# nlohmann::basic_json::default_object_comparator_t + +```cpp +using default_object_comparator_t = std::less; // until C++14 + +using default_object_comparator_t = std::less<>; // since C++14 +``` + +The default comparator used by [`object_t`](object_t.md). + +Since C++14 a transparent comparator is used which prevents unnecessary string construction +when looking up a key in an object. + +The actual comparator used depends on [`object_t`](object_t.md) and can be obtained via +[`object_comparator_t`](object_comparator_t.md). + +## Examples + +??? example + + The example below demonstrates the default comparator. + + ```cpp + --8<-- "examples/default_object_comparator_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/default_object_comparator_t.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/diff.md b/docs/mkdocs/docs/api/basic_json/diff.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/diff.md rename to docs/mkdocs/docs/api/basic_json/diff.md diff --git a/doc/mkdocs/docs/api/basic_json/dump.md b/docs/mkdocs/docs/api/basic_json/dump.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/dump.md rename to docs/mkdocs/docs/api/basic_json/dump.md diff --git a/doc/mkdocs/docs/api/basic_json/emplace.md b/docs/mkdocs/docs/api/basic_json/emplace.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/emplace.md rename to docs/mkdocs/docs/api/basic_json/emplace.md diff --git a/doc/mkdocs/docs/api/basic_json/emplace_back.md b/docs/mkdocs/docs/api/basic_json/emplace_back.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/emplace_back.md rename to docs/mkdocs/docs/api/basic_json/emplace_back.md diff --git a/doc/mkdocs/docs/api/basic_json/empty.md b/docs/mkdocs/docs/api/basic_json/empty.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/empty.md rename to docs/mkdocs/docs/api/basic_json/empty.md diff --git a/doc/mkdocs/docs/api/basic_json/end.md b/docs/mkdocs/docs/api/basic_json/end.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/end.md rename to docs/mkdocs/docs/api/basic_json/end.md diff --git a/doc/mkdocs/docs/api/basic_json/erase.md b/docs/mkdocs/docs/api/basic_json/erase.md similarity index 79% rename from doc/mkdocs/docs/api/basic_json/erase.md rename to docs/mkdocs/docs/api/basic_json/erase.md index d94c25b7f..1187995b6 100644 --- a/doc/mkdocs/docs/api/basic_json/erase.md +++ b/docs/mkdocs/docs/api/basic_json/erase.md @@ -13,6 +13,10 @@ const_iterator erase(const_iterator first, const_iterator last); size_type erase(const typename object_t::key_type& key); // (4) +template +size_type erase(KeyType&& key); + +// (5) void erase(const size_type idx); ``` @@ -29,7 +33,17 @@ void erase(const size_type idx); 3. Removes an element from a JSON object by key. -4. Removes an element from a JSON array by index. +4. See 3. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +5. Removes an element from a JSON array by index. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -56,7 +70,8 @@ void erase(const size_type idx); is returned. 3. Number of elements removed. If `ObjectType` is the default `std::map` type, the return value will always be `0` (`key` was not found) or `1` (`key` was found). -4. / +4. See 3. +5. (none) ## Exception safety @@ -83,7 +98,8 @@ Strong exception safety: if an exception occurs, the original value stays intact 3. The function can throw the following exceptions: - Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than JSON object; example: `"cannot use erase() with null"` -4. The function can throw the following exceptions: +4. See 3. +5. The function can throw the following exceptions: - Throws [`type_error.307`](../../home/exceptions.md#jsonexceptiontype_error307) when called on a type other than JSON object; example: `"cannot use erase() with null"` - Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) when `idx >= size()`; example: @@ -103,14 +119,16 @@ Strong exception safety: if an exception occurs, the original value stays intact - strings and binary: linear in the length of the member - other types: constant 3. `log(size()) + count(key)` -4. Linear in distance between `idx` and the end of the container. +4. `log(size()) + count(key)` +5. Linear in distance between `idx` and the end of the container. ## Notes 1. Invalidates iterators and references at or after the point of the `erase`, including the `end()` iterator. -2. / +2. (none) 3. References and iterators to the erased elements are invalidated. Other references and iterators are not affected. -4. / +4. See 3. +5. (none) ## Examples @@ -147,16 +165,30 @@ Strong exception safety: if an exception occurs, the original value stays intact The example shows the effect of `erase()` for different JSON types using an object key. ```cpp - --8<-- "examples/erase__key_type.cpp" + --8<-- "examples/erase__object_t_key_type.cpp" ``` Output: ```json - --8<-- "examples/erase__key_type.output" + --8<-- "examples/erase__object_t_key_type.output" ``` -??? example "Example: (4) remove element from a JSON array given an index" +??? example "Example: (4) remove element from a JSON object given a key using string_view" + + The example shows the effect of `erase()` for different JSON types using an object key. + + ```cpp + --8<-- "examples/erase__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/erase__keytype.c++17.output" + ``` + +??? example "Example: (5) remove element from a JSON array given an index" The example shows the effect of `erase()` using an array index. @@ -172,5 +204,8 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Version history -- Added in version 1.0.0. -- Added support for binary types in version 3.8.0. +1. Added in version 1.0.0. Added support for binary types in version 3.8.0. +2. Added in version 1.0.0. Added support for binary types in version 3.8.0. +3. Added in version 1.0.0. +4. Added in version 3.11.0. +5. Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/error_handler_t.md b/docs/mkdocs/docs/api/basic_json/error_handler_t.md similarity index 62% rename from doc/mkdocs/docs/api/basic_json/error_handler_t.md rename to docs/mkdocs/docs/api/basic_json/error_handler_t.md index afd20f89d..dc32ced9b 100644 --- a/doc/mkdocs/docs/api/basic_json/error_handler_t.md +++ b/docs/mkdocs/docs/api/basic_json/error_handler_t.md @@ -20,6 +20,23 @@ replace ignore : ignore invalid UTF-8 sequences; all bytes are copied to the output unchanged +## Examples + +??? example + + The example below shows how the different values of the `error_handler_t` influence the behavior of + [`dump`](dump.md) when reading serializing an invalid UTF-8 sequence. + + ```cpp + --8<-- "examples/error_handler_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/error_handler_t.output" + ``` + ## Version history - Added in version 3.4.0. diff --git a/doc/mkdocs/docs/api/basic_json/exception.md b/docs/mkdocs/docs/api/basic_json/exception.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/exception.md rename to docs/mkdocs/docs/api/basic_json/exception.md diff --git a/docs/mkdocs/docs/api/basic_json/find.md b/docs/mkdocs/docs/api/basic_json/find.md new file mode 100644 index 000000000..c64350718 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/find.md @@ -0,0 +1,86 @@ +# nlohmann::basic_json::find + +```cpp +// (1) +iterator find(const typename object_t::key_type& key); +const_iterator find(const typename object_t::key_type& key) const; + +// (2) +template +iterator find(KeyType&& key); +template +const_iterator find(KeyType&& key) const; +``` + +1. Finds an element in a JSON object with a key equivalent to `key`. If the element is not found or the + JSON value is not an object, `end()` is returned. +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +## Template parameters + +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). + +## Parameters + +`key` (in) +: key value of the element to search for. + +## Return value + +Iterator to an element with a key equivalent to `key`. If no such element is found or the JSON value is not an object, +a past-the-end iterator (see `end()`) is returned. + +## Exception safety + +Strong exception safety: if an exception occurs, the original value stays intact. + +## Complexity + +Logarithmic in the size of the JSON object. + +## Notes + +This method always returns `end()` when executed on a JSON type that is not an object. + +## Examples + +??? example "Example: (1) find object element by key" + + The example shows how `find()` is used. + + ```cpp + --8<-- "examples/find__object_t_key_type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/find__object_t_key_type.output" + ``` + +??? example "Example: (2) find object element by key using string_view" + + The example shows how `find()` is used. + + ```cpp + --8<-- "examples/find__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/find__keytype.c++17.output" + ``` + +## See also + +- [contains](contains.md) checks whether a key exists + +## Version history + +1. Added in version 3.11.0. +2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/flatten.md b/docs/mkdocs/docs/api/basic_json/flatten.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/flatten.md rename to docs/mkdocs/docs/api/basic_json/flatten.md diff --git a/docs/mkdocs/docs/api/basic_json/from_bjdata.md b/docs/mkdocs/docs/api/basic_json/from_bjdata.md new file mode 100644 index 000000000..3c5eeb351 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/from_bjdata.md @@ -0,0 +1,93 @@ +# nlohmann::basic_json::from_bjdata + +```cpp +// (1) +template +static basic_json from_bjdata(InputType&& i, + const bool strict = true, + const bool allow_exceptions = true); +// (2) +template +static basic_json from_bjdata(IteratorType first, IteratorType last, + const bool strict = true, + const bool allow_exceptions = true); +``` + +Deserializes a given input to a JSON value using the BJData (Binary JData) serialization format. + +1. Reads from a compatible input. +2. Reads from an iterator range. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Template parameters + +`InputType` +: A compatible input, for instance: + + - an `std::istream` object + - a `FILE` pointer + - a C-style array of characters + - a pointer to a null-terminated string of single byte characters + - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. + +`IteratorType` +: a compatible iterator type + +## Parameters + +`i` (in) +: an input in BJData format convertible to an input adapter + +`first` (in) +: iterator to start of the input + +`last` (in) +: iterator to end of the input + +`strict` (in) +: whether to expect the input to be consumed until EOF (`#!cpp true` by default) + +`allow_exceptions` (in) +: whether to throw exceptions in case of a parse error (optional, `#!cpp true` by default) + +## Return value + +deserialized JSON value; in case of a parse error and `allow_exceptions` set to `#!cpp false`, the return value will be +`value_t::discarded`. The latter can be checked with [`is_discarded`](is_discarded.md). + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Exceptions + +- Throws [parse_error.110](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or + the end of file was not reached when `strict` was set to true +- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs +- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string could not be parsed + successfully + +## Complexity + +Linear in the size of the input. + +## Examples + +??? example + + The example shows the deserialization of a byte vector in BJData format to a JSON value. + + ```cpp + --8<-- "examples/from_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/from_bson.md b/docs/mkdocs/docs/api/basic_json/from_bson.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_bson.md rename to docs/mkdocs/docs/api/basic_json/from_bson.md diff --git a/doc/mkdocs/docs/api/basic_json/from_cbor.md b/docs/mkdocs/docs/api/basic_json/from_cbor.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_cbor.md rename to docs/mkdocs/docs/api/basic_json/from_cbor.md diff --git a/doc/mkdocs/docs/api/basic_json/from_msgpack.md b/docs/mkdocs/docs/api/basic_json/from_msgpack.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_msgpack.md rename to docs/mkdocs/docs/api/basic_json/from_msgpack.md diff --git a/doc/mkdocs/docs/api/basic_json/from_ubjson.md b/docs/mkdocs/docs/api/basic_json/from_ubjson.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/from_ubjson.md rename to docs/mkdocs/docs/api/basic_json/from_ubjson.md diff --git a/doc/mkdocs/docs/api/basic_json/front.md b/docs/mkdocs/docs/api/basic_json/front.md similarity index 89% rename from doc/mkdocs/docs/api/basic_json/front.md rename to docs/mkdocs/docs/api/basic_json/front.md index 909f0b59b..e258c36a0 100644 --- a/doc/mkdocs/docs/api/basic_json/front.md +++ b/docs/mkdocs/docs/api/basic_json/front.md @@ -28,9 +28,9 @@ Constant. ## Notes -!!! danger +!!! info "Precondition" - Calling `front` on an empty array or object is undefined behavior and is **guarded by an assertion**! + The array or object must not be empty. Calling `front` on an empty array or object yields undefined behavior. ## Examples diff --git a/doc/mkdocs/docs/api/basic_json/get.md b/docs/mkdocs/docs/api/basic_json/get.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/get.md rename to docs/mkdocs/docs/api/basic_json/get.md index 0a0bc3bab..96fc221da 100644 --- a/doc/mkdocs/docs/api/basic_json/get.md +++ b/docs/mkdocs/docs/api/basic_json/get.md @@ -90,7 +90,7 @@ Depends on what `json_serializer` `from_json()` method throws ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the pointee (overload 3) of the result yields an undefined state. diff --git a/docs/mkdocs/docs/api/basic_json/get_allocator.md b/docs/mkdocs/docs/api/basic_json/get_allocator.md new file mode 100644 index 000000000..07a4d8456 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/get_allocator.md @@ -0,0 +1,31 @@ +# nlohmann::basic_json::get_allocator + +```cpp +static allocator_type get_allocator(); +``` + +Returns the allocator associated with the container. + +## Return value + +associated allocator + +## Examples + +??? example + + The example shows how `get_allocator()` is used to created `json` values. + + ```cpp + --8<-- "examples/get_allocator.cpp" + ``` + + Output: + + ```json + --8<-- "examples/get_allocator.output" + ``` + +## Version history + +- Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/get_binary.md b/docs/mkdocs/docs/api/basic_json/get_binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/get_binary.md rename to docs/mkdocs/docs/api/basic_json/get_binary.md diff --git a/doc/mkdocs/docs/api/basic_json/get_ptr.md b/docs/mkdocs/docs/api/basic_json/get_ptr.md similarity index 97% rename from doc/mkdocs/docs/api/basic_json/get_ptr.md rename to docs/mkdocs/docs/api/basic_json/get_ptr.md index 72517cd7e..2441e1156 100644 --- a/doc/mkdocs/docs/api/basic_json/get_ptr.md +++ b/docs/mkdocs/docs/api/basic_json/get_ptr.md @@ -33,7 +33,7 @@ Constant. ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the pointee of the result yields an undefined state. diff --git a/doc/mkdocs/docs/api/basic_json/get_ref.md b/docs/mkdocs/docs/api/basic_json/get_ref.md similarity index 95% rename from doc/mkdocs/docs/api/basic_json/get_ref.md rename to docs/mkdocs/docs/api/basic_json/get_ref.md index 1140836e4..b1219742c 100644 --- a/doc/mkdocs/docs/api/basic_json/get_ref.md +++ b/docs/mkdocs/docs/api/basic_json/get_ref.md @@ -16,7 +16,7 @@ Implicit reference access to the internally stored JSON value. No copies are mad : reference type; must be a reference to [`array_t`](array_t.md), [`object_t`](object_t.md), [`string_t`](string_t.md), [`boolean_t`](boolean_t.md), [`number_integer_t`](number_integer_t.md), or [`number_unsigned_t`](number_unsigned_t.md), [`number_float_t`](number_float_t.md), or [`binary_t`](binary_t.md). - Enforced by static assertion. + Enforced by a static assertion. ## Return value @@ -38,7 +38,7 @@ Constant. ## Notes -!!! warning +!!! danger "Undefined behavior" Writing data to the referee of the result yields an undefined state. diff --git a/doc/mkdocs/docs/api/basic_json/get_to.md b/docs/mkdocs/docs/api/basic_json/get_to.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/get_to.md rename to docs/mkdocs/docs/api/basic_json/get_to.md diff --git a/doc/mkdocs/docs/api/basic_json/index.md b/docs/mkdocs/docs/api/basic_json/index.md similarity index 95% rename from doc/mkdocs/docs/api/basic_json/index.md rename to docs/mkdocs/docs/api/basic_json/index.md index eb90ac6ec..e474b662e 100644 --- a/doc/mkdocs/docs/api/basic_json/index.md +++ b/docs/mkdocs/docs/api/basic_json/index.md @@ -54,7 +54,7 @@ The class satisfies the following concept requirements: from an rvalue argument. - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): A JSON value can be copy-constructed from an lvalue expression. -- [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): A JSON value van be assigned from an +- [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): A JSON value can be assigned from an rvalue argument. - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): A JSON value can be copy-assigned from an lvalue expression. @@ -128,6 +128,7 @@ The class satisfies the following concept requirements: - [**array_t**](array_t.md) - type for arrays - [**binary_t**](binary_t.md) - type for binary arrays - [**boolean_t**](boolean_t.md) - type for booleans +- [**default_object_comparator_t**](default_object_comparator_t.md) - default comparator for objects - [**number_float_t**](number_float_t.md) - type for numbers (floating-point) - [**number_integer_t**](number_integer_t.md) - type for numbers (integer) - [**number_unsigned_t**](number_unsigned_t.md) - type for numbers (unsigned) @@ -232,9 +233,10 @@ Access to the JSON value - [**operator==**](operator_eq.md) - comparison: equal - [**operator!=**](operator_ne.md) - comparison: not equal - [**operator<**](operator_lt.md) - comparison: less than -- [**operator<=**](operator_le.md) - comparison: less than or equal - [**operator>**](operator_gt.md) - comparison: greater than +- [**operator<=**](operator_le.md) - comparison: less than or equal - [**operator>=**](operator_ge.md) - comparison: greater than or equal +- [**operator<=>**](operator_spaceship.md) - comparison: 3-way ### Serialization / Dumping @@ -254,6 +256,7 @@ Access to the JSON value ### JSON Patch functions - [**patch**](patch.md) - applies a JSON patch +- [**patch_inplace**](patch_inplace.md) - applies a JSON patch in place - [**diff**](diff.md) (_static_) - creates a diff as a JSON patch ### JSON Merge Patch functions @@ -267,10 +270,12 @@ Access to the JSON value ### Binary formats +- [**from_bjdata**](from_bjdata.md) (_static_) - create a JSON value from an input in BJData format - [**from_bson**](from_bson.md) (_static_) - create a JSON value from an input in BSON format - [**from_cbor**](from_cbor.md) (_static_) - create a JSON value from an input in CBOR format - [**from_msgpack**](from_msgpack.md) (_static_) - create a JSON value from an input in MessagePack format - [**from_ubjson**](from_ubjson.md) (_static_) - create a JSON value from an input in UBJSON format +- [**to_bjdata**](to_bjdata.md) (_static_) - create a BJData serialization of a given JSON value - [**to_bson**](to_bson.md) (_static_) - create a BSON serialization of a given JSON value - [**to_cbor**](to_cbor.md) (_static_) - create a CBOR serialization of a given JSON value - [**to_msgpack**](to_msgpack.md) (_static_) - create a MessagePack serialization of a given JSON value @@ -278,21 +283,20 @@ Access to the JSON value ## Non-member functions -- [**operator<<(std::ostream&)**](operator_ltlt.md) - serialize to stream -- [**operator>>(std::istream&)**](operator_gtgt.md) - deserialize from stream +- [**operator<<(std::ostream&)**](../operator_ltlt.md) - serialize to stream +- [**operator>>(std::istream&)**](../operator_gtgt.md) - deserialize from stream - [**to_string**](to_string.md) - user-defined `to_string` function for JSON values ## Literals -- [**operator""_json**](operator_literal_json.md) - user-defined string literal for JSON values -- [**operator""_json_pointer**](operator_literal_json_pointer.md) - user-defined string literal for JSON pointers +- [**operator""_json**](../operator_literal_json.md) - user-defined string literal for JSON values ## Helper classes - [**std::hash<basic_json>**](std_hash.md) - return a hash value for a JSON object - [**std::swap<basic_json>**](std_swap.md) - exchanges the values of two JSON objects -## Example +## Examples ??? example diff --git a/doc/mkdocs/docs/api/basic_json/input_format_t.md b/docs/mkdocs/docs/api/basic_json/input_format_t.md similarity index 57% rename from doc/mkdocs/docs/api/basic_json/input_format_t.md rename to docs/mkdocs/docs/api/basic_json/input_format_t.md index 4accf6dee..a3baabab8 100644 --- a/doc/mkdocs/docs/api/basic_json/input_format_t.md +++ b/docs/mkdocs/docs/api/basic_json/input_format_t.md @@ -6,7 +6,8 @@ enum class input_format_t { cbor, msgpack, ubjson, - bson + bson, + bjdata }; ``` @@ -27,6 +28,25 @@ ubjson bson : BSON (Binary JSON) +bjdata +: BJData (Binary JData) + +## Examples + +??? example + + The example below shows how an `input_format_t` enum value is passed to `sax_parse` to set the input format to CBOR. + + ```cpp + --8<-- "examples/sax_parse__binary.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse__binary.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/basic_json/insert.md b/docs/mkdocs/docs/api/basic_json/insert.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/insert.md rename to docs/mkdocs/docs/api/basic_json/insert.md index fdd8fe6b5..2e6b29301 100644 --- a/doc/mkdocs/docs/api/basic_json/insert.md +++ b/docs/mkdocs/docs/api/basic_json/insert.md @@ -50,7 +50,7 @@ void insert(const_iterator first, const_iterator last); 2. iterator pointing to the first element inserted, or `pos` if `#!cpp cnt==0` 3. iterator pointing to the first element inserted, or `pos` if `#!cpp first==last` 4. iterator pointing to the first element inserted, or `pos` if `ilist` is empty -5. / +5. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/invalid_iterator.md b/docs/mkdocs/docs/api/basic_json/invalid_iterator.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/invalid_iterator.md rename to docs/mkdocs/docs/api/basic_json/invalid_iterator.md diff --git a/doc/mkdocs/docs/api/basic_json/is_array.md b/docs/mkdocs/docs/api/basic_json/is_array.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_array.md rename to docs/mkdocs/docs/api/basic_json/is_array.md diff --git a/doc/mkdocs/docs/api/basic_json/is_binary.md b/docs/mkdocs/docs/api/basic_json/is_binary.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_binary.md rename to docs/mkdocs/docs/api/basic_json/is_binary.md diff --git a/doc/mkdocs/docs/api/basic_json/is_boolean.md b/docs/mkdocs/docs/api/basic_json/is_boolean.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_boolean.md rename to docs/mkdocs/docs/api/basic_json/is_boolean.md diff --git a/doc/mkdocs/docs/api/basic_json/is_discarded.md b/docs/mkdocs/docs/api/basic_json/is_discarded.md similarity index 93% rename from doc/mkdocs/docs/api/basic_json/is_discarded.md rename to docs/mkdocs/docs/api/basic_json/is_discarded.md index 405ae6c11..663cbf889 100644 --- a/doc/mkdocs/docs/api/basic_json/is_discarded.md +++ b/docs/mkdocs/docs/api/basic_json/is_discarded.md @@ -24,7 +24,7 @@ Constant. ## Notes -!!! note +!!! note "Comparisons" Discarded values are never compared equal with [`operator==`](operator_eq.md). That is, checking whether a JSON value `j` is discarded will only work via: @@ -41,10 +41,10 @@ Constant. will always be `#!cpp false`. -!!! note +!!! note "Removal during parsing with callback functions" When a value is discarded by a callback function (see [`parser_callback_t`](parser_callback_t.md)) during parsing, - then it is removed when it is part of a structured value. For instance, if the second value of an array is discared, + then it is removed when it is part of a structured value. For instance, if the second value of an array is discarded, instead of `#!json [null, discarded, false]`, the array `#!json [null, false]` is returned. Only if the top-level value is discarded, the return value of the `parse` call is discarded. diff --git a/doc/mkdocs/docs/api/basic_json/is_null.md b/docs/mkdocs/docs/api/basic_json/is_null.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_null.md rename to docs/mkdocs/docs/api/basic_json/is_null.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number.md b/docs/mkdocs/docs/api/basic_json/is_number.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number.md rename to docs/mkdocs/docs/api/basic_json/is_number.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_float.md b/docs/mkdocs/docs/api/basic_json/is_number_float.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_float.md rename to docs/mkdocs/docs/api/basic_json/is_number_float.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_integer.md b/docs/mkdocs/docs/api/basic_json/is_number_integer.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_integer.md rename to docs/mkdocs/docs/api/basic_json/is_number_integer.md diff --git a/doc/mkdocs/docs/api/basic_json/is_number_unsigned.md b/docs/mkdocs/docs/api/basic_json/is_number_unsigned.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_number_unsigned.md rename to docs/mkdocs/docs/api/basic_json/is_number_unsigned.md diff --git a/doc/mkdocs/docs/api/basic_json/is_object.md b/docs/mkdocs/docs/api/basic_json/is_object.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_object.md rename to docs/mkdocs/docs/api/basic_json/is_object.md diff --git a/doc/mkdocs/docs/api/basic_json/is_primitive.md b/docs/mkdocs/docs/api/basic_json/is_primitive.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_primitive.md rename to docs/mkdocs/docs/api/basic_json/is_primitive.md diff --git a/doc/mkdocs/docs/api/basic_json/is_string.md b/docs/mkdocs/docs/api/basic_json/is_string.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_string.md rename to docs/mkdocs/docs/api/basic_json/is_string.md diff --git a/doc/mkdocs/docs/api/basic_json/is_structured.md b/docs/mkdocs/docs/api/basic_json/is_structured.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/is_structured.md rename to docs/mkdocs/docs/api/basic_json/is_structured.md diff --git a/doc/mkdocs/docs/api/basic_json/items.md b/docs/mkdocs/docs/api/basic_json/items.md similarity index 98% rename from doc/mkdocs/docs/api/basic_json/items.md rename to docs/mkdocs/docs/api/basic_json/items.md index b388824f9..0b34ddcba 100644 --- a/doc/mkdocs/docs/api/basic_json/items.md +++ b/docs/mkdocs/docs/api/basic_json/items.md @@ -63,7 +63,7 @@ Constant. When iterating over an array, `key()` will return the index of the element as string (see example). For primitive types (e.g., numbers), `key()` returns an empty string. -!!! warning +!!! danger "Lifetime issues" Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See for more information. diff --git a/doc/mkdocs/docs/api/basic_json/json_serializer.md b/docs/mkdocs/docs/api/basic_json/json_serializer.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/json_serializer.md rename to docs/mkdocs/docs/api/basic_json/json_serializer.md diff --git a/doc/mkdocs/docs/api/basic_json/max_size.md b/docs/mkdocs/docs/api/basic_json/max_size.md similarity index 97% rename from doc/mkdocs/docs/api/basic_json/max_size.md rename to docs/mkdocs/docs/api/basic_json/max_size.md index 31339dbe9..4c0c57520 100644 --- a/doc/mkdocs/docs/api/basic_json/max_size.md +++ b/docs/mkdocs/docs/api/basic_json/max_size.md @@ -40,7 +40,7 @@ string elements the JSON value can store which is `1`. ??? example - The following code calls `max_size()` on the different value types. Note the output is implementation specific. + The following code calls `max_size()` on the different value types. ```cpp --8<-- "examples/max_size.cpp" @@ -52,6 +52,8 @@ string elements the JSON value can store which is `1`. --8<-- "examples/max_size.output" ``` + Note the output is platform-dependent. + ## Version history - Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/merge_patch.md b/docs/mkdocs/docs/api/basic_json/merge_patch.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/merge_patch.md rename to docs/mkdocs/docs/api/basic_json/merge_patch.md diff --git a/doc/mkdocs/docs/api/basic_json/meta.md b/docs/mkdocs/docs/api/basic_json/meta.md similarity index 90% rename from doc/mkdocs/docs/api/basic_json/meta.md rename to docs/mkdocs/docs/api/basic_json/meta.md index e2b312e0c..c584f9b6d 100644 --- a/doc/mkdocs/docs/api/basic_json/meta.md +++ b/docs/mkdocs/docs/api/basic_json/meta.md @@ -32,8 +32,7 @@ Constant. ??? example - The following code shows an example output of the `meta()` - function. + The following code shows an example output of the `meta()` function. ```cpp --8<-- "examples/meta.cpp" @@ -45,6 +44,13 @@ Constant. --8<-- "examples/meta.output" ``` + Note the output is platform-dependent. + +## See also + +- [**NLOHMANN_JSON_VERSION_MAJOR**/**NLOHMANN_JSON_VERSION_MINOR**/**NLOHMANN_JSON_VERSION_PATCH**](../macros/nlohmann_json_version_major.md) + \- library version information + ## Version history - Added in version 2.1.0. diff --git a/doc/mkdocs/docs/api/basic_json/number_float_t.md b/docs/mkdocs/docs/api/basic_json/number_float_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_float_t.md rename to docs/mkdocs/docs/api/basic_json/number_float_t.md diff --git a/doc/mkdocs/docs/api/basic_json/number_integer_t.md b/docs/mkdocs/docs/api/basic_json/number_integer_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_integer_t.md rename to docs/mkdocs/docs/api/basic_json/number_integer_t.md diff --git a/doc/mkdocs/docs/api/basic_json/number_unsigned_t.md b/docs/mkdocs/docs/api/basic_json/number_unsigned_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/number_unsigned_t.md rename to docs/mkdocs/docs/api/basic_json/number_unsigned_t.md diff --git a/doc/mkdocs/docs/api/basic_json/object.md b/docs/mkdocs/docs/api/basic_json/object.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/object.md rename to docs/mkdocs/docs/api/basic_json/object.md diff --git a/docs/mkdocs/docs/api/basic_json/object_comparator_t.md b/docs/mkdocs/docs/api/basic_json/object_comparator_t.md new file mode 100644 index 000000000..496a56267 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/object_comparator_t.md @@ -0,0 +1,31 @@ +# nlohmann::basic_json::object_comparator_t + +```cpp +using object_comparator_t = typename object_t::key_compare; +// or +using object_comparator_t = default_object_comparator_t; +``` + +The comparator used by [`object_t`](object_t.md). Defined as `#!cpp typename object_t::key_compare` if available, +and [`default_object_comparator_t`](default_object_comparator_t.md) otherwise. + +## Examples + +??? example + + The example below demonstrates the used object comparator. + + ```cpp + --8<-- "examples/object_comparator_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/object_comparator_t.output" + ``` + +## Version history + +- Added in version 3.0.0. +- Changed to be conditionally defined as `#!cpp typename object_t::key_compare` or `default_object_comparator_t` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/object_t.md b/docs/mkdocs/docs/api/basic_json/object_t.md similarity index 96% rename from doc/mkdocs/docs/api/basic_json/object_t.md rename to docs/mkdocs/docs/api/basic_json/object_t.md index d4bea15aa..67b3bb78c 100644 --- a/doc/mkdocs/docs/api/basic_json/object_t.md +++ b/docs/mkdocs/docs/api/basic_json/object_t.md @@ -3,7 +3,7 @@ ```cpp using object_t = ObjectType>>; ``` @@ -52,7 +52,7 @@ std::map< > ``` -See [`object_comparator_t`](object_comparator_t.md) for more information. +See [`default_object_comparator_t`](default_object_comparator_t.md) for more information. #### Behavior diff --git a/doc/mkdocs/docs/api/basic_json/operator+=.md b/docs/mkdocs/docs/api/basic_json/operator+=.md similarity index 85% rename from doc/mkdocs/docs/api/basic_json/operator+=.md rename to docs/mkdocs/docs/api/basic_json/operator+=.md index 074b30003..dc5f2ecc4 100644 --- a/doc/mkdocs/docs/api/basic_json/operator+=.md +++ b/docs/mkdocs/docs/api/basic_json/operator+=.md @@ -41,12 +41,9 @@ reference operator+=(initializer_list_t init); ## Exceptions -1. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON array or null; example: `"cannot use operator+=() with number"` -2. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON object or null; example: `"cannot use operator+=() with number"` +All functions can throw the following exception: + - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than + JSON array or null; example: `"cannot use operator+=() with number"` ## Complexity diff --git a/doc/mkdocs/docs/api/basic_json/operator=.md b/docs/mkdocs/docs/api/basic_json/operator=.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator=.md rename to docs/mkdocs/docs/api/basic_json/operator=.md diff --git a/doc/mkdocs/docs/api/basic_json/operator[].md b/docs/mkdocs/docs/api/basic_json/operator[].md similarity index 55% rename from doc/mkdocs/docs/api/basic_json/operator[].md rename to docs/mkdocs/docs/api/basic_json/operator[].md index 5b6512a21..ebc737e4b 100644 --- a/doc/mkdocs/docs/api/basic_json/operator[].md +++ b/docs/mkdocs/docs/api/basic_json/operator[].md @@ -6,26 +6,32 @@ reference operator[](size_type idx); const_reference operator[](size_type idx) const; // (2) -reference operator[](const typename object_t::key_type& key); +reference operator[](typename object_t::key_type key); const_reference operator[](const typename object_t::key_type& key) const; -template -reference operator[](T* key); -template -const_reference operator[](T* key) const; // (3) +template +reference operator[](KeyType&& key); +template +const_reference operator[](KeyType&& key) const; + +// (4) reference operator[](const json_pointer& ptr); const_reference operator[](const json_pointer& ptr) const; ``` 1. Returns a reference to the array element at specified location `idx`. -2. Returns a reference to the object element at with specified key `key`. -3. Returns a reference to the element at with specified JSON pointer `ptr`. +2. Returns a reference to the object element with specified key `key`. The non-const qualified overload takes the key by value. +3. See 2. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. +4. Returns a reference to the element with specified JSON pointer `ptr`. ## Template parameters -`T` -: string literal convertible to `object_t::key_type` +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). ## Parameters @@ -40,9 +46,10 @@ const_reference operator[](const json_pointer& ptr) const; ## Return value -1. reference to the element at index `idx` -2. reference to the element at key `key` -3. reference to the element pointed to by `ptr` +1. (const) reference to the element at index `idx` +2. (const) reference to the element at key `key` +3. (const) reference to the element at key `key` +4. (const) reference to the element pointed to by `ptr` ## Exception safety @@ -56,7 +63,8 @@ Strong exception safety: if an exception occurs, the original value stays intact 2. The function can throw the following exceptions: - Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an object or null; in that case, using the `[]` operator with a key makes no sense. -3. The function can throw the following exceptions: +3. See 2. +4. The function can throw the following exceptions: - Throws [`parse_error.106`](../../home/exceptions.md#jsonexceptionparse_error106) if an array index in the passed JSON pointer `ptr` begins with '0'. - Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) if an array index in the passed @@ -70,14 +78,16 @@ Strong exception safety: if an exception occurs, the original value stays intact 1. Constant if `idx` is in the range of the array. Otherwise, linear in `idx - size()`. 2. Logarithmic in the size of the container. -3. Constant +3. Logarithmic in the size of the container. +4. Logarithmic in the size of the container. ## Notes -!!! danger +!!! danger "Undefined behavior and runtime assertions" 1. If the element with key `idx` does not exist, the behavior is undefined. - 2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by an assertion**! + 2. If the element with key `key` does not exist, the behavior is undefined and is **guarded by a + [runtime assertion](../../features/assertions.md)**! 1. The non-const version may add values: If `idx` is beyond the range of the array (i.e., `idx >= size()`), then the array is silently filled up with `#!json null` values to make `idx` a valid reference to the last stored element. In @@ -86,7 +96,9 @@ Strong exception safety: if an exception occurs, the original value stays intact 2. If `key` is not found in the object, then it is silently added to the object and filled with a `#!json null` value to make `key` a valid reference. In case the value was `#!json null` before, it is converted to an object. -3. `null` values are created in arrays and objects if necessary. +3. See 2. + +4. `null` values are created in arrays and objects if necessary. In particular: @@ -99,98 +111,129 @@ Strong exception safety: if an exception occurs, the original value stays intact ## Examples -??? example "Example (1): access specified array element" +??? example "Example: (1) access specified array element" The example below shows how array elements can be read and written using `[]` operator. Note the addition of `#!json null` values. ```cpp - --8<-- "examples/operatorarray__size_type.cpp" + --8<-- "examples/operator_array__size_type.cpp" ``` Output: ```json - --8<-- "examples/operatorarray__size_type.output" + --8<-- "examples/operator_array__size_type.output" ``` -??? example "Example (1): access specified array element" +??? example "Example: (1) access specified array element (const)" The example below shows how array elements can be read using the `[]` operator. ```cpp - --8<-- "examples/operatorarray__size_type_const.cpp" + --8<-- "examples/operator_array__size_type_const.cpp" ``` Output: ```json - --8<-- "examples/operatorarray__size_type_const.output" + --8<-- "examples/operator_array__size_type_const.output" ``` -??? example "Example (2): access specified object element" +??? example "Example: (2) access specified object element" The example below shows how object elements can be read and written using the `[]` operator. ```cpp - --8<-- "examples/operatorarray__key_type.cpp" + --8<-- "examples/operator_array__object_t_key_type.cpp" ``` Output: ```json - --8<-- "examples/operatorarray__key_type.output" + --8<-- "examples/operator_array__object_t_key_type.output" ``` -??? example "Example (2): access specified object element" +??? example "Example: (2) access specified object element (const)" The example below shows how object elements can be read using the `[]` operator. ```cpp - --8<-- "examples/operatorarray__key_type_const.cpp" + --8<-- "examples/operator_array__object_t_key_type_const.cpp" ``` Output: ```json - --8<-- "examples/operatorarray__key_type_const.output" + --8<-- "examples/operator_array__object_t_key_type_const.output" ``` -??? example "Example (3): access specified element via JSON Pointer" +??? example "Example: (3) access specified object element using string_view" + + The example below shows how object elements can be read using the `[]` operator. + + ```cpp + --8<-- "examples/operator_array__keytype.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_array__keytype.c++17.output" + ``` + +??? example "Example: (3) access specified object element using string_view (const)" + + The example below shows how object elements can be read using the `[]` operator. + + ```cpp + --8<-- "examples/operator_array__keytype_const.c++17.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_array__keytype_const.c++17.output" + ``` + +??? example "Example: (4) access specified element via JSON Pointer" The example below shows how values can be read and written using JSON Pointers. ```cpp - --8<-- "examples/operatorjson_pointer.cpp" + --8<-- "examples/operator_array__json_pointer.cpp" ``` Output: ```json - --8<-- "examples/operatorjson_pointer.output" + --8<-- "examples/operator_array__json_pointer.output" ``` -??? example "Example (3): access specified element via JSON Pointer" +??? example "Example: (4) access specified element via JSON Pointer (const)" The example below shows how values can be read using JSON Pointers. ```cpp - --8<-- "examples/operatorjson_pointer_const.cpp" + --8<-- "examples/operator_array__json_pointer_const.cpp" ``` Output: ```json - --8<-- "examples/operatorjson_pointer_const.output" + --8<-- "examples/operator_array__json_pointer_const.output" ``` ## See also +- documentation on [unchecked access](../../features/element_access/unchecked_access.md) +- documentation on [runtime assertions](../../features/assertions.md) - see [`at`](at.md) for access by reference with range checking - see [`value`](value.md) for access with default value ## Version history 1. Added in version 1.0.0. -2. Added in version 1.0.0. Overloads for `T* key` added in version 1.1.0. -3. Added in version 2.0.0. +2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3) in version 3.11.0. +3. Added in version 3.11.0. +4. Added in version 2.0.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_ValueType.md b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md new file mode 100644 index 000000000..bf38a3d21 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md @@ -0,0 +1,82 @@ +# nlohmann::basic_json::operator ValueType + +```cpp +template +JSON_EXPLICIT operator ValueType() const; +``` + +Implicit type conversion between the JSON value and a compatible value. The call is realized by calling +[`get()`](get.md). See [Notes](#notes) for the meaning of `JSON_EXPLICIT`. + +## Template parameters + +`ValueType` +: the value type to return + +## Return value + +copy of the JSON value, converted to `ValueType` + +## Exceptions + +Depends on what `json_serializer` `from_json()` method throws + +## Complexity + +Linear in the size of the JSON value. + +## Notes + +!!! note "Definition of `JSON_EXPLICIT`" + + By default `JSON_EXPLICIT` is defined to the empty string, so the signature is: + + ```cpp + template + operator ValueType() const; + ``` + + If [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) is set to `0`, + `JSON_EXPLICIT` is defined to `#!cpp explicit`: + + ```cpp + template + explicit operator ValueType() const; + ``` + + That is, implicit conversions can be switched off by defining + [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0`. + +!!! info "Future behavior change" + + Implicit conversions will be switched off by default in the next major release of the library. That is, + `JSON_EXPLICIT` will be set to `#!cpp explicit` by default. + + You can prepare existing code by already defining + [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) to `0` and replace any implicit + conversions with calls to [`get`](../basic_json/get.md). + +## Examples + +??? example + + The example below shows several conversions from JSON values to other types. There are a few things to note: (1) + Floating-point numbers can be converted to integers, (2) A JSON array can be converted to a standard + `std::vector`, (3) A JSON object can be converted to C++ associative containers such as + `std::unordered_map`. + + ```cpp + --8<-- "examples/operator__ValueType.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__ValueType.output" + ``` + +## Version history + +- Since version 1.0.0. +- Macros `JSON_EXPLICIT`/[`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md) added + in version 3.9.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_eq.md b/docs/mkdocs/docs/api/basic_json/operator_eq.md similarity index 55% rename from doc/mkdocs/docs/api/basic_json/operator_eq.md rename to docs/mkdocs/docs/api/basic_json/operator_eq.md index 49f96b1c0..b4d61b637 100644 --- a/doc/mkdocs/docs/api/basic_json/operator_eq.md +++ b/docs/mkdocs/docs/api/basic_json/operator_eq.md @@ -1,21 +1,31 @@ # nlohmann::basic_json::operator== ```cpp -bool operator==(const_reference lhs, const_reference rhs) noexcept; +// until C++20 +bool operator==(const_reference lhs, const_reference rhs) noexcept; // (1) template -bool operator==(const_reference lhs, const ScalarType rhs) noexcept; +bool operator==(const_reference lhs, const ScalarType rhs) noexcept; // (2) template -bool operator==(ScalarType lhs, const const_reference rhs) noexcept; +bool operator==(ScalarType lhs, const const_reference rhs) noexcept; // (2) + +// since C++20 +class basic_json { + bool operator==(const_reference rhs) const noexcept; // (1) + + template + bool operator==(ScalarType rhs) const noexcept; // (2) +}; ``` -Compares two JSON values for equality according to the following rules: +1. Compares two JSON values for equality according to the following rules: + - Two JSON values are equal if (1) neither value is discarded, or (2) they are of the same + type and their stored values are the same according to their respective `operator==`. + - Integer and floating-point numbers are automatically converted before comparison. -- Two JSON values are equal if (1) they are not discarded, (2) they are from the same type, and (3) their stored values - are the same according to their respective `operator==`. -- Integer and floating-point numbers are automatically converted before comparison. Note that two NaN values are always - treated as unequal. +2. Compares a JSON value and a scalar or a scalar and a JSON value for equality by converting the + scalar to a JSON value and comparing both JSON values according to 1. ## Template parameters @@ -32,7 +42,7 @@ Compares two JSON values for equality according to the following rules: ## Return value -whether the values `lhs` and `rhs` are equal +whether the values `lhs`/`*this` and `rhs` are equal ## Exception safety @@ -44,13 +54,17 @@ Linear. ## Notes -!!! note +!!! note "Comparing special values" - - NaN values never compare equal to themselves or to other NaN values. + - `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. - JSON `#!cpp null` values are all equal. - Discarded values never compare equal to themselves. -!!! note +!!! note "Comparing floating-point numbers" Floating-point numbers inside JSON values numbers are compared with `json::number_float_t::operator==` which is `double::operator==` by default. To compare floating-point while respecting an epsilon, an alternative @@ -85,6 +99,39 @@ Linear. } ``` +!!! note "Comparing different `basic_json` specializations" + + Comparing different `basic_json` specializations can have surprising effects. For instance, the result of comparing + the JSON objects + + ```json + { + "version": 1, + "type": "integer" + } + ``` + + and + + ```json + { + "type": "integer", + "version": 1 + } + ``` + + depends on whether [`nlohmann::json`](../json.md) or [`nlohmann::ordered_json`](../ordered_json.md) is used: + + ```cpp + --8<-- "examples/operator__equal__specializations.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__equal__specializations.output" + ``` + ## Examples ??? example @@ -117,4 +164,5 @@ Linear. ## Version history -- Added in version 1.0.0. +1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. +2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_ge.md b/docs/mkdocs/docs/api/basic_json/operator_ge.md new file mode 100644 index 000000000..847f6ca65 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ge.md @@ -0,0 +1,87 @@ +# nlohmann::basic_json::operator>= + +```cpp +// until C++20 +bool operator>=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator>=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator>=(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is greater than or equal to another JSON value `rhs` + according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs < rhs)` (see [**operator<**](operator_lt.md)). + +2. Compares wether a JSON value is greater than or equal to a scalar or a scalar is greater than or + equal to a JSON value by converting the scalar to a JSON value and comparing both JSON values + according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than or equal to `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__greaterequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__greaterequal.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_gt.md b/docs/mkdocs/docs/api/basic_json/operator_gt.md new file mode 100644 index 000000000..9516656e0 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_gt.md @@ -0,0 +1,86 @@ +# nlohmann::basic_json::operator> + +```cpp +// until C++20 +bool operator>(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator>(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator>(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is greater than another JSON value `rhs` according to the + following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs <= rhs)` (see [**operator<=**](operator_le.md)). + +2. Compares wether a JSON value is greater than a scalar or a scalar is greater than a JSON value by + converting the scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is greater than `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__greater.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__greater.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_le.md b/docs/mkdocs/docs/api/basic_json/operator_le.md new file mode 100644 index 000000000..7b648e035 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_le.md @@ -0,0 +1,87 @@ +# nlohmann::basic_json::operator<= + +```cpp +// until C++20 +bool operator<=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator<=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is less than or equal to another JSON value `rhs` + according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(rhs < lhs)` (see [**operator<**](operator_lt.md)). + +1. Compares wether a JSON value is less than or equal to a scalar or a scalar is less than or equal + to a JSON value by converting the scalar to a JSON value and comparing both JSON values according + to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than or equal to `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__lessequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__lessequal.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_lt.md b/docs/mkdocs/docs/api/basic_json/operator_lt.md new file mode 100644 index 000000000..b5d191ec4 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_lt.md @@ -0,0 +1,96 @@ +# nlohmann::basic_json::operator< + +```cpp +// until C++20 +bool operator<(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator<(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator<(ScalarType lhs, const const_reference rhs) noexcept; // (2) +``` + +1. Compares whether one JSON value `lhs` is less than another JSON value `rhs` according to the + following rules: + - If either operand is discarded, the comparison yields `#!cpp false`. + - If both operands have the same type, the values are compared using their respective `operator<`. + - Integer and floating-point numbers are automatically converted before comparison. + - In case `lhs` and `rhs` have different types, the values are ignored and the order of the types + is considered, which is: + 1. null + 2. boolean + 3. number (all types) + 4. object + 5. array + 6. string + 7. binary + For instance, any boolean value is considered less than any string. + +2. Compares wether a JSON value is less than a scalar or a scalar is less than a JSON value by converting + the scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether `lhs` is less than `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +!!! note "Operator overload resolution" + + Since C++20 overload resolution will consider the _rewritten candidate_ generated from + [`operator<=>`](operator_spaceship.md). + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__less.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__less.output" + ``` + +## See also + +- [**operator<=>**](operator_spaceship.md) comparison: 3-way + +## Version history + +1. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. +2. Added in version 1.0.0. Conditionally removed since C++20 in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_ne.md b/docs/mkdocs/docs/api/basic_json/operator_ne.md new file mode 100644 index 000000000..f5d989b50 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ne.md @@ -0,0 +1,99 @@ +# nlohmann::basic_json::operator!= + +```cpp +// until C++20 +bool operator!=(const_reference lhs, const_reference rhs) noexcept; // (1) + +template +bool operator!=(const_reference lhs, const ScalarType rhs) noexcept; // (2) + +template +bool operator!=(ScalarType lhs, const const_reference rhs) noexcept; // (2) + +// since C++20 +class basic_json { + bool operator!=(const_reference rhs) const noexcept; // (1) + + template + bool operator!=(ScalarType rhs) const noexcept; // (2) +}; +``` + +1. Compares two JSON values for inequality according to the following rules: + - The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either + operand is `NaN` and the other operand is either `NaN` or any other number. + - Otherwise, returns the result of `#!cpp !(lhs == rhs)` (until C++20) or + `#!cpp !(*this == rhs)` (since C++20). + +2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the + scalar to a JSON value and comparing both JSON values according to 1. + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`lhs` (in) +: first value to consider + +`rhs` (in) +: second value to consider + +## Return value + +whether the values `lhs`/`*this` and `rhs` are not equal + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `#!cpp false`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +## Examples + +??? example + + The example demonstrates comparing several JSON types. + + ```cpp + --8<-- "examples/operator__notequal.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__notequal.output" + ``` + +??? example + + The example demonstrates comparing several JSON types against the null pointer (JSON `#!json null`). + + ```cpp + --8<-- "examples/operator__notequal__nullptr_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator__notequal__nullptr_t.output" + ``` + +## Version history + +1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. +2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. diff --git a/docs/mkdocs/docs/api/basic_json/operator_spaceship.md b/docs/mkdocs/docs/api/basic_json/operator_spaceship.md new file mode 100644 index 000000000..f5bf1cf35 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_spaceship.md @@ -0,0 +1,100 @@ +# nlohmann::basic_json::operator<=> + +```cpp +// since C++20 +class basic_json { + std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1) + + template + std::partial_ordering operator<=>(const ScalarType rhs) const noexcept; // (2) +}; +``` + +1. 3-way compares two JSON values producing a result of type `std::partial_ordering` according to the following rules: + - Two JSON values compare with a result of `std::partial_ordering::unordered` if either value is discarded. + - If both JSON values are of the same type, the result is produced by 3-way comparing their stored values using their + respective `operator<=>`. + - Integer and floating-point numbers are converted to their common type and then 3-way compared using their respective + `operator<=>`. + For instance, comparing an integer and a floating-point value will 3-way compare the first value convertered to + floating-point with the second value. + - Otherwise, yields a result by comparing the type (see [`value_t`](value_t.md)). + +2. 3-way compares a JSON value and a scalar or a scalar and a JSON value by converting the scalar to a JSON value and 3-way + comparing both JSON values (see 1). + +## Template parameters + +`ScalarType` +: a scalar type according to `std::is_scalar::value` + +## Parameters + +`rhs` (in) +: second value to consider + +## Return value + +the `std::partial_ordering` of the 3-way comparison of `*this` and `rhs` + +## Exception safety + +No-throw guarantee: this function never throws exceptions. + +## Complexity + +Linear. + +## Notes + +!!! note "Comparing `NaN`" + + - `NaN` values are unordered within the domain of numbers. + The following comparisons all yield `std::partial_ordering::unordered`: + 1. Comparing a `NaN` with itself. + 2. Comparing a `NaN` with another `NaN`. + 3. Comparing a `NaN` and any other number. + +## Examples + +??? example "Example: (1) comparing JSON values" + + The example demonstrates comparing several JSON values. + + ```cpp + --8<-- "examples/operator_spaceship__const_reference.c++20.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_spaceship__const_reference.c++20.output" + ``` + +??? example "Example: (2) comparing JSON values and scalars" + + The example demonstrates comparing several JSON values and scalars. + + ```cpp + --8<-- "examples/operator_spaceship__scalartype.c++20.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_spaceship__scalartype.c++20.output" + ``` + +## See also + +- [**operator==**](operator_eq.md) - comparison: equal +- [**operator!=**](operator_ne.md) - comparison: not equal +- [**operator<**](operator_lt.md) - comparison: less than +- [**operator<=**](operator_le.md) - comparison: less than or equal +- [**operator>**](operator_gt.md) - comparison: greater than +- [**operator>=**](operator_ge.md) - comparison: greater than or equal + +## Version history + +1. Added in version 3.11.0. +2. Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_value_t.md b/docs/mkdocs/docs/api/basic_json/operator_value_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_value_t.md rename to docs/mkdocs/docs/api/basic_json/operator_value_t.md diff --git a/doc/mkdocs/docs/api/basic_json/other_error.md b/docs/mkdocs/docs/api/basic_json/other_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/other_error.md rename to docs/mkdocs/docs/api/basic_json/other_error.md diff --git a/doc/mkdocs/docs/api/basic_json/out_of_range.md b/docs/mkdocs/docs/api/basic_json/out_of_range.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/out_of_range.md rename to docs/mkdocs/docs/api/basic_json/out_of_range.md diff --git a/doc/mkdocs/docs/api/basic_json/parse.md b/docs/mkdocs/docs/api/basic_json/parse.md similarity index 89% rename from doc/mkdocs/docs/api/basic_json/parse.md rename to docs/mkdocs/docs/api/basic_json/parse.md index 95d876b0a..49838ad1d 100644 --- a/doc/mkdocs/docs/api/basic_json/parse.md +++ b/docs/mkdocs/docs/api/basic_json/parse.md @@ -28,9 +28,10 @@ static basic_json parse(IteratorType first, IteratorType last, : A compatible input, for instance: - an `std::istream` object - - a `FILE` pointer + - a `FILE` pointer (must not be null) - a C-style array of characters - a pointer to a null-terminated string of single byte characters + - a `std::string` - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. `IteratorType` @@ -70,6 +71,13 @@ Deserialized JSON value; in case of a parse error and `allow_exceptions` set to Strong guarantee: if an exception is thrown, there are no changes in the JSON value. +## Exceptions + +- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token. +- Throws [`parse_error.102`](../../home/exceptions.md#jsonexceptionparse_error102) if to_unicode fails or surrogate + error. +- Throws [`parse_error.103`](../../home/exceptions.md#jsonexceptionparse_error103) if to_unicode fails. + ## Complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser @@ -80,6 +88,11 @@ super-linear complexity. (1) A UTF-8 byte order mark is silently ignored. +!!! danger "Runtime assertion" + + The precondition that a passed `#!cpp FILE` pointer must not be null is enforced with a + [runtime assertion](../../features/assertions.md). + ## Examples ??? example "Parsing from a character array" @@ -183,7 +196,7 @@ super-linear complexity. ## See also - [accept](accept.md) - check if the input is valid JSON -- [operator>>](operator_gtgt.md) - deserialize from stream +- [operator>>](../operator_gtgt.md) - deserialize from stream ## Version history diff --git a/doc/mkdocs/docs/api/basic_json/parse_error.md b/docs/mkdocs/docs/api/basic_json/parse_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parse_error.md rename to docs/mkdocs/docs/api/basic_json/parse_error.md diff --git a/doc/mkdocs/docs/api/basic_json/parse_event_t.md b/docs/mkdocs/docs/api/basic_json/parse_event_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parse_event_t.md rename to docs/mkdocs/docs/api/basic_json/parse_event_t.md diff --git a/doc/mkdocs/docs/api/basic_json/parser_callback_t.md b/docs/mkdocs/docs/api/basic_json/parser_callback_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/parser_callback_t.md rename to docs/mkdocs/docs/api/basic_json/parser_callback_t.md diff --git a/doc/mkdocs/docs/api/basic_json/patch.md b/docs/mkdocs/docs/api/basic_json/patch.md similarity index 96% rename from doc/mkdocs/docs/api/basic_json/patch.md rename to docs/mkdocs/docs/api/basic_json/patch.md index b3ef963f0..deec47434 100644 --- a/doc/mkdocs/docs/api/basic_json/patch.md +++ b/docs/mkdocs/docs/api/basic_json/patch.md @@ -65,6 +65,7 @@ is thrown. In any case, the original value is not changed: the patch is applied - [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) +- [patch_inplace](patch_inplace.md) applies a JSON Patch without creating a copy of the document - [merge_patch](merge_patch.md) applies a JSON Merge Patch ## Version history diff --git a/docs/mkdocs/docs/api/basic_json/patch_inplace.md b/docs/mkdocs/docs/api/basic_json/patch_inplace.md new file mode 100644 index 000000000..e8fd176c3 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/patch_inplace.md @@ -0,0 +1,70 @@ +# nlohmann::basic_json::patch_inplace + +```cpp +void patch_inplace(const basic_json& json_patch) const; +``` + +[JSON Patch](http://jsonpatch.com) defines a JSON document structure for expressing a sequence of operations to apply to +a JSON document. With this function, a JSON Patch is applied to the current JSON value by executing all operations from +the patch. This function applies a JSON patch in place and returns void. + +## Parameters + +`json_patch` (in) +: JSON patch document + +## Exception safety + +No guarantees, value may be corrupted by an unsuccessful patch operation. + +## Exceptions + +- Throws [`parse_error.104`](../../home/exceptions.md#jsonexceptionparse_error104) if the JSON patch does not consist of + an array of objects. +- Throws [`parse_error.105`](../../home/exceptions.md#jsonexceptionparse_error105) if the JSON patch is malformed (e.g., + mandatory attributes are missing); example: `"operation add must have member path"`. +- Throws [`out_of_range.401`](../../home/exceptions.md#jsonexceptionout_of_range401) if an array index is out of range. +- Throws [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a JSON pointer inside the patch + could not be resolved successfully in the current JSON value; example: `"key baz not found"`. +- Throws [`out_of_range.405`](../../home/exceptions.md#jsonexceptionout_of_range405) if JSON pointer has no parent + ("add", "remove", "move") +- Throws [`out_of_range.501`](../../home/exceptions.md#jsonexceptionother_error501) if "test" operation was + unsuccessful. + +## Complexity + +Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is +affected by the patch, 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. However, the JSON value might be corrupted if the +function throws an exception. + +## Examples + +??? example + + The following code shows how a JSON patch is applied to a value. + + ```cpp + --8<-- "examples/patch_inplace.cpp" + ``` + + Output: + + ```json + --8<-- "examples/patch_inplace.output" + ``` + +## See also + +- [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) +- [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) +- [patch](patch.md) applies a JSON Merge Patch +- [merge_patch](merge_patch.md) applies a JSON Merge Patch + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/push_back.md b/docs/mkdocs/docs/api/basic_json/push_back.md similarity index 84% rename from doc/mkdocs/docs/api/basic_json/push_back.md rename to docs/mkdocs/docs/api/basic_json/push_back.md index 60bfed305..5c7d20dd6 100644 --- a/doc/mkdocs/docs/api/basic_json/push_back.md +++ b/docs/mkdocs/docs/api/basic_json/push_back.md @@ -37,12 +37,9 @@ void push_back(initializer_list_t init); ## Exceptions -1. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON array or null; example: `"cannot use push_back() with number"` -2. The function can throw the following exceptions: - - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than - JSON object or null; example: `"cannot use push_back() with number"` +All functions can throw the following exception: + - Throws [`type_error.308`](../../home/exceptions.md#jsonexceptiontype_error308) when called on a type other than + JSON array or null; example: `"cannot use push_back() with number"` ## Complexity diff --git a/doc/mkdocs/docs/api/basic_json/rbegin.md b/docs/mkdocs/docs/api/basic_json/rbegin.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/rbegin.md rename to docs/mkdocs/docs/api/basic_json/rbegin.md diff --git a/doc/mkdocs/docs/api/basic_json/rend.md b/docs/mkdocs/docs/api/basic_json/rend.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/rend.md rename to docs/mkdocs/docs/api/basic_json/rend.md diff --git a/doc/mkdocs/docs/api/basic_json/sax_parse.md b/docs/mkdocs/docs/api/basic_json/sax_parse.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/sax_parse.md rename to docs/mkdocs/docs/api/basic_json/sax_parse.md diff --git a/doc/mkdocs/docs/api/basic_json/size.md b/docs/mkdocs/docs/api/basic_json/size.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/size.md rename to docs/mkdocs/docs/api/basic_json/size.md diff --git a/doc/mkdocs/docs/api/basic_json/std_hash.md b/docs/mkdocs/docs/api/basic_json/std_hash.md similarity index 94% rename from doc/mkdocs/docs/api/basic_json/std_hash.md rename to docs/mkdocs/docs/api/basic_json/std_hash.md index b66515d5a..b9de74f8c 100644 --- a/doc/mkdocs/docs/api/basic_json/std_hash.md +++ b/docs/mkdocs/docs/api/basic_json/std_hash.md @@ -26,6 +26,8 @@ type of the JSON value is taken into account to have different hash values for ` --8<-- "examples/std_hash.output" ``` + Note the output is platform-dependent. + ## Version history - Added in version 1.0.0. diff --git a/doc/mkdocs/docs/api/basic_json/std_swap.md b/docs/mkdocs/docs/api/basic_json/std_swap.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/std_swap.md rename to docs/mkdocs/docs/api/basic_json/std_swap.md diff --git a/doc/mkdocs/docs/api/basic_json/string_t.md b/docs/mkdocs/docs/api/basic_json/string_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/string_t.md rename to docs/mkdocs/docs/api/basic_json/string_t.md diff --git a/doc/mkdocs/docs/api/basic_json/swap.md b/docs/mkdocs/docs/api/basic_json/swap.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/swap.md rename to docs/mkdocs/docs/api/basic_json/swap.md diff --git a/docs/mkdocs/docs/api/basic_json/to_bjdata.md b/docs/mkdocs/docs/api/basic_json/to_bjdata.md new file mode 100644 index 000000000..1ea850523 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/to_bjdata.md @@ -0,0 +1,70 @@ +# nlohmann::basic_json::to_bjdata + +```cpp +// (1) +static std::vector to_bjdata(const basic_json& j, + const bool use_size = false, + const bool use_type = false); + +// (2) +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +static void to_bjdata(const basic_json& j, detail::output_adapter o, + const bool use_size = false, const bool use_type = false); +``` + +Serializes a given JSON value `j` to a byte vector using the BJData (Binary JData) serialization format. BJData +aims to be more compact than JSON itself, yet more efficient to parse. + +1. Returns a byte vector containing the BJData serialization. +2. Writes the BJData serialization to an output adapter. + +The exact mapping and its limitations is described on a [dedicated page](../../features/binary_formats/bjdata.md). + +## Parameters + +`j` (in) +: JSON value to serialize + +`o` (in) +: output adapter to write serialization to + +`use_size` (in) +: whether to add size annotations to container types; optional, `#!cpp false` by default. + +`use_type` (in) +: whether to add type annotations to container types (must be combined with `#!cpp use_size = true`); optional, +`#!cpp false` by default. + +## Return value + +1. BJData serialization as byte vector +2. (none) + +## Exception safety + +Strong guarantee: if an exception is thrown, there are no changes in the JSON value. + +## Complexity + +Linear in the size of the JSON value `j`. + +## Examples + +??? example + + The example shows the serialization of a JSON value to a byte vector in BJData format. + + ```cpp + --8<-- "examples/to_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/to_bjdata.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/basic_json/to_bson.md b/docs/mkdocs/docs/api/basic_json/to_bson.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_bson.md rename to docs/mkdocs/docs/api/basic_json/to_bson.md index 664dd0e20..5c4324a3f 100644 --- a/doc/mkdocs/docs/api/basic_json/to_bson.md +++ b/docs/mkdocs/docs/api/basic_json/to_bson.md @@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. BSON serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_cbor.md b/docs/mkdocs/docs/api/basic_json/to_cbor.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_cbor.md rename to docs/mkdocs/docs/api/basic_json/to_cbor.md index 05d85ed85..0f944c481 100644 --- a/doc/mkdocs/docs/api/basic_json/to_cbor.md +++ b/docs/mkdocs/docs/api/basic_json/to_cbor.md @@ -29,7 +29,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. CBOR serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_msgpack.md b/docs/mkdocs/docs/api/basic_json/to_msgpack.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_msgpack.md rename to docs/mkdocs/docs/api/basic_json/to_msgpack.md index fb4b40bd0..7d40981d5 100644 --- a/doc/mkdocs/docs/api/basic_json/to_msgpack.md +++ b/docs/mkdocs/docs/api/basic_json/to_msgpack.md @@ -28,7 +28,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. MessagePack serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/to_string.md b/docs/mkdocs/docs/api/basic_json/to_string.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/to_string.md rename to docs/mkdocs/docs/api/basic_json/to_string.md diff --git a/doc/mkdocs/docs/api/basic_json/to_ubjson.md b/docs/mkdocs/docs/api/basic_json/to_ubjson.md similarity index 99% rename from doc/mkdocs/docs/api/basic_json/to_ubjson.md rename to docs/mkdocs/docs/api/basic_json/to_ubjson.md index 0a3d87e54..e3cd5d62b 100644 --- a/doc/mkdocs/docs/api/basic_json/to_ubjson.md +++ b/docs/mkdocs/docs/api/basic_json/to_ubjson.md @@ -39,7 +39,7 @@ The exact mapping and its limitations is described on a [dedicated page](../../f ## Return value 1. UBJSON serialization as byte vector -2. / +2. (none) ## Exception safety diff --git a/doc/mkdocs/docs/api/basic_json/type.md b/docs/mkdocs/docs/api/basic_json/type.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type.md rename to docs/mkdocs/docs/api/basic_json/type.md diff --git a/doc/mkdocs/docs/api/basic_json/type_error.md b/docs/mkdocs/docs/api/basic_json/type_error.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type_error.md rename to docs/mkdocs/docs/api/basic_json/type_error.md diff --git a/doc/mkdocs/docs/api/basic_json/type_name.md b/docs/mkdocs/docs/api/basic_json/type_name.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/type_name.md rename to docs/mkdocs/docs/api/basic_json/type_name.md diff --git a/doc/mkdocs/docs/api/basic_json/unflatten.md b/docs/mkdocs/docs/api/basic_json/unflatten.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/unflatten.md rename to docs/mkdocs/docs/api/basic_json/unflatten.md diff --git a/doc/mkdocs/docs/api/basic_json/update.md b/docs/mkdocs/docs/api/basic_json/update.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/update.md rename to docs/mkdocs/docs/api/basic_json/update.md diff --git a/doc/mkdocs/docs/api/basic_json/value.md b/docs/mkdocs/docs/api/basic_json/value.md similarity index 63% rename from doc/mkdocs/docs/api/basic_json/value.md rename to docs/mkdocs/docs/api/basic_json/value.md index 0b4f1cc19..b5fd14d1c 100644 --- a/doc/mkdocs/docs/api/basic_json/value.md +++ b/docs/mkdocs/docs/api/basic_json/value.md @@ -4,9 +4,14 @@ // (1) template ValueType value(const typename object_t::key_type& key, - const ValueType& default_value) const; + ValueType&& default_value) const; // (2) +template +ValueType value(KeyType&& key, + ValueType&& default_value) const; + +// (3) template ValueType value(const json_pointer& ptr, const ValueType& default_value) const; @@ -24,7 +29,10 @@ ValueType value(const json_pointer& ptr, } ``` -2. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no value +2. See 1. This overload is only available if `KeyType` is comparable with `#!cpp typename object_t::key_type` and + `#!cpp typename object_comparator_t::is_transparent` denotes a type. + +3. Returns either a copy of an object's element at the specified JSON pointer `ptr` or a given default value if no value at `ptr` exists. The function is basically equivalent to executing @@ -36,7 +44,7 @@ ValueType value(const json_pointer& ptr, } ``` -!!! note +!!! note "Differences to `at` and `operator[]`" - Unlike [`at`](at.md), this function does not throw if the given `key`/`ptr` was not found. - Unlike [`operator[]`](operator[].md), this function does not implicitly add an element to the position defined by @@ -44,6 +52,10 @@ ValueType value(const json_pointer& ptr, ## Template parameters +`KeyType` +: A type for an object key other than [`json_pointer`](../json_pointer/index.md) that is comparable with + [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). + This can also be a string view (C++17). `ValueType` : type compatible to JSON values, for instance `#!cpp int` for JSON integer numbers, `#!cpp bool` for JSON booleans, or `#!cpp std::vector` types for JSON arrays. Note the type of the expected value at `key`/`ptr` and the default @@ -55,7 +67,7 @@ ValueType value(const json_pointer& ptr, : key of the element to access `default_value` (in) -: the value to return if key/ptr found no value +: the value to return if `key`/`ptr` found no value `ptr` (in) : a JSON pointer to the element to access @@ -63,7 +75,8 @@ ValueType value(const json_pointer& ptr, ## Return value 1. copy of the element at key `key` or `default_value` if `key` is not found -1. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found +2. copy of the element at key `key` or `default_value` if `key` is not found +3. copy of the element at JSON Pointer `ptr` or `default_value` if no value for `ptr` is found ## Exception safety @@ -77,7 +90,8 @@ changes to any JSON value. the type of the value at `key` - Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object; in that case, using `value()` with a key makes no sense. -2. The function can throw the following exceptions: +2. See 1. +3. The function can throw the following exceptions: - Throws [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) if `default_value` does not match the type of the value at `ptr` - Throws [`type_error.306`](../../home/exceptions.md#jsonexceptiontype_error306) if the JSON value is not an object; @@ -87,35 +101,50 @@ changes to any JSON value. 1. Logarithmic in the size of the container. 2. Logarithmic in the size of the container. +3. Logarithmic in the size of the container. ## Examples -??? example "Example (1): access specified object element with default value" +??? example "Example: (1) access specified object element with default value" The example below shows how object elements can be queried with a default value. ```cpp - --8<-- "examples/basic_json__value.cpp" + --8<-- "examples/value__object_t_key_type.cpp" ``` Output: ```json - --8<-- "examples/basic_json__value.output" + --8<-- "examples/value__object_t_key_type.output" ``` -??? example "Example (2): access specified object element via JSON Pointer with default value" +??? example "Example: (2) access specified object element using string_view with default value" The example below shows how object elements can be queried with a default value. ```cpp - --8<-- "examples/basic_json__value_ptr.cpp" + --8<-- "examples/value__keytype.c++17.cpp" ``` Output: ```json - --8<-- "examples/basic_json__value_ptr.output" + --8<-- "examples/value__keytype.c++17.output" + ``` + +??? example "Example: (3) access specified object element via JSON Pointer with default value" + + The example below shows how object elements can be queried with a default value. + + ```cpp + --8<-- "examples/value__json_ptr.cpp" + ``` + + Output: + + ```json + --8<-- "examples/value__json_ptr.output" ``` ## See also @@ -125,5 +154,6 @@ changes to any JSON value. ## Version history -1. Added in version 1.0.0. -2. Added in version 2.0.2. +1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0. +2. Added in version 3.11.0. +3. Added in version 2.0.2. diff --git a/docs/mkdocs/docs/api/basic_json/value_t.md b/docs/mkdocs/docs/api/basic_json/value_t.md new file mode 100644 index 000000000..f83574083 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/value_t.md @@ -0,0 +1,83 @@ +# nlohmann::basic_json::value_t + +```cpp +enum class value_t : std::uint8_t { + null, + object, + array, + string, + boolean, + number_integer, + number_unsigned, + number_float, + binary, + discarded +}; +``` + +This enumeration collects the different JSON types. It is internally used to distinguish the stored values, and the +functions [`is_null`](is_null.md), [`is_object`](is_object.md), [`is_array`](is_array.md), [`is_string`](is_string.md), +[`is_boolean`](is_boolean.md), [`is_number`](is_number.md) (with [`is_number_integer`](is_number_integer.md), +[`is_number_unsigned`](is_number_unsigned.md), and [`is_number_float`](is_number_float.md)), +[`is_discarded`](is_discarded.md), [`is_binary`](is_binary.md), [`is_primitive`](is_primitive.md), and +[`is_structured`](is_structured.md) rely on it. + +## Notes + +!!! note "Ordering" + + The order of types is as follows: + + 1. `null` + 2. `boolean` + 3. `number_integer`, `number_unsigned`, `number_float` + 4. `object` + 5. `array` + 6. `string` + 7. `binary` + + `discarded` is unordered. + +!!! note "Types of numbers" + + There are three enumerators for numbers (`number_integer`, `number_unsigned`, and `number_float`) to distinguish + between different types of numbers: + + - [`number_unsigned_t`](number_unsigned_t.md) for unsigned integers + - [`number_integer_t`](number_integer_t.md) for signed integers + - [`number_float_t`](number_float_t.md) for floating-point numbers or to approximate integers which do not fit + into the limits of their respective type + +!!! warning "Comparison operators" + + `operator<` and `operator<=>` (since C++20) are overloaded and compare according to the ordering described above. + Until C++20 all other relational and equality operators yield results according to the integer value of each + enumerator. + Since C++20 some compilers consider the _rewritten candidates_ generated from `operator<=>` during overload + resolution, while others do not. + For predictable and portable behavior use: + + - `operator<` or `operator<=>` when wanting to compare according to the order described above + - `operator==` or `operator!=` when wanting to compare according to each enumerators integer value + +## Examples + +??? example + + The following code how `type()` queries the `value_t` for all JSON types. + + ```cpp + --8<-- "examples/type.cpp" + ``` + + Output: + + ```json + --8<-- "examples/type.output" + ``` + +## Version history + +- Added in version 1.0.0. +- Added unsigned integer type in version 2.0.0. +- Added binary type in version 3.8.0. diff --git a/doc/mkdocs/docs/api/basic_json/~basic_json.md b/docs/mkdocs/docs/api/basic_json/~basic_json.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/~basic_json.md rename to docs/mkdocs/docs/api/basic_json/~basic_json.md diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md similarity index 67% rename from doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md index caa273df5..9913a9b5c 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/byte_container_with_subtype.md @@ -25,6 +25,22 @@ byte_container_with_subtype(container_type&& container, subtype_type subtype); `subtype` (in) : subtype +## Examples + +??? example + + The example below demonstrates how byte containers can be created. + + ```cpp + --8<-- "examples/byte_container_with_subtype__byte_container_with_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__byte_container_with_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md similarity index 59% rename from doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md index 56f8ee0c1..c62dead36 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/clear_subtype.md @@ -15,6 +15,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how `clear_subtype` can remove subtypes. + + ```cpp + --8<-- "examples/byte_container_with_subtype__clear_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__clear_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md similarity index 53% rename from doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md index 2fe418132..e06286e29 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/has_subtype.md @@ -18,6 +18,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how `has_subtype` can check whether a subtype was set. + + ```cpp + --8<-- "examples/byte_container_with_subtype__has_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__has_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/index.md b/docs/mkdocs/docs/api/byte_container_with_subtype/index.md similarity index 100% rename from doc/mkdocs/docs/api/byte_container_with_subtype/index.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/index.md diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md similarity index 60% rename from doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md index 40cc2722f..cf21732b8 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/set_subtype.md @@ -20,6 +20,22 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how a subtype can be set with `set_subtype`. + + ```cpp + --8<-- "examples/byte_container_with_subtype__set_subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__set_subtype.output" + ``` + ## Version history Since version 3.8.0. diff --git a/doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md b/docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md similarity index 63% rename from doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md index e78654b37..389241a79 100644 --- a/doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md +++ b/docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md @@ -19,6 +19,23 @@ No-throw guarantee: this function never throws exceptions. Constant. +## Examples + +??? example + + The example below demonstrates how the subtype can be retrieved with `subtype`. Note how `subtype_type(-1)` is + returned for container `c1`. + + ```cpp + --8<-- "examples/byte_container_with_subtype__subtype.cpp" + ``` + + Output: + + ```json + --8<-- "examples/byte_container_with_subtype__subtype.output" + ``` + ## Version history - Added in version 3.8.0 diff --git a/doc/mkdocs/docs/api/json.md b/docs/mkdocs/docs/api/json.md similarity index 51% rename from doc/mkdocs/docs/api/json.md rename to docs/mkdocs/docs/api/json.md index 48d344183..36edcc2c1 100644 --- a/doc/mkdocs/docs/api/json.md +++ b/docs/mkdocs/docs/api/json.md @@ -7,6 +7,22 @@ using json = basic_json<>; This type is the default specialization of the [basic_json](basic_json/index.md) class which uses the standard template types. +## Examples + +??? example + + The example below demonstrates how to use the type `nlohmann::json`. + + ```cpp + --8<-- "examples/README.cpp" + ``` + + Output: + + ```json + --8<-- "examples/README.output" + ``` + ## Version history Since version 1.0.0. diff --git a/doc/mkdocs/docs/api/json_pointer/back.md b/docs/mkdocs/docs/api/json_pointer/back.md similarity index 82% rename from doc/mkdocs/docs/api/json_pointer/back.md rename to docs/mkdocs/docs/api/json_pointer/back.md index 2b267bc58..240bc6e1e 100644 --- a/doc/mkdocs/docs/api/json_pointer/back.md +++ b/docs/mkdocs/docs/api/json_pointer/back.md @@ -1,7 +1,7 @@ # nlohmann::json_pointer::back ```cpp -const std::string& back() const; +const string_t& back() const; ``` Return last reference token. @@ -36,4 +36,5 @@ Constant. ## Version history -Added in version 3.6.0. +- Added in version 3.6.0. +- Changed return type to `string_t` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/empty.md b/docs/mkdocs/docs/api/json_pointer/empty.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/empty.md rename to docs/mkdocs/docs/api/json_pointer/empty.md diff --git a/doc/mkdocs/docs/api/json_pointer/index.md b/docs/mkdocs/docs/api/json_pointer/index.md similarity index 55% rename from doc/mkdocs/docs/api/json_pointer/index.md rename to docs/mkdocs/docs/api/json_pointer/index.md index 6ef9435fb..75b536c1c 100644 --- a/doc/mkdocs/docs/api/json_pointer/index.md +++ b/docs/mkdocs/docs/api/json_pointer/index.md @@ -1,7 +1,7 @@ # nlohmann::json_pointer ```cpp -template +template class json_pointer; ``` @@ -11,14 +11,24 @@ are the base for JSON patches. ## Template parameters -`BasicJsonType` -: a specialization of [`basic_json`](../basic_json/index.md) +`RefStringType` +: the string type used for the reference tokens making up the JSON pointer + +!!! warning "Deprecation" + + For backwards compatibility `RefStringType` may also be a specialization of [`basic_json`](../basic_json/index.md) + in which case `string_t` will be deduced as [`basic_json::string_t`](../basic_json/string_t.md). This feature is + deprecated and may be removed in a future major version. + +## Member types + +- [**string_t**](string_t.md) - the string type used for the reference tokens ## Member functions - [(constructor)](json_pointer.md) - [**to_string**](to_string.md) - return a string representation of the JSON pointer -- [**operator std::string**](operator_string.md) - return a string representation of the JSON pointer +- [**operator string_t**](operator_string_t.md) - return a string representation of the JSON pointer - [**operator/=**](operator_slasheq.md) - append to the end of the JSON pointer - [**operator/**](operator_slash.md) - create JSON Pointer by appending - [**parent_pointer**](parent_pointer.md) - returns the parent of this JSON pointer @@ -27,10 +37,14 @@ are the base for JSON patches. - [**push_back**](push_back.md) - append an unescaped token at the end of the pointer - [**empty**](empty.md) - return whether pointer points to the root document +## Literals + +- [**operator""_json_pointer**](../operator_literal_json_pointer.md) - user-defined string literal for JSON pointers ## See also - [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901) ## Version history -Added in version 2.0.0. +- Added in version 2.0.0. +- Changed template parameter from `basic_json` to string type in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/json_pointer.md b/docs/mkdocs/docs/api/json_pointer/json_pointer.md similarity index 89% rename from doc/mkdocs/docs/api/json_pointer/json_pointer.md rename to docs/mkdocs/docs/api/json_pointer/json_pointer.md index 1e68a28f3..5e7057fc9 100644 --- a/doc/mkdocs/docs/api/json_pointer/json_pointer.md +++ b/docs/mkdocs/docs/api/json_pointer/json_pointer.md @@ -1,7 +1,7 @@ # nlohmann::json_pointer::json_pointer ```cpp -explicit json_pointer(const std::string& s = ""); +explicit json_pointer(const string_t& s = ""); ``` Create a JSON pointer according to the syntax described in @@ -37,4 +37,5 @@ Create a JSON pointer according to the syntax described in ## Version history -Added in version 2.0.0. +- Added in version 2.0.0. +- Changed type of `s` to `string_t` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slash.md b/docs/mkdocs/docs/api/json_pointer/operator_slash.md similarity index 90% rename from doc/mkdocs/docs/api/json_pointer/operator_slash.md rename to docs/mkdocs/docs/api/json_pointer/operator_slash.md index c92875435..ed77b504b 100644 --- a/doc/mkdocs/docs/api/json_pointer/operator_slash.md +++ b/docs/mkdocs/docs/api/json_pointer/operator_slash.md @@ -5,7 +5,7 @@ json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs); // (2) -json_pointer operator/(const json_pointer& lhs, std::string token); +json_pointer operator/(const json_pointer& lhs, string_t token); // (3) json_pointer operator/(const json_pointer& lhs, std::size_t array_idx); @@ -60,5 +60,5 @@ json_pointer operator/(const json_pointer& lhs, std::size_t array_idx); ## Version history 1. Added in version 3.6.0. -2. Added in version 3.6.0. +2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0. 3. Added in version 3.6.0. diff --git a/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md b/docs/mkdocs/docs/api/json_pointer/operator_slasheq.md similarity index 89% rename from doc/mkdocs/docs/api/json_pointer/operator_slasheq.md rename to docs/mkdocs/docs/api/json_pointer/operator_slasheq.md index eb6c30861..3518557d5 100644 --- a/doc/mkdocs/docs/api/json_pointer/operator_slasheq.md +++ b/docs/mkdocs/docs/api/json_pointer/operator_slasheq.md @@ -5,7 +5,7 @@ json_pointer& operator/=(const json_pointer& ptr); // (2) -json_pointer& operator/=(std::string token); +json_pointer& operator/=(string_t token); // (3) json_pointer& operator/=(std::size_t array_idx) @@ -57,5 +57,5 @@ json_pointer& operator/=(std::size_t array_idx) ## Version history 1. Added in version 3.6.0. -2. Added in version 3.6.0. +2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0. 3. Added in version 3.6.0. diff --git a/docs/mkdocs/docs/api/json_pointer/operator_string_t.md b/docs/mkdocs/docs/api/json_pointer/operator_string_t.md new file mode 100644 index 000000000..74105a4f1 --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/operator_string_t.md @@ -0,0 +1,48 @@ +# nlohmann::json_pointer::operator string_t + +```cpp +operator string_t() const +``` + +Return a string representation of the JSON pointer. + +## Return value + +A string representation of the JSON pointer + +## Possible implementation + +```cpp +operator string_t() const +{ + return to_string(); +} +``` + +## Notes + +!!! warning "Deprecation" + + This function is deprecated in favor of [`to_string`](to_string.md) and will be removed in a future major version + release. + +## Examples + +??? example + + The example shows how JSON Pointers can be implicitly converted to strings. + + ```cpp + --8<-- "examples/json_pointer__operator_string_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__operator_string_t.output" + ``` + +## Version history + +- Since version 2.0.0. +- Changed type to `string_t` and deprecated in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/parent_pointer.md b/docs/mkdocs/docs/api/json_pointer/parent_pointer.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/parent_pointer.md rename to docs/mkdocs/docs/api/json_pointer/parent_pointer.md diff --git a/doc/mkdocs/docs/api/json_pointer/pop_back.md b/docs/mkdocs/docs/api/json_pointer/pop_back.md similarity index 100% rename from doc/mkdocs/docs/api/json_pointer/pop_back.md rename to docs/mkdocs/docs/api/json_pointer/pop_back.md diff --git a/doc/mkdocs/docs/api/json_pointer/push_back.md b/docs/mkdocs/docs/api/json_pointer/push_back.md similarity index 76% rename from doc/mkdocs/docs/api/json_pointer/push_back.md rename to docs/mkdocs/docs/api/json_pointer/push_back.md index 3ebcdbc5c..c1c19cb8d 100644 --- a/doc/mkdocs/docs/api/json_pointer/push_back.md +++ b/docs/mkdocs/docs/api/json_pointer/push_back.md @@ -1,9 +1,9 @@ # nlohmann::json_pointer::push_back ```cpp -void push_back(const std::string& token); +void push_back(const string_t& token); -void push_back(std::string&& token); +void push_back(string_t&& token); ``` Append an unescaped token at the end of the reference pointer. @@ -35,4 +35,5 @@ Amortized constant. ## Version history -Added in version 3.6.0. +- Added in version 3.6.0. +- Changed type of `token` to `string_t` in version 3.11.0. diff --git a/docs/mkdocs/docs/api/json_pointer/string_t.md b/docs/mkdocs/docs/api/json_pointer/string_t.md new file mode 100644 index 000000000..c8527bc9c --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/string_t.md @@ -0,0 +1,28 @@ +# nlohmann::json_pointer::string_t +```cpp +using string_t = RefStringType; +``` + +The string type used for the reference tokens making up the JSON pointer. + +See [`basic_json::string_t`](../basic_json/string_t.md) for more information. + +## Examples + +??? example + + The example shows the type `string_t` and its relation to `basic_json::string_t`. + + ```cpp + --8<-- "examples/json_pointer__string_t.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_pointer__string_t.output" + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_pointer/to_string.md b/docs/mkdocs/docs/api/json_pointer/to_string.md similarity index 83% rename from doc/mkdocs/docs/api/json_pointer/to_string.md rename to docs/mkdocs/docs/api/json_pointer/to_string.md index 9287436e3..fae3abe5f 100644 --- a/doc/mkdocs/docs/api/json_pointer/to_string.md +++ b/docs/mkdocs/docs/api/json_pointer/to_string.md @@ -1,7 +1,7 @@ # nlohmann::json_pointer::to_string ```cpp -std::string to_string() const; +string_t to_string() const; ``` Return a string representation of the JSON pointer. @@ -36,4 +36,5 @@ ptr == json_pointer(ptr.to_string()); ## Version history -Since version 2.0.0. +- Since version 2.0.0. +- Changed return type to `string_t` in version 3.11.0. diff --git a/doc/mkdocs/docs/api/json_sax/binary.md b/docs/mkdocs/docs/api/json_sax/binary.md similarity index 56% rename from doc/mkdocs/docs/api/json_sax/binary.md rename to docs/mkdocs/docs/api/json_sax/binary.md index e9a1d3974..753e99c00 100644 --- a/doc/mkdocs/docs/api/json_sax/binary.md +++ b/docs/mkdocs/docs/api/json_sax/binary.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed binary value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse__binary.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse__binary.output" + ``` + ## Version history - Added in version 3.8.0. diff --git a/doc/mkdocs/docs/api/json_sax/boolean.md b/docs/mkdocs/docs/api/json_sax/boolean.md similarity index 53% rename from doc/mkdocs/docs/api/json_sax/boolean.md rename to docs/mkdocs/docs/api/json_sax/boolean.md index a5a8ddcb7..78163b331 100644 --- a/doc/mkdocs/docs/api/json_sax/boolean.md +++ b/docs/mkdocs/docs/api/json_sax/boolean.md @@ -15,6 +15,22 @@ A boolean value was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/end_array.md b/docs/mkdocs/docs/api/json_sax/end_array.md new file mode 100644 index 000000000..46b4c7a4b --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/end_array.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::end_array + +```cpp +virtual bool end_array() = 0; +``` + +The end of an array was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/end_object.md b/docs/mkdocs/docs/api/json_sax/end_object.md new file mode 100644 index 000000000..8df0ab4e1 --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/end_object.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::end_object + +```cpp +virtual bool end_object() = 0; +``` + +The end of an object was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/index.md b/docs/mkdocs/docs/api/json_sax/index.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/index.md rename to docs/mkdocs/docs/api/json_sax/index.md diff --git a/doc/mkdocs/docs/api/json_sax/key.md b/docs/mkdocs/docs/api/json_sax/key.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/key.md rename to docs/mkdocs/docs/api/json_sax/key.md index 5e7927256..ebd3ae2b2 100644 --- a/doc/mkdocs/docs/api/json_sax/key.md +++ b/docs/mkdocs/docs/api/json_sax/key.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed object key value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/json_sax/null.md b/docs/mkdocs/docs/api/json_sax/null.md new file mode 100644 index 000000000..71b2a458a --- /dev/null +++ b/docs/mkdocs/docs/api/json_sax/null.md @@ -0,0 +1,31 @@ +# nlohmann::json_sax::null + +```cpp +virtual bool null() = 0; +``` + +A null value was read. + +## Return value + +Whether parsing should proceed. + +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + +## Version history + +- Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_float.md b/docs/mkdocs/docs/api/json_sax/number_float.md similarity index 62% rename from doc/mkdocs/docs/api/json_sax/number_float.md rename to docs/mkdocs/docs/api/json_sax/number_float.md index 94193280b..e1b3fb60f 100644 --- a/doc/mkdocs/docs/api/json_sax/number_float.md +++ b/docs/mkdocs/docs/api/json_sax/number_float.md @@ -18,6 +18,22 @@ A floating-point number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_integer.md b/docs/mkdocs/docs/api/json_sax/number_integer.md similarity index 56% rename from doc/mkdocs/docs/api/json_sax/number_integer.md rename to docs/mkdocs/docs/api/json_sax/number_integer.md index 00ff2eaa6..8628a655c 100644 --- a/doc/mkdocs/docs/api/json_sax/number_integer.md +++ b/docs/mkdocs/docs/api/json_sax/number_integer.md @@ -15,6 +15,22 @@ An integer number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/number_unsigned.md b/docs/mkdocs/docs/api/json_sax/number_unsigned.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/number_unsigned.md rename to docs/mkdocs/docs/api/json_sax/number_unsigned.md index 66d0bdac4..7b5974823 100644 --- a/doc/mkdocs/docs/api/json_sax/number_unsigned.md +++ b/docs/mkdocs/docs/api/json_sax/number_unsigned.md @@ -15,6 +15,22 @@ An unsigned integer number was read. Whether parsing should proceed. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/parse_error.md b/docs/mkdocs/docs/api/json_sax/parse_error.md similarity index 71% rename from doc/mkdocs/docs/api/json_sax/parse_error.md rename to docs/mkdocs/docs/api/json_sax/parse_error.md index 00f1aa950..d4405d09e 100644 --- a/doc/mkdocs/docs/api/json_sax/parse_error.md +++ b/docs/mkdocs/docs/api/json_sax/parse_error.md @@ -23,6 +23,22 @@ A parse error occurred. Whether parsing should proceed (**must return `#!cpp false`**). +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/start_array.md b/docs/mkdocs/docs/api/json_sax/start_array.md similarity index 63% rename from doc/mkdocs/docs/api/json_sax/start_array.md rename to docs/mkdocs/docs/api/json_sax/start_array.md index d10a6e5a6..8ef10a4ab 100644 --- a/doc/mkdocs/docs/api/json_sax/start_array.md +++ b/docs/mkdocs/docs/api/json_sax/start_array.md @@ -19,6 +19,22 @@ Whether parsing should proceed. Binary formats may report the number of elements. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/start_object.md b/docs/mkdocs/docs/api/json_sax/start_object.md similarity index 63% rename from doc/mkdocs/docs/api/json_sax/start_object.md rename to docs/mkdocs/docs/api/json_sax/start_object.md index fd90f1947..24fedffc3 100644 --- a/doc/mkdocs/docs/api/json_sax/start_object.md +++ b/docs/mkdocs/docs/api/json_sax/start_object.md @@ -19,6 +19,22 @@ Whether parsing should proceed. Binary formats may report the number of elements. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/doc/mkdocs/docs/api/json_sax/string.md b/docs/mkdocs/docs/api/json_sax/string.md similarity index 58% rename from doc/mkdocs/docs/api/json_sax/string.md rename to docs/mkdocs/docs/api/json_sax/string.md index 113fe1393..1cb6014ac 100644 --- a/doc/mkdocs/docs/api/json_sax/string.md +++ b/docs/mkdocs/docs/api/json_sax/string.md @@ -19,6 +19,22 @@ Whether parsing should proceed. It is safe to move the passed string value. +## Examples + +??? example + + .The example below shows how the SAX interface is used. + + ```cpp + --8<-- "examples/sax_parse.cpp" + ``` + + Output: + + ```json + --8<-- "examples/sax_parse.output" + ``` + ## Version history - Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md new file mode 100644 index 000000000..8e118b03f --- /dev/null +++ b/docs/mkdocs/docs/api/macros/index.md @@ -0,0 +1,57 @@ +# Macros + +Some aspects of the library can be configured by defining preprocessor macros **before** including the `json.hpp` +header. See also the [macro overview page](../../features/macros.md). + +## Runtime assertions + +- [**JSON_ASSERT(x)**](json_assert.md) - control behavior of runtime assertions + +## Exceptions + +- [**JSON_CATCH_USER(exception)**
**JSON_THROW_USER(exception)**
**JSON_TRY_USER**](json_throw_user.md) - control exceptions +- [**JSON_DIAGNOSTICS**](json_diagnostics.md) - control extended diagnostics +- [**JSON_NOEXCEPTION**](json_noexception.md) - switch off exceptions + +## Language support + +- [**JSON_HAS_CPP_11**
**JSON_HAS_CPP_14**
**JSON_HAS_CPP_17**
**JSON_HAS_CPP_20**](json_has_cpp_11.md) - set supported C++ standard +- [**JSON_HAS_FILESYSTEM**
**JSON_HAS_EXPERIMENTAL_FILESYSTEM**](json_has_filesystem.md) - control `std::filesystem` support +- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support +- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support +- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers +- [**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 + +## Library version + +- [**JSON_SKIP_LIBRARY_VERSION_CHECK**](json_skip_library_version_check.md) - skip library version check +- [**NLOHMANN_JSON_VERSION_MAJOR**
**NLOHMANN_JSON_VERSION_MINOR**
**NLOHMANN_JSON_VERSION_PATCH**](nlohmann_json_version_major.md) + \- library version information + +## Library namespace + +- [**NLOHMANN_JSON_NAMESPACE**](nlohmann_json_namespace.md) - full name of the `nlohmann` namespace +- [**NLOHMANN_JSON_NAMESPACE_BEGIN**
**NLOHMANN_JSON_NAMESPACE_END**](nlohmann_json_namespace_begin.md) - open and close the library namespace + +## Type conversions + +- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums +- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions + + +## Comparison behavior + +- [**JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON**](json_use_legacy_discarded_value_comparison.md) - + control comparison of discarded values + +## Serialization/deserialization macros + +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefInt] + \- serialization/deserialization of types _with_ access to private variables +- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefNonInt] + \- serialization/deserialization of types _without_ access to private variables +- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum types + +[DefInt]: nlohmann_define_type_intrusive.md +[DefNonInt]: nlohmann_define_type_non_intrusive.md diff --git a/docs/mkdocs/docs/api/macros/json_assert.md b/docs/mkdocs/docs/api/macros/json_assert.md new file mode 100644 index 000000000..a093341a1 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_assert.md @@ -0,0 +1,84 @@ +# JSON_ASSERT + +```cpp +#define JSON_ASSERT(x) /* value */ +``` + +This macro controls which code is executed for [runtime assertions](../../features/assertions.md) of the library. + +## Parameters + +`x` (in) +: expression of scalar type + +## Default definition + +The default value is [`#!cpp assert(x)`](https://en.cppreference.com/w/cpp/error/assert). + +```cpp +#define JSON_ASSERT(x) assert(x) +``` + +Therefore, assertions can be switched off by defining `NDEBUG`. + +## Notes + +- The library uses numerous assertions to guarantee invariants and to abort in case of otherwise undefined behavior + (e.g., when calling [operator[]](../basic_json/operator%5B%5D.md) with a missing object key on a `const` object). See + page [runtime assertions](../../features/assertions.md) for more information. +- Defining the macro to code that does not call `std::abort` may leave the library in an undefined state. +- The macro is undefined outside the library. + +## Examples + +??? example "Example 1: default behavior" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144. + ``` + +??? example "Example 2: user-defined behavior" + + The assertion reporting can be changed by defining `JSON_ASSERT(x)` differently. + + ```cpp + #include + #include + #define JSON_ASSERT(x) if(!(x)){fprintf(stderr, "assertion error in %s\n", __FUNCTION__); std::abort();} + + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + assertion error in operator[] + ``` + +## Version history + +- Added in version 3.9.0. diff --git a/docs/mkdocs/docs/api/macros/json_diagnostics.md b/docs/mkdocs/docs/api/macros/json_diagnostics.md new file mode 100644 index 000000000..4fc0fc38e --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_diagnostics.md @@ -0,0 +1,76 @@ +# JSON_DIAGNOSTICS + +```cpp +#define JSON_DIAGNOSTICS /* value */ +``` + +This macro enables [extended diagnostics for exception messages](../../home/exceptions.md#extended-diagnostic-messages). +Possible values are `1` to enable or `0` to disable (default). + +When enabled, exception messages contain a [JSON Pointer](../json_pointer/json_pointer.md) to the JSON value that +triggered the exception. Note that enabling this macro increases the size of every JSON value by one pointer and adds +some runtime overhead. + +## Default definition + +The default value is `0` (extended diagnostics are switched off). + +```cpp +#define JSON_DIAGNOSTICS 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! note "ABI compatibility" + + As of version 3.11.0, this macro is no longer required to be defined consistently throughout a codebase to avoid + One Definition Rule (ODR) violations, as the value of this macro is encoded in the namespace, resulting in distinct + symbol names. + + This allows different parts of a codebase to use different versions or configurations of this library without + causing improper behavior. + + Where possible, it is still recommended that all code define this the same way for maximum interoperability. + +!!! hint "CMake option" + + Diagnostic messages can also be controlled with the CMake option + [`JSON_Diagnostics`](../../integration/cmake.md#json_diagnostics) (`OFF` by default) + which defines `JSON_DIAGNOSTICS` accordingly. + +## Examples + +??? example "Example 1: default behavior" + + ```cpp + --8<-- "examples/diagnostics_standard.cpp" + ``` + + Output: + + ``` + --8<-- "examples/diagnostics_standard.output" + ``` + + This exception can be hard to debug if storing the value `#!c "12"` and accessing it is further apart. + +??? example "Example 2: extended diagnostic messages" + + ```cpp + --8<-- "examples/diagnostics_extended.cpp" + ``` + + Output: + + ``` + --8<-- "examples/diagnostics_extended.output" + ``` + + Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type. + +## Version history + +- Added in version 3.10.0. +- As of version 3.11.0 the definition is allowed to vary between translation units. diff --git a/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md new file mode 100644 index 000000000..6df3dd5cb --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_disable_enum_serialization.md @@ -0,0 +1,152 @@ +# JSON_DISABLE_ENUM_SERIALIZATION + +```cpp +#define JSON_DISABLE_ENUM_SERIALIZATION /* value */ +``` + +When defined to `1`, default serialization and deserialization functions for enums are excluded and have to be provided +by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) (see +[arbitrary type conversions](../../features/arbitrary_types.md) for more details). + +Parsing or serializing an enum will result in a compiler error. + +This works for both unscoped and scoped enums. + +## Default definition + +The default value is `0`. + +```cpp +#define JSON_DISABLE_ENUM_SERIALIZATION 0 +``` + +## Notes + +!!! hint "CMake option" + + Enum serialization can also be controlled with the CMake option + [`JSON_DisableEnumSerialization`](../../integration/cmake.md#json_disableenumserialization) + (`OFF` by default) which defines `JSON_DISABLE_ENUM_SERIALIZATION` accordingly. + +## Examples + +??? example "Example 1: Disabled behavior" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, meaning the code below + **does not** compile. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + int main() + { + // normally invokes to_json serialization function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + const json j = Choice::first; + + // normally invokes from_json parse function but with JSON_DISABLE_ENUM_SERIALIZATION defined, it does not + Choice ch = j.get(); + } + ``` + +??? example "Example 2: Serialize enum macro" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, but uses + [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(Choice, + { + { Choice::first, "first" }, + { Choice::second, "second" }, + }) + + int main() + { + // uses user-defined to_json function defined by macro + const json j = Choice::first; + + // uses user-defined from_json function defined by macro + Choice ch = j.get(); + } + ``` + +??? example "Example 3: User-defined serialization/deserialization functions" + + The code below forces the library **not** to create default serialization/deserialization functions `from_json` and `to_json`, but uses user-defined + functions to parse and serialize the enum. + + ```cpp + #define JSON_DISABLE_ENUM_SERIALIZATION 1 + #include + + using json = nlohmann::json; + + enum class Choice + { + first, + second, + }; + + void from_json(const json& j, Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + void to_json(json& j, const Choice& ch) + { + auto value = j.get(); + if (value == "first") + { + ch = Choice::first; + } + else if (value == "second") + { + ch = Choice::second; + } + } + + int main() + { + // uses user-defined to_json function + const json j = Choice::first; + + // uses user-defined from_json function + Choice ch = j.get(); + } + ``` + +## See also + +- [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_has_cpp_11.md b/docs/mkdocs/docs/api/macros/json_has_cpp_11.md new file mode 100644 index 000000000..f3eaa585c --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_cpp_11.md @@ -0,0 +1,41 @@ +# JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20 + +```cpp +#define JSON_HAS_CPP_11 +#define JSON_HAS_CPP_14 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_20 +``` + +The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view` +support for C++17). For these new features, the library implements some preprocessor checks to determine the C++ +standard. By defining any of these symbols, the internal check is overridden and the provided C++ version is +unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be +detected incorrectly. + +## Default definition + +The default value is detected based on preprocessor macros such as `#!cpp __cplusplus`, `#!cpp _HAS_CXX17`, or +`#!cpp _MSVC_LANG`. + +## Notes + +- `#!cpp JSON_HAS_CPP_11` is always defined. +- All macros are undefined outside the library. + +## Examples + +??? example + + The code below forces the library to use the C++14 standard: + + ```cpp + #define JSON_HAS_CPP_14 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.5. diff --git a/docs/mkdocs/docs/api/macros/json_has_filesystem.md b/docs/mkdocs/docs/api/macros/json_has_filesystem.md new file mode 100644 index 000000000..308aea2ac --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_filesystem.md @@ -0,0 +1,43 @@ +# JSON_HAS_FILESYSTEM / JSON_HAS_EXPERIMENTAL_FILESYSTEM + +```cpp +#define JSON_HAS_FILESYSTEM /* value */ +#define JSON_HAS_EXPERIMENTAL_FILESYSTEM /* value */ +``` + +When compiling with C++17, the library provides conversions from and to +[`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path). As compiler support for filesystem is +limited, the library tries to detect whether +[``/`std::filesystem`](https://en.cppreference.com/w/cpp/header/filesystem) (`JSON_HAS_FILESYSTEM`) or +[``/`std::experimental::filesystem`](https://en.cppreference.com/w/cpp/header/experimental/filesystem) +(`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used. To override the built-in check, define `JSON_HAS_FILESYSTEM` or +`JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`. + +## Default definition + +The default value is detected based on the preprocessor macros `#!cpp __cpp_lib_filesystem`, +`#!cpp __cpp_lib_experimental_filesystem`, `#!cpp __has_include()`, or +`#!cpp __has_include()`. + +## Notes + +- Note that older compilers or older versions of libstd++ also require the library `stdc++fs` to be linked to for + filesystem support. +- Both macros are undefined outside the library. + +## Examples + +??? example + + The code below forces the library to use the header ``. + + ```cpp + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.5. diff --git a/docs/mkdocs/docs/api/macros/json_has_ranges.md b/docs/mkdocs/docs/api/macros/json_has_ranges.md new file mode 100644 index 000000000..96d51052d --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_ranges.md @@ -0,0 +1,31 @@ +# JSON_HAS_RANGES + +```cpp +#define JSON_HAS_RANGES /* value */ +``` + +This macro indicates whether the standard library has any support for ranges. Implies support for concepts. +Possible values are `1` when supported or `0` when unsupported. + +## Default definition + +The default value is detected based on the preprocessor macro `#!cpp __cpp_lib_ranges`. + +When the macro is not defined, the library will define it to its default value. + +## Examples + +??? example + + The code below forces the library to enable support for ranges: + + ```cpp + #define JSON_HAS_RANGES 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md b/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md new file mode 100644 index 000000000..f52070ebf --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_three_way_comparison.md @@ -0,0 +1,32 @@ +# JSON_HAS_THREE_WAY_COMPARISON + +```cpp +#define JSON_HAS_THREE_WAY_COMPARISON /* value */ +``` + +This macro indicates whether the compiler and standard library support 3-way comparison. +Possible values are `1` when supported or `0` when unsupported. + +## Default definition + +The default value is detected based on the preprocessor macros `#!cpp __cpp_impl_three_way_comparison` +and `#!cpp __cpp_lib_three_way_comparison`. + +When the macro is not defined, the library will define it to its default value. + +## Examples + +??? example + + The code below forces the library to use 3-way comparison: + + ```cpp + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_no_io.md b/docs/mkdocs/docs/api/macros/json_no_io.md new file mode 100644 index 000000000..ef37384a5 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_no_io.md @@ -0,0 +1,35 @@ +# JSON_NO_IO + +```cpp +#define JSON_NO_IO +``` + +When defined, headers ``, ``, ``, ``, and `` are not included and parse functions +relying on these headers are excluded. This is relevant for environments where these I/O functions are disallowed for +security reasons (e.g., Intel Software Guard Extensions (SGX)). + +## Default definition + +By default, `#!cpp JSON_NO_IO` is not defined. + +```cpp +#undef JSON_NO_IO +``` + +## Examples + +??? example + + The code below forces the library not to use the headers ``, ``, ``, ``, and + ``. + + ```cpp + #define JSON_NO_IO 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.10.0. diff --git a/docs/mkdocs/docs/api/macros/json_noexception.md b/docs/mkdocs/docs/api/macros/json_noexception.md new file mode 100644 index 000000000..c801b8567 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_noexception.md @@ -0,0 +1,45 @@ +# JSON_NOEXCEPTION + +```cpp +#define JSON_NOEXCEPTION +``` + +Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try` +is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by +`#!cpp std::abort()`. + +The same effect is achieved by setting the compiler flag `-fno-exceptions`. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_NOEXCEPTION +``` + +## Notes + +The explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not +available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). + +## Examples + +??? example + + The code below switches off exceptions in the library. + + ```cpp + #define JSON_NOEXCEPTION 1 + #include + + ... + ``` + +## See also + +- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions + +## Version history + +Added in version 2.1.0. diff --git a/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md b/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md new file mode 100644 index 000000000..c9a743c18 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_skip_library_version_check.md @@ -0,0 +1,37 @@ +# JSON_SKIP_LIBRARY_VERSION_CHECK + +```cpp +#define JSON_SKIP_LIBRARY_VERSION_CHECK +``` + +When defined, the library will not create a compiler warning when a different version of the library was already +included. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_SKIP_LIBRARY_VERSION_CHECK +``` + +## Notes + +!!! danger "ABI compatibility" + + Mixing different library versions in the same code can be a problem as the different versions may not be ABI + compatible. + +## Examples + +!!! example + + The following warning will be shown in case a different version of the library was already included: + + ``` + Already included a different version of the library! + ``` + +## Version history + +Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md b/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md new file mode 100644 index 000000000..374fa4c27 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md @@ -0,0 +1,33 @@ +# JSON_SKIP_UNSUPPORTED_COMPILER_CHECK + +```cpp +#define JSON_SKIP_UNSUPPORTED_COMPILER_CHECK +``` + +When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to +use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used. + +## Default definition + +By default, the macro is not defined. + +```cpp +#undef JSON_SKIP_UNSUPPORTED_COMPILER_CHECK +``` + +## Examples + +??? example + + The code below switches off the check whether the compiler is supported. + + ```cpp + #define JSON_SKIP_UNSUPPORTED_COMPILER_CHECK 1 + #include + + ... + ``` + +## Version history + +Added in version 3.2.0. diff --git a/docs/mkdocs/docs/api/macros/json_throw_user.md b/docs/mkdocs/docs/api/macros/json_throw_user.md new file mode 100644 index 000000000..e10db90e4 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_throw_user.md @@ -0,0 +1,75 @@ +# JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER + +```cpp +// (1) +#define JSON_CATCH_USER(exception) /* value */ +// (2) +#define JSON_THROW_USER(exception) /* value */ +// (3) +#define JSON_TRY_USER /* value */ +``` + +Controls how exceptions are handled by the library. + +1. This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library. + The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range` + exceptions internally to rethrow them as [`json::out_of_range`](../../home/exceptions.md#out-of-range) exceptions. + The macro is always followed by a scope. +2. This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that + `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield + undefined behavior. +3. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope. + +## Parameters + +`exception` (in) +: an exception type + +## Default definition + +By default, the macros map to their respective C++ keywords: + +```cpp +#define JSON_CATCH_USER(exception) catch(exception) +#define JSON_THROW_USER(exception) throw exception +#define JSON_TRY_USER try +``` + +When exceptions are switched off, the `#!cpp try` block is executed unconditionally, and throwing exceptions is +replaced by calling [`std::abort`](https://en.cppreference.com/w/cpp/utility/program/abort) to make reaching the +`#!cpp throw` branch abort the process. + +```cpp +#define JSON_THROW_USER(exception) std::abort() +#define JSON_TRY_USER if (true) +#define JSON_CATCH_USER(exception) if (false) +``` + +## Examples + +??? example + + The code below switches off exceptions and creates a log entry with a detailed error message in case of errors. + + ```cpp + #include + + #define JSON_TRY_USER if(true) + #define JSON_CATCH_USER(exception) if(false) + #define JSON_THROW_USER(exception) \ + {std::clog << "Error in " << __FILE__ << ":" << __LINE__ \ + << " (function " << __FUNCTION__ << ") - " \ + << (exception).what() << std::endl; \ + std::abort();} + + #include + ``` + +## See also + +- [Switch off exceptions](../../home/exceptions.md#switch-off-exceptions) for more information how to switch off exceptions +- [JSON_NOEXCEPTION](JSON_NOEXCEPTION) - switch off exceptions + +## Version history + +- Added in version 3.1.0. diff --git a/docs/mkdocs/docs/api/macros/json_use_global_udls.md b/docs/mkdocs/docs/api/macros/json_use_global_udls.md new file mode 100644 index 000000000..dc9b55f62 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_global_udls.md @@ -0,0 +1,99 @@ +# JSON_USE_GLOBAL_UDLS + +```cpp +#define JSON_USE_GLOBAL_UDLS /* value */ +``` + +When defined to `1`, the user-defined string literals (UDLs) are placed into the global namespace instead of +`nlohmann::literals::json_literals`. + +## Default definition + +The default value is `1`. + +```cpp +#define JSON_USE_GLOBAL_UDLS 1 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! info "Future behavior change" + + The user-defined string literals will be removed from the global namespace in the next major release of the + library. + + To prepare existing code, define `JSON_USE_GLOBAL_UDLS` to `0` and bring the string literals into scope where + needed. Refer to any of the [string literals](#see-also) for details. + +!!! hint "CMake option" + + The placement of user-defined string literals can also be controlled with the CMake option + [`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`OFF` by default) + which defines `JSON_USE_GLOBAL_UDLS` accordingly. + +## Examples + +??? example "Example 1: Default behavior" + + The code below shows the default behavior using the `_json` UDL. + + ```cpp + #include + + #include + + int main() + { + auto j = "42"_json; + + std::cout << j << std::endl; + } + ``` + + Output: + + ```json + 42 + ``` + +??? example "Example 2: Namespaced UDLs" + + The code below shows how UDLs need to be brought into scope before using `_json` when `JSON_USE_GLOBAL_UDLS` is + defined to `0`. + + ```cpp + #define JSON_USE_GLOBAL_UDLS 0 + #include + + #include + + int main() + { + // auto j = "42"_json; // This line would fail to compile, + // because the UDLs are not in the global namespace + + // Bring the UDLs into scope + using namespace nlohmann::json_literals; + + auto j = "42"_json; + + std::cout << j << std::endl; + } + ``` + + Output: + + ```json + 42 + ``` + +## See also + +- [`operator""_json`](../operator_literal_json.md) +- [`operator""_json_pointer`](../operator_literal_json_pointer.md) + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md new file mode 100644 index 000000000..adadffab6 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md @@ -0,0 +1,59 @@ +# JSON_USE_IMPLICIT_CONVERSIONS + +```cpp +#define JSON_USE_IMPLICIT_CONVERSIONS /* value */ +``` + +When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. The +value directly affects [`operator ValueType`](../basic_json/operator_ValueType.md). + +## Default definition + +By default, implicit conversions are enabled. + +```cpp +#define JSON_USE_IMPLICIT_CONVERSIONS 1 +``` + +## Notes + +!!! info "Future behavior change" + + Implicit conversions will be switched off by default in the next major release of the library. + + You can prepare existing code by already defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` and replace any implicit + conversions with calls to [`get`](../basic_json/get.md). + +!!! hint "CMake option" + + Implicit conversions can also be controlled with the CMake option + [`JSON_ImplicitConversions`](../../integration/cmake.md#json_legacydiscardedvaluecomparison) + (`ON` by default) which defines `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. + +## Examples + +??? example + + This is an example for an implicit conversion: + + ```cpp + json j = "Hello, world!"; + std::string s = j; + ``` + + When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be + written like this: + + ```cpp + json j = "Hello, world!"; + auto s = j.get(); + ``` + +## See also + +- [**operator ValueType**](../basic_json/operator_ValueType.md) - get a value (implicit) +- [**get**](../basic_json/get.md) - get a value (explicit) + +## Version history + +- Added in version 3.9.0. diff --git a/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md b/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md new file mode 100644 index 000000000..bdb0a4607 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md @@ -0,0 +1,80 @@ +# JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + +```cpp +#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON /* value */ +``` + +This macro enables the (incorrect) legacy comparison behavior of discarded JSON values. +Possible values are `1` to enable or `0` to disable (default). + +When enabled, comparisons involving at least one discarded JSON value yield results as follows: + +| **Operator** | **Result** | +|--------------|---------------| +| `==` | `#!cpp false` | +| `!=` | `#!cpp true` | +| `<` | `#!cpp false` | +| `<=` | `#!cpp true` | +| `>=` | `#!cpp true` | +| `>` | `#!cpp false` | + +Otherwise, comparisons involving at least one discarded JSON value always yield `#!cpp false`. + +## Default definition + +The default value is `0`. + +```cpp +#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! warning "Inconsistent behavior in C++20 and beyond" + + When targeting C++20 or above, enabling the legacy comparison behavior is _strongly_ + discouraged. + + - The 3-way comparison operator (`<=>`) will always give the correct result + (`#!cpp std::partial_ordering::unordered`) regardless of the value of + `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`. + - Overloads for the equality and relational operators emulate the legacy behavior. + + Code outside your control may use either 3-way comparison or the equality and + relational operators, resulting in inconsistent and unpredictable behavior. + + See [`operator<=>`](../basic_json/operator_spaceship.md) for more information on 3-way + comparison. + +!!! warning "Deprecation" + + The legacy comparison behavior is deprecated and may be removed in a future major + version release. + + New code should not depend on it and existing code should try to remove or rewrite + expressions relying on it. + +!!! hint "CMake option" + + Legacy comparison can also be controlled with the CMake option + [`JSON_LegacyDiscardedValueComparison`](../../integration/cmake.md#json_legacydiscardedvaluecomparison) + (`OFF` by default) which defines `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON` accordingly. + +## Examples + +??? example + + The code below switches on the legacy discarded value comparison behavior in the library. + + ```cpp + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 1 + #include + + ... + ``` + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md new file mode 100644 index 000000000..9a14ad723 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md @@ -0,0 +1,126 @@ +# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT + +```cpp +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1) +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2) +``` + +These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as +serialization and want to use the member variable names as object keys in that object. The macro is to be defined +**inside** the class/struct to create code for. +Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md), it can access private members. +The first parameter is the name of the class/struct, and all remaining parameters name the members. + +1. Will use [`at`](../basic_json/at.md) during deserialization and will throw + [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object. +2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the + respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function + default constructs an object and uses its values as the defaults when calling the `value` function. + +## Parameters + +`type` (in) +: name of the type (class, struct) to serialize/deserialize + +`member` (in) +: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list + +## Default definition + +The macros add two friend functions to the class which take care of the serialization and deserialization: + +```cpp +friend void to_json(nlohmann::json&, const type&); +friend void from_json(const nlohmann::json&, type&); +``` + +See examples below for the concrete generated code. + +## Notes + +!!! info "Prerequisites" + + 1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?][GetNonDefNonCopy] + for how to overcome this limitation. + 2. The macro must be used inside the type (class/struct). + +[GetNonDefNonCopy]: ../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types + +!!! warning "Implementation limits" + + - The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types + with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as + [`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported. + +## Examples + +??? example "Example (1): NLOHMANN_DEFINE_TYPE_INTRUSIVE" + + Consider the following complete example: + + ```cpp hl_lines="21" + --8<-- "examples/nlohmann_define_type_intrusive_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_intrusive_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE` applicable, but not + `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. + - The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is used _inside_ the class. + - A missing key "age" in the deserialization yields an exception. To fall back to the default value, + `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` can be used. + + The macro is equivalent to: + + ```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33" + --8<-- "examples/nlohmann_define_type_intrusive_explicit.cpp" + ``` + +??? example "Example (2): NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT" + + Consider the following complete example: + + ```cpp hl_lines="21" + --8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` applicable, + but not `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`. + - The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` is used _inside_ the class. + - A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used. + + The macro is equivalent to: + + ```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34" + --8<-- "examples/nlohmann_define_type_intrusive_with_default_explicit.cpp" + ``` + + Note how a default-initialized `person` object is used in the `from_json` to fill missing values. + +## See also + +- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md) + for a similar macro that can be defined _outside_ the type. +- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview. + +## Version history + +1. Added in version 3.9.0. +2. Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md new file mode 100644 index 000000000..28b358952 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md @@ -0,0 +1,126 @@ +# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT + +```cpp +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...) // (1) +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...) // (2) +``` + +These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as +serialization and want to use the member variable names as object keys in that object. The macro is to be defined +**outside** the class/struct to create code for, but **inside** its namespace. +Unlike [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), it **cannot** access private members. +The first parameter is the name of the class/struct, and all remaining parameters name the members. + +1. Will use [`at`](../basic_json/at.md) during deserialization and will throw + [`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object. +2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the + respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function + default constructs an object and uses its values as the defaults when calling the `value` function. + +## Parameters + +`type` (in) +: name of the type (class, struct) to serialize/deserialize + +`member` (in) +: name of the (public) member variable to serialize/deserialize; up to 64 members can be given as comma-separated list + +## Default definition + +The macros add two functions to the namespace which take care of the serialization and deserialization: + +```cpp +void to_json(nlohmann::json&, const type&); +void from_json(const nlohmann::json&, type&); +``` + +See examples below for the concrete generated code. + +## Notes + +!!! info "Prerequisites" + + 1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?][GetNonDefNonCopy] + for how to overcome this limitation. + 2. The macro must be used outside the type (class/struct). + 3. The passed members must be public. + +[GetNonDefNonCopy]: ../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types + +!!! warning "Implementation limits" + + - The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types + with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as + [`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported. + +## Examples + +??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE" + + Consider the following complete example: + + ```cpp hl_lines="15" + --8<-- "examples/nlohmann_define_type_non_intrusive_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_non_intrusive_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` applicable. + - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` is used _outside_ the class, but _inside_ its namespace `ns`. + - A missing key "age" in the deserialization yields an exception. To fall back to the default value, + `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` can be used. + + The macro is equivalent to: + + ```cpp hl_lines="15 16 17 18 19 20 21 22 23 24 25 26 27" + --8<-- "examples/nlohmann_define_type_non_intrusive_explicit.cpp" + ``` + +??? example "Example (2): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT" + + Consider the following complete example: + + ```cpp hl_lines="20" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.output" + ``` + + Notes: + + - `ns::person` is default-constructible. This is a requirement for using the macro. + - `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` + applicable. + - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` is used _outside_ the class, but _inside_ its namespace `ns`. + - A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used. + + The macro is equivalent to: + + ```cpp hl_lines="20 21 22 23 24 25 26 27 28 29 30 31 32 33" + --8<-- "examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp" + ``` + + Note how a default-initialized `person` object is used in the `from_json` to fill missing values. + +## See also + +- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md) + for a similar macro that can be defined _inside_ the type. +- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview. + +## Version history + +1. Added in version 3.9.0. +2. Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md new file mode 100644 index 000000000..d76bffb81 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace.md @@ -0,0 +1,26 @@ +# NLOHMANN_JSON_NAMESPACE + +```cpp +#define NLOHMANN_JSON_NAMESPACE +``` + +This macro evaluates to the full name of the `nlohmann` namespace, including +the name of a versioned and ABI-tagged inline namespace. Use this macro to +unambiguously refer to the `nlohmann` namespace. + +## Default definition + +The default value consists of a prefix, a version string, and optional ABI tags +depending on whether ABI-affecting macros are defined (e.g., +[`JSON_DIAGNOSTICS`](json_diagnostics.md), and +[`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](json_use_legacy_discarded_value_comparison.md)). + +When the macro is not defined, the library will define it to its default value. + +## See also + +- [`NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END`](nlohmann_json_namespace_begin.md) + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md new file mode 100644 index 000000000..83844b502 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_namespace_begin.md @@ -0,0 +1,40 @@ +# NLOHMANN_JSON_NAMESPACE_BEGIN, NLOHMANN_JSON_NAMESPACE_END + +```cpp +#define NLOHMANN_JSON_NAMESPACE_BEGIN // (1) +#define NLOHMANN_JSON_NAMESPACE_END // (2) +``` + +These macros can be used to open and close the `nlohmann` namespace. They +include an inline namespace used to differentiate symbols when linking multiple +versions (including different ABI-affecting macros) of this library. + +1. Opens the namespace. + ```cpp + namespace nlohmann + { + inline namespace json_v3_11_0 + { + ``` + +2. Closes the namespace. + ```cpp + } // namespace nlohmann + } // json_v3_11_0 + ``` + +## Default definition + +The default definitions open and close the `nlohmann` as well as an inline +namespace. + +When these macros are not defined, the library will define them to their +default definitions. + +## See also + +- [NLOHMANN_JSON_NAMESPACE](nlohmann_json_namespace.md) + +## Version history + +- Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md new file mode 100644 index 000000000..b7204a808 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -0,0 +1,85 @@ +# NLOHMANN_JSON_SERIALIZE_ENUM + +```cpp +#define NLOHMANN_JSON_SERIALIZE_ENUM(type, conversion...) +``` + +By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an +enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be +undefined or a different enum value than was originally intended. + +The `NLOHMANN_JSON_SERIALIZE_ENUM` allows to define a user-defined serialization for every enumerator. + +## Parameters + +`type` (in) +: name of the enum to serialize/deserialize + +`conversion` (in) +: a pair of an enumerator and a JSON serialization; arbitrary pairs can can be given as comma-separated list + +## Default definition + +The macros add two friend functions to the class which take care of the serialization and deserialization: + +```cpp +template +inline void to_json(BasicJsonType& j, const type& e); +template +inline void from_json(const BasicJsonType& j, type& e); +``` + +## Notes + +!!! info "Prerequisites" + + The macro must be used inside the namespace of the enum. + +!!! important "Important notes" + + - When using [`get()`](../basic_json/get.md), undefined JSON values will default to the first specified + conversion. Select this default pair carefully. See example 1 below. + - If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the + list will be returned when converting to or from JSON. See example 2 below. + +## Examples + +??? example "Example 1: Basic usage" + + The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM` can be used to serialize/deserialize both classical enums and + C++11 enum classes: + + ```cpp hl_lines="16 17 18 19 20 21 22 29 30 31 32 33" + --8<-- "examples/nlohmann_json_serialize_enum.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum.output" + ``` + +??? example "Example 2: Multiple conversions for one enumerator" + + The example shows how to use multiple conversions for a single enumerator. In the example, `Color::red` will always + be *serialized* to `"red"`, because the first occurring conversion. The second conversion, however, offers an + alternative *deserialization* from `"rot"` to `Color::red`. + + ```cpp hl_lines="17" + --8<-- "examples/nlohmann_json_serialize_enum_2.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_serialize_enum_2.output" + ``` + +## See also + +- [Specializing enum conversion](../../features/enum_conversion.md) +- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md) + +## Version history + +Added in version 3.4.0. diff --git a/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md b/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md new file mode 100644 index 000000000..d7a314276 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md @@ -0,0 +1,40 @@ +# NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH + +```cpp +#define NLOHMANN_JSON_VERSION_MAJOR /* value */ +#define NLOHMANN_JSON_VERSION_MINOR /* value */ +#define NLOHMANN_JSON_VERSION_PATCH /* value */ +``` + +These macros are defined by the library and contain the version numbers according to +[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). + +## Default definition + +The macros are defined according to the current library version. + +## Examples + +??? example + + The example below shows how `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and + `NLOHMANN_JSON_VERSION_PATCH` are defined by the library. + + ```cpp + --8<-- "examples/nlohmann_json_version.cpp" + ``` + + Output: + + ```json + --8<-- "examples/nlohmann_json_version.output" + ``` + +## See also + +- [meta](../basic_json/meta.md) - returns version information on the library +- [JSON_SKIP_LIBRARY_VERSION_CHECK](json_skip_library_version_check.md) - skip library version check + +## Version history + +- Added in version 3.1.0. diff --git a/doc/mkdocs/docs/api/basic_json/operator_gtgt.md b/docs/mkdocs/docs/api/operator_gtgt.md similarity index 65% rename from doc/mkdocs/docs/api/basic_json/operator_gtgt.md rename to docs/mkdocs/docs/api/operator_gtgt.md index 97c2f0b4e..98d575add 100644 --- a/doc/mkdocs/docs/api/basic_json/operator_gtgt.md +++ b/docs/mkdocs/docs/api/operator_gtgt.md @@ -1,4 +1,4 @@ -# operator>>(basic_json) +# nlohmann::operator>>(basic_json) ```cpp std::istream& operator>>(std::istream& i, basic_json& j); @@ -20,10 +20,10 @@ the stream `i` ## Exceptions -- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token. -- Throws [`parse_error.102`](../../home/exceptions.md#jsonexceptionparse_error102) if to_unicode fails or surrogate +- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token. +- Throws [`parse_error.102`](../home/exceptions.md#jsonexceptionparse_error102) if to_unicode fails or surrogate error. -- Throws [`parse_error.103`](../../home/exceptions.md#jsonexceptionparse_error103) if to_unicode fails. +- Throws [`parse_error.103`](../home/exceptions.md#jsonexceptionparse_error103) if to_unicode fails. ## Complexity @@ -33,6 +33,12 @@ Linear in the length of the input. The parser is a predictive LL(1) parser. A UTF-8 byte order mark is silently ignored. +!!! warning "Deprecation" + + This function replaces function `#!cpp std::istream& operator<<(basic_json& j, std::istream& i)` which has + been deprecated in version 3.0.0. It will be removed in version 4.0.0. Please replace calls like `#!cpp j << i;` + with `#!cpp i >> j;`. + ## Examples ??? example @@ -51,15 +57,9 @@ A UTF-8 byte order mark is silently ignored. ## See also -- [accept](accept.md) - check if the input is valid JSON -- [parse](parse.md) - deserialize from a compatible input +- [accept](basic_json/accept.md) - check if the input is valid JSON +- [parse](basic_json/parse.md) - deserialize from a compatible input ## Version history -- Added in version 1.0.0 - -!!! warning "Deprecation" - - This function replaces function `#!cpp std::istream& operator<<(basic_json& j, std::istream& i)` which has - been deprecated in version 3.0.0. It will be removed in version 4.0.0. Please replace calls like `#!cpp j << i;` - with `#!cpp i >> j;`. +- Added in version 1.0.0. Deprecated in version 3.0.0. diff --git a/docs/mkdocs/docs/api/operator_literal_json.md b/docs/mkdocs/docs/api/operator_literal_json.md new file mode 100644 index 000000000..330729de0 --- /dev/null +++ b/docs/mkdocs/docs/api/operator_literal_json.md @@ -0,0 +1,59 @@ +# nlohmann::operator""_json + +```cpp +json operator "" _json(const char* s, std::size_t n); +``` + +This operator implements a user-defined string literal for JSON objects. It can be used by adding `#!cpp _json` to a +string literal and returns a [`json`](json.md) object if no parse error occurred. + +Use any of the following lines to bring the operator into scope: +```cpp +using namespace nlohmann::literals; +using namespace nlohmann::json_literals; +using namespace nlohmann::literals::json_literals; +using namespace nlohmann; +``` + +Alternatively, define [`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md) to make them available in the global +namespace. +## Parameters + +`s` (in) +: a string representation of a JSON object + +`n` (in) +: length of string `s` + +## Return value + +[`json`](json.md) value parsed from `s` + +## Exceptions + +The function can throw anything that [`parse(s, s+n)`](basic_json/parse.md) would throw. + +## Complexity + +Linear. + +## Examples + +??? example + + The following code shows how to create JSON values from string literals. + + ```cpp + --8<-- "examples/operator_literal_json.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_literal_json.output" + ``` + +## Version history + +- Added in version 1.0.0. +- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0. diff --git a/docs/mkdocs/docs/api/operator_literal_json_pointer.md b/docs/mkdocs/docs/api/operator_literal_json_pointer.md new file mode 100644 index 000000000..7c788db2c --- /dev/null +++ b/docs/mkdocs/docs/api/operator_literal_json_pointer.md @@ -0,0 +1,63 @@ +# nlohmann::operator""_json_pointer + +```cpp +json_pointer operator "" _json_pointer(const char* s, std::size_t n); +``` + +This operator implements a user-defined string literal for JSON Pointers. It can be used by adding `#!cpp _json_pointer` +to a string literal and returns a [`json_pointer`](json_pointer/index.md) object if no parse error occurred. + +Use any of the following lines to bring the operator into scope: +```cpp +using namespace nlohmann::literals; +using namespace nlohmann::json_literals; +using namespace nlohmann::literals::json_literals; +using namespace nlohmann; +``` + +Alternatively, define [`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md) to make them available in the global +namespace. +## Parameters + +`s` (in) +: a string representation of a JSON Pointer + +`n` (in) +: length of string `s` + +## Return value + +[`json_pointer`](json_pointer/index.md) value parsed from `s` + +## Exceptions + +The function can throw anything that [`json_pointer::json_pointer`](json_pointer/index.md) would throw. + +## Complexity + +Linear. + +## Examples + +??? example + + The following code shows how to create JSON Pointers from string literals. + + ```cpp + --8<-- "examples/operator_literal_json_pointer.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_literal_json_pointer.output" + ``` + +## See also + +- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers + +## Version history + +- Added in version 2.0.0. +- Moved to namespace `nlohmann::literals::json_literals` in 3.11.0. diff --git a/docs/mkdocs/docs/api/operator_ltlt.md b/docs/mkdocs/docs/api/operator_ltlt.md new file mode 100644 index 000000000..ea857718b --- /dev/null +++ b/docs/mkdocs/docs/api/operator_ltlt.md @@ -0,0 +1,86 @@ +# nlohmann::operator<<(basic_json), nlohmann::operator<<(json_pointer) + +```cpp +std::ostream& operator<<(std::ostream& o, const basic_json& j); // (1) + +std::ostream& operator<<(std::ostream& o, const json_pointer& ptr); // (2) +``` + +1. Serialize the given JSON value `j` to the output stream `o`. The JSON value will be serialized using the + [`dump`](basic_json/dump.md) member function. + - The indentation of the output can be controlled with the member variable `width` of the output stream `o`. For + instance, using the manipulator `std::setw(4)` on `o` sets the indentation level to `4` and the serialization + result is the same as calling `dump(4)`. + - The indentation character can be controlled with the member variable `fill` of the output stream `o`. + For instance, the manipulator `std::setfill('\\t')` sets indentation to use a tab character rather than the + default space character. +2. Write a string representation of the given JSON pointer `ptr` to the output stream `o`. The string representation is + obtained using the [`to_string`](json_pointer/to_string.md) member function. + +## Parameters + +`o` (in, out) +: stream to write to + +`j` (in) +: JSON value to serialize + +`ptr` (in) +: JSON pointer to write + +## Return value + +the stream `o` + +## Exceptions + +1. Throws [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) if a string stored inside the JSON + value is not UTF-8 encoded. Note that unlike the [`dump`](basic_json/dump.md) member functions, no `error_handler` can be set. +2. None. + +## Complexity + +Linear. + +## Notes + +!!! warning "Deprecation" + + Function `#!cpp std::ostream& operator<<(std::ostream& o, const basic_json& j)` replaces function + `#!cpp std::ostream& operator>>(const basic_json& j, std::ostream& o)` which has been deprecated in version 3.0.0. + It will be removed in version 4.0.0. Please replace calls like `#!cpp j >> o;` with `#!cpp o << j;`. + +## Examples + +??? example "Example: (1) serialize JSON value to stream" + + The example below shows the serialization with different parameters to `width` to adjust the indentation level. + + ```cpp + --8<-- "examples/operator_ltlt__basic_json.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_ltlt__basic_json.output" + ``` + +??? example "Example: (2) write JSON pointer to stream" + + The example below shows how to write a JSON pointer to a stream. + + ```cpp + --8<-- "examples/operator_ltlt__json_pointer.cpp" + ``` + + Output: + + ```json + --8<-- "examples/operator_ltlt__json_pointer.output" + ``` +## Version history + +1. Added in version 1.0.0. Added support for indentation character and deprecated + `#!cpp std::ostream& operator>>(const basic_json& j, std::ostream& o)` in version 3.0.0. +3. Added in version 3.11.0. diff --git a/docs/mkdocs/docs/api/ordered_json.md b/docs/mkdocs/docs/api/ordered_json.md new file mode 100644 index 000000000..7cfd9f4dd --- /dev/null +++ b/docs/mkdocs/docs/api/ordered_json.md @@ -0,0 +1,32 @@ +# nlohmann::ordered_json + +```cpp +using ordered_json = basic_json; +``` + +This type preserves the insertion order of object keys. + +## Examples + +??? example + + The example below demonstrates how `ordered_json` preserves the insertion order of object keys. + + ```cpp + --8<-- "examples/ordered_json.cpp" + ``` + + Output: + + ```json + --8<-- "examples/ordered_json.output" + ``` + +## See also + +- [ordered_map](ordered_map.md) +- [Object Order](../features/object_order.md) + +## Version history + +Since version 3.9.0. diff --git a/doc/mkdocs/docs/api/ordered_map.md b/docs/mkdocs/docs/api/ordered_map.md similarity index 89% rename from doc/mkdocs/docs/api/ordered_map.md rename to docs/mkdocs/docs/api/ordered_map.md index 74b248ff2..160b85c28 100644 --- a/doc/mkdocs/docs/api/ordered_map.md +++ b/docs/mkdocs/docs/api/ordered_map.md @@ -32,6 +32,12 @@ A minimal map-like container that preserves insertion order for use within [`nlo - **const_iterator** - **size_type** - **value_type** +- **key_compare** - key comparison function +```cpp +std::equal_to // until C++14 + +std::equal_to<> // since C++14 +``` ## Member functions @@ -68,3 +74,4 @@ A minimal map-like container that preserves insertion order for use within [`nlo ## Version history - Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md). +- Added **key_compare** member in version 3.11.0. diff --git a/docs/mkdocs/docs/css/custom.css b/docs/mkdocs/docs/css/custom.css new file mode 100644 index 000000000..7a1008b0b --- /dev/null +++ b/docs/mkdocs/docs/css/custom.css @@ -0,0 +1,4 @@ +/* disable ligatures in code and preformatted blocks */ +code, pre { + font-variant-ligatures: none; +} diff --git a/doc/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md similarity index 68% rename from doc/mkdocs/docs/features/arbitrary_types.md rename to docs/mkdocs/docs/features/arbitrary_types.md index fe80dc701..2d2e6f28b 100644 --- a/doc/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -1,4 +1,4 @@ -# Arbitrary Types Conversions +# Arbitrary Type Conversions Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines: @@ -77,7 +77,7 @@ Some important things: * Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). * Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. * When using `get()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) -* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. +* In function `from_json`, use function [`at()`](../api/basic_json/at.md) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. @@ -85,29 +85,34 @@ Some important things: If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate. -There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object: +There are four macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object: -- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. -- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. +- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object. +- [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type. +- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object. +- [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type. -In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. +In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](macros.md#nlohmann_define_type_intrusivetype-member). -!!! note +!!! info "Implementation limits" - At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. + - The current macro implementations are limited to at most 64 member variables. If you want to serialize/deserialize + types with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually. + - The macros only work for the [`nlohmann::json`](../api/json.md) type; other specializations such as + [`nlohmann::ordered_json`](../api/ordered_json.md) are currently unsupported. ??? example The `to_json`/`from_json` functions for the `person` struct above can be created with: - + ```cpp namespace ns { NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age) } ``` - + Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed: - + ```cpp namespace ns { class address { @@ -115,7 +120,7 @@ In both macros, the first parameter is the name of the class/struct, and all rem std::string street; int housenumber; int postcode; - + public: NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode) }; @@ -150,30 +155,35 @@ To solve this, you need to add a specialization of `adl_serializer` to the `nloh ```cpp // partial specialization (full specialization works too) -namespace nlohmann { - template - struct adl_serializer> { - static void to_json(json& j, const boost::optional& opt) { - if (opt == boost::none) { - j = nullptr; - } else { - j = *opt; // this will call adl_serializer::to_json which will - // find the free function to_json in T's namespace! - } +NLOHMANN_JSON_NAMESPACE_BEGIN +template +struct adl_serializer> { + static void to_json(json& j, const boost::optional& opt) { + if (opt == boost::none) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! } + } - static void from_json(const json& j, boost::optional& opt) { - if (j.is_null()) { - opt = boost::none; - } else { - opt = j.get(); // same as above, but with - // adl_serializer::from_json - } + static void from_json(const json& j, boost::optional& opt) { + if (j.is_null()) { + opt = boost::none; + } else { + opt = j.get(); // same as above, but with + // adl_serializer::from_json } - }; -} + } +}; +NLOHMANN_JSON_NAMESPACE_END ``` +!!! note "ABI compatibility" + + Use [`NLOHMANN_JSON_NAMESPACE_BEGIN`](../api/macros/nlohmann_json_namespace_begin.md) and `NLOHMANN_JSON_NAMESPACE_END` + instead of `#!cpp namespace nlohmann { }` in code which may be linked with different versions of this library. + ## How can I use `get()` for non-default constructible/non-copyable types? There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload: @@ -209,7 +219,7 @@ namespace nlohmann { ## Can I write my own serializer? (Advanced use) -Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/test/src/unit-udt.cpp) in the test suite, to see a few examples. +Yes. You might want to take a look at [`unit-udt.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-udt.cpp) in the test suite, to see a few examples. If you write your own serializer, you'll need to do a few things: diff --git a/docs/mkdocs/docs/features/assertions.md b/docs/mkdocs/docs/features/assertions.md new file mode 100644 index 000000000..2bad62e81 --- /dev/null +++ b/docs/mkdocs/docs/features/assertions.md @@ -0,0 +1,131 @@ +# Runtime Assertions + +The code contains numerous debug assertions to ensure class invariants are valid or to detect undefined behavior. +Whereas the former class invariants are nothing to be concerned of, the latter checks for undefined behavior are to +detect bugs in client code. + +## Switch off runtime assertions + +Runtime assertions can be switched off by defining the preprocessor macro `NDEBUG` (see the +[documentation of assert](https://en.cppreference.com/w/cpp/error/assert)) which is the default for release builds. + +## Change assertion behavior + +The behavior of runtime assertions can be changes by defining macro [`JSON_ASSERT(x)`](../api/macros/json_assert.md) +before including the `json.hpp` header. + +## Function with runtime assertions + +### Unchecked object access to a const value + +Function [`operator[]`](../api/basic_json/operator%5B%5D.md) implements unchecked access for objects. Whereas a missing +key is added in case of non-const objects, accessing a const object with a missing key is undefined behavior (think of a +dereferenced null pointer) and yields a runtime assertion. + +If you are not sure whether an element in an object exists, use checked access with the +[`at` function](../api/basic_json/at.md) or call the [`contains` function](../api/basic_json/contains.md) before. + +See also the documentation on [element access](element_access/index.md). + +??? example "Example 1: Missing object key" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + const json j = {{"key", "value"}}; + auto v = j["missing"]; + } + ``` + + Output: + + ``` + Assertion failed: (m_value.object->find(key) != m_value.object->end()), function operator[], file json.hpp, line 2144. + ``` + +### Constructing from an uninitialized iterator range + +Constructing a JSON value from an iterator range (see [constructor](../api/basic_json/basic_json.md)) with an +uninitialized iterator is undefined behavior and yields a runtime assertion. + +??? example "Example 2: Uninitialized iterator range" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + json::iterator it1, it2; + json j(it1, it2); + } + ``` + + Output: + + ``` + Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368. + ``` + +### Operations on uninitialized iterators + +Any operation on uninitialized iterators (i.e., iterators that are not associated with any JSON value) is undefined +behavior and yields a runtime assertion. + +??? example "Example 3: Uninitialized iterator" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + json::iterator it; + ++it; + } + ``` + + Output: + + ``` + Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368. + ``` + +### Reading from a null `FILE` pointer + +Reading from a null `#!cpp FILE` pointer is undefined behavior and yields a runtime assertion. This can happen when +calling `#!cpp std::fopen` on a nonexistent file. + +??? example "Example 4: Uninitialized iterator" + + The following code will trigger an assertion at runtime: + + ```cpp + #include + + using json = nlohmann::json; + + int main() + { + std::FILE* f = std::fopen("nonexistent_file.json", "r"); + json j = json::parse(f); + } + ``` + + Output: + + ``` + Assertion failed: (m_file != nullptr), function file_input_adapter, file input_adapters.hpp, line 55. + ``` diff --git a/docs/mkdocs/docs/features/binary_formats/bjdata.md b/docs/mkdocs/docs/features/binary_formats/bjdata.md new file mode 100644 index 000000000..74b4499e9 --- /dev/null +++ b/docs/mkdocs/docs/features/binary_formats/bjdata.md @@ -0,0 +1,212 @@ +# BJData + +The [BJData format](https://neurojson.org) was derived from and improved upon +[Universal Binary JSON(UBJSON)](https://ubjson.org) specification (Draft 12). +Specifically, it introduces an optimized array container for efficient storage +of N-dimensional packed arrays (**ND-arrays**); it also adds 4 new type markers - +`[u] - uint16`, `[m] - uint32`, `[M] - uint64` and `[h] - float16` - to +unambigiously map common binary numeric types; furthermore, it uses little-endian +(LE) to store all numerics instead of big-endian (BE) as in UBJSON to avoid +unnecessary conversions on commonly available platforms. + +Compared to other binary JSON-like formats such as MessagePack and CBOR, both BJData and +UBJSON demonstrate a rare combination of being both binary and **quasi-human-readable**. This +is because all semantic elements in BJData and UBJSON, including the data-type markers +and name/string types are directly human-readable. Data stored in the BJData/UBJSON format +are not only compact in size, fast to read/write, but also can be directly searched +or read using simple processing. + +!!! abstract "References" + + - [BJData Specification](https://neurojson.org/bjdata/draft2) + +## Serialization + +The library uses the following mapping from JSON values types to BJData types according to the BJData specification: + +| JSON value type | value/range | BJData type | marker | +|-----------------|-------------------------------------------|----------------|--------| +| null | `null` | null | `Z` | +| boolean | `true` | true | `T` | +| boolean | `false` | false | `F` | +| number_integer | -9223372036854775808..-2147483649 | int64 | `L` | +| number_integer | -2147483648..-32769 | int32 | `l` | +| number_integer | -32768..-129 | int16 | `I` | +| number_integer | -128..127 | int8 | `i` | +| number_integer | 128..255 | uint8 | `U` | +| number_integer | 256..32767 | int16 | `I` | +| number_integer | 32768..65535 | uint16 | `u` | +| number_integer | 65536..2147483647 | int32 | `l` | +| number_integer | 2147483648..4294967295 | uint32 | `m` | +| number_integer | 4294967296..9223372036854775807 | int64 | `L` | +| number_integer | 9223372036854775808..18446744073709551615 | uint64 | `M` | +| number_unsigned | 0..127 | int8 | `i` | +| number_unsigned | 128..255 | uint8 | `U` | +| number_unsigned | 256..32767 | int16 | `I` | +| number_unsigned | 32768..65535 | uint16 | `u` | +| number_unsigned | 65536..2147483647 | int32 | `l` | +| number_unsigned | 2147483648..4294967295 | uint32 | `m` | +| number_unsigned | 4294967296..9223372036854775807 | int64 | `L` | +| number_unsigned | 9223372036854775808..18446744073709551615 | uint64 | `M` | +| number_float | *any value* | float64 | `D` | +| string | *with shortest length indicator* | string | `S` | +| array | *see notes on optimized format/ND-array* | array | `[` | +| object | *see notes on optimized format* | map | `{` | + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any JSON value type can be converted to a BJData value. + + Any BJData output created by `to_bjdata` can be successfully parsed by `from_bjdata`. + +!!! warning "Size constraints" + + The following values can **not** be converted to a BJData value: + + - strings with more than 18446744073709551615 bytes, i.e., $2^{64}-1$ bytes (theoretical) + +!!! info "Unused BJData markers" + + The following markers are not used in the conversion: + + - `Z`: no-op values are not created. + - `C`: single-byte strings are serialized with `S` markers. + +!!! info "NaN/infinity handling" + + If NaN or Infinity are stored inside a JSON number, they are + serialized properly. This behavior differs from the `dump()` + function which serializes NaN or Infinity to `null`. + + +!!! info "Endianness" + + A breaking difference between BJData and UBJSON is the endianness + of numerical values. In BJData, all numerical data types (integers + `UiuImlML` and floating-point values `hdD`) are stored in the little-endian (LE) + byte order as opposed to big-endian as used by UBJSON. Adopting LE + to store numeric records avoids unnecessary byte swapping on most modern + computers where LE is used as the default byte order. + +!!! info "Optimized formats" + + Optimized formats for containers are supported via two parameters of + [`to_bjdata`](../../api/basic_json/to_bjdata.md): + + - Parameter `use_size` adds size information to the beginning of a container and + removes the closing marker. + - Parameter `use_type` further checks whether all elements of a container have the + same type and adds the type marker to the beginning of the container. + The `use_type` parameter must only be used together with `use_size = true`. + + Note that `use_size = true` alone may result in larger representations - + the benefit of this parameter is that the receiving side is + immediately informed of the number of elements in the container. + +!!! info "ND-array optimized format" + + BJData extends UBJSON's optimized array **size** marker to support ND-arrays of + uniform numerical data types (referred to as *packed arrays*). + For example, the 2-D `uint8` integer array `[[1,2],[3,4],[5,6]]`, stored + as nested optimized array in UBJSON `[ [$U#i2 1 2 [$U#i2 3 4 [$U#i2 5 6 ]`, + can be further compressed in BJData to `[$U#[$i#i2 2 3 1 2 3 4 5 6` + or `[$U#[i2 i3] 1 2 3 4 5 6`. + + To maintina type and size information, ND-arrays are converted to JSON objects following the + **annotated array format** (defined in the [JData specification (Draft 3)][JDataAAFmt]), + when parsed using [`from_bjdata`](../../api/basic_json/from_bjdata.md). + For example, the above 2-D `uint8` array can be parsed and accessed as + + ```json + { + "_ArrayType_": "uint8", + "_ArraySize_": [2,3], + "_ArrayData_": [1,2,3,4,5,6] + } + ``` + + Likewise, when a JSON object in the above form is serialzed using + [`to_bjdata`](../../api/basic_json/to_bjdata.md), it is automatically converted + into a compact BJData ND-array. The only exception is, that when the 1-dimensional + vector stored in `"_ArraySize_"` contains a single integer or two integers with one + being 1, a regular 1-D optimized array is generated. + + The current version of this library does not yet support automatic detection of and + conversion from a nested JSON array input to a BJData ND-array. + + [JDataAAFmt]: https://github.com/NeuroJSON/jdata/blob/master/JData_specification.md#annotated-storage-of-n-d-arrays) + +!!! info "Restrictions in optimized data types for arrays and objects" + + Due to diminished space saving, hampered readability, and increased + security risks, in BJData, the allowed data types following the `$` marker + in an optimized array and object container are restricted to + **non-zero-fixed-length** data types. Therefore, the valid optimized + type markers can only be one of `UiuImlMLhdDC`. This also means other + variable (`[{SH`) or zero-length types (`TFN`) can not be used in an + optimized array or object in BJData. + +!!! info "Binary values" + + If the JSON data contains the binary type, the value stored is a list + of integers, as suggested by the BJData documentation. In particular, + this means that the serialization and the deserialization of JSON + containing binary values into BJData and back will result in a + different JSON object. + + +??? example + + ```cpp + --8<-- "examples/to_bjdata.cpp" + ``` + + Output: + + ```c + --8<-- "examples/to_bjdata.output" + ``` + +## Deserialization + +The library maps BJData types to JSON value types as follows: + +| BJData type | JSON value type | marker | +|-------------|-----------------------------------------|--------| +| no-op | *no value, next value is read* | `N` | +| null | `null` | `Z` | +| false | `false` | `F` | +| true | `true` | `T` | +| float16 | number_float | `h` | +| float32 | number_float | `d` | +| float64 | number_float | `D` | +| uint8 | number_unsigned | `U` | +| int8 | number_integer | `i` | +| uint16 | number_unsigned | `u` | +| int16 | number_integer | `I` | +| uint32 | number_unsigned | `m` | +| int32 | number_integer | `l` | +| uint64 | number_unsigned | `M` | +| int64 | number_integer | `L` | +| string | string | `S` | +| char | string | `C` | +| array | array (optimized values are supported) | `[` | +| ND-array | object (in JData annotated array format)|`[$.#[.`| +| object | object (optimized values are supported) | `{` | + +!!! success "Complete mapping" + + The mapping is **complete** in the sense that any BJData value can be converted to a JSON value. + + +??? example + + ```cpp + --8<-- "examples/from_bjdata.cpp" + ``` + + Output: + + ```json + --8<-- "examples/from_bjdata.output" + ``` diff --git a/doc/mkdocs/docs/features/binary_formats/bson.md b/docs/mkdocs/docs/features/binary_formats/bson.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/bson.md rename to docs/mkdocs/docs/features/binary_formats/bson.md diff --git a/doc/mkdocs/docs/features/binary_formats/cbor.md b/docs/mkdocs/docs/features/binary_formats/cbor.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/cbor.md rename to docs/mkdocs/docs/features/binary_formats/cbor.md diff --git a/doc/mkdocs/docs/features/binary_formats/index.md b/docs/mkdocs/docs/features/binary_formats/index.md similarity index 60% rename from doc/mkdocs/docs/features/binary_formats/index.md rename to docs/mkdocs/docs/features/binary_formats/index.md index 3a969a5dc..e74290b09 100644 --- a/doc/mkdocs/docs/features/binary_formats/index.md +++ b/docs/mkdocs/docs/features/binary_formats/index.md @@ -1,7 +1,9 @@ # Binary Formats -Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports +Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over +a network. Hence, the library supports +- [BJData](bjdata.md) (Binary JData), - [BSON](bson.md) (Binary JSON), - [CBOR](cbor.md) (Concise Binary Object Representation), - [MessagePack](messagepack.md), and @@ -15,6 +17,7 @@ to efficiently encode JSON values to byte vectors and to decode such vectors. | Format | Serialization | Deserialization | |-------------|-----------------------------------------------|----------------------------------------------| +| BJData | complete | complete | | BSON | incomplete: top-level value must be an object | incomplete, but all JSON types are supported | | CBOR | complete | incomplete, but all JSON types are supported | | MessagePack | complete | complete | @@ -24,6 +27,7 @@ to efficiently encode JSON values to byte vectors and to decode such vectors. | Format | Binary values | Binary subtypes | |-------------|---------------|-----------------| +| BJData | not supported | not supported | | BSON | supported | supported | | CBOR | supported | supported | | MessagePack | supported | supported | @@ -35,11 +39,14 @@ See [binary values](../binary_values.md) for more information. | Format | canada.json | twitter.json | citm_catalog.json | jeopardy.json | |--------------------|-------------|--------------|-------------------|---------------| -| BSON | 85,8 % | 95,2 % | 95,8 % | 106,7 % | -| CBOR | 50,5 % | 86,3 % | 68,4 % | 88,0 % | -| MessagePack | 50,6 % | 86,0 % | 68,5 % | 87,9 % | -| UBJSON | 53,2 % | 91,3 % | 78,2 % | 96,6 % | -| UBJSON (size) | 58,6 % | 92,3 % | 86,8 % | 97,4 % | -| UBJSON (size+type) | 55,9 % | 92,3 % | 85,0 % | 95,0 % | +| BJData | 53.2 % | 91.1 % | 78.1 % | 96.6 % | +| BJData (size) | 58.6 % | 92.1 % | 86.7 % | 97.4 % | +| BJData (size+tyoe) | 58.6 % | 92.1 % | 86.5 % | 97.4 % | +| BSON | 85.8 % | 95.2 % | 95.8 % | 106.7 % | +| CBOR | 50.5 % | 86.3 % | 68.4 % | 88.0 % | +| MessagePack | 50.5 % | 86.0 % | 68.5 % | 87.9 % | +| UBJSON | 53.2 % | 91.3 % | 78.2 % | 96.6 % | +| UBJSON (size) | 58.6 % | 92.3 % | 86.8 % | 97.4 % | +| UBJSON (size+type) | 55.9 % | 92.3 % | 85.0 % | 95.0 % | Sizes compared to minified JSON value. diff --git a/doc/mkdocs/docs/features/binary_formats/messagepack.md b/docs/mkdocs/docs/features/binary_formats/messagepack.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/messagepack.md rename to docs/mkdocs/docs/features/binary_formats/messagepack.md diff --git a/doc/mkdocs/docs/features/binary_formats/ubjson.md b/docs/mkdocs/docs/features/binary_formats/ubjson.md similarity index 100% rename from doc/mkdocs/docs/features/binary_formats/ubjson.md rename to docs/mkdocs/docs/features/binary_formats/ubjson.md diff --git a/doc/mkdocs/docs/features/binary_values.md b/docs/mkdocs/docs/features/binary_values.md similarity index 65% rename from doc/mkdocs/docs/features/binary_values.md rename to docs/mkdocs/docs/features/binary_values.md index c58834c05..5ad6433cf 100644 --- a/doc/mkdocs/docs/features/binary_values.md +++ b/docs/mkdocs/docs/features/binary_values.md @@ -1,8 +1,12 @@ # Binary Values -The library implements several [binary formats](binary_formats/index.md) that encode JSON in an efficient way. Most of these formats support binary values; that is, values that have semantics define outside the library and only define a sequence of bytes to be stored. +The library implements several [binary formats](binary_formats/index.md) that encode JSON in an efficient way. Most of +these formats support binary values; that is, values that have semantics define outside the library and only define a +sequence of bytes to be stored. -JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store values received by a binary format. Binary values are never created by the JSON parser, and are only part of a serialized JSON text if they have been created manually or via a binary format. +JSON itself does not have a binary value. As such, binary values are an extension that this library implements to store +values received by a binary format. Binary values are never created by the JSON parser, and are only part of a +serialized JSON text if they have been created manually or via a binary format. ## API for binary values @@ -19,7 +23,9 @@ class json::binary_t { "std::vector" <|-- json::binary_t ``` -By default, binary values are stored as `std::vector`. This type can be changed by providing a template parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as `json::binary_t`: +By default, binary values are stored as `std::vector`. This type can be changed by providing a template +parameter to the `basic_json` type. To store binary subtypes, the storage type is extended and exposed as +`json::binary_t`: ```cpp auto binary = json::binary_t({0xCA, 0xFE, 0xBA, 0xBE}); @@ -87,7 +93,9 @@ Binary values are serialized differently according to the formats. ### JSON -JSON does not have a binary type, and this library does not introduce a new type as this would break conformance. Instead, binary values are serialized as an object with two keys: `bytes` holds an array of integers, and `subtype` is an integer or `null`. +JSON does not have a binary type, and this library does not introduce a new type as this would break conformance. +Instead, binary values are serialized as an object with two keys: `bytes` holds an array of integers, and `subtype` +is an integer or `null`. ??? example @@ -115,11 +123,72 @@ JSON does not have a binary type, and this library does not introduce a new type !!! warning "No roundtrip for binary values" - The JSON parser will not parse the objects generated by binary values back to binary values. This is by design to remain standards compliant. Serializing binary values to JSON is only implemented for debugging purposes. + The JSON parser will not parse the objects generated by binary values back to binary values. This is by design to + remain standards compliant. Serializing binary values to JSON is only implemented for debugging purposes. + +### BJData + +[BJData](binary_formats/bjdata.md) neither supports binary values nor subtypes, and proposes to serialize binary values +as array of uint8 values. This translation is implemented by the library. + +??? example + + Code: + + ```cpp + // create a binary value of subtype 42 (will be ignored in BJData) + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to BJData + auto v = json::to_bjdata(j); + ``` + + `v` is a `std::vector` with the following 20 elements: + + ```c + 0x7B // '{' + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x5B // '[' + 0x55 0xCA 0x55 0xFE 0x55 0xBA 0x55 0xBE // content (each byte prefixed with 'U') + 0x5D // ']' + 0x7D // '}' + ``` + + The following code uses the type and size optimization for UBJSON: + + ```cpp + // convert to UBJSON using the size and type optimization + auto v = json::to_bjdata(j, true, true); + ``` + + The resulting vector has 22 elements; the optimization is not effective for examples with few values: + + ```c + 0x7B // '{' + 0x23 0x69 0x01 // '#' 'i' type of the array elements: unsigned integers + 0x69 0x06 // i 6 (length of the key) + 0x62 0x69 0x6E 0x61 0x72 0x79 // "binary" + 0x5B // '[' array + 0x24 0x55 // '$' 'U' type of the array elements: unsigned integers + 0x23 0x69 0x04 // '#' i 4 number of array elements + 0xCA 0xFE 0xBA 0xBE // content + ``` + + Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would + yield the following value: + + ```json + { + "binary": [202, 254, 186, 190] + } + ``` ### BSON -[BSON](binary_formats/bson.md) supports binary values and subtypes. If a subtype is given, it is used and added as unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 is used. +[BSON](binary_formats/bson.md) supports binary values and subtypes. If a subtype is given, it is used and added as +unsigned 8-bit integer. If no subtype is given, the generic binary subtype 0x00 is used. ??? example @@ -159,7 +228,9 @@ JSON does not have a binary type, and this library does not introduce a new type ### CBOR -[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Subtypes will be serialized as tags. Any binary value will be serialized as byte strings. The library will choose the smallest representation using the length of the byte array. +[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Subtypes will be serialized as tags. Any binary +value will be serialized as byte strings. The library will choose the smallest representation using the length of the +byte array. ??? example @@ -185,7 +256,8 @@ JSON does not have a binary type, and this library does not introduce a new type 0xCA 0xFE 0xBA 0xBE // content ``` - Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless `json::cbor_tag_handler_t::ignore` or `json::cbor_tag_handler_t::store` is passed to `json::from_cbor`. + Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless + `json::cbor_tag_handler_t::ignore` or `json::cbor_tag_handler_t::store` is passed to `json::from_cbor`. ```json { @@ -198,7 +270,9 @@ JSON does not have a binary type, and this library does not introduce a new type ### MessagePack -[MessagePack](binary_formats/messagepack.md) supports binary values and subtypes. If a subtype is given, the ext family is used. The library will choose the smallest representation among fixext1, fixext2, fixext4, fixext8, ext8, ext16, and ext32. The subtype is then added as signed 8-bit integer. +[MessagePack](binary_formats/messagepack.md) supports binary values and subtypes. If a subtype is given, the ext family +is used. The library will choose the smallest representation among fixext1, fixext2, fixext4, fixext8, ext8, ext16, and +ext32. The subtype is then added as signed 8-bit integer. If no subtype is given, the bin family (bin8, bin16, bin32) is used. @@ -239,7 +313,8 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. ### UBJSON -[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values as array of uint8 values. This translation is implemented by the library. +[UBJSON](binary_formats/ubjson.md) neither supports binary values nor subtypes, and proposes to serialize binary values +as array of uint8 values. This translation is implemented by the library. ??? example @@ -251,7 +326,7 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); // convert to UBJSON - auto v = json::to_msgpack(j); + auto v = json::to_ubjson(j); ``` `v` is a `std::vector` with the following 20 elements: @@ -287,7 +362,8 @@ If no subtype is given, the bin family (bin8, bin16, bin32) is used. 0xCA 0xFE 0xBA 0xBE // content ``` - Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would yield the following value: + Note that subtype (42) is **not** serialized and that UBJSON has **no binary type**, and deserializing `v` would + yield the following value: ```json { diff --git a/doc/mkdocs/docs/features/comments.md b/docs/mkdocs/docs/features/comments.md similarity index 100% rename from doc/mkdocs/docs/features/comments.md rename to docs/mkdocs/docs/features/comments.md diff --git a/docs/mkdocs/docs/features/element_access/checked_access.md b/docs/mkdocs/docs/features/element_access/checked_access.md new file mode 100644 index 000000000..c4023cce5 --- /dev/null +++ b/docs/mkdocs/docs/features/element_access/checked_access.md @@ -0,0 +1,91 @@ +# Checked access: at + +## Overview + +The [`at`](../../api/basic_json/at.md) member function performs checked access; that is, it returns a reference to the +desired value if it exists and throws a [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) +otherwise. + +??? example "Read access" + + Consider the following JSON value: + + ```json + { + "name": "Mary Smith", + "age": 42, + "hobbies": ["hiking", "reading"] + } + ``` + + Assume the value is parsed to a `json` variable `j`. + + | expression | value | + |-------------------------------|------------------------------------------------------------------------------| + | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | + | `#!cpp j.at("name")` | `#!json "Mary Smith"` | + | `#!cpp j.at("age")` | `#!json 42` | + | `#!cpp j.at("hobbies")` | `#!json ["hiking", "reading"]` | + | `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` | + | `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` | + +The return value is a reference, so it can be modified by the original value. + +??? example "Write access" + + ```cpp + j.at("name") = "John Smith"; + ``` + + This code produces the following JSON value: + + ```json + { + "name": "John Smith", + "age": 42, + "hobbies": ["hiking", "reading"] + } + ``` + +When accessing an invalid index (i.e., an index greater than or equal to the array size) or the passed object key is +non-existing, an exception is thrown. + +??? example "Accessing via invalid index or missing key" + + ```cpp + j.at("hobbies").at(3) = "cooking"; + ``` + + This code produces the following exception: + + ``` + [json.exception.out_of_range.401] array index 3 is out of range + ``` + + When you [extended diagnostic messages](../../home/exceptions.md#extended-diagnostic-messages) are enabled by + defining [`JSON_DIAGNOSTICS`](../../api/macros/json_diagnostics.md), the exception further gives information where + the key or index is missing or out of range. + + ``` + [json.exception.out_of_range.401] (/hobbies) array index 3 is out of range + ``` + +## Notes + + +!!! failure "Exceptions" + + - [`at`](../../api/basic_json/at.md) can only be used with objects (with a string argument) or with arrays (with a + numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error304) + is thrown. + - [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) exceptions are thrown if the + provided key is not found in an object or the provided index is invalid. + +## Summary + +| scenario | non-const value | const value | +|-----------------------------------|------------------------------------------------|------------------------------------------------| +| access to existing object key | reference to existing value is returned | const reference to existing value is returned | +| access to valid array index | reference to existing value is returned | const reference to existing value is returned | +| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | +| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown | diff --git a/doc/mkdocs/docs/features/element_access/default_value.md b/docs/mkdocs/docs/features/element_access/default_value.md similarity index 100% rename from doc/mkdocs/docs/features/element_access/default_value.md rename to docs/mkdocs/docs/features/element_access/default_value.md diff --git a/doc/mkdocs/docs/features/element_access/index.md b/docs/mkdocs/docs/features/element_access/index.md similarity index 100% rename from doc/mkdocs/docs/features/element_access/index.md rename to docs/mkdocs/docs/features/element_access/index.md diff --git a/doc/mkdocs/docs/features/element_access/unchecked_access.md b/docs/mkdocs/docs/features/element_access/unchecked_access.md similarity index 55% rename from doc/mkdocs/docs/features/element_access/unchecked_access.md rename to docs/mkdocs/docs/features/element_access/unchecked_access.md index bb7228777..1bdea94e7 100644 --- a/doc/mkdocs/docs/features/element_access/unchecked_access.md +++ b/docs/mkdocs/docs/features/element_access/unchecked_access.md @@ -2,9 +2,10 @@ ## Overview -Elements in a JSON object and a JSON array can be accessed via `#!cpp operator[]` similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively. +Elements in a JSON object and a JSON array can be accessed via [`operator[]`](../../api/basic_json/operator%5B%5D.md) +similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively. -??? example +??? example "Read access" Consider the following JSON value: @@ -18,18 +19,19 @@ Elements in a JSON object and a JSON array can be accessed via `#!cpp operator[] Assume the value is parsed to a `json` variable `j`. - | expression | value | - | ---------- | ----- | - | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | - | `#!cpp j["name"]` | `#!json "Mary Smith"` | - | `#!cpp j["age"]` | `#!json 42` | - | `#!cpp j["hobbies"]` | `#!json ["hiking", "reading"]` | - | `#!cpp j["hobbies"][0]` | `#!json "hiking"` | - | `#!cpp j["hobbies"][1]` | `#!json "reading"` | + | expression | value | + |-------------------------|------------------------------------------------------------------------------| + | `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` | + | `#!cpp j["name"]` | `#!json "Mary Smith"` | + | `#!cpp j["age"]` | `#!json 42` | + | `#!cpp j["hobbies"]` | `#!json ["hiking", "reading"]` | + | `#!cpp j["hobbies"][0]` | `#!json "hiking"` | + | `#!cpp j["hobbies"][1]` | `#!json "reading"` | -The return value is a reference, so it can modify the original value. In case the passed object key is non-existing, a `#!json null` value is inserted which can be immediately be overwritten. +The return value is a reference, so it can modify the original value. In case the passed object key is non-existing, a +`#!json null` value is inserted which can be immediately be overwritten. -??? example +??? example "Write access" ```cpp j["name"] = "John Smith"; @@ -47,9 +49,10 @@ The return value is a reference, so it can modify the original value. In case th } ``` -When accessing an invalid index (i.e., an index greater than or equal to the array size), the JSON array is resized such that the passed index is the new maximal index. Intermediate values are filled with `#!json null`. +When accessing an invalid index (i.e., an index greater than or equal to the array size), the JSON array is resized such +that the passed index is the new maximal index. Intermediate values are filled with `#!json null`. -??? example +??? example "Filling up arrays with `#!json null` values" ```cpp j["hobbies"][0] = "running"; @@ -76,17 +79,23 @@ When accessing an invalid index (i.e., an index greater than or equal to the arr - `#!cpp std::vector::operator[]` never inserts a new element. - `#!cpp std::map::operator[]` is not available for const values. - The type `#!cpp json` wraps all JSON value types. It would be impossible to remove `operator[]` for const objects. At the same time, inserting elements for non-const objects is really convenient as it avoids awkward `insert` calls. To this end, we decided to have an inserting non-const behavior for both arrays and objects. + The type `#!cpp json` wraps all JSON value types. It would be impossible to remove + [`operator[]`](../../api/basic_json/operator%5B%5D.md) for const objects. At the same time, inserting elements for + non-const objects is really convenient as it avoids awkward `insert` calls. To this end, we decided to have an + inserting non-const behavior for both arrays and objects. !!! info - The access is unchecked. In case the passed object key does not exist or the passed array index is invalid, no exception is thrown. + The access is unchecked. In case the passed object key does not exist or the passed array index is invalid, no + exception is thrown. !!! danger - It is **undefined behavior** to access a const object with a non-existing key. - It is **undefined behavior** to access a const array with an invalid index. - - In debug mode, an **assertion** will fire in both cases. You can disable assertions by defining the preprocessor symbol `#!cpp NDEBUG` or redefine the macro [`JSON_ASSERT(x)`](../macros.md#json_assertx). + - In debug mode, an **assertion** will fire in both cases. You can disable assertions by defining the preprocessor + symbol `#!cpp NDEBUG` or redefine the macro [`JSON_ASSERT(x)`](../macros.md#json_assertx). See the documentation + on [runtime assertions](../assertions.md) for more information. !!! failure "Exceptions" @@ -94,9 +103,9 @@ When accessing an invalid index (i.e., an index greater than or equal to the arr ## Summary -| scenario | non-const value | const value | -|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------| -| access to existing object key | reference to existing value is returned | const reference to existing value is returned | -| access to valid array index | reference to existing value is returned | const reference to existing value is returned | -| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; assertion in debug mode | -| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; assertion in debug mode | +| scenario | non-const value | const value | +|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------| +| access to existing object key | reference to existing value is returned | const reference to existing value is returned | +| access to valid array index | reference to existing value is returned | const reference to existing value is returned | +| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode | +| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; [runtime assertion](../assertions.md) in debug mode | diff --git a/doc/mkdocs/docs/features/enum_conversion.md b/docs/mkdocs/docs/features/enum_conversion.md similarity index 67% rename from doc/mkdocs/docs/features/enum_conversion.md rename to docs/mkdocs/docs/features/enum_conversion.md index 8f474a702..59ffbd5f1 100644 --- a/doc/mkdocs/docs/features/enum_conversion.md +++ b/docs/mkdocs/docs/features/enum_conversion.md @@ -24,8 +24,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { }) ``` -The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` -while avoiding repetition and boilerplate serialization code. +The [`NLOHMANN_JSON_SERIALIZE_ENUM()` macro](../api/macros/nlohmann_json_serialize_enum.md) declares a set of +`to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code. ## Usage @@ -45,10 +45,11 @@ assert(jPi.get() == TS_INVALID ); ## Notes -Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, +Just as in [Arbitrary Type Conversions](arbitrary_types.md) above, -- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace), - or the library will not be able to locate it, and it will default to integer serialization. +- [`NLOHMANN_JSON_SERIALIZE_ENUM()`](../api/macros/nlohmann_json_serialize_enum.md) MUST be declared in your enum type's + namespace (which can be the global namespace), or the library will not be able to locate it, and it will default to + integer serialization. - It MUST be available (e.g., proper headers must be included) everywhere you use the conversions. Other Important points: @@ -57,3 +58,4 @@ Other Important points: default pair carefully. - If an enum or JSON value is specified more than once in your map, the first matching occurrence from the top of the map will be returned when converting to or from JSON. +- To disable the default serialization of enumerators as integers and force a compiler error instead, see [`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). diff --git a/doc/mkdocs/docs/features/iterators.md b/docs/mkdocs/docs/features/iterators.md similarity index 98% rename from doc/mkdocs/docs/features/iterators.md rename to docs/mkdocs/docs/features/iterators.md index 46f28f189..ce627e012 100644 --- a/doc/mkdocs/docs/features/iterators.md +++ b/docs/mkdocs/docs/features/iterators.md @@ -113,7 +113,7 @@ for (auto& [key, val] : j_object.items()) ```cpp json j = {1, 2, 3, 4}; - for (auto it = j.begin(); it != j.end(); ++it) + for (auto it = j.rbegin(); it != j.rend(); ++it) { std::cout << *it << std::endl; } diff --git a/doc/mkdocs/docs/features/json_patch.md b/docs/mkdocs/docs/features/json_patch.md similarity index 100% rename from doc/mkdocs/docs/features/json_patch.md rename to docs/mkdocs/docs/features/json_patch.md diff --git a/docs/mkdocs/docs/features/json_pointer.md b/docs/mkdocs/docs/features/json_pointer.md new file mode 100644 index 000000000..a3980b4c6 --- /dev/null +++ b/docs/mkdocs/docs/features/json_pointer.md @@ -0,0 +1,126 @@ +# JSON Pointer + +## Introduction + +The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address +structured values. A JSON Pointer is a string that identifies a specific value withing a JSON document. + +Consider the following JSON document + +```json +{ + "array": ["A", "B", "C"], + "nested": { + "one": 1, + "two": 2, + "three": [true, false] + } +} +``` + +Then every value inside the JSON document can be identified as follows: + +| JSON Pointer | JSON value | +|-------------------|----------------------------------------------------------------------------------| +| `` | `#!json {"array":["A","B","C"],"nested":{"one":1,"two":2,"three":[true,false]}}` | +| `/array` | `#!json ["A","B","C"]` | +| `/array/0` | `#!json A` | +| `/array/1` | `#!json B` | +| `/array/2` | `#!json C` | +| `/nested` | `#!json {"one":1,"two":2,"three":[true,false]}` | +| `/nested/one` | `#!json 1` | +| `/nested/two` | `#!json 2` | +| `/nested/three` | `#!json [true,false]` | +| `/nested/three/0` | `#!json true` | +| `/nested/three/1` | `#!json false` | + +Note `/` does not identify the root (i.e., the whole document), but an object entry with empty key `""`. See +[RFC 6901](https://tools.ietf.org/html/rfc6901) for more information. + +## JSON Pointer creation + +JSON Pointers can be created from a string: + +```cpp +json::json_pointer p = "/nested/one"; +``` + +Furthermore, a user-defined string literal can be used to achieve the same result: + +```cpp +auto p = "/nested/one"_json_pointer; +``` + +The escaping rules of [RFC 6901](https://tools.ietf.org/html/rfc6901) are implemented. See the +[constructor documentation](../api/json_pointer/json_pointer.md) for more information. + +## Value access + +JSON Pointers can be used in the [`at`](../api/basic_json/at.md), [`operator[]`](../api/basic_json/operator%5B%5D.md), +and [`value`](../api/basic_json/value.md) functions just like object keys or array indices. + +```cpp +// the JSON value from above +auto j = json::parse(R"({ + "array": ["A", "B", "C"], + "nested": { + "one": 1, + "two": 2, + "three": [true, false] + } +})"); + +// access values +auto val = j["/"_json_pointer]; // {"array":["A","B","C"],...} +auto val1 = j["/nested/one"_json_pointer]; // 1 +auto val2 = j.at[json::json_pointer("/nested/three/1")]; // false +auto val3 = j.value[json::json_pointer("/nested/four", 0)]; // 0 +``` + +## Flatten / unflatten + +The library implements a function [`flatten`](../api/basic_json/flatten.md) to convert any JSON document into a JSON +object where each key is a JSON Pointer and each value is a primitive JSON value (i.e., a string, boolean, number, or +null). + +```cpp +// the JSON value from above +auto j = json::parse(R"({ + "array": ["A", "B", "C"], + "nested": { + "one": 1, + "two": 2, + "three": [true, false] + } +})"); + +// create flattened value +auto j_flat = j.flatten(); +``` + +The resulting value `j_flat` is: + +```json +{ + "/array/0": "A", + "/array/1": "B", + "/array/2": "C", + "/nested/one": 1, + "/nested/two": 2, + "/nested/three/0": true, + "/nested/three/1": false +} +``` + +The reverse function, [`unflatten`](../api/basic_json/unflatten.md) recreates the original value. + +```cpp +auto j_original = j_flat.unflatten(); +``` + +## See also + +- Class [`json_pointer`](../api/json_pointer/index.md) +- Function [`flatten`](../api/basic_json/flatten.md) +- Function [`unflatten`](../api/basic_json/unflatten.md) +- [JSON Patch](json_patch.md) diff --git a/doc/mkdocs/docs/features/macros.md b/docs/mkdocs/docs/features/macros.md similarity index 53% rename from doc/mkdocs/docs/features/macros.md rename to docs/mkdocs/docs/features/macros.md index d324a1325..1be95d35d 100644 --- a/doc/mkdocs/docs/features/macros.md +++ b/docs/mkdocs/docs/features/macros.md @@ -1,18 +1,19 @@ # Supported Macros Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. +See also the [API documentation for macros](../api/macros/index.md) for examples and more information. ## `JSON_ASSERT(x)` -The default value is `#!cpp assert(x)`. +This macro controls which code is executed for [runtime assertions](assertions.md) of the library. + +See [full documentation of `JSON_ASSERT(x)`](../api/macros/json_assert.md). ## `JSON_CATCH_USER(exception)` -This macro overrides `#!cpp catch` calls inside the library. The argument is the type of the exception to catch. As of -version 3.8.0, the library only catches `std::out_of_range` exceptions internally to rethrow them as -[`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The macro is always followed by a scope. +This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/try_catch) calls inside the library. -See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example. +See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md). ## `JSON_DIAGNOSTICS` @@ -26,6 +27,8 @@ that enabling this macro increases the size of every JSON value by one pointer a The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets `JSON_DIAGNOSTICS` accordingly. +See [full documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). + ## `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, `JSON_HAS_CPP_20` The library targets C++11, but also supports some features introduced in later C++ versions (e.g., `std::string_view` @@ -34,6 +37,8 @@ standard. By defining any of these symbols, the internal check is overridden and unconditionally assumed. This can be helpful for compilers that only implement parts of the standard and would be detected incorrectly. +See [full documentation of `JSON_HAS_CPP_11`, `JSON_HAS_CPP_14`, `JSON_HAS_CPP_17`, and `JSON_HAS_CPP_20`](../api/macros/json_has_cpp_11.md). + ## `JSON_HAS_FILESYSTEM`, `JSON_HAS_EXPERIMENTAL_FILESYSTEM` When compiling with C++17, the library provides conversions from and to `std::filesystem::path`. As compiler support @@ -41,16 +46,19 @@ for filesystem is limited, the library tries to detect whether ``/`s or ``/`std::experimental::filesystem` (`JSON_HAS_EXPERIMENTAL_FILESYSTEM`) should be used. To override the built-in check, define `JSON_HAS_FILESYSTEM` or `JSON_HAS_EXPERIMENTAL_FILESYSTEM` to `1`. +See [full documentation of `JSON_HAS_FILESYSTEM` and `JSON_HAS_EXPERIMENTAL_FILESYSTEM`](../api/macros/json_has_filesystem.md). + ## `JSON_NOEXCEPTION` -Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. When defining `JSON_NOEXCEPTION`, `#!cpp try` -is replaced by `#!cpp if (true)`, `#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by -`#!cpp std::abort()`. +Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`. -The same effect is achieved by setting the compiler flag `-fno-exceptions`. +See [full documentation of `JSON_NOEXCEPTION`](../api/macros/json_noexception.md). -Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not -available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). +## `JSON_DISABLE_ENUM_SERIALIZATION` + +When defined, default parse and serialize functions for enums are excluded and have to be provided by the user, for example, using [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md). + +See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). ## `JSON_NO_IO` @@ -58,48 +66,39 @@ When defined, headers ``, ``, ``, ``, and `(); - ``` - -Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which -sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. +See [full documentation of `JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md). ## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` @@ -110,7 +109,15 @@ The macro is to be defined inside the class/struct to create code for. Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members. The first parameter is the name of the class/struct, and all remaining parameters name the members. -See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. +See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE`](../api/macros/nlohmann_define_type_intrusive.md). + +## `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)` + +This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a +missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs +an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_intrusive.md). ## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` @@ -121,14 +128,26 @@ The macro is to be defined inside the namespace of the class/struct to create co accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The first parameter is the name of the class/struct, and all remaining parameters name the members. -See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. +See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](../api/macros/nlohmann_define_type_non_intrusive.md). + +## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)` + +This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a +missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs +an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function. + +See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_non_intrusive.md). ## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` This macro simplifies the serialization/deserialization of enum types. See [Specializing enum conversion](enum_conversion.md) for more information. +See [full documentation of `NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md). + ## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` These macros are defined by the library and contain the version numbers according to -[Semantic Versioning 2.0.0](https://semver.org). +[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). + +See [full documentation of `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and `NLOHMANN_JSON_VERSION_PATCH`](../api/macros/nlohmann_json_version_major.md). diff --git a/doc/mkdocs/docs/features/merge_patch.md b/docs/mkdocs/docs/features/merge_patch.md similarity index 100% rename from doc/mkdocs/docs/features/merge_patch.md rename to docs/mkdocs/docs/features/merge_patch.md diff --git a/doc/mkdocs/docs/features/object_order.md b/docs/mkdocs/docs/features/object_order.md similarity index 52% rename from doc/mkdocs/docs/features/object_order.md rename to docs/mkdocs/docs/features/object_order.md index 86bb253ba..3ee16a90e 100644 --- a/doc/mkdocs/docs/features/object_order.md +++ b/docs/mkdocs/docs/features/object_order.md @@ -2,6 +2,8 @@ The [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". As such, an implementation does not need to preserve any specific order of object keys. +## Default behavior: sort keys + The default type `nlohmann::json` uses a `std::map` to store JSON objects, and thus stores object keys **sorted alphabetically**. ??? example @@ -33,29 +35,49 @@ The default type `nlohmann::json` uses a `std::map` to store JSON objects, and t } ``` +## Alternative behavior: preserve insertion order + If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). ??? example ```cpp - #include - #include - - using ordered_json = nlohmann::ordered_json; - - int main() - { - ordered_json j; - j["one"] = 1; - j["two"] = 2; - j["three"] = 3; - - std::cout << j.dump(2) << '\n'; - } + --8<-- "examples/ordered_json.cpp" ``` Output: + ```json + --8<-- "examples/ordered_json.output" + ``` + +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)). + +### Notes on parsing + +Note that you also need to call the right [`parse`](../api/basic_json/parse.md) function when reading from a file. +Assume file `input.json` contains the JSON object above: + +```json +{ + "one": 1, + "two": 2, + "three": 3 +} +``` + +!!! success "Right way" + + The following code correctly calls the `parse` function from `nlohmann::ordered_json`: + + ```cpp + std::ifstream i("input.json"); + auto j = nlohmann::ordered_json::parse(i); + std::cout << j.dump(2) << std::endl; + ``` + + The output will be: + ```json { "one": 1, @@ -64,4 +86,24 @@ If you do want to preserve the **insertion order**, you can try the type [`nlohm } ``` -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)). +??? failure "Wrong way" + + The following code incorrectly calls the `parse` function from `nlohmann::json` which does not preserve the + insertion order, but sorts object keys. Assigning the result to `nlohmann::ordered_json` compiles, but does not + restore the order from the input file. + + ```cpp + std::ifstream i("input.json"); + nlohmann::ordered_json j = nlohmann::json::parse(i); + std::cout << j.dump(2) << std::endl; + ``` + + The output will be: + + ```json + { + "one": 1, + "three": 3 + "two": 2, + } + ``` diff --git a/doc/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/index.md rename to docs/mkdocs/docs/features/parsing/index.md diff --git a/docs/mkdocs/docs/features/parsing/json_lines.md b/docs/mkdocs/docs/features/parsing/json_lines.md new file mode 100644 index 000000000..659d31792 --- /dev/null +++ b/docs/mkdocs/docs/features/parsing/json_lines.md @@ -0,0 +1,49 @@ +# JSON Lines + +The [JSON Lines](https://jsonlines.org) format is a text format of newline-delimited JSON. In particular: + +1. The input must be UTF-8 encoded. +2. Every line must be a valid JSON value. +3. The line separator must be `\n`. As `\r` is silently ignored, `\r\n` is also supported. +4. The final character may be `\n`, but is not required to be one. + +!!! example "JSON Text example" + + ```json + {"name": "Gilbert", "wins": [["straight", "7â™Ŗ"], ["one pair", "10â™Ĩ"]]} + {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]} + {"name": "May", "wins": []} + {"name": "Deloise", "wins": [["three of a kind", "5â™Ŗ"]]} + ``` + +JSON Lines input with more than one value is treated as invalid JSON by the [`parse`](../../api/basic_json/parse.md) or +[`accept`](../../api/basic_json/accept.md) functions. To process it line by line, functions like +[`std::getline`](https://en.cppreference.com/w/cpp/string/basic_string/getline) can be used: + +!!! example "Example: Parse JSON Text input line by line" + + The example below demonstrates how JSON Lines can be processed. + + ```cpp + --8<-- "examples/json_lines.cpp" + ``` + + Output: + + ```json + --8<-- "examples/json_lines.output" + ``` + +!!! warning "Note" + + Using [`operator>>`](../../api/operator_gtgt.md) like + + ```cpp + json j; + while (input >> j) + { + std::cout << j << std::endl; + } + ``` + + with a JSON Lines input does not work, because the parser will try to parse one value after the last one. diff --git a/doc/mkdocs/docs/features/parsing/parse_exceptions.md b/docs/mkdocs/docs/features/parsing/parse_exceptions.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/parse_exceptions.md rename to docs/mkdocs/docs/features/parsing/parse_exceptions.md diff --git a/doc/mkdocs/docs/features/parsing/parser_callbacks.md b/docs/mkdocs/docs/features/parsing/parser_callbacks.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/parser_callbacks.md rename to docs/mkdocs/docs/features/parsing/parser_callbacks.md diff --git a/doc/mkdocs/docs/features/parsing/sax_interface.md b/docs/mkdocs/docs/features/parsing/sax_interface.md similarity index 100% rename from doc/mkdocs/docs/features/parsing/sax_interface.md rename to docs/mkdocs/docs/features/parsing/sax_interface.md diff --git a/doc/mkdocs/docs/features/types/index.md b/docs/mkdocs/docs/features/types/index.md similarity index 100% rename from doc/mkdocs/docs/features/types/index.md rename to docs/mkdocs/docs/features/types/index.md diff --git a/doc/mkdocs/docs/features/types/number_handling.md b/docs/mkdocs/docs/features/types/number_handling.md similarity index 99% rename from doc/mkdocs/docs/features/types/number_handling.md rename to docs/mkdocs/docs/features/types/number_handling.md index dd6507353..03d8c9c69 100644 --- a/doc/mkdocs/docs/features/types/number_handling.md +++ b/docs/mkdocs/docs/features/types/number_handling.md @@ -275,7 +275,7 @@ The rationale is twofold: ### Determine number types -As the example in [Number conversion](#number_conversion) shows, there are different functions to determine the type of +As the example in [Number conversion](#number-conversion) shows, there are different functions to determine the type of the stored number: - [`is_number()`](../../api/basic_json/is_number.md) returns `#!c true` for any number type diff --git a/doc/mkdocs/docs/home/code_of_conduct.md b/docs/mkdocs/docs/home/code_of_conduct.md similarity index 100% rename from doc/mkdocs/docs/home/code_of_conduct.md rename to docs/mkdocs/docs/home/code_of_conduct.md diff --git a/doc/mkdocs/docs/home/design_goals.md b/docs/mkdocs/docs/home/design_goals.md similarity index 100% rename from doc/mkdocs/docs/home/design_goals.md rename to docs/mkdocs/docs/home/design_goals.md diff --git a/doc/mkdocs/docs/home/exceptions.md b/docs/mkdocs/docs/home/exceptions.md similarity index 92% rename from doc/mkdocs/docs/home/exceptions.md rename to docs/mkdocs/docs/home/exceptions.md index 1241926cf..0ecf8557c 100644 --- a/doc/mkdocs/docs/home/exceptions.md +++ b/docs/mkdocs/docs/home/exceptions.md @@ -28,9 +28,9 @@ class json::parse_error { ### Switch off exceptions -Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`). +Exceptions are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol [`JSON_NOEXCEPTION`](../api/macros/json_noexception.md). In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `#!cpp throw`), `JSON_TRY_USER` (overriding `#!cpp try`), and `JSON_CATCH_USER` (overriding `#!cpp catch`). -Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. +Note that [`JSON_THROW_USER`](../api/macros/json_throw_user.md) should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior. ??? example @@ -52,6 +52,8 @@ Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or Note the explanatory [`what()`](https://en.cppreference.com/w/cpp/error/exception/what) string of exceptions is not available for MSVC if exceptions are disabled, see [#2824](https://github.com/nlohmann/json/discussions/2824). +See [documentation of `JSON_TRY_USER`, `JSON_CATCH_USER` and `JSON_THROW_USER`](../api/macros/json_throw_user.md) for more information. + ### Extended diagnostic messages Exceptions in the library are thrown in the local context of the JSON value they are detected. This makes detailed diagnostics messages, and hence debugging, difficult. @@ -72,7 +74,7 @@ Exceptions in the library are thrown in the local context of the JSON value they To create better diagnostics messages, each JSON value needs a pointer to its parent value such that a global context (i.e., a path from the root value to the value that lead to the exception) can be created. That global context is provided as [JSON Pointer](../features/json_pointer.md). -As this global context comes at the price of storing one additional pointer per JSON value and runtime overhead to maintain the parent relation, extended diagnostics are disabled by default. They can, however, be enabled by defining the preprocessor symbol [`JSON_DIAGNOSTICS`](../features/macros.md#json_diagnostics) to `1` before including `json.hpp`. +As this global context comes at the price of storing one additional pointer per JSON value and runtime overhead to maintain the parent relation, extended diagnostics are disabled by default. They can, however, be enabled by defining the preprocessor symbol [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) to `1` before including `json.hpp`. ??? example @@ -88,6 +90,7 @@ As this global context comes at the price of storing one additional pointer per Now the exception message contains a JSON Pointer `/address/housenumber` that indicates which value has the wrong type. +See [documentation of `JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) for more information. ## Parse errors @@ -268,7 +271,7 @@ In a JSON Pointer, only `~0` and `~1` are valid escape sequences. A JSON Pointer array index must be a number. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.109] parse error: array index 'one' is not a number @@ -292,19 +295,34 @@ When parsing CBOR or MessagePack, the byte vector ends before the complete value ### json.exception.parse_error.112 -Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +An unexpected byte was read in a [binary format](../features/binary_formats/index.md) or length information is invalid ([BSON](../features/binary_formats/bson.md)). -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.112] parse error at byte 1: syntax error while parsing CBOR value: invalid byte: 0x1C ``` + ``` + [json.exception.parse_error.112] parse error at byte 1: syntax error while parsing MessagePack value: invalid byte: 0xC1 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x02 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 4: syntax error while parsing UBJSON size: expected '#' after type information; last byte: 0x02 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BSON string: string length must be at least 1, is -2147483648 + ``` + ``` + [json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1 + ``` ### json.exception.parse_error.113 While parsing a map key, a value that is not a string has been read. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF @@ -371,7 +389,7 @@ The iterators passed to constructor `basic_json(InputIT first, InputIT last)` ar In the [erase](../api/basic_json/erase.md) or insert function, the passed iterator `pos` does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.invalid_iterator.202] iterator does not fit current value @@ -535,7 +553,7 @@ To create an object from an initializer list, the initializer list must consist During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.302] type must be object, but is null @@ -548,7 +566,7 @@ During implicit or explicit value conversion, the JSON type must be compatible t To retrieve a reference to a value stored in a `basic_json` object with `get_ref`, the type of the reference must match the value type. For instance, for a JSON array, the `ReferenceType` must be `array_t &`. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is object @@ -561,7 +579,7 @@ To retrieve a reference to a value stored in a `basic_json` object with `get_ref The `at()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.304] cannot use at() with string @@ -574,7 +592,7 @@ The `at()` member functions can only be executed for certain JSON types. The `operator[]` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.305] cannot use operator[] with a string argument with array @@ -617,7 +635,7 @@ The `push_back()` and `operator+=` member functions can only be executed for cer The `insert()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.309] cannot use insert() with array @@ -640,7 +658,7 @@ The `swap()` member functions can only be executed for certain JSON types. The `emplace()` and `emplace_back()` member functions can only be executed for certain JSON types. -!!! failure "Example message" +!!! failure "Example messages" ``` [json.exception.type_error.311] cannot use emplace() with number @@ -715,7 +733,7 @@ The `dump()` function only works with UTF-8 encoded strings; that is, if you ass The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) -!!! failure "Example message" +!!! failure "Example messages" Serializing `#!json null` to BSON: ``` diff --git a/doc/mkdocs/docs/home/faq.md b/docs/mkdocs/docs/home/faq.md similarity index 97% rename from doc/mkdocs/docs/home/faq.md rename to docs/mkdocs/docs/home/faq.md index c6a283bc7..878b8a64e 100644 --- a/doc/mkdocs/docs/home/faq.md +++ b/docs/mkdocs/docs/home/faq.md @@ -126,7 +126,7 @@ Yes, see [Parsing and exceptions](../features/parsing/parse_exceptions.md). Can I get the key of the object item that caused an exception? -Yes, you can. Please define the symbol [`JSON_DIAGNOSTICS`](../features/macros.md#json_diagnostics) to get [extended diagnostics messages](exceptions.md#extended-diagnostic-messages). +Yes, you can. Please define the symbol [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md) to get [extended diagnostics messages](exceptions.md#extended-diagnostic-messages). ## Serialization issues diff --git a/doc/mkdocs/docs/home/license.md b/docs/mkdocs/docs/home/license.md similarity index 100% rename from doc/mkdocs/docs/home/license.md rename to docs/mkdocs/docs/home/license.md diff --git a/doc/mkdocs/docs/home/releases.md b/docs/mkdocs/docs/home/releases.md similarity index 100% rename from doc/mkdocs/docs/home/releases.md rename to docs/mkdocs/docs/home/releases.md diff --git a/doc/mkdocs/docs/home/sponsors.md b/docs/mkdocs/docs/home/sponsors.md similarity index 100% rename from doc/mkdocs/docs/home/sponsors.md rename to docs/mkdocs/docs/home/sponsors.md diff --git a/doc/mkdocs/docs/images/callback_events.png b/docs/mkdocs/docs/images/callback_events.png similarity index 100% rename from doc/mkdocs/docs/images/callback_events.png rename to docs/mkdocs/docs/images/callback_events.png diff --git a/doc/mkdocs/docs/images/json_syntax_number.png b/docs/mkdocs/docs/images/json_syntax_number.png similarity index 100% rename from doc/mkdocs/docs/images/json_syntax_number.png rename to docs/mkdocs/docs/images/json_syntax_number.png diff --git a/doc/mkdocs/docs/images/range-begin-end.svg b/docs/mkdocs/docs/images/range-begin-end.svg similarity index 100% rename from doc/mkdocs/docs/images/range-begin-end.svg rename to docs/mkdocs/docs/images/range-begin-end.svg diff --git a/doc/mkdocs/docs/images/range-rbegin-rend.svg b/docs/mkdocs/docs/images/range-rbegin-rend.svg similarity index 100% rename from doc/mkdocs/docs/images/range-rbegin-rend.svg rename to docs/mkdocs/docs/images/range-rbegin-rend.svg diff --git a/doc/mkdocs/docs/index.md b/docs/mkdocs/docs/index.md similarity index 100% rename from doc/mkdocs/docs/index.md rename to docs/mkdocs/docs/index.md diff --git a/docs/mkdocs/docs/integration/cmake.md b/docs/mkdocs/docs/integration/cmake.md new file mode 100644 index 000000000..fc7d8d2be --- /dev/null +++ b/docs/mkdocs/docs/integration/cmake.md @@ -0,0 +1,172 @@ +# CMake + +## Integration + +You can use the `nlohmann_json::nlohmann_json` interface target in CMake. This target populates the appropriate usage +requirements for [`INTERFACE_INCLUDE_DIRECTORIES`](https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES.html) +to point to the appropriate include directories and [`INTERFACE_COMPILE_FEATURES`](https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_COMPILE_FEATURES.html) +for the necessary C++11 flags. + +### External + +To use this library from a CMake project, you can locate it directly with [`find_package()`](https://cmake.org/cmake/help/latest/command/find_package.html) +and use the namespaced imported target from the generated package configuration: + +!!! example + + ```cmake title="CMakeLists.txt" + cmake_minimum_required(VERSION 3.1) + project(ExampleProject LANGUAGES CXX) + + find_package(nlohmann_json 3.11.0 REQUIRED) + + add_executable(example example.cpp) + target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json) + ``` + +The package configuration file, `nlohmann_jsonConfig.cmake`, can be used either from an install tree or directly out of +the build tree. + +### Embedded + +To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call +`add_subdirectory()` in your `CMakeLists.txt` file. + +!!! example + + ```cmake title="CMakeLists.txt" + cmake_minimum_required(VERSION 3.1) + project(ExampleProject LANGUAGES CXX) + + # If you only include this third party in PRIVATE source files, you do not need to install it + # when your main project gets installed. + set(JSON_Install OFF CACHE INTERNAL "") + + add_subdirectory(nlohmann_json) + + add_executable(example example.cpp) + target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json) + ``` + +!!! note + + Do not use `#!cmake include(nlohmann_json/CMakeLists.txt)`, since that carries with it unintended consequences that + will break the build. It is generally discouraged (although not necessarily well documented as such) to use + `#!cmake include(...)` for pulling in other CMake projects anyways. + + +### Supporting Both + +To allow your project to support either an externally supplied or an embedded JSON library, you can use a pattern akin +to the following. + +!!! example + + ```cmake title="CMakeLists.txt" + project(ExampleProject LANGUAGES CXX) + + option(EXAMPLE_USE_EXTERNAL_JSON "Use an external JSON library" OFF) + + add_subdirectory(thirdparty) + + add_executable(example example.cpp) + + # Note that the namespaced target will always be available regardless of the import method + target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json) + ``` + + ```cmake title="thirdparty/CMakeLists.txt" + if(EXAMPLE_USE_EXTERNAL_JSON) + find_package(nlohmann_json 3.11.0 REQUIRED) + else() + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory(nlohmann_json) + endif() + ``` + + `thirdparty/nlohmann_json` is then a complete copy of this source tree. + + +### FetchContent + +Since CMake v3.11, [FetchContent](https://cmake.org/cmake/help/v3.11/module/FetchContent.html) can be used to +automatically download a release as a dependency at configure type. + +!!! example + + ```cmake title="CMakeLists.txt" + cmake_minimum_required(VERSION 3.11) + project(ExampleProject LANGUAGES CXX) + + include(FetchContent) + + FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.0/json.tar.xz) + FetchContent_MakeAvailable(json) + + add_executable(example example.cpp) + target_link_libraries(example PRIVATE nlohmann_json::nlohmann_json) + ``` + +!!! Note + + It is recommended to use the URL approach described above which is supported as of version 3.10.0. It is also + possible to pass the Git repository like + + ```cmake + FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.0 + ) + ``` + + However, the repository download size is quite large. You might want to depend on + a smaller repository. For instance, you might want to replace the URL in the example by + . + +## CMake Options + +### `JSON_BuildTests` + +Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option. + +### `JSON_CI` + +Enable CI build targets. The exact targets are used during the several CI steps and are subject to change without notice. This option is `OFF` by default. + +### `JSON_Diagnostics` + +Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This option is `OFF` by default. + +### `JSON_DisableEnumSerialization` + +Disable default `enum` serialization by defining the macro +[`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). This option is `OFF` by default. + +### `JSON_FastTests` + +Skip expensive/slow test suites. This option is `OFF` by default. Depends on `JSON_BuildTests`. + +### `JSON_GlobalUDLs` + +Place user-defined string literals in the global namespace by defining the macro +[`JSON_USE_GLOBAL_UDLS`](../api/macros/json_use_global_udls.md). This option is `OFF` by default. + +### `JSON_ImplicitConversions` + +Enable implicit conversions by defining macro [`JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md). This option is `ON` by default. + +### `JSON_Install` + +Install CMake targets during install step. This option is `ON` by default if the library's CMake project is the top project. + +### `JSON_MultipleHeaders` + +Use non-amalgamated version of the library. This option is `OFF` by default. + +### `JSON_SystemInclude` + +Treat the library headers like system headers (i.e., adding `SYSTEM` to the [`target_include_directories`](https://cmake.org/cmake/help/latest/command/target_include_directories.html) call) to checks for this library by tools like Clang-Tidy. This option is `OFF` by default. + +### `JSON_Valgrind` + +Execute test suite with [Valgrind](https://valgrind.org). This option is `OFF` by default. Depends on `JSON_BuildTests`. diff --git a/doc/mkdocs/docs/integration/conan/CMakeLists.txt b/docs/mkdocs/docs/integration/conan/CMakeLists.txt similarity index 100% rename from doc/mkdocs/docs/integration/conan/CMakeLists.txt rename to docs/mkdocs/docs/integration/conan/CMakeLists.txt diff --git a/doc/mkdocs/docs/integration/conan/Conanfile.txt b/docs/mkdocs/docs/integration/conan/Conanfile.txt similarity index 100% rename from doc/mkdocs/docs/integration/conan/Conanfile.txt rename to docs/mkdocs/docs/integration/conan/Conanfile.txt diff --git a/doc/mkdocs/docs/integration/conan/example.cpp b/docs/mkdocs/docs/integration/conan/example.cpp similarity index 100% rename from doc/mkdocs/docs/integration/conan/example.cpp rename to docs/mkdocs/docs/integration/conan/example.cpp diff --git a/doc/mkdocs/docs/integration/vcpkg/example.cpp b/docs/mkdocs/docs/integration/example.cpp similarity index 54% rename from doc/mkdocs/docs/integration/vcpkg/example.cpp rename to docs/mkdocs/docs/integration/example.cpp index e5a31be4b..1a7ac4de2 100644 --- a/doc/mkdocs/docs/integration/vcpkg/example.cpp +++ b/docs/mkdocs/docs/integration/example.cpp @@ -1,9 +1,10 @@ #include #include +#include using json = nlohmann::json; int main() { - std::cout << json::meta() << std::endl; + std::cout << std::setw(4) << json::meta() << std::endl; } diff --git a/docs/mkdocs/docs/integration/index.md b/docs/mkdocs/docs/integration/index.md new file mode 100644 index 000000000..bfa94ae8a --- /dev/null +++ b/docs/mkdocs/docs/integration/index.md @@ -0,0 +1,18 @@ +# Header only + +[`json.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) is the single required +file in `single_include/nlohmann` or [released here](https://github.com/nlohmann/json/releases). You need to add + +```cpp +#include + +// for convenience +using json = nlohmann::json; +``` + +to the files you want to process JSON and set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and +Clang). + +You can further use file [`include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/json_fwd.hpp) +for forward-declarations. The installation of `json_fwd.hpp` (as part of CMake's install step), can be achieved by +setting `-DJSON_MultipleHeaders=ON`. diff --git a/doc/mkdocs/docs/integration/package_managers.md b/docs/mkdocs/docs/integration/package_managers.md similarity index 78% rename from doc/mkdocs/docs/integration/package_managers.md rename to docs/mkdocs/docs/integration/package_managers.md index d98005da9..c2fb1a7f4 100644 --- a/doc/mkdocs/docs/integration/package_managers.md +++ b/docs/mkdocs/docs/integration/package_managers.md @@ -6,6 +6,12 @@ Throughout this page, we will describe how to compile the example file `example. --8<-- "integration/example.cpp" ``` +When executed, this program should create output similar to + +```json +--8<-- "../../examples/meta.output" +``` + ## Homebrew If you are using OS X and [Homebrew](http://brew.sh), just type @@ -26,11 +32,9 @@ instead. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for 1. Create the following file: - === "example.cpp" - - ```cpp - --8<-- "integration/example.cpp" - ``` + ```cpp title="example.cpp" + --8<-- "integration/example.cpp" + ``` 2. Install the package @@ -50,6 +54,8 @@ instead. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for clang++ example.cpp -I/usr/local/Cellar/nlohmann-json/3.7.3/include -std=c++11 -o example ``` +:material-update: The [formula](https://formulae.brew.sh/formula/nlohmann-json) is updated automatically. + ## Meson If you are using the [Meson Build System](http://mesonbuild.com), add this source tree as a [meson subproject](https://mesonbuild.com/Subprojects.html#using-a-subproject). You may also use the `include.zip` published in this project's [Releases](https://github.com/nlohmann/json/releases) to reduce the size of the vendored source tree. Alternatively, you can get a wrap file by downloading it from [Meson WrapDB](https://wrapdb.mesonbuild.com/nlohmann_json), or simply use `meson wrap install nlohmann_json`. Please see the meson project for any issues regarding the packaging. @@ -64,24 +70,17 @@ If you are using [Conan](https://www.conan.io/) to manage your dependencies, mer 1. Create the following files: - === "Conanfile.txt" - - ```ini - --8<-- "integration/conan/Conanfile.txt" - ``` + ```ini title="Conanfile.txt" + --8<-- "integration/conan/Conanfile.txt" + ``` - === "CMakeLists.txt" - - ```cmake - --8<-- "integration/conan/CMakeLists.txt" - ``` - - === "example.cpp" - - ```cpp - --8<-- "integration/conan/example.cpp" - ``` + ```cmake title="CMakeLists.txt" + --8<-- "integration/conan/CMakeLists.txt" + ``` + ```cpp title="example.cpp" + --8<-- "integration/conan/example.cpp" + ``` 2. Build: @@ -93,6 +92,8 @@ If you are using [Conan](https://www.conan.io/) to manage your dependencies, mer cmake --build . ``` +:material-update: The [package](https://conan.io/center/nlohmann_json) is updated automatically. + ## Spack If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the [`nlohmann-json` package](https://spack.readthedocs.io/en/latest/package_list.html#nlohmann-json). Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging. @@ -113,17 +114,13 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo 1. Create the following files: - === "CMakeLists.txt" - - ```cmake - --8<-- "integration/vcpkg/CMakeLists.txt" - ``` - - === "example.cpp" - - ```cpp - --8<-- "integration/vcpkg/example.cpp" - ``` + ```cmake title="CMakeLists.txt" + --8<-- "integration/vcpkg/CMakeLists.txt" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/vcpkg/example.cpp" + ``` 2. Install package: @@ -146,6 +143,8 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`). +:material-update: cget reads directly from the [GitHub repository](https://github.com/nlohmann/json) and is always up-to-date. + ## CocoaPods If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open). @@ -162,19 +161,27 @@ If you are using [conda](https://conda.io/), you can use the package [nlohmann_j If you are using [MSYS2](http://www.msys2.org/), you can use the [mingw-w64-nlohmann-json](https://packages.msys2.org/base/mingw-w64-nlohmann-json) package, just type `pacman -S mingw-w64-i686-nlohmann-json` or `pacman -S mingw-w64-x86_64-nlohmann-json` for installation. Please file issues [here](https://github.com/msys2/MINGW-packages/issues/new?title=%5Bnlohmann-json%5D) if you experience problems with the packages. +:material-update: The [package](https://packages.msys2.org/base/mingw-w64-nlohmann-json) is updated automatically. + ## MacPorts If you are using [MacPorts](https://ports.macports.org), execute `sudo port install nlohmann-json` to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) package. +:material-update: The [package](https://ports.macports.org/port/nlohmann-json/) is updated automatically. + ## build2 -If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository http://cppget.org or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). +If you are using [`build2`](https://build2.org), you can use the [`nlohmann-json`](https://cppget.org/nlohmann-json) package from the public repository or directly from the [package's sources repository](https://github.com/build2-packaging/nlohmann-json). In your project's `manifest` file, just add `depends: nlohmann-json` (probably with some [version constraints](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml#guide-add-remove-deps)). If you are not familiar with using dependencies in `build2`, [please read this introduction](https://build2.org/build2-toolchain/doc/build2-toolchain-intro.xhtml). Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if you experience problems with the packages. +:material-update: The [package](https://cppget.org/nlohmann-json) is updated automatically. + ## wsjcpp If you are using [`wsjcpp`](http://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch. +:material-update: wsjcpp reads directly from the [GitHub repository](https://github.com/nlohmann/json) and is always up-to-date. + ## CPM.cmake If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), you can check this [`example`](https://github.com/TheLartians/CPM.cmake/tree/master/examples/json). After [adding CPM script](https://github.com/TheLartians/CPM.cmake#adding-cpm) to your project, implement the following snippet to your CMake: diff --git a/doc/mkdocs/docs/integration/pkg-config.md b/docs/mkdocs/docs/integration/pkg-config.md similarity index 100% rename from doc/mkdocs/docs/integration/pkg-config.md rename to docs/mkdocs/docs/integration/pkg-config.md diff --git a/doc/mkdocs/docs/integration/vcpkg/CMakeLists.txt b/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt similarity index 100% rename from doc/mkdocs/docs/integration/vcpkg/CMakeLists.txt rename to docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt diff --git a/doc/mkdocs/docs/integration/example.cpp b/docs/mkdocs/docs/integration/vcpkg/example.cpp similarity index 100% rename from doc/mkdocs/docs/integration/example.cpp rename to docs/mkdocs/docs/integration/vcpkg/example.cpp diff --git a/doc/mkdocs/mkdocs.yml b/docs/mkdocs/mkdocs.yml similarity index 74% rename from doc/mkdocs/mkdocs.yml rename to docs/mkdocs/mkdocs.yml index 542d4f173..65182adbf 100644 --- a/doc/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -6,7 +6,7 @@ site_url: https://json.nlohmann.me/ # Repository repo_name: nlohmann/json repo_url: https://github.com/nlohmann/json -edit_uri: edit/develop/doc/mkdocs/docs +edit_uri: edit/develop/docs/mkdocs/docs # Copyright copyright: Copyright © 2013 - 2022 Niels Lohmann @@ -42,6 +42,7 @@ nav: - features/arbitrary_types.md - Binary Formats: - features/binary_formats/index.md + - features/binary_formats/bjdata.md - features/binary_formats/bson.md - features/binary_formats/cbor.md - features/binary_formats/messagepack.md @@ -60,9 +61,11 @@ nav: - features/object_order.md - Parsing: - features/parsing/index.md + - features/parsing/json_lines.md - features/parsing/parse_exceptions.md - features/parsing/parser_callbacks.md - features/parsing/sax_interface.md + - features/assertions.md - features/enum_conversion.md - features/macros.md - Types: @@ -95,6 +98,7 @@ nav: - 'count': api/basic_json/count.md - 'crbegin': api/basic_json/crbegin.md - 'crend': api/basic_json/crend.md + - 'default_object_comparator_t': api/basic_json/default_object_comparator_t.md - 'diff': api/basic_json/diff.md - 'dump': api/basic_json/dump.md - 'emplace': api/basic_json/emplace.md @@ -106,6 +110,7 @@ nav: - 'exception': api/basic_json/exception.md - 'find': api/basic_json/find.md - 'flatten': api/basic_json/flatten.md + - 'from_bjdata': api/basic_json/from_bjdata.md - 'from_bson': api/basic_json/from_bson.md - 'from_cbor': api/basic_json/from_cbor.md - 'from_msgpack': api/basic_json/from_msgpack.md @@ -149,17 +154,14 @@ nav: - 'operator value_t': api/basic_json/operator_value_t.md - 'operator[]': api/basic_json/operator[].md - 'operator=': api/basic_json/operator=.md + - 'operator+=': api/basic_json/operator+=.md - 'operator==': api/basic_json/operator_eq.md - 'operator!=': api/basic_json/operator_ne.md - 'operator<': api/basic_json/operator_lt.md - - 'operator<<': api/basic_json/operator_ltlt.md - - 'operator<=': api/basic_json/operator_le.md - 'operator>': api/basic_json/operator_gt.md - - 'operator>>': api/basic_json/operator_gtgt.md + - 'operator<=': api/basic_json/operator_le.md - 'operator>=': api/basic_json/operator_ge.md - - 'operator+=': api/basic_json/operator+=.md - - 'operator""_json': api/basic_json/operator_literal_json.md - - 'operator""_json_pointer': api/basic_json/operator_literal_json_pointer.md + - 'operator<=>': api/basic_json/operator_spaceship.md - 'out_of_range': api/basic_json/out_of_range.md - 'other_error': api/basic_json/other_error.md - 'parse': api/basic_json/parse.md @@ -167,6 +169,7 @@ nav: - 'parse_event_t': api/basic_json/parse_event_t.md - 'parser_callback_t': api/basic_json/parser_callback_t.md - 'patch': api/basic_json/patch.md + - 'patch_inplace': api/basic_json/patch_inplace.md - 'push_back': api/basic_json/push_back.md - 'rbegin': api/basic_json/rbegin.md - 'rend': api/basic_json/rend.md @@ -175,6 +178,7 @@ nav: - 'string_t': api/basic_json/string_t.md - 'swap': api/basic_json/swap.md - 'std::swap<basic_json>': api/basic_json/std_swap.md + - 'to_bjdata': api/basic_json/to_bjdata.md - 'to_bson': api/basic_json/to_bson.md - 'to_cbor': api/basic_json/to_cbor.md - 'to_msgpack': api/basic_json/to_msgpack.md @@ -204,12 +208,13 @@ nav: - '(Constructor)': api/json_pointer/json_pointer.md - 'back': api/json_pointer/back.md - 'empty': api/json_pointer/empty.md - - 'operator std::string': api/json_pointer/operator_string.md + - 'operator string_t': api/json_pointer/operator_string_t.md - 'operator/': api/json_pointer/operator_slash.md - 'operator/=': api/json_pointer/operator_slasheq.md - 'parent_pointer': api/json_pointer/parent_pointer.md - 'pop_back': api/json_pointer/pop_back.md - 'push_back': api/json_pointer/push_back.md + - 'string_t': api/json_pointer/string_t.md - 'to_string': api/json_pointer/to_string.md - json_sax: - 'Overview': api/json_sax/index.md @@ -226,11 +231,47 @@ nav: - 'start_array': api/json_sax/start_array.md - 'start_object': api/json_sax/start_object.md - 'string': api/json_sax/string.md + - 'operator<<(basic_json)': api/operator_ltlt.md + - 'operator<<(json_pointer)': api/operator_ltlt.md + - 'operator>>(basic_json)': api/operator_gtgt.md + - 'operator""_json': api/operator_literal_json.md + - 'operator""_json_pointer': api/operator_literal_json_pointer.md - 'ordered_json': api/ordered_json.md - 'ordered_map': api/ordered_map.md - macros: - 'Overview': api/macros/index.md - - 'JSON_ASSERT(x)': api/macros/json_assert.md + - 'JSON_ASSERT': api/macros/json_assert.md + - 'JSON_CATCH_USER': api/macros/json_throw_user.md + - 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md + - 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md + - 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_14': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_17': api/macros/json_has_cpp_11.md + - 'JSON_HAS_CPP_20': api/macros/json_has_cpp_11.md + - 'JSON_HAS_EXPERIMENTAL_FILESYSTEM': api/macros/json_has_filesystem.md + - 'JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md + - 'JSON_HAS_RANGES': api/macros/json_has_ranges.md + - 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md + - 'JSON_NOEXCEPTION': api/macros/json_noexception.md + - 'JSON_NO_IO': api/macros/json_no_io.md + - 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md + - 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md + - 'JSON_THROW_USER': api/macros/json_throw_user.md + - 'JSON_TRY_USER': api/macros/json_throw_user.md + - 'JSON_USE_GLOBAL_UDLS': api/macros/json_use_global_udls.md + - 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md + - 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON': api/macros/json_use_legacy_discarded_value_comparison.md + - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE': api/macros/nlohmann_define_type_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md + - 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md + - 'NLOHMANN_JSON_NAMESPACE': api/macros/nlohmann_json_namespace.md + - 'NLOHMANN_JSON_NAMESPACE_BEGIN': api/macros/nlohmann_json_namespace_begin.md + - 'NLOHMANN_JSON_NAMESPACE_END': api/macros/nlohmann_json_namespace_begin.md + - 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md + - 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md + - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md + - 'NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md # Extras extra: @@ -287,6 +328,17 @@ plugins: lang: en - minify: minify_html: true + - git-revision-date-localized + - redirects: + redirect_maps: + 'api/basic_json/operator_gtgt.md': api/operator_gtgt.md + 'api/basic_json/operator_ltlt.md': api/operator_ltlt.md + 'api/basic_json/operator_literal_json.md': api/operator_literal_json.md + 'api/basic_json/operator_literal_json_pointer.md': api/operator_literal_json_pointer.md + 'api/json_pointer/operator_string.md': api/json_pointer/operator_string_t.md + +extra_css: + - css/custom.css extra_javascript: - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML diff --git a/docs/mkdocs/requirements.txt b/docs/mkdocs/requirements.txt new file mode 100644 index 000000000..51fceb5d3 --- /dev/null +++ b/docs/mkdocs/requirements.txt @@ -0,0 +1,49 @@ +Babel==2.10.1 +certifi==2021.10.8 +charset-normalizer==2.0.12 +click==8.1.2 +csscompressor==0.9.5 +future==0.18.2 +ghp-import==2.0.2 +gitdb==4.0.9 +GitPython==3.1.27 +htmlmin==0.1.12 +httplib2==0.20.4 +idna==3.3 +importlib-metadata==4.11.3 +Jinja2==3.1.1 +joblib==1.1.0 +jsmin==3.0.1 +livereload==2.6.3 +lunr==0.6.2 +Markdown==3.3.6 +markdown-include==0.6.0 +MarkupSafe==2.1.1 +mergedeep==1.3.4 +mkdocs==1.3.0 +mkdocs-git-revision-date-localized-plugin==1.0.1 +mkdocs-material==8.2.10 +mkdocs-material-extensions==1.0.3 +mkdocs-minify-plugin==0.5.0 +mkdocs-redirects==1.0.4 +mkdocs-simple-hooks==0.1.5 +nltk==3.7 +packaging==21.3 +plantuml==0.3.0 +plantuml-markdown==3.5.2 +Pygments==2.11.0 +pymdown-extensions==9.3 +pyparsing==3.0.8 +python-dateutil==2.8.2 +pytz==2022.1 +PyYAML==6.0 +pyyaml_env_tag==0.1 +regex==2022.4.24 +requests==2.27.1 +six==1.16.0 +smmap==5.0.0 +tornado==6.1 +tqdm==4.64.0 +urllib3==1.26.9 +watchdog==2.1.7 +zipp==3.8.0 diff --git a/docs/mkdocs/scripts/check_structure.py b/docs/mkdocs/scripts/check_structure.py new file mode 100755 index 000000000..37c4ce356 --- /dev/null +++ b/docs/mkdocs/scripts/check_structure.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +import glob +import os.path +import re + +warnings = 0 + + +def report(rule, location, description): + global warnings + warnings += 1 + print(f'{warnings:3}. {location}: {description} [{rule}]') + + +def check_structure(): + expected_sections = [ + 'Template parameters', + 'Specializations', + 'Iterator invalidation', + 'Requirements', + 'Member types', + 'Member functions', + 'Member variables', + 'Static functions', + 'Non-member functions', + 'Literals', + 'Helper classes', + 'Parameters', + 'Return value', + 'Exception safety', + 'Exceptions', + 'Complexity', + 'Possible implementation', + 'Default definition', + 'Notes', + 'Examples', + 'See also', + 'Version history' + ] + + required_sections = [ + 'Examples', + 'Version history' + ] + + files = sorted(glob.glob('api/**/*.md', recursive=True)) + for file in files: + with open(file) as file_content: + section_idx = -1 # the index of the current h2 section + existing_sections = [] # the list of h2 sections in the file + in_initial_code_example = False # whether we are inside the first code example block + previous_line = None # the previous read line + h1sections = 0 # the number of h1 sections in the file + last_overload = 0 # the last seen overload number in the code example + documented_overloads = {} # the overloads that have been documented in the current block + current_section = None # the name of the current section + + for lineno, original_line in enumerate(file_content.readlines()): + line = original_line.strip() + + if line.startswith('# '): + h1sections += 1 + + # there should only be one top-level title + if h1sections > 1: + report('structure/unexpected_section', f'{file}:{lineno+1}', f'unexpected top-level title "{line}"') + h1sections = 1 + + # Overview pages should have a better title + if line == '# Overview': + report('style/title', f'{file}:{lineno+1}', 'overview pages should have a better title than "Overview"') + + # lines longer than 160 characters are bad (unless they are tables) + if len(line) > 160 and '|' not in line: + report('whitespace/line_length', f'{file}:{lineno+1} ({current_section})', f'line is too long ({len(line)} vs. 160 chars)') + + # check if sections are correct + if line.startswith('## '): + # before starting a new section, check if the previous one documented all overloads + if current_section in documented_overloads and last_overload != 0: + if len(documented_overloads[current_section]) > 0 and len(documented_overloads[current_section]) != last_overload: + expected = list(range(1, last_overload+1)) + undocumented = [x for x in expected if x not in documented_overloads[current_section]] + unexpected = [x for x in documented_overloads[current_section] if x not in expected] + if len(undocumented): + report('style/numbering', f'{file}:{lineno} ({current_section})', f'undocumented overloads: {", ".join([f"({x})" for x in undocumented])}') + if len(unexpected): + report('style/numbering', f'{file}:{lineno} ({current_section})', f'unexpected overloads: {", ".join([f"({x})" for x in unexpected])}') + + current_section = line.strip('## ') + existing_sections.append(current_section) + + if current_section in expected_sections: + idx = expected_sections.index(current_section) + if idx <= section_idx: + report('structure/section_order', f'{file}:{lineno+1}', f'section "{current_section}" is in an unexpected order (should be before "{expected_sections[section_idx]}")') + section_idx = idx + else: + if 'index.md' not in file: # index.md files may have a different structure + report('structure/unknown_section', f'{file}:{lineno+1}', f'section "{current_section}" is not part of the expected sections') + + # collect the numbered items of the current section to later check if they match the number of overloads + if last_overload != 0 and not in_initial_code_example: + if len(original_line) and original_line[0].isdigit(): + number = int(re.findall(r"^(\d+).", original_line)[0]) + if current_section not in documented_overloads: + documented_overloads[current_section] = [] + documented_overloads[current_section].append(number) + + # code example + if line == '```cpp' and section_idx == -1: + in_initial_code_example = True + + if in_initial_code_example and line.startswith('//') and line not in ['// since C++20', '// until C++20']: + # check numbering of overloads + if any(map(str.isdigit, line)): + number = int(re.findall(r'\d+', line)[0]) + if number != last_overload + 1: + report('style/numbering', f'{file}:{lineno+1}', f'expected number ({number}) to be ({last_overload +1 })') + last_overload = number + + if any(map(str.isdigit, line)) and '(' not in line: + report('style/numbering', f'{file}:{lineno+1}', f'number should be in parentheses: {line}') + + if line == '```' and in_initial_code_example: + in_initial_code_example = False + + # consecutive blank lines are bad + if line == '' and previous_line == '': + report('whitespace/blank_lines', f'{file}:{lineno}-{lineno+1} ({current_section})', 'consecutive blank lines') + + # check that non-example admonitions have titles + untitled_admonition = re.match(r'^(\?\?\?|!!!) ([^ ]+)$', line) + if untitled_admonition and untitled_admonition.group(2) != 'example': + report('style/admonition_title', f'{file}:{lineno} ({current_section})', f'"{untitled_admonition.group(2)}" admonitions should have a title') + + previous_line = line + + if 'index.md' not in file: # index.md files may have a different structure + for required_section in required_sections: + if required_section not in existing_sections: + report('structure/missing_section', f'{file}:{lineno+1}', f'required section "{required_section}" was not found') + + +def check_examples(): + example_files = sorted(glob.glob('../../examples/*.cpp')) + markdown_files = sorted(glob.glob('**/*.md', recursive=True)) + + # check if every example file is used in at least one markdown file + for example_file in example_files: + example_file = os.path.join('examples', os.path.basename(example_file)) + + found = False + for markdown_file in markdown_files: + content = ' '.join(open(markdown_file).readlines()) + if example_file in content: + found = True + break + + if not found: + report('examples/missing', f'{example_file}', 'example file is not used in any documentation file') + + +if __name__ == '__main__': + print(120 * '-') + check_structure() + check_examples() + print(120 * '-') diff --git a/doc/usages/ios.png b/docs/usages/ios.png similarity index 100% rename from doc/usages/ios.png rename to docs/usages/ios.png diff --git a/doc/usages/macos.png b/docs/usages/macos.png similarity index 100% rename from doc/usages/macos.png rename to docs/usages/macos.png diff --git a/include/nlohmann/adl_serializer.hpp b/include/nlohmann/adl_serializer.hpp index 030063ea5..bc222b469 100644 --- a/include/nlohmann/adl_serializer.hpp +++ b/include/nlohmann/adl_serializer.hpp @@ -1,15 +1,21 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once -#include #include +#include #include #include #include -#include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /// @sa https://json.nlohmann.me/api/adl_serializer/ template @@ -45,4 +51,5 @@ struct adl_serializer ::nlohmann::to_json(j, std::forward(val)); } }; -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/byte_container_with_subtype.hpp b/include/nlohmann/byte_container_with_subtype.hpp index 6e9e38d16..4432d31ae 100644 --- a/include/nlohmann/byte_container_with_subtype.hpp +++ b/include/nlohmann/byte_container_with_subtype.hpp @@ -1,11 +1,20 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // uint8_t, uint64_t #include // tie #include // move -namespace nlohmann -{ +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN /// @brief an internal type for a backed binary type /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/ @@ -91,4 +100,4 @@ class byte_container_with_subtype : public BinaryType bool m_has_subtype = false; }; -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/abi_macros.hpp b/include/nlohmann/detail/abi_macros.hpp new file mode 100644 index 000000000..19c5d516c --- /dev/null +++ b/include/nlohmann/detail/abi_macros.hpp @@ -0,0 +1,79 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 0 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \ + json_v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \ + NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) + +#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c +#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) + +#define NLOHMANN_JSON_ABI_STRING \ + NLOHMANN_JSON_ABI_CONCAT( \ + NLOHMANN_JSON_ABI_PREFIX( \ + NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH), \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +#ifndef NLOHMANN_JSON_NAMESPACE + #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_ABI_STRING \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (abi_string) */ \ + } /* namespace nlohmann */ +#endif diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 207d3e302..a0d37e961 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // transform @@ -16,33 +24,21 @@ #include #include #include +#include #include +#include #include -#if JSON_HAS_EXPERIMENTAL_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::experimental::filesystem; -} // namespace nlohmann::detail -#elif JSON_HAS_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::filesystem; -} // namespace nlohmann::detail -#endif - -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j)); } n = nullptr; } @@ -80,82 +76,84 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) case value_t::binary: case value_t::discarded: default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j)); } b = *j.template get_ptr(); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr(); } template < - typename BasicJsonType, typename ConstructibleStringType, + typename BasicJsonType, typename StringType, enable_if_t < - is_constructible_string_type::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ConstructibleStringType& s) + std::is_assignable::value + && is_detected_exact::value + && !std::is_same::value + && !is_json_ref::value, int > = 0 > +inline void from_json(const BasicJsonType& j, StringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } s = *j.template get_ptr(); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) { get_arithmetic_value(j, val); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) { get_arithmetic_value(j, val); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) { get_arithmetic_value(j, val); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) +inline void from_json(const BasicJsonType& j, EnumType& e) { typename std::underlying_type::type val; get_arithmetic_value(j, val); e = static_cast(val); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION // forward_list doesn't have an insert method template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) +inline void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.clear(); std::transform(j.rbegin(), j.rend(), @@ -168,11 +166,11 @@ void from_json(const BasicJsonType& j, std::forward_list& l) // valarray doesn't have an insert method template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) +inline void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), @@ -193,7 +191,7 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines } template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { arr = *j.template get_ptr(); } @@ -237,8 +235,8 @@ template::value, int> = 0> -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) +inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) { using std::end; @@ -269,7 +267,7 @@ void()) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } from_json_array_impl(j, arr, priority_tag<3> {}); @@ -288,18 +286,18 @@ auto from_json(BasicJsonType&& j, identity_tag> tag) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_inplace_array_impl(std::forward(j), tag, make_index_sequence {}); } template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) +inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j)); } bin = *j.template get_ptr(); @@ -307,11 +305,11 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j)); } ConstructibleObjectType ret; @@ -339,7 +337,7 @@ template < typename BasicJsonType, typename ArithmeticType, !std::is_same::value&& !std::is_same::value, int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) +inline void from_json(const BasicJsonType& j, ArithmeticType& val) { switch (static_cast(j)) { @@ -371,7 +369,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) case value_t::binary: case value_t::discarded: default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j)); } } @@ -389,7 +387,7 @@ std::pair from_json_tuple_impl(BasicJsonType&& j, identity_tag -void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) +inline void from_json_tuple_impl(BasicJsonType&& j, std::pair& p, priority_tag<1> /*unused*/) { p = from_json_tuple_impl(std::forward(j), identity_tag> {}, priority_tag<0> {}); } @@ -401,7 +399,7 @@ std::tuple from_json_tuple_impl(BasicJsonType&& j, identity_tag -void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) +inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple& t, priority_tag<3> /*unused*/) { t = from_json_tuple_impl_base(std::forward(j), index_sequence_for {}); } @@ -412,7 +410,7 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } return from_json_tuple_impl(std::forward(j), std::forward(t), priority_tag<3> {}); @@ -421,18 +419,18 @@ auto from_json(BasicJsonType&& j, TupleRelated&& t) template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) +inline void from_json(const BasicJsonType& j, std::map& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } @@ -441,18 +439,18 @@ void from_json(const BasicJsonType& j, std::map& template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, typename = enable_if_t < !std::is_constructible < typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) +inline void from_json(const BasicJsonType& j, std::unordered_map& m) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } @@ -460,11 +458,11 @@ void from_json(const BasicJsonType& j, std::unordered_map -void from_json(const BasicJsonType& j, std_fs::path& p) +inline void from_json(const BasicJsonType& j, std_fs::path& p) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); + JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j)); } p = *j.template get_ptr(); } @@ -480,13 +478,20 @@ struct from_json_fn return from_json(j, std::forward(val)); } }; + } // namespace detail +#ifndef JSON_HAS_CPP_17 /// namespace to hold default `from_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { -constexpr const auto& from_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) -} // namespace -} // namespace nlohmann +#endif +JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 +} // namespace +#endif + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp index f6c729b07..608b4574b 100644 --- a/include/nlohmann/detail/conversions/to_chars.hpp +++ b/include/nlohmann/detail/conversions/to_chars.hpp @@ -1,3 +1,12 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2009 Florian Loitsch +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // array @@ -9,8 +18,7 @@ #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -1039,7 +1047,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent, return append_exponent(buf, n - 1); } -} // namespace dtoa_impl +} // namespace dtoa_impl /*! @brief generates a decimal representation of the floating-point number value in [first, last). @@ -1106,5 +1114,5 @@ char* to_chars(char* first, const char* last, FloatType value) return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); } -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 7628ae011..e25e0102b 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // copy @@ -9,30 +17,17 @@ #include // valarray #include // vector -#include #include +#include #include +#include #include #include -#if JSON_HAS_EXPERIMENTAL_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::experimental::filesystem; -} // namespace nlohmann::detail -#elif JSON_HAS_FILESYSTEM -#include -namespace nlohmann::detail -{ -namespace std_fs = std::filesystem; -} // namespace nlohmann::detail -#endif - -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + ////////////////// // constructors // ////////////////// @@ -267,55 +262,64 @@ struct external_constructor template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept +inline void to_json(BasicJsonType& j, T b) noexcept { external_constructor::construct(j, b); } +template::reference&, typename BasicJsonType::boolean_t>::value, int> = 0> +inline void to_json(BasicJsonType& j, const std::vector::reference& b) noexcept +{ + external_constructor::construct(j, static_cast(b)); +} + template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) +inline void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); } template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) { external_constructor::construct(j, std::move(s)); } template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept +inline void to_json(BasicJsonType& j, FloatType val) noexcept { external_constructor::construct(j, static_cast(val)); } template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); } template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); } +#if !JSON_DISABLE_ENUM_SERIALIZATION template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept +inline void to_json(BasicJsonType& j, EnumType e) noexcept { using underlying_type = typename std::underlying_type::type; external_constructor::construct(j, static_cast(e)); } +#endif // JSON_DISABLE_ENUM_SERIALIZATION template -void to_json(BasicJsonType& j, const std::vector& e) +inline void to_json(BasicJsonType& j, const std::vector& e) { external_constructor::construct(j, e); } @@ -328,39 +332,39 @@ template < typename BasicJsonType, typename CompatibleArrayType, !std::is_same::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { external_constructor::construct(j, arr); } template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) +inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) { external_constructor::construct(j, bin); } template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) +inline void to_json(BasicJsonType& j, const std::valarray& arr) { external_constructor::construct(j, std::move(arr)); } template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { external_constructor::construct(j, std::move(arr)); } template < typename BasicJsonType, typename CompatibleObjectType, enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); } template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { external_constructor::construct(j, std::move(obj)); } @@ -370,13 +374,13 @@ template < enable_if_t < !std::is_constructible::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) { external_constructor::construct(j, arr); } template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) +inline void to_json(BasicJsonType& j, const std::pair& p) { j = { p.first, p.second }; } @@ -384,26 +388,26 @@ void to_json(BasicJsonType& j, const std::pair& p) // for https://github.com/nlohmann/json/pull/1134 template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) +inline void to_json(BasicJsonType& j, const T& b) { j = { {b.key(), b.value()} }; } template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) { j = { std::get(t)... }; } template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) +inline void to_json(BasicJsonType& j, const T& t) { to_json_tuple_impl(j, t, make_index_sequence::value> {}); } #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM template -void to_json(BasicJsonType& j, const std_fs::path& p) +inline void to_json(BasicJsonType& j, const std_fs::path& p) { j = p.string(); } @@ -420,11 +424,17 @@ struct to_json_fn }; } // namespace detail +#ifndef JSON_HAS_CPP_17 /// namespace to hold default `to_json` function /// to see why this is required: /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces) { -constexpr const auto& to_json = detail::static_const::value; // NOLINT(misc-definitions-in-headers) -} // namespace -} // namespace nlohmann +#endif +JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers) + detail::static_const::value; +#ifndef JSON_HAS_CPP_17 +} // namespace +#endif + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index b4b180496..b84094ce6 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -1,5 +1,14 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once +#include // nullptr_t #include // exception #include // runtime_error #include // to_string @@ -9,11 +18,15 @@ #include #include #include +#include +#include +#include -namespace nlohmann -{ + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + //////////////// // exceptions // //////////////// @@ -38,15 +51,20 @@ class exception : public std::exception static std::string name(const std::string& ename, int id_) { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + return concat("[json.exception.", ename, '.', std::to_string(id_), "] "); + } + + static std::string diagnostics(std::nullptr_t /*leaf_element*/) + { + return ""; } template - static std::string diagnostics(const BasicJsonType& leaf_element) + static std::string diagnostics(const BasicJsonType* leaf_element) { #if JSON_DIAGNOSTICS std::vector tokens; - for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent) + for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent) { switch (current->m_parent->type()) { @@ -94,11 +112,12 @@ class exception : public std::exception return ""; } - return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, - [](const std::string & a, const std::string & b) + auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) { - return a + "/" + detail::escape(b); - }) + ") "; + return concat(a, '/', detail::escape(b)); + }); + return concat('(', str, ") "); #else static_cast(leaf_element); return ""; @@ -124,20 +143,20 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ - template - static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("parse_error", id_), "parse error", + position_string(pos), ": ", exception::diagnostics(context), what_arg); return {id_, pos.chars_read_total, w.c_str()}; } - template - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("parse_error", id_), "parse error", + (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), + ": ", exception::diagnostics(context), what_arg); return {id_, byte_, w.c_str()}; } @@ -158,8 +177,8 @@ class parse_error : public exception static std::string position_string(const position_t& pos) { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); + return concat(" at line ", std::to_string(pos.lines_read + 1), + ", column ", std::to_string(pos.chars_read_current_line)); } }; @@ -168,10 +187,10 @@ class parse_error : public exception class invalid_iterator : public exception { public: - template - static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -186,10 +205,10 @@ class invalid_iterator : public exception class type_error : public exception { public: - template - static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -203,10 +222,10 @@ class type_error : public exception class out_of_range : public exception { public: - template - static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -220,10 +239,10 @@ class out_of_range : public exception class other_error : public exception { public: - template - static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context) + template::value, int> = 0> + static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg; + std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -233,4 +252,4 @@ class other_error : public exception }; } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/hash.hpp b/include/nlohmann/detail/hash.hpp index 776b9ca61..032afe09c 100644 --- a/include/nlohmann/detail/hash.hpp +++ b/include/nlohmann/detail/hash.hpp @@ -1,14 +1,21 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // uint8_t #include // size_t #include // hash -#include +#include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -119,4 +126,4 @@ std::size_t hash(const BasicJsonType& j) } } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 65e0047ac..8ba66acb2 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // generate_n @@ -12,6 +20,7 @@ #include // char_traits, string #include // make_pair, move #include // vector +#include // map #include #include @@ -20,10 +29,10 @@ #include #include #include +#include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -73,7 +82,7 @@ class binary_reader @param[in] adapter input adapter to read from */ - explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter)) + explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) { (void)detail::is_sax_static_asserts {}; } @@ -117,6 +126,7 @@ class binary_reader break; case input_format_t::ubjson: + case input_format_t::bjdata: result = parse_ubjson_internal(); break; @@ -128,7 +138,7 @@ class binary_reader // strict mode: next byte must be EOF if (result && strict) { - if (format == input_format_t::ubjson) + if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) { get_ignore_noop(); } @@ -139,8 +149,8 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { - return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType())); + return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, + exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); } } @@ -216,7 +226,8 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 1)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); } return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); @@ -237,7 +248,8 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 0)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr)); } // All BSON binary values have a subtype @@ -319,7 +331,9 @@ class binary_reader { std::array cr{{}}; static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType())); + std::string cr_str{cr.data()}; + return sax->parse_error(element_type_parse_position, cr_str, + parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); } } } @@ -611,7 +625,8 @@ class binary_reader case 0x95: case 0x96: case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); + return get_cbor_array( + conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0x98: // array (one-byte uint8_t for n follows) { @@ -628,13 +643,13 @@ class binary_reader case 0x9A: // array (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); } case 0x9B: // array (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast(len), tag_handler); } case 0x9F: // array (indefinite length) @@ -665,7 +680,7 @@ class binary_reader case 0xB5: case 0xB6: case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); + return get_cbor_object(conditional_static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0xB8: // map (one-byte uint8_t for n follows) { @@ -682,13 +697,13 @@ class binary_reader case 0xBA: // map (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); } case 0xBB: // map (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast(len), tag_handler); + return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast(len), tag_handler); } case 0xBF: // map (indefinite length) @@ -719,7 +734,8 @@ class binary_reader case cbor_tag_handler_t::error: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); } case cbor_tag_handler_t::ignore: @@ -876,7 +892,8 @@ class binary_reader default: // anything else (0xFF is handled inside the other types) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -971,7 +988,8 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -1070,7 +1088,8 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr)); } } } @@ -1331,7 +1350,7 @@ class binary_reader case 0x8D: case 0x8E: case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + return get_msgpack_object(conditional_static_cast(static_cast(current) & 0x0Fu)); // fixarray case 0x90: @@ -1350,7 +1369,7 @@ class binary_reader case 0x9D: case 0x9E: case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + return get_msgpack_array(conditional_static_cast(static_cast(current) & 0x0Fu)); // fixstr case 0xA0: @@ -1487,7 +1506,7 @@ class binary_reader case 0xDD: // array 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); + return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast(len)); } case 0xDE: // map 16 @@ -1499,7 +1518,7 @@ class binary_reader case 0xDF: // map 32 { std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); + return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast(len)); } // negative fixint @@ -1540,7 +1559,8 @@ class binary_reader default: // anything else { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr)); } } } @@ -1622,7 +1642,8 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr)); } } } @@ -1833,7 +1854,7 @@ class binary_reader get(); // TODO(niels): may we ignore N here? } - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } @@ -1843,51 +1864,162 @@ class binary_reader case 'U': { std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'i': { std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'I': { std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'l': { std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); } case 'L': { std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t len{}; + return get_number(input_format, len) && get_string(input_format, len, result); } default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType())); + break; } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr)); + } + + /*! + @param[out] dim an integer vector storing the ND array dimensions + @return whether reading ND array size vector is successful + */ + bool get_ubjson_ndarray_size(std::vector& dim) + { + std::pair size_and_type; + size_t dimlen = 0; + bool no_ndarray = true; + + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) + { + return false; + } + dim.push_back(dimlen); + get_ignore_noop(); + } + } + return true; } /*! @param[out] result determined size + @param[in,out] is_ndarray for input, `true` means already inside an ndarray vector + or ndarray dimension is not allowed; `false` means ndarray + is allowed; for output, `true` means an ndarray is found; + is_ndarray can only return `true` when its initial value + is `false` + @param[in] prefix type marker if already read, otherwise set to 0 + @return whether size determination completed */ - bool get_ubjson_size_value(std::size_t& result) + bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0) { - switch (get_ignore_noop()) + if (prefix == 0) + { + prefix = get_ignore_noop(); + } + + switch (prefix) { case 'U': { std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } @@ -1898,10 +2030,15 @@ class binary_reader case 'i': { std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char return true; } @@ -1909,10 +2046,15 @@ class binary_reader case 'I': { std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); return true; } @@ -1920,10 +2062,15 @@ class binary_reader case 'l': { std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } result = static_cast(number); return true; } @@ -1931,7 +2078,32 @@ class binary_reader case 'L': { std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (number < 0) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, + exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr)); + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = static_cast(number); + return true; + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) { return false; } @@ -1939,12 +2111,112 @@ class binary_reader return true; } - default: + case 'm': { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType())); + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = conditional_static_cast(number); + return true; } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + if (!value_in_range_of(number)) + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, + exception_message(input_format, "integer value overflow", "size"), nullptr)); + } + result = detail::conditional_static_cast(number); + return true; + } + + case '[': + { + if (input_format != input_format_t::bjdata) + { + break; + } + if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr)); + } + std::vector dim; + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) + { + return false; + } + if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector + { + result = dim.at(dim.size() - 1); + return true; + } + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format + { + for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container + { + if ( i == 0 ) + { + result = 0; + return true; + } + } + + string_t key = "_ArraySize_"; + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) + { + return false; + } + result = 1; + for (auto i : dim) + { + result *= i; + if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type() + { + return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); + } + if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast(i)))) + { + return false; + } + } + is_ndarray = true; + return sax->end_array(); + } + result = 0; + return true; + } + + default: + break; } + auto last_token = get_token_string(); + std::string message; + + if (input_format != input_format_t::bjdata) + { + message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token; + } + else + { + message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token; + } + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr)); } /*! @@ -1954,20 +2226,31 @@ class binary_reader for a more compact representation. @param[out] result pair of the size and the type + @param[in] inside_ndarray whether the parser is parsing an ND array dimensional vector @return whether pair creation completed */ - bool get_ubjson_size_type(std::pair& result) + bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) { result.first = string_t::npos; // size result.second = 0; // type + bool is_ndarray = false; get_ignore_noop(); if (current == '$') { + std::vector bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type + result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) + if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() )) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type"))) { return false; } @@ -1975,20 +2258,37 @@ class binary_reader get_ignore_noop(); if (JSON_HEDLEY_UNLIKELY(current != '#')) { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value"))) { return false; } auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } - return get_ubjson_size_value(result.first); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + if (inside_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray can not be recursive", "size"), nullptr)); + } + result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters + } + return is_error; } if (current == '#') { - return get_ubjson_size_value(result.first); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); + if (input_format == input_format_t::bjdata && is_ndarray) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, + exception_message(input_format, "ndarray requires both type and size", "size"), nullptr)); + } + return is_error; } return true; @@ -2003,7 +2303,7 @@ class binary_reader switch (prefix) { case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); + return unexpect_eof(input_format, "value"); case 'T': // true return sax->boolean(true); @@ -2016,43 +2316,125 @@ class binary_reader case 'U': { std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); + return get_number(input_format, number) && sax->number_unsigned(number); } case 'i': { std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'I': { std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'l': { std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); } case 'L': { std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); + return get_number(input_format, number) && sax->number_integer(number); + } + + case 'u': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint16_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'M': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint64_t number{}; + return get_number(input_format, number) && sax->number_unsigned(number); + } + + case 'h': + { + if (input_format != input_format_t::bjdata) + { + break; + } + const auto byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + const auto byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte2 << 8u) + byte1); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + JSON_ASSERT(0 <= exp&& exp <= 32); + JSON_ASSERT(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); } case 'd': { float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); } case 'D': { double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); + return get_number(input_format, number) && sax->number_float(static_cast(number), ""); } case 'H': @@ -2063,14 +2445,15 @@ class binary_reader case 'C': // char { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char"))) { return false; } if (JSON_HEDLEY_UNLIKELY(current > 127)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, + exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr)); } string_t s(1, static_cast(current)); return sax->string(s); @@ -2089,11 +2472,10 @@ class binary_reader return get_ubjson_object(); default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); - } + break; } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr)); } /*! @@ -2107,6 +2489,52 @@ class binary_reader return false; } + // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): + // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} + + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + { + std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, + {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} + }; + + size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker + + string_t key = "_ArrayType_"; + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); + } + + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + { + return false; + } + + if (size_and_type.second == 'C') + { + size_and_type.second = 'U'; + } + + key = "_ArrayData_"; + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) + { + return false; + } + + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) + { + return false; + } + } + + return (sax->end_array() && sax->end_object()); + } + if (size_and_type.first != string_t::npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) @@ -2169,6 +2597,14 @@ class binary_reader return false; } + // do not accept ND-array size in objects in BJData + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, + exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr)); + } + string_t key; if (size_and_type.first != string_t::npos) { @@ -2240,7 +2676,8 @@ class binary_reader { // get size of following number string std::size_t size{}; - auto res = get_ubjson_size_value(size); + bool no_ndarray = true; + auto res = get_ubjson_size_value(size, no_ndarray); if (JSON_HEDLEY_UNLIKELY(!res)) { return res; @@ -2251,7 +2688,7 @@ class binary_reader for (std::size_t i = 0; i < size; ++i) { get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number"))) { return false; } @@ -2269,7 +2706,8 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); } switch (result_number) @@ -2295,7 +2733,8 @@ class binary_reader case token_type::end_of_input: case token_type::literal_or_value: default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, + exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr)); } } @@ -2344,6 +2783,8 @@ class binary_reader @note This function needs to respect the system's endianness, because bytes in CBOR, MessagePack, and UBJSON are stored in network order (big endian) and therefore need reordering on little endian systems. + On the other hand, BSON and BJData use little endian and should reorder + on big endian systems. */ template bool get_number(const input_format_t format, NumberType& result) @@ -2359,7 +2800,7 @@ class binary_reader } // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) { vec[sizeof(NumberType) - i - 1] = static_cast(current); } @@ -2451,7 +2892,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) { return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType())); + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); } return true; } @@ -2496,12 +2937,16 @@ class binary_reader error_msg += "BSON"; break; + case input_format_t::bjdata: + error_msg += "BJData"; + break; + case input_format_t::json: // LCOV_EXCL_LINE default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } - return error_msg + " " + context + ": " + detail; + return concat(error_msg, ' ', context, ": ", detail); } private: @@ -2517,8 +2962,12 @@ class binary_reader /// whether we can assume little endianness const bool is_little_endian = little_endianness(); + /// input format + const input_format_t input_format = input_format_t::json; + /// the SAX parser json_sax_t* sax = nullptr; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index d196aec54..1ae08ea58 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // array @@ -18,12 +26,12 @@ #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; +enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata }; //////////////////// // input adapters // @@ -42,7 +50,9 @@ class file_input_adapter JSON_HEDLEY_NON_NULL(2) explicit file_input_adapter(std::FILE* f) noexcept : m_file(f) - {} + { + JSON_ASSERT(m_file != nullptr); + } // make class move-only file_input_adapter(const file_input_adapter&) = delete; @@ -400,7 +410,7 @@ struct container_input_adapter_factory< ContainerType, } }; -} // namespace container_input_adapter_factory_impl +} // namespace container_input_adapter_factory_impl template typename container_input_adapter_factory_impl::container_input_adapter_factory::adapter_type input_adapter(const ContainerType& container) @@ -479,5 +489,6 @@ class span_input_adapter private: contiguous_bytes_input_adapter ia; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index fd9dab87a..416d153c2 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include @@ -7,9 +15,9 @@ #include #include +#include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief SAX interface @@ -224,7 +232,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); } return true; @@ -232,6 +240,9 @@ class json_sax_dom_parser bool key(string_t& val) { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + // add null at given key and store the reference for later object_element = &(ref_stack.back()->m_value.object->operator[](val)); return true; @@ -239,6 +250,9 @@ class json_sax_dom_parser bool end_object() { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; @@ -250,7 +264,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); } return true; @@ -258,6 +272,9 @@ class json_sax_dom_parser bool end_array() { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_array()); + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; @@ -405,7 +422,7 @@ class json_sax_dom_callback_parser // check object limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); } return true; @@ -475,7 +492,7 @@ class json_sax_dom_callback_parser // check array limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); } return true; @@ -706,6 +723,6 @@ class json_sax_acceptor return false; } }; -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index d0c063a1c..371b19d5f 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // array @@ -14,10 +22,10 @@ #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /////////// // lexer // /////////// @@ -1619,5 +1627,6 @@ scan_number_done: /// the decimal point const char_int_type decimal_point_char = '.'; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index 024dd040f..106c66f12 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // isfinite @@ -13,10 +21,10 @@ #include #include #include +#include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { //////////// @@ -95,7 +103,7 @@ class parser sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"), BasicJsonType())); + exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value @@ -122,7 +130,7 @@ class parser { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } // in case of an error, return discarded value @@ -160,7 +168,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr)); } return result; @@ -206,7 +214,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { @@ -218,7 +226,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // remember we are now inside an object @@ -261,7 +269,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType())); + out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) @@ -331,7 +339,7 @@ class parser // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); } case token_type::uninitialized: @@ -345,7 +353,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); } } } @@ -391,7 +399,7 @@ class parser return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr)); } // states.back() is false -> object @@ -404,7 +412,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr)); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) @@ -417,7 +425,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr)); } // parse values @@ -445,7 +453,7 @@ class parser return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType())); + parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr)); } } @@ -461,24 +469,24 @@ class parser if (!context.empty()) { - error_msg += "while parsing " + context + " "; + error_msg += concat("while parsing ", context, ' '); } error_msg += "- "; if (last_token == token_type::parse_error) { - error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + - m_lexer.get_token_string() + "'"; + error_msg += concat(m_lexer.get_error_message(), "; last read: '", + m_lexer.get_token_string(), '\''); } else { - error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + error_msg += concat("unexpected ", lexer_t::token_type_name(last_token)); } if (expected != token_type::uninitialized) { - error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + error_msg += concat("; expected ", lexer_t::token_type_name(expected)); } return error_msg; @@ -496,4 +504,4 @@ class parser }; } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/input/position_t.hpp b/include/nlohmann/detail/input/position_t.hpp index 14e9649fb..949d06da5 100644 --- a/include/nlohmann/detail/input/position_t.hpp +++ b/include/nlohmann/detail/input/position_t.hpp @@ -1,11 +1,21 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // size_t -namespace nlohmann -{ +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /// struct to capture the start position of the current token struct position_t { @@ -23,5 +33,5 @@ struct position_t } }; -} // namespace detail -} // namespace nlohmann +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/iterators/internal_iterator.hpp b/include/nlohmann/detail/iterators/internal_iterator.hpp index 2c81f723f..24a559e7b 100644 --- a/include/nlohmann/detail/iterators/internal_iterator.hpp +++ b/include/nlohmann/detail/iterators/internal_iterator.hpp @@ -1,11 +1,20 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once +#include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /*! @brief an iterator value @@ -21,5 +30,6 @@ template struct internal_iterator /// generic iterator for all other types primitive_iterator_t primitive_iterator {}; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 434a62d3e..6152c94f8 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next @@ -11,10 +19,10 @@ #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + // forward declare, to be able to friend it later on template class iteration_proxy; template class iteration_proxy_value; @@ -51,9 +59,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci // make sure BasicJsonType is basic_json or const basic_json static_assert(is_basic_json::type>::value, "iter_impl only accepts (const) basic_json"); + // superficial check for the LegacyBidirectionalIterator named requirement + static_assert(std::is_base_of::value + && std::is_base_of::iterator_category>::value, + "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement."); public: - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. /// The C++ Standard has never required user-defined iterators to derive from std::iterator. /// A user-defined iterator should provide publicly accessible typedefs named @@ -285,7 +296,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci } case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); case value_t::string: case value_t::boolean: @@ -301,7 +312,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); } } } @@ -343,7 +354,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci return m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); } } } @@ -352,7 +363,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief post-increment (it++) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl const operator++(int) // NOLINT(readability-const-return-type) + iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp) { auto result = *this; ++(*this); @@ -403,7 +414,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci @brief post-decrement (it--) @pre The iterator is initialized; i.e. `m_object != nullptr`. */ - iter_impl const operator--(int) // NOLINT(readability-const-return-type) + iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp) { auto result = *this; --(*this); @@ -460,7 +471,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } JSON_ASSERT(m_object != nullptr); @@ -505,7 +516,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } JSON_ASSERT(m_object != nullptr); @@ -513,7 +524,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); @@ -569,7 +580,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); case value_t::array: { @@ -648,7 +659,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; @@ -677,13 +688,13 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); case value_t::array: return *std::next(m_it.array_iterator, n); case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); case value_t::string: case value_t::boolean: @@ -699,7 +710,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); + JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object)); } } } @@ -717,7 +728,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci return m_it.object_iterator->first; } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object)); } /*! @@ -735,5 +746,6 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /// the actual iterator of the associated instance internal_iterator::type> m_it {}; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp index 9994b364c..19bd3e64e 100644 --- a/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // size_t @@ -6,13 +14,18 @@ #include // tuple_size, get, tuple_element #include // move +#if JSON_HAS_RANGES + #include // enable_borrowed_range +#endif + +#include #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template void int_to_string( string_type& target, std::size_t value ) { @@ -25,14 +38,14 @@ template class iteration_proxy_value public: using difference_type = std::ptrdiff_t; using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; + using pointer = value_type *; + using reference = value_type &; using iterator_category = std::input_iterator_tag; using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: /// the iterator - IteratorType anchor; + IteratorType anchor{}; /// an index for arrays (used to create key names) std::size_t array_index = 0; /// last stringified array index @@ -40,15 +53,30 @@ template class iteration_proxy_value /// a string representation of the array index mutable string_type array_index_str = "0"; /// an empty string (to return a reference for primitive values) - const string_type empty_str{}; + string_type empty_str{}; public: - explicit iteration_proxy_value(IteratorType it) noexcept + explicit iteration_proxy_value() = default; + explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_default_constructible::value) : anchor(std::move(it)) + , array_index(array_index_) {} + iteration_proxy_value(iteration_proxy_value const&) = default; + iteration_proxy_value& operator=(iteration_proxy_value const&) = default; + // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions + iteration_proxy_value(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_constructible::value + && std::is_nothrow_move_constructible::value) = default; + iteration_proxy_value& operator=(iteration_proxy_value&&) + noexcept(std::is_nothrow_move_assignable::value + && std::is_nothrow_move_assignable::value) = default; + ~iteration_proxy_value() = default; + /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() + const iteration_proxy_value& operator*() const { return *this; } @@ -62,6 +90,14 @@ template class iteration_proxy_value return *this; } + iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp) + { + auto tmp = iteration_proxy_value(anchor, array_index); + ++anchor; + ++array_index; + return tmp; + } + /// equality operator (needed for InputIterator) bool operator==(const iteration_proxy_value& o) const { @@ -122,25 +158,34 @@ template class iteration_proxy { private: /// the container to iterate - typename IteratorType::reference container; + typename IteratorType::pointer container = nullptr; public: + explicit iteration_proxy() = default; + /// construct iteration proxy from a container explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} + : container(&cont) {} + + iteration_proxy(iteration_proxy const&) = default; + iteration_proxy& operator=(iteration_proxy const&) = default; + iteration_proxy(iteration_proxy&&) noexcept = default; + iteration_proxy& operator=(iteration_proxy&&) noexcept = default; + ~iteration_proxy() = default; /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept + iteration_proxy_value begin() const noexcept { - return iteration_proxy_value(container.begin()); + return iteration_proxy_value(container->begin()); } /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept + iteration_proxy_value end() const noexcept { - return iteration_proxy_value(container.end()); + return iteration_proxy_value(container->end()); } }; + // Structured Bindings Support // For further reference see https://blog.tartanllama.xyz/structured-bindings/ // And see https://github.com/nlohmann/json/pull/1391 @@ -157,8 +202,9 @@ auto get(const nlohmann::detail::iteration_proxy_value& i) -> decl { return i.value(); } + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // The Addition to the STD Namespace is required to add // Structured Bindings Support to the iteration_proxy_value class @@ -166,6 +212,7 @@ auto get(const nlohmann::detail::iteration_proxy_value& i) -> decl // And see https://github.com/nlohmann/json/pull/1391 namespace std { + #if defined(__clang__) // Fix: https://github.com/nlohmann/json/issues/1401 #pragma clang diagnostic push @@ -186,4 +233,10 @@ class tuple_element> #if defined(__clang__) #pragma clang diagnostic pop #endif -} // namespace std + +} // namespace std + +#if JSON_HAS_RANGES + template + inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; +#endif diff --git a/include/nlohmann/detail/iterators/iterator_traits.hpp b/include/nlohmann/detail/iterators/iterator_traits.hpp index da5636188..b04914d7e 100644 --- a/include/nlohmann/detail/iterators/iterator_traits.hpp +++ b/include/nlohmann/detail/iterators/iterator_traits.hpp @@ -1,14 +1,23 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // random_access_iterator_tag +#include #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template struct iterator_types {}; @@ -47,5 +56,6 @@ struct iterator_traits::value>> using pointer = T*; using reference = T&; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp index e787fdbcd..f7e8503fc 100644 --- a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +++ b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -1,13 +1,23 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // ptrdiff_t #include // reverse_iterator #include // declval -namespace nlohmann -{ +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + ////////////////////// // reverse_iterator // ////////////////////// @@ -48,7 +58,7 @@ class json_reverse_iterator : public std::reverse_iterator explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} /// post-increment (it++) - json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type) + json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp) { return static_cast(base_iterator::operator++(1)); } @@ -60,7 +70,7 @@ class json_reverse_iterator : public std::reverse_iterator } /// post-decrement (it--) - json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type) + json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp) { return static_cast(base_iterator::operator--(1)); } @@ -115,5 +125,6 @@ class json_reverse_iterator : public std::reverse_iterator return it.operator * (); } }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/iterators/primitive_iterator.hpp b/include/nlohmann/detail/iterators/primitive_iterator.hpp index 15aa2f08a..5d0594ab8 100644 --- a/include/nlohmann/detail/iterators/primitive_iterator.hpp +++ b/include/nlohmann/detail/iterators/primitive_iterator.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // ptrdiff_t @@ -5,10 +13,10 @@ #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + /* @brief an iterator for primitive JSON types @@ -87,7 +95,7 @@ class primitive_iterator_t return *this; } - primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type) + primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp) { auto result = *this; ++m_it; @@ -100,7 +108,7 @@ class primitive_iterator_t return *this; } - primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type) + primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp) { auto result = *this; --m_it; @@ -119,5 +127,6 @@ class primitive_iterator_t return *this; } }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index caed67c9e..867d9cbf5 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -1,7 +1,20 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // all_of #include // isdigit +#include // errno, ERANGE +#include // strtoull +#ifndef JSON_NO_IO + #include // ostream +#endif // JSON_NO_IO #include // max #include // accumulate #include // string @@ -10,47 +23,76 @@ #include #include +#include #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document /// @sa https://json.nlohmann.me/api/json_pointer/ -template +template class json_pointer { // allow basic_json to access private members NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; + template + friend class json_pointer; + + template + struct string_t_helper + { + using type = T; + }; + + NLOHMANN_BASIC_JSON_TPL_DECLARATION + struct string_t_helper + { + using type = StringType; + }; + public: + // for backwards compatibility accept BasicJsonType + using string_t = typename string_t_helper::type; + /// @brief create JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/ - explicit json_pointer(const std::string& s = "") + explicit json_pointer(const string_t& s = "") : reference_tokens(split(s)) {} /// @brief return a string representation of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/to_string/ - std::string to_string() const + string_t to_string() const { return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - std::string{}, - [](const std::string & a, const std::string & b) + string_t{}, + [](const string_t& a, const string_t& b) { - return a + "/" + detail::escape(b); + return detail::concat(a, '/', detail::escape(b)); }); } /// @brief return a string representation of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/ - operator std::string() const + JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string()) + operator string_t() const { return to_string(); } +#ifndef JSON_NO_IO + /// @brief write string representation of the JSON pointer to stream + /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/ + friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr) + { + o << ptr.to_string(); + return o; + } +#endif + /// @brief append another JSON pointer at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ json_pointer& operator/=(const json_pointer& ptr) @@ -63,7 +105,7 @@ class json_pointer /// @brief append an unescaped reference token at the end of this JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/ - json_pointer& operator/=(std::string token) + json_pointer& operator/=(string_t token) { push_back(std::move(token)); return *this; @@ -86,7 +128,7 @@ class json_pointer /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/ - friend json_pointer operator/(const json_pointer& lhs, std::string token) // NOLINT(performance-unnecessary-value-param) + friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param) { return json_pointer(lhs) /= std::move(token); } @@ -118,7 +160,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } reference_tokens.pop_back(); @@ -126,11 +168,11 @@ class json_pointer /// @brief return last reference token /// @sa https://json.nlohmann.me/api/json_pointer/back/ - const std::string& back() const + const string_t& back() const { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } return reference_tokens.back(); @@ -138,14 +180,14 @@ class json_pointer /// @brief append an unescaped token at the end of the reference pointer /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ - void push_back(const std::string& token) + void push_back(const string_t& token) { reference_tokens.push_back(token); } /// @brief append an unescaped token at the end of the reference pointer /// @sa https://json.nlohmann.me/api/json_pointer/push_back/ - void push_back(std::string&& token) + void push_back(string_t&& token) { reference_tokens.push_back(std::move(token)); } @@ -168,44 +210,39 @@ class json_pointer @throw out_of_range.404 if string @a s could not be converted to an integer @throw out_of_range.410 if an array index exceeds size_type */ - static typename BasicJsonType::size_type array_index(const std::string& s) + template + static typename BasicJsonType::size_type array_index(const string_t& s) { using size_type = typename BasicJsonType::size_type; // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr)); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType())); + JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr)); } - std::size_t processed_chars = 0; - unsigned long long res = 0; // NOLINT(runtime/int) - JSON_TRY + const char* p = s.c_str(); + char* p_end = nullptr; + errno = 0; // strtoull doesn't reset errno + unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) + if (p == p_end // invalid input or empty string + || errno == ERANGE // out of range + || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read { - res = std::stoull(s, &processed_chars); - } - JSON_CATCH(std::out_of_range&) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); - } - - // check if the string was completely read - if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr)); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 if (res >= static_cast((std::numeric_limits::max)())) // NOLINT(runtime/int) { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE } return static_cast(res); @@ -216,7 +253,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr)); } json_pointer result = *this; @@ -233,6 +270,7 @@ class json_pointer @throw parse_error.109 if array index is not a number @throw type_error.313 if value cannot be unflattened */ + template BasicJsonType& get_and_create(BasicJsonType& j) const { auto* result = &j; @@ -268,7 +306,7 @@ class json_pointer case detail::value_t::array: { // create an entry in the array - result = &result->operator[](array_index(reference_token)); + result = &result->operator[](array_index(reference_token)); break; } @@ -286,7 +324,7 @@ class json_pointer case detail::value_t::binary: case detail::value_t::discarded: default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j)); } } @@ -312,6 +350,7 @@ class json_pointer @throw parse_error.109 if an array index was not a number @throw out_of_range.404 if the JSON pointer can not be resolved */ + template BasicJsonType& get_unchecked(BasicJsonType* ptr) const { for (const auto& reference_token : reference_tokens) @@ -352,7 +391,7 @@ class json_pointer else { // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); + ptr = &ptr->operator[](array_index(reference_token)); } break; } @@ -366,7 +405,7 @@ class json_pointer case detail::value_t::binary: case detail::value_t::discarded: default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -379,6 +418,7 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ + template BasicJsonType& get_checked(BasicJsonType* ptr) const { for (const auto& reference_token : reference_tokens) @@ -397,13 +437,13 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range", *ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat( + "array index '-' (", std::to_string(ptr->m_value.array->size()), + ") is out of range"), ptr)); } // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); + ptr = &ptr->at(array_index(reference_token)); break; } @@ -416,7 +456,7 @@ class json_pointer case detail::value_t::binary: case detail::value_t::discarded: default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -436,6 +476,7 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ + template const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const { for (const auto& reference_token : reference_tokens) @@ -454,11 +495,11 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); + ptr = &ptr->operator[](array_index(reference_token)); break; } @@ -471,7 +512,7 @@ class json_pointer case detail::value_t::binary: case detail::value_t::discarded: default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -484,6 +525,7 @@ class json_pointer @throw out_of_range.402 if the array index '-' is used @throw out_of_range.404 if the JSON pointer can not be resolved */ + template const BasicJsonType& get_checked(const BasicJsonType* ptr) const { for (const auto& reference_token : reference_tokens) @@ -502,13 +544,13 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range", *ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat( + "array index '-' (", std::to_string(ptr->m_value.array->size()), + ") is out of range"), ptr)); } // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); + ptr = &ptr->at(array_index(reference_token)); break; } @@ -521,7 +563,7 @@ class json_pointer case detail::value_t::binary: case detail::value_t::discarded: default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); + JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr)); } } @@ -532,6 +574,7 @@ class json_pointer @throw parse_error.106 if an array index begins with '0' @throw parse_error.109 if an array index was not a number */ + template bool contains(const BasicJsonType* ptr) const { for (const auto& reference_token : reference_tokens) @@ -579,7 +622,7 @@ class json_pointer } } - const auto idx = array_index(reference_token); + const auto idx = array_index(reference_token); if (idx >= ptr->size()) { // index out of range @@ -620,9 +663,9 @@ class json_pointer @throw parse_error.107 if the pointer is not empty or begins with '/' @throw parse_error.108 if character '~' is not followed by '0' or '1' */ - static std::vector split(const std::string& reference_string) + static std::vector split(const string_t& reference_string) { - std::vector result; + std::vector result; // special case: empty reference string -> no reference tokens if (reference_string.empty()) @@ -633,7 +676,7 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr)); } // extract the reference tokens: @@ -644,11 +687,11 @@ class json_pointer std::size_t slash = reference_string.find_first_of('/', 1), // set the beginning of the first reference token start = 1; - // we can stop if start == 0 (if slash == std::string::npos) + // we can stop if start == 0 (if slash == string_t::npos) start != 0; // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = (slash == std::string::npos) ? 0 : slash + 1, + // (will eventually be 0 if slash == string_t::npos) + start = (slash == string_t::npos) ? 0 : slash + 1, // find next slash slash = reference_string.find_first_of('/', start)) { @@ -658,7 +701,7 @@ class json_pointer // check reference tokens are properly escaped for (std::size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; + pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1)) { JSON_ASSERT(reference_token[pos] == '~'); @@ -668,7 +711,7 @@ class json_pointer (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType())); + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr)); } } @@ -688,7 +731,8 @@ class json_pointer @note Empty objects or arrays are flattened to `null`. */ - static void flatten(const std::string& reference_string, + template + static void flatten(const string_t& reference_string, const BasicJsonType& value, BasicJsonType& result) { @@ -706,7 +750,7 @@ class json_pointer // iterate array and use index as reference string for (std::size_t i = 0; i < value.m_value.array->size(); ++i) { - flatten(reference_string + "/" + std::to_string(i), + flatten(detail::concat(reference_string, '/', std::to_string(i)), value.m_value.array->operator[](i), result); } } @@ -725,7 +769,7 @@ class json_pointer // iterate object and use keys as reference string for (const auto& element : *value.m_value.object) { - flatten(reference_string + "/" + detail::escape(element.first), element.second, result); + flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); } } break; @@ -758,12 +802,13 @@ class json_pointer @throw type_error.315 if object values are not primitive @throw type_error.313 if value cannot be unflattened */ + template static BasicJsonType unflatten(const BasicJsonType& value) { if (JSON_HEDLEY_UNLIKELY(!value.is_object())) { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value)); } BasicJsonType result; @@ -773,7 +818,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second)); } // assign value to reference pointed to by JSON pointer; Note that if @@ -786,6 +831,21 @@ class json_pointer return result; } + // can't use conversion operator because of ambiguity + json_pointer convert() const& + { + json_pointer result; + result.reference_tokens = reference_tokens; + return result; + } + + json_pointer convert()&& + { + json_pointer result; + result.reference_tokens = std::move(reference_tokens); + return result; + } + /*! @brief compares two JSON pointers for equality @@ -797,11 +857,10 @@ class json_pointer @exceptionsafety No-throw guarantee: this function never throws exceptions. */ - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept; /*! @brief compares two JSON pointers for inequality @@ -814,13 +873,28 @@ class json_pointer @exceptionsafety No-throw guarantee: this function never throws exceptions. */ - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept; /// the reference tokens - std::vector reference_tokens; + std::vector reference_tokens; }; -} // namespace nlohmann + +// functions cannot be defined inside class due to ODR violations +template +inline bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept +{ + return lhs.reference_tokens == rhs.reference_tokens; +} + +template +inline bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept +{ + return !(lhs == rhs); +} + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/json_ref.hpp b/include/nlohmann/detail/json_ref.hpp index b4e5dabaf..b672e1941 100644 --- a/include/nlohmann/detail/json_ref.hpp +++ b/include/nlohmann/detail/json_ref.hpp @@ -1,14 +1,23 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include #include +#include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template class json_ref { @@ -64,5 +73,6 @@ class json_ref mutable value_type owned_value = nullptr; value_type const* value_ref = nullptr; }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index b2843f067..cd01039e4 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -1,12 +1,22 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // declval, pair -#include #include +#include -// This file contains all internal macro definitions +// This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them +#include + // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -37,6 +47,12 @@ #define JSON_HAS_CPP_11 #endif +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) #ifdef JSON_HAS_CPP_17 #if defined(__cpp_lib_filesystem) @@ -70,7 +86,7 @@ #endif // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1940 + #if defined(_MSC_VER) && _MSC_VER < 1914 #undef JSON_HAS_FILESYSTEM #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM #endif @@ -97,6 +113,38 @@ #define JSON_HAS_FILESYSTEM 0 #endif +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + // disable documentation warnings on clang #if defined(__clang__) #pragma clang diagnostic push @@ -334,6 +382,7 @@ #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); /*! @brief macro @@ -344,6 +393,10 @@ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + /*! @brief macro @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @@ -353,6 +406,10 @@ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + // inspired from https://stackoverflow.com/a/26745591 // allows to call any std function as if (e.g. with begin): @@ -402,6 +459,10 @@ #define JSON_EXPLICIT explicit #endif -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 0 #endif diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 1a29fb5e0..9416e18a4 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once // restore clang diagnostic settings @@ -8,19 +16,29 @@ // clean up #undef JSON_ASSERT #undef JSON_INTERNAL_CATCH -#undef JSON_CATCH #undef JSON_THROW -#undef JSON_TRY #undef JSON_PRIVATE_UNLESS_TESTED -#undef JSON_HAS_CPP_11 -#undef JSON_HAS_CPP_14 -#undef JSON_HAS_CPP_17 -#undef JSON_HAS_CPP_20 -#undef JSON_HAS_FILESYSTEM -#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL #undef JSON_EXPLICIT #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL +#undef JSON_INLINE_VARIABLE +#undef JSON_NO_UNIQUE_ADDRESS +#undef JSON_DISABLE_ENUM_SERIALIZATION +#undef JSON_USE_GLOBAL_UDLS + +#ifndef JSON_TEST_KEEP_MACROS + #undef JSON_CATCH + #undef JSON_TRY + #undef JSON_HAS_CPP_11 + #undef JSON_HAS_CPP_14 + #undef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_20 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #undef JSON_HAS_THREE_WAY_COMPARISON + #undef JSON_HAS_RANGES + #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON +#endif #include diff --git a/include/nlohmann/detail/meta/call_std/begin.hpp b/include/nlohmann/detail/meta/call_std/begin.hpp index da937144c..610f4cd0a 100644 --- a/include/nlohmann/detail/meta/call_std/begin.hpp +++ b/include/nlohmann/detail/meta/call_std/begin.hpp @@ -1,8 +1,17 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN + NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/call_std/end.hpp b/include/nlohmann/detail/meta/call_std/end.hpp index 190900739..1515e7520 100644 --- a/include/nlohmann/detail/meta/call_std/end.hpp +++ b/include/nlohmann/detail/meta/call_std/end.hpp @@ -1,8 +1,17 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN + NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); -} // namespace nlohmann + +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/cpp_future.hpp b/include/nlohmann/detail/meta/cpp_future.hpp index 147f2fa35..fe6784dd8 100644 --- a/include/nlohmann/detail/meta/cpp_future.hpp +++ b/include/nlohmann/detail/meta/cpp_future.hpp @@ -1,3 +1,12 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + #pragma once #include // size_t @@ -6,8 +15,7 @@ #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -147,8 +155,12 @@ struct static_const static constexpr T value{}; }; -template -constexpr T static_const::value; // NOLINT(readability-redundant-declaration) +#ifndef JSON_HAS_CPP_17 + + template + constexpr T static_const::value; // NOLINT(readability-redundant-declaration) + +#endif } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/detected.hpp b/include/nlohmann/detail/meta/detected.hpp index 8480e1c05..9746dae00 100644 --- a/include/nlohmann/detail/meta/detected.hpp +++ b/include/nlohmann/detail/meta/detected.hpp @@ -1,14 +1,22 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include #include -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + +// https://en.cppreference.com/w/cpp/experimental/is_detected struct nonesuch { nonesuch() = delete; @@ -57,5 +65,6 @@ using is_detected_exact = std::is_same>; template class Op, class... Args> using is_detected_convertible = std::is_convertible, To>; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/identity_tag.hpp b/include/nlohmann/detail/meta/identity_tag.hpp index 73a3e9170..002d60543 100644 --- a/include/nlohmann/detail/meta/identity_tag.hpp +++ b/include/nlohmann/detail/meta/identity_tag.hpp @@ -1,10 +1,21 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once -namespace nlohmann -{ +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + // dispatching helper struct template struct identity_tag {}; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/is_sax.hpp b/include/nlohmann/detail/meta/is_sax.hpp index e1e48a0ba..8be4d3483 100644 --- a/include/nlohmann/detail/meta/is_sax.hpp +++ b/include/nlohmann/detail/meta/is_sax.hpp @@ -1,16 +1,25 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // size_t #include // declval #include // string +#include #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template using null_function_t = decltype(std::declval().null()); @@ -145,5 +154,6 @@ struct is_sax_static_asserts "Missing/invalid function: bool parse_error(std::size_t, const " "std::string&, const exception&)"); }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END diff --git a/include/nlohmann/detail/meta/std_fs.hpp b/include/nlohmann/detail/meta/std_fs.hpp new file mode 100644 index 000000000..f457682c2 --- /dev/null +++ b/include/nlohmann/detail/meta/std_fs.hpp @@ -0,0 +1,29 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#if JSON_HAS_EXPERIMENTAL_FILESYSTEM +#include +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +namespace std_fs = std::experimental::filesystem; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END +#elif JSON_HAS_FILESYSTEM +#include +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ +namespace std_fs = std::filesystem; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END +#endif diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 984ca1931..920e8abd6 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -1,3 +1,11 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #pragma once #include // numeric_limits @@ -5,17 +13,15 @@ #include // declval #include // tuple -#include - #include +#include #include #include #include #include #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief detail namespace with internal helper functions @@ -26,6 +32,7 @@ implementations of some @ref basic_json methods, and meta-programming helpers. */ namespace detail { + ///////////// // helpers // ///////////// @@ -44,6 +51,16 @@ template struct is_basic_json : std::false_type {}; NLOHMANN_BASIC_JSON_TPL_DECLARATION struct is_basic_json : std::true_type {}; +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + ////////////////////// // json_ref helpers // ////////////////////// @@ -145,6 +162,24 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> T>::value; }; +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; /////////////////// // is_ functions // @@ -152,10 +187,10 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> // https://en.cppreference.com/w/cpp/types/conjunction template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; // https://en.cppreference.com/w/cpp/types/negation template struct negation : std::integral_constant < bool, !B::value > { }; @@ -319,9 +354,18 @@ struct is_compatible_string_type template struct is_constructible_string_type { + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + static constexpr auto value = - is_constructible::value; + conjunction < + is_constructible, + is_detected_exact>::value; }; template @@ -439,6 +483,81 @@ struct is_constructible_tuple : std::false_type {}; template struct is_constructible_tuple> : conjunction...> {}; +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template