diff --git a/.clang-tidy b/.clang-tidy index 30886d7c8..3673930d4 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, 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 2b592ee65..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.4 -- [ ] 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..9ede0b3d7 --- /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.10.5). 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..af35f4f26 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,6 +9,7 @@ on: pull_request: schedule: - cron: '0 19 * * 1' + workflow_dispatch: jobs: CodeQL-Build: @@ -17,10 +18,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 +31,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 +39,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 +53,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..03c652a81 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -7,6 +7,7 @@ on: - master - release/* pull_request: + workflow_dispatch: jobs: xcode: @@ -18,7 +19,7 @@ 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 @@ -35,9 +36,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..b5f583367 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -7,13 +7,14 @@ on: - master - release/* pull_request: + workflow_dispatch: jobs: ci_test_clang: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.3.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -21,9 +22,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.3.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -31,12 +32,12 @@ jobs: ci_static_analysis: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.3.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 @@ -44,12 +45,12 @@ jobs: ci_cmake_options: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.3.0 strategy: matrix: target: [ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build @@ -57,15 +58,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.3.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 +78,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.3.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, 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,13 +91,13 @@ jobs: ci_test_standards: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.3.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 @@ -104,9 +105,9 @@ jobs: ci_cuda_example: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.2.0 + container: ghcr.io/nlohmann/json-ci:v2.3.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: cmake run: cmake -S . -B build -DJSON_CI=On - name: build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 597da4774..8d3e54358 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -7,6 +7,7 @@ on: - master - release/* pull_request: + workflow_dispatch: jobs: mingw: @@ -16,7 +17,7 @@ jobs: architecture: [x64, x86] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up MinGW uses: egor-tensin/setup-mingw@v2 with: @@ -28,50 +29,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 +50,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 +61,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 +111,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..db6dcecb4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,33 @@ -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 +/.vs/ +/.vscode/ -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*/ + +/docs/mkdocs/docs/examples/ +/docs/mkdocs/docs/__pycache__/ +/docs/mkdocs/site/ +/docs/mkdocs/venv/ +/docs/docset/JSON_for_Modern_C++.docset/ +/docs/docset/JSON_for_Modern_C++.tgz +/docs/mkdocs/docs/images/json.gif + +# serve_header +/serve_header.yml +/localhost.pem +/localhost-key.pem diff --git a/CITATION.cff b/CITATION.cff index 37dbed4be..40a1d26a2 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.4 -date-released: 2021 +version: 3.10.5 +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 53bb06e28..8f65d9a32 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.4 LANGUAGES CXX) +project(nlohmann_json VERSION 3.10.5 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,7 +31,13 @@ if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif () -option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${MAIN_PROJECT}) +# 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_ImplicitConversions "Enable implicit conversions." ON) @@ -39,7 +46,7 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OF option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF) if (JSON_CI) - include(cmake/ci.cmake) + include(ci) endif () ## @@ -129,7 +136,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 92df98220..9a92b9f1f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,22 +1,55 @@ # Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [3.10.4](https://github.com/nlohmann/json/releases/tag/3.10.4) (2021-10-16) +## [3.10.5](https://github.com/nlohmann/json/releases/tag/3.10.5) (2022-01-02) -[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.3...3.10.4) +[Full Changelog](https://github.com/nlohmann/json/compare/v3.10.4...3.10.5) -- Compiler error in output serializer due to 'incompatible initializer' [\#3081](https://github.com/nlohmann/json/issues/3081) -- Strange behaviour when using std::sort on std::vector\ [\#3080](https://github.com/nlohmann/json/issues/3080) -- Unhandled exception: nlohmann::detail::parse\_error [\#3078](https://github.com/nlohmann/json/issues/3078) -- explicit constructor with default does not compile [\#3077](https://github.com/nlohmann/json/issues/3077) -- Parse an object but get an array using GCC [\#3076](https://github.com/nlohmann/json/issues/3076) -- Version 3.10.3 breaks backward-compatibility with 3.10.2 [\#3070](https://github.com/nlohmann/json/issues/3070) -- Feature request, Add to\_json/from\_json to align with other to/from binary api. [\#3067](https://github.com/nlohmann/json/issues/3067) -- vcpkg is out of date [\#3066](https://github.com/nlohmann/json/issues/3066) +- \#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) +- Warning for shadowed variables [\#3188](https://github.com/nlohmann/json/issues/3188) +- Accessing missing keys on const json object leads to assert [\#3183](https://github.com/nlohmann/json/issues/3183) +- Data member is available, but null is reported, and program throws error [\#3173](https://github.com/nlohmann/json/issues/3173) +- serialization problem, from\_json need construct new object [\#3169](https://github.com/nlohmann/json/issues/3169) +- std::filesystem unavailable on macOS lower deployment targets [\#3156](https://github.com/nlohmann/json/issues/3156) +- \[json.exception.type\_error.305\] cannot use operator\[\] with a string argument with string [\#3151](https://github.com/nlohmann/json/issues/3151) +- json::dump\(\) is not compatible with C++ standards [\#3147](https://github.com/nlohmann/json/issues/3147) +- Issue with json::parse decoding codepoints [\#3142](https://github.com/nlohmann/json/issues/3142) +- Simple parse of json object thinks it should be an array [\#3136](https://github.com/nlohmann/json/issues/3136) +- How to properly read a Json string that may be null in some cases? [\#3135](https://github.com/nlohmann/json/issues/3135) +- Deadlock on create json - windows only [\#3129](https://github.com/nlohmann/json/issues/3129) +- Wrong parsing of int64 values nearest of limit [\#3126](https://github.com/nlohmann/json/issues/3126) +- ordered\_json doesn't support range based erase [\#3108](https://github.com/nlohmann/json/issues/3108) +- Apple build failed with json/single\_include/nlohmann/json.hpp:4384:57: 'path' is unavailable [\#3097](https://github.com/nlohmann/json/issues/3097) +- GCC 7.5.0 with --std=c++17: filesystem: No such file or directory [\#3090](https://github.com/nlohmann/json/issues/3090) +- Drop Travis CI [\#3087](https://github.com/nlohmann/json/issues/3087) +- ordered\_json::reset\(\) compile error with nvcc [\#3013](https://github.com/nlohmann/json/issues/3013) +- Support for unordered\_map as object\_t [\#2932](https://github.com/nlohmann/json/issues/2932) +- Compiler warning with Intel compiler, same as \#755 [\#2712](https://github.com/nlohmann/json/issues/2712) +- Compiler warnings with NVCC 11.2 [\#2676](https://github.com/nlohmann/json/issues/2676) +- 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)) @@ -27,6 +60,19 @@ All notable changes to this project will be documented in this file. This projec - 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) + +- Compiler error in output serializer due to 'incompatible initializer' [\#3081](https://github.com/nlohmann/json/issues/3081) +- Strange behaviour when using std::sort on std::vector\ [\#3080](https://github.com/nlohmann/json/issues/3080) +- Unhandled exception: nlohmann::detail::parse\_error [\#3078](https://github.com/nlohmann/json/issues/3078) +- explicit constructor with default does not compile [\#3077](https://github.com/nlohmann/json/issues/3077) +- Parse an object but get an array using GCC [\#3076](https://github.com/nlohmann/json/issues/3076) +- Version 3.10.3 breaks backward-compatibility with 3.10.2 [\#3070](https://github.com/nlohmann/json/issues/3070) +- Feature request, Add to\_json/from\_json to align with other to/from binary api. [\#3067](https://github.com/nlohmann/json/issues/3067) +- vcpkg is out of date [\#3066](https://github.com/nlohmann/json/issues/3066) + ## [v3.10.3](https://github.com/nlohmann/json/releases/tag/v3.10.3) (2021-10-08) [Full Changelog](https://github.com/nlohmann/json/compare/v3.10.2...v3.10.3) @@ -768,7 +814,7 @@ All notable changes to this project will be documented in this file. This projec - catch exceptions for json\_pointer : ..../+99 [\#1990](https://github.com/nlohmann/json/pull/1990) ([dota17](https://github.com/dota17)) - Modify the document about operator== [\#1984](https://github.com/nlohmann/json/pull/1984) ([dota17](https://github.com/dota17)) - Rename argument array\_index to array\_indx in json\_pointer methods [\#1980](https://github.com/nlohmann/json/pull/1980) ([linev](https://github.com/linev)) -- README: Fix string representation of `dump`ed `json` [\#1979](https://github.com/nlohmann/json/pull/1979) ([alex-weej](https://github.com/alex-weej)) +- README: Fix string representation of `dump`ed `json` [\#1979](https://github.com/nlohmann/json/pull/1979) ([alexweej](https://github.com/alexweej)) - fix warnings in serializer.hpp for VS2019 [\#1969](https://github.com/nlohmann/json/pull/1969) ([dota17](https://github.com/dota17)) - Fix C26451 warnnings in to\_chars.hpp [\#1967](https://github.com/nlohmann/json/pull/1967) ([dota17](https://github.com/dota17)) - appveyor.yml: Compile and test with latest version for \_\_cplusplus maโ€ฆ [\#1958](https://github.com/nlohmann/json/pull/1958) ([t-b](https://github.com/t-b)) @@ -1224,7 +1270,6 @@ All notable changes to this project will be documented in this file. This projec - Copyconstructor inserts original into array with single element [\#1397](https://github.com/nlohmann/json/issues/1397) - Get value without explicit typecasting [\#1395](https://github.com/nlohmann/json/issues/1395) - Big file parsing [\#1393](https://github.com/nlohmann/json/issues/1393) -- some static analysis warning at line 11317 [\#1390](https://github.com/nlohmann/json/issues/1390) - Adding Structured Binding Support [\#1388](https://github.com/nlohmann/json/issues/1388) - map\ exhibits unexpected behavior [\#1387](https://github.com/nlohmann/json/issues/1387) - Error Code Return [\#1386](https://github.com/nlohmann/json/issues/1386) @@ -1812,7 +1857,7 @@ All notable changes to this project will be documented in this file. This projec - 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)) -- :art: Namespace `uint8_t` from the C++ stdlib [\#510](https://github.com/nlohmann/json/pull/510) ([alex-weej](https://github.com/alex-weej)) +- :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)) @@ -1901,7 +1946,6 @@ All notable changes to this project will be documented in this file. This projec - Compilation error with unordered\_map\< int, int \> [\#758](https://github.com/nlohmann/json/issues/758) - CBOR string [\#757](https://github.com/nlohmann/json/issues/757) - Proposal: out\_of\_range should be a subclass of std::out\_of\_range [\#756](https://github.com/nlohmann/json/issues/756) -- Compiling with icpc [\#755](https://github.com/nlohmann/json/issues/755) - Getter is setting the value to null if the key does not exist [\#754](https://github.com/nlohmann/json/issues/754) - parsing works sometimes and crashes others [\#752](https://github.com/nlohmann/json/issues/752) - Static\_assert failed "incompatible pointer type" with Xcode [\#751](https://github.com/nlohmann/json/issues/751) diff --git a/LICENSE.MIT b/LICENSE.MIT index f0622d6dc..1c1f7a690 100644 --- a/LICENSE.MIT +++ b/LICENSE.MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2013-2021 Niels Lohmann +Copyright (c) 2013-2022 Niels Lohmann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 43db74d85..ce26524ad 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) @@ -48,7 +45,7 @@ all: # compile example files and check output doctest: - $(MAKE) check_output -C doc + $(MAKE) check_output -C docs ########################################################################## @@ -58,10 +55,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 +68,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 +133,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 +159,18 @@ pretty: --preserve-date \ --suffix=none \ --formatted \ - $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp + $(SRCS) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp tests/benchmarks/src/benchmarks.cpp 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) $(AMALGAMATED_FILE) tests/src/*.cpp tests/src/*.hpp benchmarks/src/benchmarks.cpp 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 +202,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 +233,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 +251,10 @@ 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) diff --git a/README.md b/README.md index d3ad394bb..a46a8569c 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,7 +10,7 @@ [![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) [![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases) @@ -32,7 +32,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 +54,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 class is heavily [unit-tested](https://github.com/nlohmann/json/tree/develop/tests/src) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](https://valgrind.org) and the [Clang Sanitizers](https://clang.llvm.org/docs/index.html) that there are no memory leaks. [Google OSS-Fuzz](https://github.com/google/oss-fuzz/tree/master/projects/json) additionally runs fuzz tests against all parsers 24/7, effectively executing billions of tests so far. To maintain high quality, the project is following the [Core Infrastructure Initiative (CII) best practices](https://bestpractices.coreinfrastructure.org/projects/289). Other aspects were not so important to us: @@ -83,9 +83,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 +93,7 @@ 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)). +Beside the examples below, you may want to check the [documentation](https://json.nlohmann.me/) where each function contains a separate code example (e.g., check out [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/docs/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/docs/examples/emplace.cpp)). ### JSON as first-class data type @@ -162,7 +162,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 [] @@ -197,7 +197,7 @@ auto j2 = R"( 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 above example can also be expressed explicitly using [`json::parse()`](https://json.nlohmann.me/api/basic_json/parse/): ```cpp // parse explicitly @@ -240,9 +240,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 +857,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 +961,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 @@ -1035,16 +1035,17 @@ auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE ## Supported compilers -Though it's 2021 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: +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. @@ -1092,8 +1093,8 @@ The following compilers are currently used in continuous integration at [AppVeyo | 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 | +| GCC 12.0.0 20211219 (experimental) | Ubuntu 20.04.3 LTS | 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 | @@ -1113,12 +1114,13 @@ The following compilers are currently used in continuous integration at [AppVeyo | 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 15.0.0 (15.0.0-++20220403052648+896770c9a92e-1~exp1~20220403172744.209) | 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 +1185,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.10.5/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 @@ -1304,7 +1297,7 @@ json = dependency('nlohmann_json', required: true) The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): -Copyright © 2013-2021 [Niels Lohmann](https://nlohmann.me) +Copyright © 2013-2022 [Niels Lohmann](https://nlohmann.me) 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: @@ -1336,7 +1329,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. @@ -1598,6 +1591,13 @@ I deeply appreciate the help of the following people. - [Giovanni Cerretani](https://github.com/gcerretani) fixed `-Wunused` warnings on `JSON_DIAGNOSTICS`. - [Bogdan Popescu](https://github.com/Kapeli) hosts the [docset](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for offline documentation viewers. - [Carl Smedstad](https://github.com/carlsmedstad) fixed an assertion error when using `JSON_DIAGNOSTICS`. +- [miikka75](https://github.com/miikka75) provided an important fix to compile C++17 code with Clang 9. +- [Maarten Becker](https://github.com/kernie) fixed a warning for shadowed variables. +- [Cristi Vรฎjdea](https://github.com/axnsan12) fixed typos in the `operator[]` documentation. +- [Alex Beregszaszi](https://github.com/axic) fixed spelling mistakes in comments. +- [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. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. @@ -1617,13 +1617,14 @@ The library itself consists of a single header file licensed under the MIT licen - [**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 @@ -1646,7 +1647,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 @@ -1681,7 +1682,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). diff --git a/cmake/ci.cmake b/cmake/ci.cmake index d0b989c80..b2a2f470f 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) 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 12.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,283 +121,295 @@ 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-write-to-const + -Wanalyzer-write-to-string-literal + -Warith-conversion + -Warray-bounds + -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 + -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 + -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 + -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 +) 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 -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_gcc @@ -406,7 +419,7 @@ 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 -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang @@ -421,10 +434,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 +445,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 @@ -499,7 +512,7 @@ add_custom_target(ci_test_coverage 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 +542,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 +559,7 @@ 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" ) ############################################################################### @@ -592,7 +605,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" ) @@ -670,7 +683,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 @@ -756,50 +769,67 @@ 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_Install;JSON_MultipleHeaders;JSON_ImplicitConversions;JSON_Valgrind;JSON_Diagnostics;JSON_SystemInclude") +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 +841,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 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,7 +873,7 @@ 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 ) 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..1d146646b --- /dev/null +++ b/cmake/test.cmake @@ -0,0 +1,204 @@ +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 ...]) +# +# Supply test- and standard-specific build settings. +# 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" + ${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}) + endforeach() + endforeach() +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) + + 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( +# +# 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 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" "CXX_STANDARDS" ${ARGN}) + + get_filename_component(file_basename ${file} NAME_WE) + string(REGEX REPLACE "unit-([^$]+)" "test-\\1" test_name ${file_basename}) + + if("${args_MAIN}" STREQUAL "") + message(FATAL_ERROR "Required argument MAIN
missing.") + 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() diff --git a/doc/avatars.png b/doc/avatars.png deleted file mode 100644 index a3d8bade4..000000000 Binary files a/doc/avatars.png and /dev/null differ diff --git a/doc/json.gif b/doc/json.gif deleted file mode 100644 index 67eaf7f07..000000000 Binary files a/doc/json.gif and /dev/null differ 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/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/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/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/Makefile b/docs/Makefile similarity index 100% rename from doc/Makefile rename to docs/Makefile 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..51243580d 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/doc/docset/Makefile b/docs/docset/Makefile similarity index 95% rename from doc/docset/Makefile rename to docs/docset/Makefile index e538661ec..fcefa413a 100644 --- a/doc/docset/Makefile +++ b/docs/docset/Makefile @@ -13,7 +13,6 @@ JSON_for_Modern_C++.docset: Info.plist docSet.sql # 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 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/doc/docset/docSet.sql b/docs/docset/docSet.sql similarity index 100% rename from doc/docset/docSet.sql rename to docs/docset/docSet.sql 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..96f7cd259 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.10.5", "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__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/doc/examples/at__object_t_key_type.output b/docs/examples/at__object_t_key_type.output similarity index 100% rename from doc/examples/at__object_t_key_type.output rename to docs/examples/at__object_t_key_type.output 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/doc/examples/at__object_t_key_type_const.output b/docs/examples/at__object_t_key_type_const.output similarity index 100% rename from doc/examples/at__object_t_key_type_const.output rename to docs/examples/at__object_t_key_type_const.output 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/at_json_pointer.cpp b/docs/examples/at_json_pointer.cpp similarity index 100% rename from doc/examples/at_json_pointer.cpp rename to docs/examples/at_json_pointer.cpp 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 100% rename from doc/examples/at_json_pointer_const.cpp rename to docs/examples/at_json_pointer_const.cpp 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/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 100% rename from doc/examples/basic_json__CompatibleType.output rename to docs/examples/basic_json__CompatibleType.output 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.cpp b/docs/examples/basic_json__value.cpp similarity index 100% rename from doc/examples/basic_json__value.cpp rename to docs/examples/basic_json__value.cpp diff --git a/doc/examples/basic_json__value.output b/docs/examples/basic_json__value.output similarity index 100% rename from doc/examples/basic_json__value.output rename to docs/examples/basic_json__value.output diff --git a/doc/examples/basic_json__value_ptr.cpp b/docs/examples/basic_json__value_ptr.cpp similarity index 100% rename from doc/examples/basic_json__value_ptr.cpp rename to docs/examples/basic_json__value_ptr.cpp diff --git a/doc/examples/basic_json__value_ptr.output b/docs/examples/basic_json__value_ptr.output similarity index 100% rename from doc/examples/basic_json__value_ptr.output rename to docs/examples/basic_json__value_ptr.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/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/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.cpp b/docs/examples/contains.cpp similarity index 100% rename from doc/examples/contains.cpp rename to docs/examples/contains.cpp diff --git a/doc/examples/contains.output b/docs/examples/contains.output similarity index 100% rename from doc/examples/contains.output rename to docs/examples/contains.output diff --git a/doc/examples/contains_json_pointer.cpp b/docs/examples/contains_json_pointer.cpp similarity index 100% rename from doc/examples/contains_json_pointer.cpp rename to docs/examples/contains_json_pointer.cpp 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/doc/examples/count.cpp b/docs/examples/count.cpp similarity index 100% rename from doc/examples/count.cpp rename to docs/examples/count.cpp diff --git a/doc/examples/count.output b/docs/examples/count.output similarity index 100% rename from doc/examples/count.output rename to docs/examples/count.output 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/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 100% rename from doc/examples/diff.cpp rename to docs/examples/diff.cpp 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/doc/examples/erase__key_type.cpp b/docs/examples/erase__key_type.cpp similarity index 100% rename from doc/examples/erase__key_type.cpp rename to docs/examples/erase__key_type.cpp diff --git a/doc/examples/erase__key_type.output b/docs/examples/erase__key_type.output similarity index 100% rename from doc/examples/erase__key_type.output rename to docs/examples/erase__key_type.output 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/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/doc/examples/find__key_type.cpp b/docs/examples/find__key_type.cpp similarity index 100% rename from doc/examples/find__key_type.cpp rename to docs/examples/find__key_type.cpp diff --git a/doc/examples/find__key_type.output b/docs/examples/find__key_type.output similarity index 100% rename from doc/examples/find__key_type.output rename to docs/examples/find__key_type.output 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/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_bson.output b/docs/examples/from_bson.output similarity index 100% rename from doc/examples/from_bson.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_cbor.output b/docs/examples/from_cbor.output similarity index 100% rename from doc/examples/from_cbor.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_msgpack.output b/docs/examples/from_msgpack.output similarity index 100% rename from doc/examples/from_msgpack.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/doc/examples/from_ubjson.output b/docs/examples/from_ubjson.output similarity index 100% rename from doc/examples/from_ubjson.output rename to docs/examples/from_ubjson.output 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/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/doc/examples/iterator_wrapper.cpp b/docs/examples/iterator_wrapper.cpp similarity index 100% rename from doc/examples/iterator_wrapper.cpp rename to docs/examples/iterator_wrapper.cpp diff --git a/doc/examples/iterator_wrapper.output b/docs/examples/iterator_wrapper.output similarity index 100% rename from doc/examples/iterator_wrapper.output rename to docs/examples/iterator_wrapper.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 100% rename from doc/examples/json_pointer__back.cpp rename to docs/examples/json_pointer__back.cpp diff --git a/doc/examples/json_pointer__back.output b/docs/examples/json_pointer__back.output similarity index 100% rename from doc/examples/json_pointer__back.output rename to docs/examples/json_pointer__back.output diff --git a/doc/examples/json_pointer__empty.cpp b/docs/examples/json_pointer__empty.cpp similarity index 100% rename from doc/examples/json_pointer__empty.cpp rename to docs/examples/json_pointer__empty.cpp 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 100% rename from doc/examples/json_pointer__operator_add.cpp rename to docs/examples/json_pointer__operator_add.cpp 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 100% rename from doc/examples/json_pointer__operator_add_binary.cpp rename to docs/examples/json_pointer__operator_add_binary.cpp 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/doc/examples/json_pointer__parent_pointer.cpp b/docs/examples/json_pointer__parent_pointer.cpp similarity index 100% rename from doc/examples/json_pointer__parent_pointer.cpp rename to docs/examples/json_pointer__parent_pointer.cpp 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 100% rename from doc/examples/json_pointer__pop_back.cpp rename to docs/examples/json_pointer__pop_back.cpp 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 100% rename from doc/examples/json_pointer__push_back.cpp rename to docs/examples/json_pointer__push_back.cpp 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/doc/examples/json_pointer__to_string.cpp b/docs/examples/json_pointer__to_string.cpp similarity index 100% rename from doc/examples/json_pointer__to_string.cpp rename to docs/examples/json_pointer__to_string.cpp diff --git a/doc/examples/json_pointer__to_string.output b/docs/examples/json_pointer__to_string.output similarity index 100% rename from doc/examples/json_pointer__to_string.output rename to docs/examples/json_pointer__to_string.output 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/doc/examples/max_size.output b/docs/examples/max_size.output similarity index 100% rename from doc/examples/max_size.output rename to docs/examples/max_size.output diff --git a/doc/examples/merge_patch.cpp b/docs/examples/merge_patch.cpp similarity index 100% rename from doc/examples/merge_patch.cpp rename to docs/examples/merge_patch.cpp 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 76% rename from doc/examples/meta.output rename to docs/examples/meta.output index 9cc5cf29f..c35a3200a 100644 --- a/doc/examples/meta.output +++ b/docs/examples/meta.output @@ -4,14 +4,14 @@ "family": "clang", "version": "13.0.0 (clang-1300.0.29.30)" }, - "copyright": "(C) 2013-2021 Niels Lohmann", + "copyright": "(C) 2013-2022 Niels Lohmann", "name": "JSON for Modern C++", "platform": "apple", "url": "https://github.com/nlohmann/json", "version": { "major": 3, "minor": 10, - "patch": 4, - "string": "3.10.4" + "patch": 5, + "string": "3.10.5" } } 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..fb7701dec --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_explicit.cpp @@ -0,0 +1,59 @@ +#include +#include + +using json = nlohmann::json; + +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..ce292659a --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_macro.cpp @@ -0,0 +1,47 @@ +#include +#include + +using json = nlohmann::json; + +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..621ed1452 --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_explicit.cpp @@ -0,0 +1,54 @@ +#include +#include + +using json = nlohmann::json; + +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..7851f526e --- /dev/null +++ b/docs/examples/nlohmann_define_type_intrusive_with_default_macro.cpp @@ -0,0 +1,41 @@ +#include +#include + +using json = nlohmann::json; + +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..b9d30dd8f --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_explicit.cpp @@ -0,0 +1,52 @@ +#include +#include + +using json = nlohmann::json; + +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..b073ef615 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_macro.cpp @@ -0,0 +1,40 @@ +#include +#include + +using json = nlohmann::json; + +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..21967b638 --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp @@ -0,0 +1,52 @@ +#include +#include + +using json = nlohmann::json; + +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..470fed69c --- /dev/null +++ b/docs/examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp @@ -0,0 +1,39 @@ +#include +#include + +using json = nlohmann::json; + +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/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/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/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/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 100% rename from doc/examples/operator_literal_json.cpp rename to docs/examples/operator_literal_json.cpp 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 100% rename from doc/examples/operator_literal_json_pointer.cpp rename to docs/examples/operator_literal_json_pointer.cpp 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_serialize.cpp similarity index 100% rename from doc/examples/operator_serialize.cpp rename to docs/examples/operator_serialize.cpp diff --git a/doc/examples/operator_serialize.output b/docs/examples/operator_serialize.output similarity index 100% rename from doc/examples/operator_serialize.output rename to docs/examples/operator_serialize.output diff --git a/doc/examples/operatorarray__key_type.cpp b/docs/examples/operatorarray__key_type.cpp similarity index 100% rename from doc/examples/operatorarray__key_type.cpp rename to docs/examples/operatorarray__key_type.cpp diff --git a/doc/examples/operatorarray__key_type.output b/docs/examples/operatorarray__key_type.output similarity index 100% rename from doc/examples/operatorarray__key_type.output rename to docs/examples/operatorarray__key_type.output diff --git a/doc/examples/operatorarray__key_type_const.cpp b/docs/examples/operatorarray__key_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__key_type_const.cpp rename to docs/examples/operatorarray__key_type_const.cpp diff --git a/doc/examples/operatorarray__key_type_const.output b/docs/examples/operatorarray__key_type_const.output similarity index 100% rename from doc/examples/operatorarray__key_type_const.output rename to docs/examples/operatorarray__key_type_const.output diff --git a/doc/examples/operatorarray__size_type.cpp b/docs/examples/operatorarray__size_type.cpp similarity index 100% rename from doc/examples/operatorarray__size_type.cpp rename to docs/examples/operatorarray__size_type.cpp diff --git a/doc/examples/operatorarray__size_type.output b/docs/examples/operatorarray__size_type.output similarity index 100% rename from doc/examples/operatorarray__size_type.output rename to docs/examples/operatorarray__size_type.output diff --git a/doc/examples/operatorarray__size_type_const.cpp b/docs/examples/operatorarray__size_type_const.cpp similarity index 100% rename from doc/examples/operatorarray__size_type_const.cpp rename to docs/examples/operatorarray__size_type_const.cpp diff --git a/doc/examples/operatorarray__size_type_const.output b/docs/examples/operatorarray__size_type_const.output similarity index 100% rename from doc/examples/operatorarray__size_type_const.output rename to docs/examples/operatorarray__size_type_const.output diff --git a/doc/examples/operatorjson_pointer.cpp b/docs/examples/operatorjson_pointer.cpp similarity index 100% rename from doc/examples/operatorjson_pointer.cpp rename to docs/examples/operatorjson_pointer.cpp diff --git a/doc/examples/operatorjson_pointer.output b/docs/examples/operatorjson_pointer.output similarity index 100% rename from doc/examples/operatorjson_pointer.output rename to docs/examples/operatorjson_pointer.output diff --git a/doc/examples/operatorjson_pointer_const.cpp b/docs/examples/operatorjson_pointer_const.cpp similarity index 100% rename from doc/examples/operatorjson_pointer_const.cpp rename to docs/examples/operatorjson_pointer_const.cpp diff --git a/doc/examples/operatorjson_pointer_const.output b/docs/examples/operatorjson_pointer_const.output similarity index 100% rename from doc/examples/operatorjson_pointer_const.output rename to docs/examples/operatorjson_pointer_const.output 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 100% rename from doc/examples/other_error.cpp rename to docs/examples/other_error.cpp 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 100% rename from doc/examples/patch.cpp rename to docs/examples/patch.cpp 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/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 100% rename from doc/examples/sax_parse.cpp rename to docs/examples/sax_parse.cpp diff --git a/doc/examples/sax_parse.output b/docs/examples/sax_parse.output similarity index 100% rename from doc/examples/sax_parse.output rename to docs/examples/sax_parse.output 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 100% rename from doc/examples/std_hash.cpp rename to docs/examples/std_hash.cpp diff --git a/doc/examples/std_hash.output b/docs/examples/std_hash.output similarity index 100% rename from doc/examples/std_hash.output rename to docs/examples/std_hash.output 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/doc/examples/to_bon8.cpp b/docs/examples/to_bon8.cpp similarity index 100% rename from doc/examples/to_bon8.cpp rename to docs/examples/to_bon8.cpp diff --git a/doc/examples/to_bon8.output b/docs/examples/to_bon8.output similarity index 100% rename from doc/examples/to_bon8.output rename to docs/examples/to_bon8.output diff --git a/doc/examples/to_bson.cpp b/docs/examples/to_bson.cpp similarity index 100% rename from doc/examples/to_bson.cpp rename to docs/examples/to_bson.cpp 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 100% rename from doc/examples/to_cbor.cpp rename to docs/examples/to_cbor.cpp 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 100% rename from doc/examples/to_msgpack.cpp rename to docs/examples/to_msgpack.cpp 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 100% rename from doc/examples/to_ubjson.cpp rename to docs/examples/to_ubjson.cpp diff --git a/doc/examples/to_ubjson.output b/docs/examples/to_ubjson.output similarity index 100% rename from doc/examples/to_ubjson.output rename to docs/examples/to_ubjson.output 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 100% rename from doc/examples/update.cpp rename to docs/examples/update.cpp 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 100% rename from doc/examples/update__range.cpp rename to docs/examples/update__range.cpp 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/index.md b/docs/index.md similarity index 99% rename from doc/index.md rename to docs/index.md index 6ab716f34..cb782e7d3 100644 --- a/doc/index.md +++ b/docs/index.md @@ -327,9 +327,9 @@ Note that this table only lists those exceptions thrown due to the type. For ins -@copyright Copyright © 2013-2021 Niels Lohmann. The code is licensed under the [MIT License](http://opensource.org/licenses/MIT). +@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.4 +@version 3.10.5 diff --git a/docs/json.gif b/docs/json.gif new file mode 100644 index 000000000..9f0d8a2f0 Binary files /dev/null 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 93% rename from doc/mkdocs/docs/api/basic_json/accept.md rename to docs/mkdocs/docs/api/basic_json/accept.md index 8794c585d..bbbac053a 100644 --- a/doc/mkdocs/docs/api/basic_json/accept.md +++ b/docs/mkdocs/docs/api/basic_json/accept.md @@ -32,10 +32,14 @@ Unlike the [`parse`](parse.md) function, this function neither throws an excepti - a `FILE` pointer - 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 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 81% rename from doc/mkdocs/docs/api/basic_json/at.md rename to docs/mkdocs/docs/api/basic_json/at.md index 1ad661322..dbd4cb6c9 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 @@ -134,7 +152,7 @@ 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 (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. @@ -149,7 +167,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --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. @@ -173,4 +191,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..9a289d6e9 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 @@ -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: 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 100% 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 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/doc/mkdocs/docs/api/basic_json/contains.md b/docs/mkdocs/docs/api/basic_json/contains.md similarity index 61% rename from doc/mkdocs/docs/api/basic_json/contains.md rename to docs/mkdocs/docs/api/basic_json/contains.md index 8463f4ea9..67a5ffcc0 100644 --- a/doc/mkdocs/docs/api/basic_json/contains.md +++ b/docs/mkdocs/docs/api/basic_json/contains.md @@ -2,21 +2,28 @@ ```cpp // (1) -template -bool contains(KeyT && key) const; +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 key equivalent to `key`. If the element is not found or the +1. Check whether an element exists in a JSON object with a key equivalent to `key`. If the element is not found or the 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. +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 -`KeyT` -: A type for an object key other than `basic_json::json_pointer`. +`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 @@ -30,7 +37,8 @@ bool contains(const json_pointer& ptr) const; 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. +2. See 1. +3. `#!cpp true` if the JSON pointer can be resolved to a stored value, `#!cpp false` otherwise. ## Exception safety @@ -39,7 +47,8 @@ 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: +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 @@ -74,7 +83,7 @@ Logarithmic in the size of the JSON object. --8<-- "examples/contains.output" ``` -??? example "Example (1) check with JSON pointer" +??? example "Example (3) check with JSON pointer" The example shows how `contains()` is used. @@ -90,5 +99,6 @@ Logarithmic in the size of the JSON object. ## Version history -1. Added in version 3.6.0. -2. Added in version 3.7.0. +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..de135be21 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/count.md @@ -0,0 +1,64 @@ +# 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 + + The example shows how `count()` is used. + + ```cpp + --8<-- "examples/count.cpp" + ``` + + Output: + + ```json + --8<-- "examples/count.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..9e5f6c5bd --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/default_object_comparator_t.md @@ -0,0 +1,19 @@ +# 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). + +## 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 84% rename from doc/mkdocs/docs/api/basic_json/erase.md rename to docs/mkdocs/docs/api/basic_json/erase.md index d94c25b7f..6cb749b8c 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 @@ -156,7 +174,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/erase__key_type.output" ``` -??? example "Example: (4) remove element from a JSON array given an index" +??? 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 +190,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 100% rename from doc/mkdocs/docs/api/basic_json/error_handler_t.md rename to docs/mkdocs/docs/api/basic_json/error_handler_t.md 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..d4fddc579 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/find.md @@ -0,0 +1,72 @@ +# 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 + + 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 + +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/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/doc/mkdocs/docs/api/basic_json/get_allocator.md b/docs/mkdocs/docs/api/basic_json/get_allocator.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/get_allocator.md rename to docs/mkdocs/docs/api/basic_json/get_allocator.md 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 98% rename from doc/mkdocs/docs/api/basic_json/index.md rename to docs/mkdocs/docs/api/basic_json/index.md index 2b832a29b..02f5c514c 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) @@ -293,7 +294,7 @@ Access to the JSON value - [**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 100% rename from doc/mkdocs/docs/api/basic_json/input_format_t.md rename to docs/mkdocs/docs/api/basic_json/input_format_t.md 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 100% rename from doc/mkdocs/docs/api/basic_json/max_size.md rename to docs/mkdocs/docs/api/basic_json/max_size.md 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 94% rename from doc/mkdocs/docs/api/basic_json/meta.md rename to docs/mkdocs/docs/api/basic_json/meta.md index e2b312e0c..87767e4d5 100644 --- a/doc/mkdocs/docs/api/basic_json/meta.md +++ b/docs/mkdocs/docs/api/basic_json/meta.md @@ -45,6 +45,10 @@ Constant. --8<-- "examples/meta.output" ``` +## 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..6c64b6453 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/object_comparator_t.md @@ -0,0 +1,16 @@ +# 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. + +## 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 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 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 74% rename from doc/mkdocs/docs/api/basic_json/operator[].md rename to docs/mkdocs/docs/api/basic_json/operator[].md index 5b6512a21..cd5638b97 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: @@ -142,7 +154,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorarray__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. @@ -156,7 +168,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorarray__key_type_const.output" ``` -??? example "Example (3): access specified element via JSON Pointer" +??? example "Example (4): access specified element via JSON Pointer" The example below shows how values can be read and written using JSON Pointers. @@ -170,7 +182,7 @@ Strong exception safety: if an exception occurs, the original value stays intact --8<-- "examples/operatorjson_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. @@ -192,5 +204,6 @@ Strong exception safety: if an exception occurs, the original value stays intact ## 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..787588781 --- /dev/null +++ b/docs/mkdocs/docs/api/basic_json/operator_ValueType.md @@ -0,0 +1,83 @@ +# 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`](../../features/macros.md#json_use_implicit_conversions) 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 100% rename from doc/mkdocs/docs/api/basic_json/operator_eq.md rename to docs/mkdocs/docs/api/basic_json/operator_eq.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_ge.md b/docs/mkdocs/docs/api/basic_json/operator_ge.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_ge.md rename to docs/mkdocs/docs/api/basic_json/operator_ge.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_gt.md b/docs/mkdocs/docs/api/basic_json/operator_gt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_gt.md rename to docs/mkdocs/docs/api/basic_json/operator_gt.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_gtgt.md b/docs/mkdocs/docs/api/basic_json/operator_gtgt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_gtgt.md rename to docs/mkdocs/docs/api/basic_json/operator_gtgt.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_le.md b/docs/mkdocs/docs/api/basic_json/operator_le.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_le.md rename to docs/mkdocs/docs/api/basic_json/operator_le.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json.md b/docs/mkdocs/docs/api/basic_json/operator_literal_json.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_literal_json.md rename to docs/mkdocs/docs/api/basic_json/operator_literal_json.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md b/docs/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md similarity index 92% rename from doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md rename to docs/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md index 38c957e61..897ac07cd 100644 --- a/doc/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md +++ b/docs/mkdocs/docs/api/basic_json/operator_literal_json_pointer.md @@ -43,6 +43,10 @@ Linear. --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. diff --git a/doc/mkdocs/docs/api/basic_json/operator_lt.md b/docs/mkdocs/docs/api/basic_json/operator_lt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_lt.md rename to docs/mkdocs/docs/api/basic_json/operator_lt.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_ltlt.md b/docs/mkdocs/docs/api/basic_json/operator_ltlt.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_ltlt.md rename to docs/mkdocs/docs/api/basic_json/operator_ltlt.md diff --git a/doc/mkdocs/docs/api/basic_json/operator_ne.md b/docs/mkdocs/docs/api/basic_json/operator_ne.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/operator_ne.md rename to docs/mkdocs/docs/api/basic_json/operator_ne.md 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 99% rename from doc/mkdocs/docs/api/basic_json/parse.md rename to docs/mkdocs/docs/api/basic_json/parse.md index 95d876b0a..92808cd6b 100644 --- a/doc/mkdocs/docs/api/basic_json/parse.md +++ b/docs/mkdocs/docs/api/basic_json/parse.md @@ -31,6 +31,7 @@ static basic_json parse(IteratorType first, IteratorType last, - a `FILE` pointer - 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` 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 100% rename from doc/mkdocs/docs/api/basic_json/patch.md rename to docs/mkdocs/docs/api/basic_json/patch.md diff --git a/doc/mkdocs/docs/api/basic_json/push_back.md b/docs/mkdocs/docs/api/basic_json/push_back.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/push_back.md rename to docs/mkdocs/docs/api/basic_json/push_back.md 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 100% rename from doc/mkdocs/docs/api/basic_json/std_hash.md rename to docs/mkdocs/docs/api/basic_json/std_hash.md 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/doc/mkdocs/docs/api/basic_json/to_bon8.md b/docs/mkdocs/docs/api/basic_json/to_bon8.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/to_bon8.md rename to docs/mkdocs/docs/api/basic_json/to_bon8.md 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 73% rename from doc/mkdocs/docs/api/basic_json/value.md rename to docs/mkdocs/docs/api/basic_json/value.md index 0b4f1cc19..6a1f3481d 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,6 +101,7 @@ 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 @@ -104,7 +119,7 @@ changes to any JSON value. --8<-- "examples/basic_json__value.output" ``` -??? example "Example (2): access specified object element via JSON Pointer with default value" +??? 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. @@ -125,5 +140,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/doc/mkdocs/docs/api/basic_json/value_t.md b/docs/mkdocs/docs/api/basic_json/value_t.md similarity index 100% rename from doc/mkdocs/docs/api/basic_json/value_t.md rename to docs/mkdocs/docs/api/basic_json/value_t.md 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 100% 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 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 100% 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 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 100% 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 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 100% 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 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 100% rename from doc/mkdocs/docs/api/byte_container_with_subtype/subtype.md rename to docs/mkdocs/docs/api/byte_container_with_subtype/subtype.md diff --git a/doc/mkdocs/docs/api/json.md b/docs/mkdocs/docs/api/json.md similarity index 100% rename from doc/mkdocs/docs/api/json.md rename to docs/mkdocs/docs/api/json.md 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 56% rename from doc/mkdocs/docs/api/json_pointer/index.md rename to docs/mkdocs/docs/api/json_pointer/index.md index 6ef9435fb..dca9c382c 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 + +## Notes + +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.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 @@ -29,8 +39,10 @@ are the base for JSON patches. ## See also +- [operator""_json_pointer](../basic_json/operator_literal_json_pointer.md) - user-defined string literal for JSON pointers - [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/doc/mkdocs/docs/api/json_pointer/operator_string.md b/docs/mkdocs/docs/api/json_pointer/operator_string.md similarity index 54% rename from doc/mkdocs/docs/api/json_pointer/operator_string.md rename to docs/mkdocs/docs/api/json_pointer/operator_string.md index 56d8eebeb..836728c18 100644 --- a/doc/mkdocs/docs/api/json_pointer/operator_string.md +++ b/docs/mkdocs/docs/api/json_pointer/operator_string.md @@ -1,7 +1,7 @@ -# nlohmann::json_pointer::operator std::string +# nlohmann::json_pointer::operator string_t ```cpp -operator std::string() const +operator string_t() const ``` Return a string representation of the JSON pointer. @@ -13,7 +13,7 @@ A string representation of the JSON pointer ## Possible implementation ```cpp -operator std::string() const +operator string_t() const { return to_string(); } @@ -21,4 +21,5 @@ operator std::string() const ## Version history -Since version 2.0.0. +- Since version 2.0.0. +- Changed type to `string_t` 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..f18b51b81 --- /dev/null +++ b/docs/mkdocs/docs/api/json_pointer/string_t.md @@ -0,0 +1,12 @@ +# 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. + +## 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 100% rename from doc/mkdocs/docs/api/json_sax/binary.md rename to docs/mkdocs/docs/api/json_sax/binary.md diff --git a/doc/mkdocs/docs/api/json_sax/boolean.md b/docs/mkdocs/docs/api/json_sax/boolean.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/boolean.md rename to docs/mkdocs/docs/api/json_sax/boolean.md diff --git a/doc/mkdocs/docs/api/json_sax/end_array.md b/docs/mkdocs/docs/api/json_sax/end_array.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/end_array.md rename to docs/mkdocs/docs/api/json_sax/end_array.md diff --git a/doc/mkdocs/docs/api/json_sax/end_object.md b/docs/mkdocs/docs/api/json_sax/end_object.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/end_object.md rename to docs/mkdocs/docs/api/json_sax/end_object.md 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 100% rename from doc/mkdocs/docs/api/json_sax/key.md rename to docs/mkdocs/docs/api/json_sax/key.md diff --git a/doc/mkdocs/docs/api/json_sax/null.md b/docs/mkdocs/docs/api/json_sax/null.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/null.md rename to docs/mkdocs/docs/api/json_sax/null.md diff --git a/doc/mkdocs/docs/api/json_sax/number_float.md b/docs/mkdocs/docs/api/json_sax/number_float.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/number_float.md rename to docs/mkdocs/docs/api/json_sax/number_float.md diff --git a/doc/mkdocs/docs/api/json_sax/number_integer.md b/docs/mkdocs/docs/api/json_sax/number_integer.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/number_integer.md rename to docs/mkdocs/docs/api/json_sax/number_integer.md diff --git a/doc/mkdocs/docs/api/json_sax/number_unsigned.md b/docs/mkdocs/docs/api/json_sax/number_unsigned.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/number_unsigned.md rename to docs/mkdocs/docs/api/json_sax/number_unsigned.md diff --git a/doc/mkdocs/docs/api/json_sax/parse_error.md b/docs/mkdocs/docs/api/json_sax/parse_error.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/parse_error.md rename to docs/mkdocs/docs/api/json_sax/parse_error.md diff --git a/doc/mkdocs/docs/api/json_sax/start_array.md b/docs/mkdocs/docs/api/json_sax/start_array.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/start_array.md rename to docs/mkdocs/docs/api/json_sax/start_array.md diff --git a/doc/mkdocs/docs/api/json_sax/start_object.md b/docs/mkdocs/docs/api/json_sax/start_object.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/start_object.md rename to docs/mkdocs/docs/api/json_sax/start_object.md diff --git a/doc/mkdocs/docs/api/json_sax/string.md b/docs/mkdocs/docs/api/json_sax/string.md similarity index 100% rename from doc/mkdocs/docs/api/json_sax/string.md rename to docs/mkdocs/docs/api/json_sax/string.md diff --git a/docs/mkdocs/docs/api/macros/index.md b/docs/mkdocs/docs/api/macros/index.md new file mode 100644 index 000000000..56924da44 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/index.md @@ -0,0 +1,37 @@ +# 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_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 + +## 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 + +## Type conversions + +- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions + +## Serialization/deserialization macros + +- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_intrusive.md) - 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...)**](nlohmann_define_type_non_intrusive.md) - serialization/deserialization of types _without_ access to private variables +- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum + types 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..d42025092 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_diagnostics.md @@ -0,0 +1,67 @@ +# 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. + +The diagnostics messages can also be controlled with the CMake option `JSON_Diagnostics` (`OFF` by default) which sets +`JSON_DIAGNOSTICS` accordingly. + +## 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 + +!!! danger "ABI incompatibility" + + As this macro changes the definition of the `basic_json` object, it MUST be defined in the same way globally, even + across different compilation units: `basic_json` objects with differently defined `JSON_DIAGNOSTICS` macros are + not compatible! + +## 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. 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..3bee84324 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_cpp_11.md @@ -0,0 +1,28 @@ +# 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. + +## 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..160ad8c24 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_has_filesystem.md @@ -0,0 +1,30 @@ +# 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. + +## Version history + +- Added in version 3.10.5. 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..10ae24c8a --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_no_io.md @@ -0,0 +1,21 @@ +# 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 +``` + +## 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..0f32b63e9 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_noexception.md @@ -0,0 +1,32 @@ +# 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). + +## 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..c58d0ea85 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_skip_unsupported_compiler_check.md @@ -0,0 +1,20 @@ +# 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 +``` + +## 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_implicit_conversions.md b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md new file mode 100644 index 000000000..3ee81b061 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md @@ -0,0 +1,56 @@ +# 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). + +Implicit conversions can also be controlled with the CMake option `JSON_ImplicitConversions` (`ON` by default) which +sets `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. + +## 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). + +## 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/nlohmann_define_type_intrusive.md b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md new file mode 100644 index 000000000..7269ef081 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md @@ -0,0 +1,124 @@ +# 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?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types) + for how to overcome this limitation. + 2. The macro must be used inside the type (class/struct). + +!!! 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 Types 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..7ed5a6b43 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_define_type_non_intrusive.md @@ -0,0 +1,124 @@ +# 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?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types) + for how to overcome this limitation. + 2. The macro must be used outside the type (class/struct). + 3. The passed members must be public. + +!!! 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 Types 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_serialize_enum.md b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md new file mode 100644 index 000000000..7b0f89802 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_serialize_enum.md @@ -0,0 +1,84 @@ +# 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) + +## 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..826785292 --- /dev/null +++ b/docs/mkdocs/docs/api/macros/nlohmann_json_version_major.md @@ -0,0 +1,23 @@ +# 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. + +## 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/ordered_json.md b/docs/mkdocs/docs/api/ordered_json.md similarity index 100% rename from doc/mkdocs/docs/api/ordered_json.md rename to docs/mkdocs/docs/api/ordered_json.md 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/doc/mkdocs/docs/features/arbitrary_types.md b/docs/mkdocs/docs/features/arbitrary_types.md similarity index 78% rename from doc/mkdocs/docs/features/arbitrary_types.md rename to docs/mkdocs/docs/features/arbitrary_types.md index fe80dc701..49a541ef5 100644 --- a/doc/mkdocs/docs/features/arbitrary_types.md +++ b/docs/mkdocs/docs/features/arbitrary_types.md @@ -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) }; diff --git a/docs/mkdocs/docs/features/assertions.md b/docs/mkdocs/docs/features/assertions.md new file mode 100644 index 000000000..a0b118722 --- /dev/null +++ b/docs/mkdocs/docs/features/assertions.md @@ -0,0 +1,104 @@ +# 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. + ``` 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 100% rename from doc/mkdocs/docs/features/binary_formats/index.md rename to docs/mkdocs/docs/features/binary_formats/index.md 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 100% rename from doc/mkdocs/docs/features/binary_values.md rename to docs/mkdocs/docs/features/binary_values.md 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/doc/mkdocs/docs/features/element_access/checked_access.md b/docs/mkdocs/docs/features/element_access/checked_access.md similarity index 100% rename from doc/mkdocs/docs/features/element_access/checked_access.md rename to docs/mkdocs/docs/features/element_access/checked_access.md 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 90% rename from doc/mkdocs/docs/features/element_access/unchecked_access.md rename to docs/mkdocs/docs/features/element_access/unchecked_access.md index bb7228777..4fdef35c7 100644 --- a/doc/mkdocs/docs/features/element_access/unchecked_access.md +++ b/docs/mkdocs/docs/features/element_access/unchecked_access.md @@ -94,9 +94,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 73% rename from doc/mkdocs/docs/features/enum_conversion.md rename to docs/mkdocs/docs/features/enum_conversion.md index 8f474a702..7e61f67bb 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: diff --git a/doc/mkdocs/docs/features/iterators.md b/docs/mkdocs/docs/features/iterators.md similarity index 100% rename from doc/mkdocs/docs/features/iterators.md rename to docs/mkdocs/docs/features/iterators.md 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..a7861ec7d --- /dev/null +++ b/docs/mkdocs/docs/features/json_pointer.md @@ -0,0 +1,123 @@ +# 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 idientified 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` | + +## 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 56% rename from doc/mkdocs/docs/features/macros.md rename to docs/mkdocs/docs/features/macros.md index d324a1325..e04a426a5 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,13 @@ 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`. - -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 [full documentation of `JSON_NOEXCEPTION`](../api/macros/json_noexception.md). ## `JSON_NO_IO` @@ -58,48 +60,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 +103,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 +122,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 57% rename from doc/mkdocs/docs/features/object_order.md rename to docs/mkdocs/docs/features/object_order.md index 86bb253ba..0768f8020 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,6 +35,8 @@ 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 @@ -65,3 +69,58 @@ 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)). + +### 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, + "two": 2, + "three": 3 + } + ``` + +??? 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..69c2163b7 --- /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/basic_json/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 97% rename from doc/mkdocs/docs/home/exceptions.md rename to docs/mkdocs/docs/home/exceptions.md index 1241926cf..666d225bd 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. @@ -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 diff --git a/doc/mkdocs/docs/home/faq.md b/docs/mkdocs/docs/home/faq.md similarity index 100% rename from doc/mkdocs/docs/home/faq.md rename to docs/mkdocs/docs/home/faq.md diff --git a/doc/mkdocs/docs/home/license.md b/docs/mkdocs/docs/home/license.md similarity index 96% rename from doc/mkdocs/docs/home/license.md rename to docs/mkdocs/docs/home/license.md index d359468e0..baef2f51b 100644 --- a/doc/mkdocs/docs/home/license.md +++ b/docs/mkdocs/docs/home/license.md @@ -4,7 +4,7 @@ The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): -Copyright © 2013-2021 [Niels Lohmann](https://nlohmann.me) +Copyright © 2013-2022 [Niels Lohmann](https://nlohmann.me) 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: 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..2247ba009 --- /dev/null +++ b/docs/mkdocs/docs/integration/cmake.md @@ -0,0 +1,162 @@ +# 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.10.5 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.10.5 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.10.5/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.10.5 + ) + ``` + + 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`](../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/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 84% rename from doc/mkdocs/mkdocs.yml rename to docs/mkdocs/mkdocs.yml index 8df467b2f..8ee9bba25 100644 --- a/doc/mkdocs/mkdocs.yml +++ b/docs/mkdocs/mkdocs.yml @@ -6,10 +6,10 @@ 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 - 2021 Niels Lohmann +copyright: Copyright © 2013 - 2022 Niels Lohmann # Configuration theme: @@ -60,9 +60,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 +97,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 @@ -211,6 +214,7 @@ nav: - '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 @@ -231,7 +235,30 @@ nav: - '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_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_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_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.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_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: @@ -288,6 +315,7 @@ plugins: lang: en - minify: minify_html: true + - git-revision-date-localized 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..aa9fcaf0e --- /dev/null +++ b/docs/mkdocs/requirements.txt @@ -0,0 +1,48 @@ +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-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/doc/mkdocs/scripts/check_structure.py b/docs/mkdocs/scripts/check_structure.py old mode 100644 new mode 100755 similarity index 51% rename from doc/mkdocs/scripts/check_structure.py rename to docs/mkdocs/scripts/check_structure.py index cacc51cb4..92f6ff182 --- a/doc/mkdocs/scripts/check_structure.py +++ b/docs/mkdocs/scripts/check_structure.py @@ -2,10 +2,19 @@ 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_headers = [ + expected_sections = [ 'Template parameters', 'Specializations', 'Iterator invalidation', @@ -23,13 +32,14 @@ def check_structure(): 'Exceptions', 'Complexity', 'Possible implementation', + 'Default definition', 'Notes', 'Examples', 'See also', 'Version history' ] - required_headers = [ + required_sections = [ 'Examples', 'Version history' ] @@ -37,8 +47,8 @@ def check_structure(): files = sorted(glob.glob('api/**/*.md', recursive=True)) for file in files: with open(file) as file_content: - header_idx = -1 - existing_headers = [] + section_idx = -1 + existing_sections = [] in_initial_code_example = False previous_line = None h1sections = 0 @@ -51,50 +61,55 @@ def check_structure(): # there should only be one top-level title if h1sections > 1: - print(f'{file}:{lineno+1}: Error: unexpected top-level title "{line}"!') + 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': - print(f'{file}:{lineno+1}: Error: overview pages should have a better title!') + 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: - print(f'{file}:{lineno+1}: Error: line is too long ({len(line)} vs. 160 chars)!') + report('whitespace/line_length', f'{file}:{lineno+1}', f'line is too long ({len(line)} vs. 160 chars)') - # check if headers are correct + # check if sections are correct if line.startswith('## '): - header = line.strip('## ') - existing_headers.append(header) + current_section = line.strip('## ') + existing_sections.append(current_section) - 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 + 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: - print(f'{file}:{lineno+1}: Error: header "{header}" is not part of the expected headers!') + report('structure/unknown_section', f'{file}:{lineno+1}', f'section "{current_section}" is not part of the expected sections') # code example - if line == '```cpp' and header_idx == -1: + if line == '```cpp' and section_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}') + report('style/numbering', 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!') + report('whitespace/blank_lines', f'{file}:{lineno}-{lineno+1}', '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}', f'"{untitled_admonition.group(2)}" admonitions should have a title') 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!') + 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(): @@ -113,9 +128,11 @@ def check_examples(): break if not found: - print(f'{example_file}: Error: example file is not used in any documentation file!') + 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/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 207d3e302..079baa723 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #if JSON_HAS_EXPERIMENTAL_FILESYSTEM @@ -42,7 +43,7 @@ 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,7 +81,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) case value_t::binary: case value_t::discarded: default: - JSON_THROW(type_error::create(302, "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)); } } @@ -89,7 +90,7 @@ 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(); } @@ -99,23 +100,22 @@ 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 + && !std::is_same::value + && !is_json_ref::value, int > = 0 > +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(); @@ -155,7 +155,7 @@ 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(), @@ -172,7 +172,7 @@ 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), @@ -269,7 +269,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,7 +288,7 @@ 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 {}); @@ -299,7 +299,7 @@ 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(); @@ -311,7 +311,7 @@ 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; @@ -371,7 +371,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)); } } @@ -412,7 +412,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> {}); @@ -425,14 +425,14 @@ void from_json(const BasicJsonType& j, std::map& { 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()); } @@ -445,14 +445,14 @@ void from_json(const BasicJsonType& j, std::unordered_map(), p.at(1).template get()); } @@ -464,7 +464,7 @@ 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(); } diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index b4b180496..4d61de402 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -1,5 +1,6 @@ #pragma once +#include // nullptr_t #include // exception #include // runtime_error #include // to_string @@ -9,6 +10,10 @@ #include #include #include +#include +#include +#include + namespace nlohmann { @@ -38,15 +43,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 +104,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 +135,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 +169,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 +179,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 +197,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 +214,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 +231,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()}; } diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 127f1457e..9323c5f05 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -12,6 +12,7 @@ #include // char_traits, string #include // make_pair, move #include // vector +#include // map #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include namespace nlohmann @@ -73,7 +75,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 +119,7 @@ class binary_reader break; case input_format_t::ubjson: + case input_format_t::bjdata: result = parse_ubjson_internal(); break; @@ -132,7 +135,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(); } @@ -143,8 +146,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)); } } @@ -220,7 +223,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(); @@ -241,7 +245,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 @@ -323,7 +328,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)); } } } @@ -723,7 +730,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: @@ -880,7 +888,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)); } } } @@ -975,7 +984,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)); } } } @@ -1074,7 +1084,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)); } } } @@ -1544,7 +1555,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)); } } } @@ -1626,7 +1638,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)); } } } @@ -1837,7 +1850,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; } @@ -1847,51 +1860,154 @@ 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; + + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) + { + 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, 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))) + { + return false; + } + dim.push_back(dimlen); + } + } + } + else + { + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, current))) + { + return false; + } + dim.push_back(dimlen); + get_ignore_noop(); + } + } + return true; } /*! @param[out] result determined size @return whether size determination completed */ - bool get_ubjson_size_value(std::size_t& result) + bool get_ubjson_size_value(std::size_t& result, 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; } @@ -1902,7 +2018,7 @@ 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; } @@ -1913,7 +2029,7 @@ 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; } @@ -1924,7 +2040,7 @@ 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; } @@ -1935,7 +2051,7 @@ 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; } @@ -1943,12 +2059,105 @@ class binary_reader return true; } - default: + case 'u': { - 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::uint16_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = static_cast(number); + return true; } + + case 'm': + { + if (input_format != input_format_t::bjdata) + { + break; + } + std::uint32_t number{}; + if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) + { + return false; + } + result = 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; + } + result = detail::conditional_static_cast(number); + return true; + } + + case '[': + { + if (input_format != input_format_t::bjdata) + { + break; + } + 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 + { + 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 (JSON_HEDLEY_UNLIKELY(!sax->number_integer(static_cast(i)))) + { + return false; + } + } + result |= (1ull << (sizeof(result) * 8 - 1)); // low 63 bit of result stores the total element count, sign-bit indicates ndarray + 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)); } /*! @@ -1970,8 +2179,10 @@ class binary_reader 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(!unexpect_eof(input_format, "type") || (input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() ))) { return false; } @@ -1979,12 +2190,13 @@ 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); @@ -2007,7 +2219,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); @@ -2020,43 +2232,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': @@ -2067,14 +2361,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); @@ -2093,11 +2388,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)); } /*! @@ -2111,6 +2405,44 @@ class binary_reader return false; } + // detect and 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.first >= (1ull << (sizeof(std::size_t) * 8 - 1))) + { + 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"} + }; + + string_t key = "_ArrayType_"; + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0 || !sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + { + return false; + } + + if (size_and_type.second == 'C') + { + size_and_type.second = 'U'; + } + + size_and_type.first &= ~(1ull << (sizeof(std::size_t) * 8 - 1)); + 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))) @@ -2173,6 +2505,11 @@ class binary_reader return false; } + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && size_and_type.first >= (1ull << (sizeof(std::size_t) * 8 - 1))) + { + return false; + } + string_t key; if (size_and_type.first != string_t::npos) { @@ -2255,7 +2592,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; } @@ -2273,7 +2610,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) @@ -2299,7 +2637,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)); } } @@ -2643,6 +2982,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) @@ -2658,7 +2999,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); } @@ -2750,7 +3091,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; } @@ -2799,12 +3140,16 @@ class binary_reader error_msg += "BON8"; 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: @@ -2820,6 +3165,9 @@ 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; }; diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index c63d3723f..0f0a8e5c3 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -23,7 +23,7 @@ namespace nlohmann namespace detail { /// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson, bon8 }; +enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata, bon8 }; //////////////////// // input adapters // diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index fd9dab87a..406008167 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace nlohmann { @@ -224,7 +225,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; @@ -250,7 +251,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; @@ -405,7 +406,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 +476,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; diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index 024dd040f..32b360969 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace nlohmann @@ -95,7 +96,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 +123,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 +161,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 +207,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 +219,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 +262,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 +332,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 +346,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 +392,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 +405,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 +418,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 +446,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 +462,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; diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 434a62d3e..cdcdaff1f 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -285,7 +285,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 +301,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 +343,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 +352,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 +403,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 +460,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 +505,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 +513,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 +569,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 +648,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 +677,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 +699,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 +717,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)); } /*! diff --git a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp index e787fdbcd..65bb327a5 100644 --- a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +++ b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -48,7 +48,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 +60,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)); } diff --git a/include/nlohmann/detail/iterators/primitive_iterator.hpp b/include/nlohmann/detail/iterators/primitive_iterator.hpp index 15aa2f08a..03bc37e2c 100644 --- a/include/nlohmann/detail/iterators/primitive_iterator.hpp +++ b/include/nlohmann/detail/iterators/primitive_iterator.hpp @@ -87,7 +87,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 +100,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; diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index caed67c9e..f94f3bdf9 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -2,6 +2,8 @@ #include // all_of #include // isdigit +#include // errno, ERANGE +#include // strtoull #include // max #include // accumulate #include // string @@ -10,6 +12,7 @@ #include #include +#include #include #include @@ -18,35 +21,53 @@ namespace nlohmann /// @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 + operator string_t() const { return to_string(); } @@ -63,7 +84,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 +107,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 +139,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 +147,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 +159,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 +189,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 +232,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 +249,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 +285,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 +303,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 +329,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 +370,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 +384,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 +397,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 +416,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 +435,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 +455,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 +474,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 +491,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 +504,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 +523,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 +542,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 +553,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 +601,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 +642,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 +655,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 +666,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 +680,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 +690,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 +710,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 +729,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 +748,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 +781,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 +797,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 +810,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 +836,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 +852,27 @@ 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; }; + +// 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); +} } // namespace nlohmann diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index b2843f067..cc9ac5fc7 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -70,7 +70,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 +97,21 @@ #define JSON_HAS_FILESYSTEM 0 #endif +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L \ + && defined(__cpp_impl_three_way_comparison)&& __cpp_impl_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#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 +349,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 +360,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 +373,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): diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp index 1a29fb5e0..ec57b02cc 100644 --- a/include/nlohmann/detail/macro_unscope.hpp +++ b/include/nlohmann/detail/macro_unscope.hpp @@ -8,19 +8,24 @@ // 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_NO_UNIQUE_ADDRESS + +#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 +#endif #include diff --git a/include/nlohmann/detail/meta/cpp_future.hpp b/include/nlohmann/detail/meta/cpp_future.hpp index 147f2fa35..ef2da370d 100644 --- a/include/nlohmann/detail/meta/cpp_future.hpp +++ b/include/nlohmann/detail/meta/cpp_future.hpp @@ -147,8 +147,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 diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 984ca1931..2cc13f3ac 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -44,6 +44,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 +155,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 +180,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>::type {}; // https://en.cppreference.com/w/cpp/types/negation template struct negation : std::integral_constant < bool, !B::value > { }; @@ -439,6 +467,78 @@ 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