diff --git a/external/json/.clang-format b/external/json/.clang-format deleted file mode 100644 index 5b9e3fd5..00000000 --- a/external/json/.clang-format +++ /dev/null @@ -1,84 +0,0 @@ -#AccessModifierOffset: 2 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: false -#AlignConsecutiveBitFields: false -AlignConsecutiveDeclarations: false -AlignConsecutiveMacros: false -AlignEscapedNewlines: Right -#AlignOperands: AlignAfterOperator -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: false -AllowAllConstructorInitializersOnNextLine: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Empty -AllowShortCaseLabelsOnASingleLine: false -#AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: Empty -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Empty -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -#BitFieldColonSpacing: Both -BreakBeforeBraces: Custom # or Allman -BraceWrapping: - AfterCaseLabel: true - AfterClass: true - AfterControlStatement: Always - AfterEnum: true - AfterFunction: true - AfterNamespace: false - AfterStruct: true - AfterUnion: true - AfterExternBlock: false - BeforeCatch: true - BeforeElse: true - #BeforeLambdaBody: false - #BeforeWhile: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeComma -BreakStringLiterals: false -ColumnLimit: 0 -CompactNamespaces: false -ConstructorInitializerIndentWidth: 2 -Cpp11BracedListStyle: true -PointerAlignment: Left -FixNamespaceComments: true -IncludeBlocks: Preserve -#IndentCaseBlocks: false -IndentCaseLabels: true -IndentGotoLabels: false -IndentPPDirectives: BeforeHash -IndentWidth: 4 -KeepEmptyLinesAtTheStartOfBlocks: false -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ReflowComments: false -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 2 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInConditionalStatement: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: c++11 -TabWidth: 4 -UseTab: Never diff --git a/external/json/.clang-tidy b/external/json/.clang-tidy index 339360b0..ca6b9b09 100644 --- a/external/json/.clang-tidy +++ b/external/json/.clang-tidy @@ -1,8 +1,16 @@ +# TODO: The first three checks are only removed to get the CI going. They have to be addressed at some point. + Checks: '*, + + -portability-template-virtual-member-function, + -bugprone-use-after-move, + -hicpp-invalid-access-moved, + -altera-id-dependent-backward-branch, -altera-struct-pack-align, -altera-unroll-loops, -android-cloexec-fopen, + -boost-use-ranges, -bugprone-easily-swappable-parameters, -cert-err58-cpp, -concurrency-mt-unsafe, @@ -44,7 +52,10 @@ Checks: '*, -modernize-concat-nested-namespaces, -modernize-type-traits, -modernize-use-constraints, + -modernize-use-designated-initializers, -modernize-use-nodiscard, + -modernize-use-ranges, + -modernize-use-std-numbers, -modernize-use-trailing-return-type, -performance-enum-size, -readability-function-cognitive-complexity, diff --git a/external/json/.github/CONTRIBUTING.md b/external/json/.github/CONTRIBUTING.md index 4d33c67b..87b13df3 100644 --- a/external/json/.github/CONTRIBUTING.md +++ b/external/json/.github/CONTRIBUTING.md @@ -1,5 +1,3 @@ -[![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/pr?style=flat)](http://issuestats.com/github/nlohmann/json) [![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/issue?style=flat)](http://issuestats.com/github/nlohmann/json) - # How to contribute This project started as a little excuse to exercise some of the cool new C++11 features. Over time, people actually started to use the JSON library (yey!) and started to help improve it by proposing features, finding bugs, or even fixing my mistakes. I am really [thankful](https://github.com/nlohmann/json/blob/master/README.md#thanks) for this and try to keep track of all the helpers. @@ -22,7 +20,7 @@ Clearly describe the issue: - If you propose a change or addition, try to give an **example** how the improved code could look like or how to use it. - If you found a compilation error, please tell us which **compiler** (version and operating system) you used and paste the (relevant part of) the error messages to the ticket. -Please stick to the provided issue template ([bug report](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE/bug.yml) if possible. For questions, feature or support requests, please [open a discussion](https://github.com/nlohmann/json/discussions/new). +Please stick to the provided issue template ([bug report](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE/bug.yaml) if possible. For questions, feature or support requests, please [open a discussion](https://github.com/nlohmann/json/discussions/new). ## Files to change diff --git a/external/json/.github/dependabot.yml b/external/json/.github/dependabot.yml new file mode 100644 index 00000000..c56ed590 --- /dev/null +++ b/external/json/.github/dependabot.yml @@ -0,0 +1,26 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + + - package-ecosystem: pip + directory: /docs/mkdocs + schedule: + interval: daily + + - package-ecosystem: pip + directory: /tools/astyle + schedule: + interval: daily + + - package-ecosystem: pip + directory: /tools/serve_header + schedule: + interval: daily + + - package-ecosystem: pip + directory: /cmake/requirements + schedule: + interval: daily diff --git a/external/json/.github/workflows/check_amalgamation.yml b/external/json/.github/workflows/check_amalgamation.yml index 0fadb520..38d7c2fd 100644 --- a/external/json/.github/workflows/check_amalgamation.yml +++ b/external/json/.github/workflows/check_amalgamation.yml @@ -3,18 +3,24 @@ name: "Check amalgamation" on: pull_request: -permissions: read-all +permissions: + contents: read jobs: save: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + - name: Save PR number run: | mkdir -p ./pr echo ${{ github.event.number }} > ./pr/number echo ${{ github.event.pull_request.user.login }} > ./pr/author - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: name: pr path: pr/ @@ -25,29 +31,29 @@ jobs: MAIN_DIR: ${{ github.workspace }}/main INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate - ASTYLE_FLAGS: > - --style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block - --indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type - --align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date - --formatted steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + - name: Checkout pull request - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: main ref: ${{ github.event.pull_request.head.sha }} - name: Checkout tools - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: tools ref: develop - name: Install astyle run: | - sudo apt-get update - sudo apt-get install astyle + python3 -mvenv venv + venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt - name: Check amalgamation run: | @@ -60,11 +66,11 @@ jobs: python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s . python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s . echo "Format (1)" - astyle $ASTYLE_FLAGS --suffix=none --quiet $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp + ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp diff $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json.hpp diff $INCLUDE_DIR/json_fwd.hpp~ $INCLUDE_DIR/json_fwd.hpp - astyle $ASTYLE_FLAGS $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) + ${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=orig $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort) echo Check find $MAIN_DIR -name '*.orig' -exec false {} \+ diff --git a/external/json/.github/workflows/cifuzz.yml b/external/json/.github/workflows/cifuzz.yml index 0fd355bc..425993f0 100644 --- a/external/json/.github/workflows/cifuzz.yml +++ b/external/json/.github/workflows/cifuzz.yml @@ -8,22 +8,27 @@ jobs: Fuzzing: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + - name: Build Fuzzers id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@57fe4475324c5506adbfecdcdd2917f65c86ee9e # master with: oss-fuzz-project-name: 'json' dry-run: false language: c++ - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@57fe4475324c5506adbfecdcdd2917f65c86ee9e # master with: oss-fuzz-project-name: 'json' fuzz-seconds: 300 dry-run: false language: c++ - name: Upload Crash - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/external/json/.github/workflows/codeql-analysis.yml b/external/json/.github/workflows/codeql-analysis.yml index 93923a18..6af859d6 100644 --- a/external/json/.github/workflows/codeql-analysis.yml +++ b/external/json/.github/workflows/codeql-analysis.yml @@ -11,13 +11,13 @@ on: - cron: '0 19 * * 1' workflow_dispatch: -permissions: - contents: read - concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} cancel-in-progress: true +permissions: + contents: read + jobs: CodeQL-Build: @@ -26,19 +26,24 @@ jobs: security-events: write steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: languages: c-cpp # 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@v2 + uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 diff --git a/external/json/.github/workflows/comment_check_amalgamation.yml b/external/json/.github/workflows/comment_check_amalgamation.yml index 2ab5ebb9..edbece45 100644 --- a/external/json/.github/workflows/comment_check_amalgamation.yml +++ b/external/json/.github/workflows/comment_check_amalgamation.yml @@ -5,7 +5,8 @@ on: types: - completed -permissions: {} +permissions: + contents: read jobs: comment: @@ -17,8 +18,13 @@ jobs: issues: read pull-requests: write steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + - name: 'Download artifact' - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6.4.0 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -40,7 +46,7 @@ jobs: - run: unzip pr.zip - name: 'Comment on PR' - uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975 # v6.4.0 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/external/json/.github/workflows/dependency-review.yml b/external/json/.github/workflows/dependency-review.yml new file mode 100644 index 00000000..21a469b1 --- /dev/null +++ b/external/json/.github/workflows/dependency-review.yml @@ -0,0 +1,27 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: 'Checkout Repository' + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: 'Dependency Review' + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 diff --git a/external/json/.github/workflows/labeler.yml b/external/json/.github/workflows/labeler.yml index 11925e1a..0898980e 100644 --- a/external/json/.github/workflows/labeler.yml +++ b/external/json/.github/workflows/labeler.yml @@ -4,7 +4,8 @@ on: pull_request_target: types: [opened, synchronize] -permissions: {} +permissions: + contents: read jobs: label: @@ -15,6 +16,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: srvaroa/labeler@master + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - uses: srvaroa/labeler@1b3cdb1af3e59155a08b9b2436d0d54feaff49e2 # master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/external/json/.github/workflows/macos.yml b/external/json/.github/workflows/macos.yml index 9ac1fe3f..4a22a5ba 100644 --- a/external/json/.github/workflows/macos.yml +++ b/external/json/.github/workflows/macos.yml @@ -9,24 +9,60 @@ on: pull_request: workflow_dispatch: -permissions: - contents: read - concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} cancel-in-progress: true +permissions: + contents: read + jobs: - xcode_1: - runs-on: macos-11 +# macos-11 is deprecated +# macos-11: +# runs-on: macos-11 +# strategy: +# matrix: +# xcode: ['11.7', '12.4', '12.5.1', '13.0'] +# env: +# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer +# +# steps: +# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +# - name: Run CMake +# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON +# - name: Build +# run: cmake --build build --parallel 10 +# - name: Test +# run: cd build ; ctest -j 10 --output-on-failure + +# macos-12 is deprecated (https://github.com/actions/runner-images/issues/10721) +# macos-12: +# runs-on: macos-12 # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md +# strategy: +# matrix: +# xcode: ['13.1', '13.2.1', '13.3.1', '13.4.1', '14.0', '14.0.1', '14.1'] +# env: +# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer +# +# steps: +# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 +# - name: Run CMake +# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON +# - name: Build +# run: cmake --build build --parallel 10 +# - name: Test +# run: cd build ; ctest -j 10 --output-on-failure + + macos-13: + runs-on: macos-13 # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md strategy: matrix: - xcode: ['11.7', '12.4', '12.5.1', '13.0'] + xcode: ['14.1', '14.2', '14.3', '14.3.1', '15.0.1', '15.1', '15.2'] env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON - name: Build @@ -34,16 +70,33 @@ jobs: - name: Test run: cd build ; ctest -j 10 --output-on-failure - xcode_2: - runs-on: macos-12 + macos-14: + runs-on: macos-14 # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md strategy: matrix: - xcode: ['13.1', '13.2.1', '13.3.1', '13.4.1', '14.0', '14.0.1', '14.1'] + xcode: ['15.3', '15.4'] env: DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Run CMake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON + - name: Build + run: cmake --build build --parallel 10 + - name: Test + run: cd build ; ctest -j 10 --output-on-failure + + macos-15: + runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md + strategy: + matrix: + xcode: ['16.0', '16.1'] + env: + DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON - name: Build @@ -58,7 +111,7 @@ jobs: standard: [11, 14, 17, 20, 23] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_TestStandards=${{ matrix.standard }} - name: Build diff --git a/external/json/.github/workflows/publish_documentation.yml b/external/json/.github/workflows/publish_documentation.yml index 5a32d13a..c6b56a53 100644 --- a/external/json/.github/workflows/publish_documentation.yml +++ b/external/json/.github/workflows/publish_documentation.yml @@ -10,23 +10,28 @@ on: - docs/examples/** workflow_dispatch: -permissions: - contents: read - # we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications concurrency: group: documentation cancel-in-progress: false +permissions: + contents: read + jobs: publish_documentation: + permissions: + contents: write + if: github.repository == 'nlohmann/json' runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit - - name: Install and update PlantUML - run: sudo apt-get update ; sudo apt-get install -y plantuml + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install virtual environment run: make install_venv -C docs/mkdocs @@ -35,7 +40,7 @@ jobs: run: make build -C docs/mkdocs - name: Deploy documentation - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/mkdocs/site diff --git a/external/json/.github/workflows/scorecards.yml b/external/json/.github/workflows/scorecards.yml new file mode 100644 index 00000000..4a271301 --- /dev/null +++ b/external/json/.github/workflows/scorecards.yml @@ -0,0 +1,81 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '20 7 * * 2' + push: + branches: ["develop"] + +permissions: + contents: read + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + contents: read + actions: read + # To allow GraphQL ListCommits to work + issues: read + pull-requests: read + # To detect SAST tools + checks: read + + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: "Checkout code" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecards on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + with: + sarif_file: results.sarif diff --git a/external/json/.github/workflows/ubuntu.yml b/external/json/.github/workflows/ubuntu.yml index 35fb9573..21028f85 100644 --- a/external/json/.github/workflows/ubuntu.yml +++ b/external/json/.github/workflows/ubuntu.yml @@ -8,7 +8,7 @@ on: - release/* pull_request: workflow_dispatch: - + permissions: contents: read @@ -23,9 +23,9 @@ jobs: steps: - name: Install git and unzip run: apt-get update ; apt-get install -y git unzip - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -33,36 +33,54 @@ jobs: ci_test_gcc: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 + container: gcc:latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Get latest CMake and ninja + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build run: cmake --build build --target ci_test_gcc - ci_static_analysis: + ci_infer: runs-on: ubuntu-latest container: ghcr.io/nlohmann/json-ci:v2.4.0 - strategy: - matrix: - target: [ci_cppcheck, ci_test_valgrind, ci_test_amalgamation, ci_test_single_header, ci_single_binaries, ci_infer] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build - run: cmake --build build --target ${{ matrix.target }} + run: cmake --build build --target ci_infer + + ci_test_single_header: + runs-on: ubuntu-latest + container: gcc:latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Get latest CMake and ninja + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 + - name: Run CMake + run: cmake -S . -B build -DJSON_CI=On + - name: Build + run: cmake --build build --target ci_test_single_header ci_static_analysis_ubuntu: runs-on: ubuntu-latest strategy: matrix: - target: [ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata] + target: [ci_test_amalgamation, ci_cppcheck, ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata, ci_reuse_compliance, ci_test_valgrind] steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: Install Valgrind + run: sudo apt-get update ; sudo apt-get install -y valgrind + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -73,13 +91,13 @@ jobs: container: silkeh/clang:dev strategy: matrix: - target: [ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze] + target: [ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze, ci_single_binaries] steps: - name: Install git, clang-tools, and unzip - run: apt-get update ; apt-get install -y git clang-tools unzip - - uses: actions/checkout@v3 + run: apt-get update ; apt-get install -y git clang-tools iwyu unzip + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -90,13 +108,13 @@ jobs: container: ubuntu:focal strategy: matrix: - target: [ci_cmake_flags, ci_test_diagnostics, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls] + target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls] steps: - name: Install build-essential run: apt-get update ; apt-get install -y build-essential unzip wget git - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -104,37 +122,59 @@ jobs: ci_test_coverage: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 - permissions: - contents: read - checks: write steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Install dependencies and de_DE locale + run: | + sudo apt-get clean + sudo apt-get update + sudo apt-get install -y build-essential cmake lcov ninja-build make locales gcc-multilib g++-multilib + sudo locale-gen de_DE + sudo update-locale - name: Run 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@v3 + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 with: name: code-coverage-report path: ${{ github.workspace }}/build/html - name: Publish report to Coveralls - uses: coverallsapp/github-action@master + uses: coverallsapp/github-action@cfd0633edbd2411b532b808ba7a8b5e04f76d2c8 # v2.3.4 with: github-token: ${{ secrets.GITHUB_TOKEN }} path-to-lcov: ${{ github.workspace }}/build/json.info.filtered.noexcept + ci_test_compilers_gcc_old: + runs-on: ubuntu-latest + strategy: + matrix: + compiler: ['4.8', '4.9', '5', '6'] + container: ghcr.io/nlohmann/json-ci:v2.4.0 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Run CMake + run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On + - name: Build + run: cmake --build build --target ci_test_compiler_g++-${{ matrix.compiler }} + ci_test_compilers_gcc: runs-on: ubuntu-latest strategy: matrix: - compiler: ['4', '5', '6', '7', '8', '9', '10', '11', '12', 'latest'] + # older GCC docker images (4, 5, 6) fail to check out code + compiler: ['7', '8', '9', '10', '11', '12', '13', '14', 'latest'] container: gcc:${{ matrix.compiler }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -144,14 +184,14 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - compiler: ['3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', 'latest'] + compiler: ['3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', '16', '17', '18', '19', 'latest'] container: silkeh/clang:${{ matrix.compiler }} steps: - name: Install unzip and git run: apt-get update ; apt-get install -y unzip git - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10 run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV" if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }} @@ -160,27 +200,16 @@ jobs: - name: Build run: cmake --build build --target ci_test_compiler_default - ci_test_compilers: - runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 - strategy: - matrix: - compiler: [g++-4.8] - steps: - - uses: actions/checkout@v3 - - name: Run CMake - run: cmake -S . -B build -DJSON_CI=On - - name: Build - run: cmake --build build --target ci_test_compiler_${{ matrix.compiler }} - ci_test_standards_gcc: runs-on: ubuntu-latest - container: ghcr.io/nlohmann/json-ci:v2.4.0 + container: gcc:latest strategy: matrix: standard: [11, 14, 17, 20, 23] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Get latest CMake and ninja + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -192,22 +221,27 @@ jobs: strategy: matrix: standard: [11, 14, 17, 20, 23] + stdlib: [libcxx, libstdcxx] steps: - name: Install git and unzip run: apt-get update ; apt-get install -y git unzip - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get latest CMake and ninja - uses: lukka/get-cmake@v3.27.7 + uses: lukka/get-cmake@5979409e62bdf841487c5fb3c053149de97a86d3 # v3.31.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - - name: Build + - name: Build with libc++ + run: cmake --build build --target ci_test_clang_libcxx_cxx${{ matrix.standard }} + if: ${{ matrix.stdlib == 'libcxx' }} + - name: Build with libstdc++ run: cmake --build build --target ci_test_clang_cxx${{ matrix.standard }} + if: ${{ matrix.stdlib == 'libstdcxx' }} ci_cuda_example: runs-on: ubuntu-latest container: ghcr.io/nlohmann/json-ci:v2.4.0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -217,7 +251,7 @@ jobs: runs-on: ubuntu-latest container: ghcr.io/nlohmann/json-ci:v2.2.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build @@ -225,23 +259,18 @@ jobs: . /opt/intel/oneapi/setvars.sh cmake --build build --target ci_icpc - ci_reuse_compliance: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - name: Install REUSE tool - run: python -m pip install reuse - - name: Run REUSE lint - run: reuse lint - ci_test_documentation: runs-on: ubuntu-latest strategy: matrix: - target: [ci_test_examples, ci_test_api_documentation] + target: [ci_test_examples, ci_test_build_documentation] steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -DJSON_CI=On - name: Build diff --git a/external/json/.github/workflows/windows.yml b/external/json/.github/workflows/windows.yml index 7ddd4be2..4e21d995 100644 --- a/external/json/.github/workflows/windows.yml +++ b/external/json/.github/workflows/windows.yml @@ -24,9 +24,9 @@ jobs: architecture: [x64, x86] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Set up MinGW - uses: egor-tensin/setup-mingw@v2 + uses: egor-tensin/setup-mingw@84c781b557efd538dec66bde06988d81cd3138cf # v2.2.0 with: platform: ${{ matrix.architecture }} version: 12.2.0 # https://github.com/egor-tensin/setup-mingw/issues/14 @@ -45,7 +45,7 @@ jobs: architecture: [Win32, x64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run 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' @@ -61,7 +61,7 @@ jobs: runs-on: windows-2019 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run 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 @@ -77,7 +77,7 @@ jobs: architecture: [Win32, x64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run 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' @@ -93,7 +93,7 @@ jobs: runs-on: windows-2022 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run 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 @@ -108,7 +108,7 @@ jobs: version: [11, 12, 13, 14, 15] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - 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: Run CMake @@ -125,7 +125,7 @@ jobs: architecture: [Win32, x64] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Run CMake run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On - name: Build diff --git a/external/json/.gitignore b/external/json/.gitignore index bfd52b4c..e3339eac 100644 --- a/external/json/.gitignore +++ b/external/json/.gitignore @@ -41,4 +41,6 @@ /serve_header.yml # Swift Package Manager build directory -/.build \ No newline at end of file +/.build + +/tools/astyle/venv/ diff --git a/external/json/.pre-commit-config.yaml b/external/json/.pre-commit-config.yaml new file mode 100644 index 00000000..f517e8ae --- /dev/null +++ b/external/json/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +repos: +- repo: https://github.com/gitleaks/gitleaks + rev: v8.16.3 + hooks: + - id: gitleaks +- repo: https://github.com/pocc/pre-commit-hooks + rev: v1.3.5 + hooks: + - id: cpplint +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/pylint-dev/pylint + rev: v2.17.2 + hooks: + - id: pylint diff --git a/external/json/.reuse/dep5 b/external/json/.reuse/dep5 index 315cae92..96080238 100644 --- a/external/json/.reuse/dep5 +++ b/external/json/.reuse/dep5 @@ -4,9 +4,13 @@ Upstream-Contact: Niels Lohmann Source: https://github.com/nlohmann/json Files: * -Copyright: 2013-2022 Niels Lohmann +Copyright: 2013-2024 Niels Lohmann License: MIT +Files: include/nlohmann/thirdparty/hedley.hpp +Copyright: 2016-2021 Evan Nemerson +License: CC0 + Files: tests/thirdparty/doctest/* Copyright: 2016-2021 Viktor Kirilov License: MIT @@ -16,7 +20,7 @@ Copyright: 2015-2017 Niels Lohmann License: MIT Files: tests/thirdparty/Fuzzer/* -Copyright: 2003-2022, LLVM Project. +Copyright: 2003-2022 LLVM Project. License: Apache-2.0 Files: tests/thirdparty/imapdl/* diff --git a/external/json/BUILD.bazel b/external/json/BUILD.bazel index 15d84f16..354460d2 100644 --- a/external/json/BUILD.bazel +++ b/external/json/BUILD.bazel @@ -49,5 +49,4 @@ cc_library( ], includes = ["include"], visibility = ["//visibility:public"], - alwayslink = True, ) diff --git a/external/json/CMakeLists.txt b/external/json/CMakeLists.txt index 7a49dc47..da5799cb 100644 --- a/external/json/CMakeLists.txt +++ b/external/json/CMakeLists.txt @@ -40,7 +40,8 @@ endif() option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${JSON_BuildTests_INIT}) option(JSON_CI "Enable CI build targets." OFF) option(JSON_Diagnostics "Use extended diagnostic messages." OFF) -option(JSON_GlobalUDLs "Place use-defined string literals in the global namespace." ON) +option(JSON_Diagnostic_Positions "Enable diagnostic positions." OFF) +option(JSON_GlobalUDLs "Place user-defined string literals in the global namespace." ON) option(JSON_ImplicitConversions "Enable implicit conversions." ON) option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF) option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF) @@ -57,7 +58,11 @@ endif () ## include(GNUInstallDirs) -set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME}) +if (NOT DEFINED NLOHMANN_JSON_TARGET_NAME) + # Allow overriding the target name when using FetchContent / add_subdirectory. + set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME}) +endif() + set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "") set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") @@ -77,19 +82,27 @@ else() endif() if (NOT JSON_ImplicitConversions) - message(STATUS "Implicit conversions are disabled") + message(STATUS "Implicit conversions are disabled (JSON_USE_IMPLICIT_CONVERSIONS=0)") endif() if (JSON_DisableEnumSerialization) - message(STATUS "Enum integer serialization is disabled") + message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=0)") endif() if (JSON_LegacyDiscardedValueComparison) - message(STATUS "Legacy discarded value comparison enabled") + message(STATUS "Legacy discarded value comparison enabled (JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1)") endif() if (JSON_Diagnostics) - message(STATUS "Diagnostics enabled") + message(STATUS "Diagnostics enabled (JSON_DIAGNOSTICS=1)") +endif() + +if (JSON_Diagnostic_Positions) + message(STATUS "Diagnostic positions enabled") +endif() + +if (NOT JSON_GlobalUDLs) + message(STATUS "User-defined string literals are not put in the global namespace (JSON_USE_GLOBAL_UDLS=0)") endif() if (JSON_SystemInclude) @@ -115,6 +128,7 @@ target_compile_definitions( $<$>:JSON_USE_IMPLICIT_CONVERSIONS=0> $<$:JSON_DISABLE_ENUM_SERIALIZATION=1> $<$:JSON_DIAGNOSTICS=1> + $<$:JSON_DIAGNOSTIC_POSITIONS=1> $<$:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1> ) @@ -141,6 +155,7 @@ endif() CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" + @ONLY ) ## @@ -206,4 +221,5 @@ if(JSON_Install) FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc" DESTINATION ${NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR} ) + include(CPack) endif() diff --git a/external/json/LICENSE.MIT b/external/json/LICENSE.MIT index 1c1f7a69..ee11a231 100644 --- a/external/json/LICENSE.MIT +++ b/external/json/LICENSE.MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2013-2022 Niels Lohmann +Copyright (c) 2013-2024 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/external/json/Makefile b/external/json/Makefile index a1b4e732..6ce306f5 100644 --- a/external/json/Makefile +++ b/external/json/Makefile @@ -142,29 +142,16 @@ pvs_studio: # Code format and source amalgamation ########################################################################## +ASTYLE=tools/astyle/venv/bin/astyle + +install_astyle: + @test -d tools/astyle/venv || python3 -mvenv tools/astyle/venv ; tools/astyle/venv/bin/pip3 install --quiet --upgrade pip + @test -f $(ASTYLE) || tools/astyle/venv/bin/pip3 install --quiet -r tools/astyle/requirements.txt + @$(ASTYLE) --version + # call the Artistic Style pretty printer on all source files -pretty: - astyle \ - --style=allman \ - --indent=spaces=4 \ - --indent-modifiers \ - --indent-switches \ - --indent-preproc-block \ - --indent-preproc-define \ - --indent-col1-comments \ - --pad-oper \ - --pad-header \ - --align-pointer=type \ - --align-reference=type \ - --add-braces \ - --squeeze-lines=2 \ - --convert-tabs \ - --close-templates \ - --lineend=linux \ - --preserve-date \ - --suffix=none \ - --formatted \ - $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/examples/*.cpp +pretty: install_astyle + $(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/examples/*.cpp # call the Clang-Format on all source files pretty_format: @@ -280,6 +267,6 @@ serve_header: ########################################################################## reuse: - pipx run reuse addheader --recursive single_include include -tjson --license MIT --copyright "Niels Lohmann " --year "2013-2022" - pipx run reuse addheader $(TESTS_SRCS) --style=c -tjson_support --license MIT --copyright "Niels Lohmann " --year "2013-2022" + pipx run reuse annotate --recursive single_include include -tjson --license MIT --copyright "Niels Lohmann " --year "2013-2024" --merge-copyrights + pipx run reuse annotate $(TESTS_SRCS) -tjson_support --license MIT --copyright "Niels Lohmann " --year "2013-2024" --merge-copyrights pipx run reuse lint diff --git a/external/json/README.md b/external/json/README.md index 91090270..12ce676a 100644 --- a/external/json/README.md +++ b/external/json/README.md @@ -19,6 +19,7 @@ [![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](https://github.com/nlohmann/json/issues) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/nlohmann/json.svg)](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue") [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/nlohmann/json/badge)](https://scorecard.dev/viewer/?uri=github.com/nlohmann/json) [![GitHub Sponsors](https://img.shields.io/badge/GitHub-Sponsors-ff69b4)](https://github.com/sponsors/nlohmann) [![REUSE status](https://api.reuse.software/badge/github.com/nlohmann/json)](https://api.reuse.software/info/github.com/nlohmann/json) [![Discord](https://img.shields.io/discord/1003743314341793913)](https://discord.gg/6mrGXKvX7y) @@ -39,6 +40,7 @@ - [Conversions to/from arbitrary types](#arbitrary-types-conversions) - [Specializing enum conversion](#specializing-enum-conversion) - [Binary formats (BSON, CBOR, MessagePack, UBJSON, and BJData)](#binary-formats-bson-cbor-messagepack-ubjson-and-bjdata) +- [Customers](#customers) - [Supported compilers](#supported-compilers) - [Integration](#integration) - [CMake](#cmake) @@ -52,6 +54,7 @@ - [Notes](#notes) - [Execute unit tests](#execute-unit-tests) + ## Design goals There are myriads of [JSON](https://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: @@ -75,9 +78,10 @@ See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/. You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). -### :office: Corporate Sponsor +### :raising_hand: Priority Sponsor -[![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Codacy-logo-black.svg/320px-Codacy-logo-black.svg.png)](https://github.com/codacy/About) +- [Martti Laine](https://github.com/codeclown) +- [Paul Harrington](https://github.com/phrrngtn) ### :label: Named Sponsors @@ -90,6 +94,7 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl Thanks everyone! + ## Support :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. @@ -102,6 +107,7 @@ Thanks everyone! There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B) for the documentation browsers [Dash](https://kapeli.com/dash), [Velocity](https://velocity.silverlakesoftware.com), and [Zeal](https://zealdocs.org) that contains the full [documentation](https://json.nlohmann.me) as offline resource. + ## Examples Here are some examples to give you an idea how to use the class. @@ -385,7 +391,7 @@ struct MyIterator { using iterator_category = std::input_iterator_tag; MyIterator& operator++() { - MyContainer.advance(); + target->advance(); return *this; } @@ -394,7 +400,7 @@ struct MyIterator { } reference operator*() const { - return target.get_current(); + return target->get_current(); } MyContainer* target = nullptr; @@ -1108,14 +1114,19 @@ binary.set_subtype(0x10); auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE ``` +## Customers + +The library is used in multiple projects, applications, operating systems, etc. The list below is not exhaustive, but the result of an internet search. If you know further customers of the library, please let me know, see [contact](#contact). + +[![](docs/mkdocs/docs/images/customers.png)](https://json.nlohmann.me/home/customers/) ## Supported compilers -Though it's 2023 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: +Though it's 2024 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: -- 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) +- GCC 4.8 - 14.2 (and possibly later) +- Clang 3.4 - 20.0 (and possibly later) +- Apple Clang 9.1 - 16.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) @@ -1146,29 +1157,29 @@ The following compilers are currently used in continuous integration at [AppVeyo | Compiler | Operating System | CI Provider | |--------------------------------------------------------------------------------------------------------|--------------------|----------------| -| Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.7 | macOS 11.7.1 | GitHub Actions | -| Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 11.7.1 | GitHub Actions | -| Apple Clang 12.0.5 (clang-1205.0.22.11); Xcode 12.5.1 | macOS 11.7.1 | GitHub Actions | -| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.0 | macOS 11.7.1 | GitHub Actions | -| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.1 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2.1 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 13.1.6 (clang-1316.0.21.2.3); Xcode 13.3.1 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 13.1.6 (clang-1316.0.21.2.5); Xcode 13.4.1 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0.1 | macOS 12.6.1 | GitHub Actions | -| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.1 | macOS 12.6.1 | GitHub Actions | -| Clang 3.5.2 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 3.6.2 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 3.7.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 3.8.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 3.9.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 4.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 5.0.2 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 6.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 7.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 8.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 9.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| Clang 10.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions | +| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.1 | macOS 13.7 | GitHub Actions | +| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.2 | macOS 13.7 | GitHub Actions | +| Apple Clang 14.0.3 (clang-1403.0.22.14.1); Xcode 14.3 | macOS 13.7 | GitHub Actions | +| Apple Clang 14.0.3 (clang-1403.0.22.14.1); Xcode 14.3.1 | macOS 13.7.1 | GitHub Actions | +| Apple Clang 15.0.0 (clang-1500.0.40.1); Xcode 15.0.1 | macOS 13.7 | GitHub Actions | +| Apple Clang 15.0.0 (clang-1500.1.0.2.5); Xcode 15.1 | macOS 13.7 | GitHub Actions | +| Apple Clang 15.0.0 (clang-1500.1.0.2.5); Xcode 15.2 | macOS 13.7 | GitHub Actions | +| Apple Clang 15.0.0 (clang-1500.3.9.4); Xcode 15.3 | macOS 14.7 | GitHub Actions | +| Apple Clang 15.0.0 (clang-1500.3.9.4); Xcode 15.4 | macOS 14.7 | GitHub Actions | +| Apple Clang 16.0.0 (clang-1600.0.26.3); Xcode 16.0 | macOS 15.0.1 | GitHub Actions | +| Apple Clang 16.0.0 (clang-1600.0.26.4); Xcode 16.1 | macOS 15.0.1 | GitHub Actions | +| Clang 3.5.2 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 3.6.2 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 3.7.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 3.8.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 3.9.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 4.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 5.0.2 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 6.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 7.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 8.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 9.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| Clang 10.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions | | Clang 10.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions | | Clang 11.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions | | Clang 11.0.0 with MSVC-like command-line | Windows-10.0.17763 | GitHub Actions | @@ -1182,20 +1193,28 @@ The following compilers are currently used in continuous integration at [AppVeyo | Clang 15.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions | | Clang 15.0.4 | Ubuntu 20.04.3 LTS | GitHub Actions | | Clang 16.0.0 (16.0.0-++20221031071727+500876226c60-1~exp1~20221031071831.439) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 4.9.4 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 5.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 6.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 7.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions | +| Clang 16.0.6 (++20231112084702+7cbf1a259152-1~exp1~20231112084757.16) | Ubuntu 20.04.1 LTS | GitHub Actions | +| Clang 17.0.6 (++20231208085813+6009708b4367-1~exp1~20231208085906.81) | Ubuntu 20.04.1 LTS | GitHub Actions | +| Clang 18.1.8 (++20240731024826+3b5b5c1ec4a3-1~exp1~20240731144843.145) | Ubuntu 20.04.1 LTS | GitHub Actions | +| Clang 19.1.2 (++20241016063422+7ba7d8e2f7b6-1~exp1~20241016063541.55) | Ubuntu 20.04.1 LTS | GitHub Actions | +| Clang 20.0.0 (++20241022113049+f1ade1f874db-1~exp1~20241022113104.1036) | Ubuntu 22.04.1 LTS | GitHub Actions | +| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8) | Ubuntu 20.04.4 LTS | GitHub Actions | +| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.4 LTS | GitHub Actions | +| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.4 LTS | GitHub Actions | +| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1) | Ubuntu 20.04.4 LTS | GitHub Actions | +| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.4 LTS | GitHub Actions | +| GCC 7.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions | | GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | | GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions | -| GCC 8.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 9.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 10.4.0 | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 8.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| GCC 9.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| GCC 10.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions | | GCC 11.1.0 | Ubuntu (aarch64) | Cirrus CI | -| GCC 11.3.0 | Ubuntu 20.04.3 LTS | GitHub Actions | -| GCC 12.2.0 | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 11.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| GCC 12.4.0 | Ubuntu 22.04.1 LTS | GitHub Actions | | GCC 13.0.0 20220605 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions | +| GCC 13.3.0 | Ubuntu 22.04.1 LTS | GitHub Actions | +| GCC 14.2.0 | Ubuntu 22.04.1 LTS | GitHub Actions | | Intel C++ Compiler 2021.5.0.20211109 | Ubuntu 20.04.3 LTS | GitHub Actions | | NVCC 11.0.221 | Ubuntu 20.04.3 LTS | GitHub Actions | | Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor | @@ -1379,11 +1398,11 @@ json = dependency('nlohmann_json', required: true) ## License - +OSI approved license The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): -Copyright © 2013-2022 [Niels Lohmann](https://nlohmann.me) +Copyright © 2013-2024 [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: @@ -1393,13 +1412,19 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I * * * -The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) +- The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](https://bjoern.hoehrmann.de/) +- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/) +- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/). +- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0). -The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/) +REUSE Software -The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/). +The library is compliant to version 3.3 of the [**REUSE specification**](https://reuse.software): -The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0). +- Every source file contains an SPDX copyright header. +- The full text of all licenses used in the repository can be found in the `LICENSES` folder. +- File `.reuse/dep5` contains an overview of all files' copyrights and licenses. +- Run `pipx run reuse lint` to verify the project's REUSE compliance and `pipx run reuse spdx` to generate a SPDX SBOM. ## Contact @@ -1884,7 +1909,7 @@ json/tests/src/make_test_data_available.hpp:23: FATAL ERROR: REQUIRE( utils::che In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information. -Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. +Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. Furthermore, assertions must be switched off to ensure reproducible builds (see [discussion 4494](https://github.com/nlohmann/json/discussions/4494)). Note you need to call `cmake -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information. diff --git a/external/json/cmake/ci.cmake b/external/json/cmake/ci.cmake index bbb2d4cb..1b163f1e 100644 --- a/external/json/cmake/ci.cmake +++ b/external/json/cmake/ci.cmake @@ -8,34 +8,24 @@ set(N 10) include(FindPython3) find_package(Python3 COMPONENTS Interpreter) -find_program(ASTYLE_TOOL NAMES astyle) -execute_process(COMMAND ${ASTYLE_TOOL} --version OUTPUT_VARIABLE ASTYLE_TOOL_VERSION ERROR_VARIABLE ASTYLE_TOOL_VERSION) -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++ clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++) +find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 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-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy) +find_program(CLANG_TIDY_TOOL NAMES clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy) 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})") message(STATUS "🔖 CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})") -find_program(CPPCHECK_TOOL NAMES cppcheck) -execute_process(COMMAND ${CPPCHECK_TOOL} --version OUTPUT_VARIABLE CPPCHECK_TOOL_VERSION ERROR_VARIABLE CPPCHECK_TOOL_VERSION) -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++-latest g++-HEAD g++-13 g++-12 g++-11 g++-10) +find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-15 g++-14 g++-13 g++-12 g++-11 g++-10) execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION) string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}") message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})") -find_program(GCOV_TOOL NAMES gcov-HEAD gcov-11 gcov-10 gcov) +find_program(GCOV_TOOL NAMES gcov-HEAD gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10 gcov) execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION) string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}") message(STATUS "🔖 GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})") @@ -96,8 +86,6 @@ file(GLOB_RECURSE SRC_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp) # -Wno-padded We do not care about padding warnings. # -Wno-covered-switch-default All switches list all cases and a default case. # -Wno-unsafe-buffer-usage Otherwise Doctest would not compile. -# -Wno-weak-vtables The library is header-only. -# -Wreserved-identifier See https://github.com/onqtam/doctest/issues/536. set(CLANG_CXXFLAGS -Werror @@ -109,16 +97,15 @@ set(CLANG_CXXFLAGS -Wno-padded -Wno-covered-switch-default -Wno-unsafe-buffer-usage - -Wno-weak-vtables - -Wno-reserved-identifier ) -# Warning flags determined for GCC 13.0 (experimental) with https://github.com/nlohmann/gcc_flags: +# Warning flags determined for GCC 14.2.0 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. # -Wno-long-long The library uses the long long type to interface with system functions. # -Wno-namespaces The library uses namespaces. +# -Wno-nrvo Doctest triggers this warning. # -Wno-padded We do not care about padding warnings. # -Wno-system-headers We do not care about warnings in system headers. # -Wno-templates The library uses templates. @@ -137,28 +124,49 @@ set(GCC_CXXFLAGS -Waggressive-loop-optimizations -Waligned-new=all -Wall + -Walloc-size -Walloc-zero -Walloca + -Wanalyzer-allocation-size + -Wanalyzer-deref-before-check -Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file + -Wanalyzer-exposure-through-uninit-copy + -Wanalyzer-fd-access-mode-mismatch + -Wanalyzer-fd-double-close + -Wanalyzer-fd-leak + -Wanalyzer-fd-phase-mismatch + -Wanalyzer-fd-type-mismatch + -Wanalyzer-fd-use-after-close + -Wanalyzer-fd-use-without-check -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap + -Wanalyzer-imprecise-fp-arithmetic + -Wanalyzer-infinite-loop + -Wanalyzer-infinite-recursion + -Wanalyzer-jump-through-null -Wanalyzer-malloc-leak -Wanalyzer-mismatching-deallocation -Wanalyzer-null-argument -Wanalyzer-null-dereference + -Wanalyzer-out-of-bounds + -Wanalyzer-overlapping-buffers -Wanalyzer-possible-null-argument -Wanalyzer-possible-null-dereference + -Wanalyzer-putenv-of-auto-var -Wanalyzer-shift-count-negative -Wanalyzer-shift-count-overflow -Wanalyzer-stale-setjmp-buffer + -Wanalyzer-symbol-too-complex -Wanalyzer-tainted-allocation-size -Wanalyzer-tainted-array-index + -Wanalyzer-tainted-assertion -Wanalyzer-tainted-divisor -Wanalyzer-tainted-offset -Wanalyzer-tainted-size -Wanalyzer-too-complex + -Wanalyzer-undefined-behavior-strtok -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame @@ -191,13 +199,17 @@ set(GCC_CXXFLAGS -Wc++20-compat -Wc++20-extensions -Wc++23-extensions + -Wc++26-extensions -Wc++2a-compat + -Wcalloc-transposed-args -Wcannot-profile -Wcast-align -Wcast-align=strict -Wcast-function-type -Wcast-qual + -Wcast-user-defined -Wcatch-value=3 + -Wchanges-meaning -Wchar-subscripts -Wclass-conversion -Wclass-memaccess @@ -205,16 +217,19 @@ set(GCC_CXXFLAGS -Wcomma-subscript -Wcomment -Wcomments + -Wcomplain-wrong-lang -Wconditionally-supported -Wconversion -Wconversion-null -Wcoverage-invalid-line-number -Wcoverage-mismatch + -Wcoverage-too-many-conditions -Wcpp -Wctad-maybe-unsupported -Wctor-dtor-privacy -Wdangling-else -Wdangling-pointer=2 + -Wdangling-reference -Wdate-time -Wdelete-incomplete -Wdelete-non-virtual-dtor @@ -230,6 +245,7 @@ set(GCC_CXXFLAGS -Wduplicated-branches -Wduplicated-cond -Weffc++ + -Welaborated-enum-base -Wempty-body -Wendif-labels -Wenum-compare @@ -238,8 +254,15 @@ set(GCC_CXXFLAGS -Wexpansion-to-defined -Wextra -Wextra-semi + -Wflex-array-member-not-at-end -Wfloat-conversion -Wfloat-equal + -Wformat -Wformat-contains-nul + -Wformat -Wformat-extra-args + -Wformat -Wformat-nonliteral + -Wformat -Wformat-security + -Wformat -Wformat-y2k + -Wformat -Wformat-zero-length -Wformat-diag -Wformat-overflow=2 -Wformat-signedness @@ -247,6 +270,8 @@ set(GCC_CXXFLAGS -Wformat=2 -Wframe-address -Wfree-nonheap-object + -Wglobal-module + -Whardened -Whsa -Wif-not-aligned -Wignored-attributes @@ -261,10 +286,12 @@ set(GCC_CXXFLAGS -Wint-in-bool-context -Wint-to-pointer-cast -Winterference-size + -Winvalid-constexpr -Winvalid-imported-macros -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch + -Winvalid-utf8 -Wliteral-suffix -Wlogical-not-parentheses -Wlogical-op @@ -298,14 +325,16 @@ set(GCC_CXXFLAGS -Wnonnull -Wnonnull-compare -Wnormalized=nfkc + -Wno-nrvo -Wnull-dereference -Wodr -Wold-style-cast -Wopenacc-parallelism + -Wopenmp -Wopenmp-simd -Woverflow -Woverlength-strings - -Woverloaded-virtual + -Woverloaded-virtual=2 -Wpacked -Wpacked-bitfield-compat -Wpacked-not-aligned @@ -330,6 +359,7 @@ set(GCC_CXXFLAGS -Wreturn-local-addr -Wreturn-type -Wscalar-storage-order + -Wself-move -Wsequence-point -Wshadow=compatible-local -Wshadow=global @@ -349,7 +379,7 @@ set(GCC_CXXFLAGS -Wstack-protector -Wstrict-aliasing=3 -Wstrict-null-sentinel - -Wno-strict-overflow + -Wstrict-overflow -Wstring-compare -Wstringop-overflow=4 -Wstringop-overread @@ -361,6 +391,7 @@ set(GCC_CXXFLAGS -Wsuggest-attribute=malloc -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure + -Wsuggest-attribute=returns_nonnull -Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override @@ -382,6 +413,7 @@ set(GCC_CXXFLAGS -Wtsan -Wtype-limits -Wundef + -Wunicode -Wuninitialized -Wunknown-pragmas -Wunreachable-code @@ -411,6 +443,7 @@ set(GCC_CXXFLAGS -Wvolatile -Wvolatile-register-var -Wwrite-strings + -Wxor-used-as-pow -Wzero-as-null-pointer-constant -Wzero-length-bounds ) @@ -461,6 +494,19 @@ foreach(CXX_STANDARD 11 14 17 20 23) COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure COMMENT "Compile and test with Clang for C++${CXX_STANDARD}" ) + + add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD} + COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_FastTests=ON + -DJSON_TestStandards=${CXX_STANDARD} + -DCMAKE_CXX_FLAGS="-stdlib=libc++" + -DCMAKE_EXE_LINKER_FLAGS="-lc++abi" + -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 + COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)" + ) endforeach() ############################################################################### @@ -505,6 +551,20 @@ add_custom_target(ci_test_diagnostics COMMENT "Compile and test with improved diagnostics enabled" ) +############################################################################### +# Enable diagnostic positions support. +############################################################################### + +add_custom_target(ci_test_diagnostic_positions + COMMAND ${CMAKE_COMMAND} + -DCMAKE_BUILD_TYPE=Debug -GNinja + -DJSON_BuildTests=ON -DJSON_Diagnostic_Positions=ON + -S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_diagnostic_positions + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_diagnostic_positions + COMMAND cd ${PROJECT_BINARY_DIR}/build_diagnostic_positions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure + COMMENT "Compile and test with diagnostic positions enabled" +) + ############################################################################### # Enable legacy discarded value comparison. ############################################################################### @@ -581,8 +641,6 @@ add_custom_target(ci_test_clang_sanitizer # Check if header is amalgamated and sources are properly indented. ############################################################################### -set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type --align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date --formatted) - file(GLOB_RECURSE INDENT_FILES ${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp ${PROJECT_SOURCE_DIR}/tests/src/*.cpp @@ -598,14 +656,18 @@ add_custom_target(ci_test_amalgamation COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~ COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~ + COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle + COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt + COMMAND venv_astyle/bin/astyle --version + COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s . COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s . - COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp + COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp - COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} ${INDENT_FILES} + COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES} COMMAND for FILE in `find . -name '*.orig'`\; do false \; done WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} @@ -660,7 +722,14 @@ add_custom_target(ci_clang_analyze ############################################################################### add_custom_target(ci_cppcheck - COMMAND ${CPPCHECK_TOOL} --enable=warning --suppress=missingReturn --inline-suppr --inconclusive --force --std=c++11 ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp --error-exitcode=1 + COMMAND ${Python3_EXECUTABLE} -mvenv venv_cppcheck + COMMAND clang -dM -E -x c++ -std=c++11 ${CMAKE_SOURCE_DIR}/include/nlohmann/thirdparty/hedley/hedley.hpp > default_defines.hpp 2> /dev/null + COMMAND venv_cppcheck/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/cmake/requirements/requirements-cppcheck.txt + COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force + --std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include + --error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j 10 --include=default_defines.hpp + -UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW + -DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON COMMENT "Check code with Cppcheck" ) @@ -670,7 +739,7 @@ add_custom_target(ci_cppcheck add_custom_target(ci_cpplint COMMAND ${Python3_EXECUTABLE} -mvenv venv_cpplint - COMMAND venv_cpplint/bin/pip3 --quiet install cpplint + COMMAND venv_cpplint/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/cmake/requirements/requirements-cpplint.txt COMMAND venv_cpplint/bin/cpplint --filter=-whitespace,-legal,-runtime/references,-runtime/explicit,-runtime/indentation_namespace,-readability/casting,-readability/nolint --quiet --recursive ${SRC_FILES} COMMENT "Check code with cpplint" WORKING_DIRECTORY ${PROJECT_BINARY_DIR} @@ -855,7 +924,7 @@ endfunction() ci_get_cmake(3.1.0 CMAKE_3_1_0_BINARY) ci_get_cmake(3.13.0 CMAKE_3_13_0_BINARY) -set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization +set(JSON_CMAKE_FLAGS_3_1_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind) set(JSON_CMAKE_FLAGS_3_13_0 JSON_BuildTests) @@ -900,7 +969,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 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17) +foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17 clang++-18 clang++-19 clang++-20) find_program(COMPILER_TOOL NAMES ${COMPILER}) if (COMPILER_TOOL) unset(ADDITIONAL_FLAGS) @@ -957,6 +1026,17 @@ add_custom_target(ci_icpc COMMENT "Compile and test with ICPC" ) +############################################################################### +# REUSE +############################################################################### + +add_custom_target(ci_reuse_compliance + COMMAND ${Python3_EXECUTABLE} -mvenv venv_reuse + COMMAND venv_reuse/bin/pip3 --quiet install -r ${PROJECT_SOURCE_DIR}/cmake/requirements/requirements-reuse.txt + COMMAND venv_reuse/bin/reuse --root ${PROJECT_SOURCE_DIR} lint + COMMENT "Check REUSE specification compliance" +) + ############################################################################### # test documentation ############################################################################### @@ -967,10 +1047,12 @@ add_custom_target(ci_test_examples COMMENT "Check that all examples compile and create the desired output" ) -add_custom_target(ci_test_api_documentation - COMMAND ${Python3_EXECUTABLE} scripts/check_structure.py +add_custom_target(ci_test_build_documentation + COMMAND ${Python3_EXECUTABLE} -mvenv venv + COMMAND venv/bin/pip3 --quiet install -r requirements.txt + COMMAND make build WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/docs/mkdocs - COMMENT "Lint the API documentation" + COMMENT "Build the documentation" ) ############################################################################### diff --git a/external/json/cmake/pkg-config.pc.in b/external/json/cmake/pkg-config.pc.in index d36317f0..21a91a3c 100644 --- a/external/json/cmake/pkg-config.pc.in +++ b/external/json/cmake/pkg-config.pc.in @@ -1,4 +1,7 @@ -Name: ${PROJECT_NAME} +prefix=@CMAKE_INSTALL_PREFIX@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: @PROJECT_NAME@ Description: JSON for Modern C++ -Version: ${PROJECT_VERSION} -Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR} +Version: @PROJECT_VERSION@ +Cflags: -I${includedir} diff --git a/external/json/cmake/requirements/requirements-cppcheck.txt b/external/json/cmake/requirements/requirements-cppcheck.txt new file mode 100644 index 00000000..1881f5d0 --- /dev/null +++ b/external/json/cmake/requirements/requirements-cppcheck.txt @@ -0,0 +1 @@ +cppcheck==1.4.7 diff --git a/external/json/cmake/requirements/requirements-cpplint.txt b/external/json/cmake/requirements/requirements-cpplint.txt new file mode 100644 index 00000000..00318e43 --- /dev/null +++ b/external/json/cmake/requirements/requirements-cpplint.txt @@ -0,0 +1 @@ +cpplint==2.0.0 diff --git a/external/json/cmake/requirements/requirements-reuse.txt b/external/json/cmake/requirements/requirements-reuse.txt new file mode 100644 index 00000000..e7677662 --- /dev/null +++ b/external/json/cmake/requirements/requirements-reuse.txt @@ -0,0 +1 @@ +reuse==5.0.2 diff --git a/external/json/docs/examples/at__keytype_const.c++17.cpp b/external/json/docs/examples/at__keytype_const.c++17.cpp index b08cd17b..712d456e 100644 --- a/external/json/docs/examples/at__keytype_const.c++17.cpp +++ b/external/json/docs/examples/at__keytype_const.c++17.cpp @@ -36,7 +36,7 @@ int main() // try to read from a nonexisting key using string_view std::cout << object.at("the fast"sv) << '\n'; } - catch (const json::out_of_range) + catch (const json::out_of_range& e) { std::cout << "out of range" << '\n'; } diff --git a/external/json/docs/examples/diagnostic_positions.cpp b/external/json/docs/examples/diagnostic_positions.cpp new file mode 100644 index 00000000..259344cd --- /dev/null +++ b/external/json/docs/examples/diagnostic_positions.cpp @@ -0,0 +1,51 @@ +#include + +#define JSON_DIAGNOSTIC_POSITIONS 1 +#include + +using json = nlohmann::json; + +int main() +{ + std::string json_string = R"( + { + "address": { + "street": "Fake Street", + "housenumber": 1 + } + } + )"; + json j = json::parse(json_string); + + std::cout << "Root diagnostic positions: \n"; + std::cout << "\tstart_pos: " << j.start_pos() << '\n'; + std::cout << "\tend_pos:" << j.end_pos() << "\n"; + std::cout << "Original string: \n"; + std::cout << "{\n \"address\": {\n \"street\": \"Fake Street\",\n \"housenumber\": 1\n }\n }" << "\n"; + std::cout << "Parsed string: \n"; + std::cout << json_string.substr(j.start_pos(), j.end_pos() - j.start_pos()) << "\n\n"; + + std::cout << "address diagnostic positions: \n"; + std::cout << "\tstart_pos:" << j["address"].start_pos() << '\n'; + std::cout << "\tend_pos:" << j["address"].end_pos() << "\n\n"; + std::cout << "Original string: \n"; + std::cout << "{ \"street\": \"Fake Street\",\n \"housenumber\": 1\n }" << "\n"; + std::cout << "Parsed string: \n"; + std::cout << json_string.substr(j["address"].start_pos(), j["address"].end_pos() - j["address"].start_pos()) << "\n\n"; + + std::cout << "street diagnostic positions: \n"; + std::cout << "\tstart_pos:" << j["address"]["street"].start_pos() << '\n'; + std::cout << "\tend_pos:" << j["address"]["street"].end_pos() << "\n\n"; + std::cout << "Original string: \n"; + std::cout << "\"Fake Street\"" << "\n"; + std::cout << "Parsed string: \n"; + std::cout << json_string.substr(j["address"]["street"].start_pos(), j["address"]["street"].end_pos() - j["address"]["street"].start_pos()) << "\n\n"; + + std::cout << "housenumber diagnostic positions: \n"; + std::cout << "\tstart_pos:" << j["address"]["housenumber"].start_pos() << '\n'; + std::cout << "\tend_pos:" << j["address"]["housenumber"].end_pos() << "\n\n"; + std::cout << "Original string: \n"; + std::cout << "1" << "\n"; + std::cout << "Parsed string: \n"; + std::cout << json_string.substr(j["address"]["housenumber"].start_pos(), j["address"]["housenumber"].end_pos() - j["address"]["housenumber"].start_pos()) << "\n\n"; +} diff --git a/external/json/docs/examples/diagnostic_positions.output b/external/json/docs/examples/diagnostic_positions.output new file mode 100644 index 00000000..a6becc0e --- /dev/null +++ b/external/json/docs/examples/diagnostic_positions.output @@ -0,0 +1,50 @@ +Root diagnostic positions: + start_pos: 5 + end_pos:109 +Original string: +{ + "address": { + "street": "Fake Street", + "housenumber": 1 + } + } +Parsed string: +{ + "address": { + "street": "Fake Street", + "housenumber": 1 + } + } + +address diagnostic positions: + start_pos:26 + end_pos:103 + +Original string: +{ "street": "Fake Street", + "housenumber": 1 + } +Parsed string: +{ + "street": "Fake Street", + "housenumber": 1 + } + +street diagnostic positions: + start_pos:50 + end_pos:63 + +Original string: +"Fake Street" +Parsed string: +"Fake Street" + +housenumber diagnostic positions: + start_pos:92 + end_pos:93 + +Original string: +1 +Parsed string: +1 + diff --git a/external/json/docs/examples/json_base_class_t.cpp b/external/json/docs/examples/json_base_class_t.cpp index d993522a..3fb2d46a 100644 --- a/external/json/docs/examples/json_base_class_t.cpp +++ b/external/json/docs/examples/json_base_class_t.cpp @@ -79,8 +79,8 @@ int main() // visit and output j.visit( - [&](const json::json_pointer & p, - const json & j) + [&](const json::json_pointer & p, + const json & j) { std::cout << (p.empty() ? std::string{"/"} : p.to_string()) << " - metadata = " << j.metadata << " -> " << j.dump() << '\n'; diff --git a/external/json/docs/mkdocs/Makefile b/external/json/docs/mkdocs/Makefile index d3356b82..fa525a5f 100644 --- a/external/json/docs/mkdocs/Makefile +++ b/external/json/docs/mkdocs/Makefile @@ -35,3 +35,11 @@ install_venv: requirements.txt # uninstall the virtual environment uninstall_venv: clean rm -fr venv + +update_requirements: + rm -fr venv_small + python3 -mvenv venv_small + venv_small/bin/pip3 install pur + venv_small/bin/pur -r requirements.txt + rm -fr venv_small venv + make install_venv diff --git a/external/json/docs/mkdocs/docs/api/basic_json/accept.md b/external/json/docs/mkdocs/docs/api/basic_json/accept.md index 1c806e82..b12d6223 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/accept.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/accept.md @@ -29,9 +29,9 @@ Unlike the [`parse`](parse.md) function, this function neither throws an excepti : A compatible input, for instance: - an `std::istream` object - - a `FILE` pointer (must not be null) + - a `FILE` pointer (throws if null) - a C-style array of characters - - a pointer to a null-terminated string of single byte characters + - a pointer to a null-terminated string of single byte characters (throws if null) - a `std::string` - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. @@ -64,18 +64,17 @@ Whether the input is valid JSON. Strong guarantee: if an exception is thrown, there are no changes in the JSON value. +## Exceptions + +Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an empty input like a null `FILE*` or `char*` pointer. + ## Complexity Linear in the length of the input. The parser is a predictive LL(1) parser. ## Notes -(1) A UTF-8 byte order mark is silently ignored. - -!!! danger "Runtime assertion" - - The precondition that a passed `#!cpp FILE` pointer must not be null is enforced with a - [runtime assertion](../../features/assertions.md). +A UTF-8 byte order mark is silently ignored. ## Examples @@ -102,6 +101,7 @@ Linear in the length of the input. The parser is a predictive LL(1) parser. - Added in version 3.0.0. - Ignoring comments via `ignore_comments` added in version 3.9.0. +- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.11.4. !!! warning "Deprecation" diff --git a/external/json/docs/mkdocs/docs/api/basic_json/emplace.md b/external/json/docs/mkdocs/docs/api/basic_json/emplace.md index 6cc2c98d..cf637d62 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/emplace.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/emplace.md @@ -14,6 +14,11 @@ created from `args`. `Args` : compatible types to create a `basic_json` object +## Iterator invalidation + +For [`ordered_json`](../ordered_json.md), adding a value to an object can yield a reallocation, in which case all +iterators (including the `end()` iterator) and all references to the elements are invalidated. + ## Parameters `args` (in) diff --git a/external/json/docs/mkdocs/docs/api/basic_json/emplace_back.md b/external/json/docs/mkdocs/docs/api/basic_json/emplace_back.md index 597ad41e..21829c21 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/emplace_back.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/emplace_back.md @@ -13,6 +13,12 @@ Creates a JSON value from the passed parameters `args` to the end of the JSON va `Args` : compatible types to create a `basic_json` object +## Iterator invalidation + +By adding an element to the end of the array, a reallocation can happen, in which case all iterators (including the +[`end()`](end.md) iterator) and all references to the elements are invalidated. Otherwise, only the [`end()`](end.md) +iterator is invalidated. + ## Parameters `args` (in) @@ -48,6 +54,11 @@ Amortized constant. --8<-- "examples/emplace_back.output" ``` +## See also + +- [operator+=](operator+=.md) add a value to an array/object +- [push_back](push_back.md) add a value to an array/object + ## Version history - Since version 2.0.8. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/exception.md b/external/json/docs/mkdocs/docs/api/basic_json/exception.md index 794b7d1e..b592d62e 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/exception.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/exception.md @@ -8,24 +8,36 @@ This class is an extension of [`std::exception`](https://en.cppreference.com/w/c member `id` for exception ids. It is used as the base class for all exceptions thrown by the `basic_json` class. This class can hence be used as "wildcard" to catch exceptions, see example below. -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception #FFFF00 { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error + + style json_exception fill:#CCCCFF ``` Subclasses: diff --git a/external/json/docs/mkdocs/docs/api/basic_json/get_ptr.md b/external/json/docs/mkdocs/docs/api/basic_json/get_ptr.md index 2441e115..7c000f1a 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/get_ptr.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/get_ptr.md @@ -35,7 +35,37 @@ Constant. !!! danger "Undefined behavior" - Writing data to the pointee of the result yields an undefined state. + The pointer becomes invalid if the underlying JSON object changes. + + Consider the following example code where the pointer `ptr` changes after the array is resized. As a result, + reading or writing to `ptr` after the array change would be undefined behavior. The address of the first array + element changes, because the underlying `std::vector` is resized after adding a fifth element. + + ```cpp + #include + #include + + using json = nlohmann::json; + + int main() + { + json j = {1, 2, 3, 4}; + auto* ptr = j[0].get_ptr(); + std::cout << "value at " << ptr << " is " << *ptr << std::endl; + + j.push_back(5); + + ptr = j[0].get_ptr(); + std::cout << "value at " << ptr << " is " << *ptr << std::endl; + } + ``` + + Output: + + ``` + value at 0x6000012fc1c8 is 1 + value at 0x6000029fc088 is 1 + ``` ## Examples @@ -54,6 +84,10 @@ Constant. --8<-- "examples/get_ptr.output" ``` +## See also + +- [get_ref()](get_ref.md) get a reference value + ## Version history - Added in version 1.0.0. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/get_ref.md b/external/json/docs/mkdocs/docs/api/basic_json/get_ref.md index b1219742..73b20b0e 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/get_ref.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/get_ref.md @@ -40,7 +40,7 @@ Constant. !!! danger "Undefined behavior" - Writing data to the referee of the result yields an undefined state. + The reference becomes invalid if the underlying JSON object changes. ## Examples @@ -58,6 +58,10 @@ Constant. --8<-- "examples/get_ref.output" ``` +## See also + +- [get_ptr()](get_ptr.md) get a pointer value + ## Version history - Added in version 1.1.0. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/index.md b/external/json/docs/mkdocs/docs/api/basic_json/index.md index 64867014..e90091b5 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/index.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/index.md @@ -42,7 +42,15 @@ class basic_json; ## Iterator invalidation -Todo +All operations that add values to an **array** ([`push_back`](push_back.md) , [`operator+=`](operator+=.md), +[`emplace_back`](emplace_back.md), [`insert`](insert.md), and [`operator[]`](operator%5B%5D.md) for a non-existing +index) can yield a reallocation, in which case all iterators (including the [`end()`](end.md) iterator) and all +references to the elements are invalidated. + +For [`ordered_json`](../ordered_json.md), also all operations that add a value to an **object** +([`push_back`](push_back.md), [`operator+=`](operator+=.md), [`emplace`](emplace.md), [`insert`](insert.md), +[`update`](update.md), and [`operator[]`](operator%5B%5D.md) for a non-existing key) can yield a reallocation, in +which case all iterators (including the [`end()`](end.md) iterator) and all references to the elements are invalidated. ## Requirements diff --git a/external/json/docs/mkdocs/docs/api/basic_json/insert.md b/external/json/docs/mkdocs/docs/api/basic_json/insert.md index 2e6b2930..b9260488 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/insert.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/insert.md @@ -24,6 +24,17 @@ void insert(const_iterator first, const_iterator last); 4. Inserts elements from initializer list `ilist` into array before iterator `pos`. 5. Inserts elements from range `[first, last)` into object. +## Iterator invalidation + +For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators +(including the [`end()`](end.md) iterator) and all references to the elements are invalidated. Otherwise, only the +[`end()`](end.md) iterator is invalidated. Also, any iterator or reference after the insertion point will point to the +same index which is now a different value. + +For [`ordered_json`](../ordered_json.md), also adding an element to an **object** can yield a reallocation which again +invalidates all iterators and all references. Also, any iterator or reference after the insertion point will point to +the same index which is now a different value. + ## Parameters `pos` (in) diff --git a/external/json/docs/mkdocs/docs/api/basic_json/invalid_iterator.md b/external/json/docs/mkdocs/docs/api/basic_json/invalid_iterator.md index f9fdce5b..3f0f7535 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/invalid_iterator.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/invalid_iterator.md @@ -8,26 +8,36 @@ This exception is thrown if iterators passed to a library function do not match Exceptions have ids 2xx (see [list of iterator errors](../../home/exceptions.md#iterator-errors)). -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error -class basic_json::invalid_iterator #FFFF00 {} + style json_invalid_iterator fill:#CCCCFF ``` ## Member functions diff --git a/external/json/docs/mkdocs/docs/api/basic_json/is_structured.md b/external/json/docs/mkdocs/docs/api/basic_json/is_structured.md index f8fe4dcb..ecca80d8 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/is_structured.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/is_structured.md @@ -21,7 +21,7 @@ Constant. ## Possible implementation ```cpp -constexpr bool is_primitive() const noexcept +constexpr bool is_structured() const noexcept { return is_array() || is_object(); } diff --git a/external/json/docs/mkdocs/docs/api/basic_json/items.md b/external/json/docs/mkdocs/docs/api/basic_json/items.md index 0b34ddcb..be32bbfd 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/items.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/items.md @@ -66,7 +66,7 @@ When iterating over an array, `key()` will return the index of the element as st !!! danger "Lifetime issues" Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See - for more information. + [#2040](https://github.com/nlohmann/json/issues/2040) for more information. ## Examples diff --git a/external/json/docs/mkdocs/docs/api/basic_json/operator+=.md b/external/json/docs/mkdocs/docs/api/basic_json/operator+=.md index dc5f2ecc..1591007f 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/operator+=.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/operator+=.md @@ -27,6 +27,15 @@ reference operator+=(initializer_list_t init); `init` is converted into an object element and added using `operator+=(const typename object_t::value_type&)`. Otherwise, `init` is converted to a JSON value and added using `operator+=(basic_json&&)`. +## Iterator invalidation + +For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including +the [`end()`](end.md) iterator) and all references to the elements are invalidated. Otherwise, only the +[`end()`](end.md) iterator is invalidated. + +For [`ordered_json`](../ordered_json.md), also adding an element to an **object** can yield a reallocation which again +invalidates all iterators and all references. + ## Parameters `val` (in) @@ -103,6 +112,11 @@ interpreted as `object_t::value_type` or `std::initializer_list`, se --8<-- "examples/push_back__initializer_list.output" ``` +## See also + +- [emplace_back](emplace_back.md) add a value to an array +- [push_back](push_back.md) add a value to an array/object + ## Version history 1. Since version 1.0.0. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/operator[].md b/external/json/docs/mkdocs/docs/api/basic_json/operator[].md index 51dd8588..3eebd562 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/operator[].md +++ b/external/json/docs/mkdocs/docs/api/basic_json/operator[].md @@ -34,6 +34,15 @@ const_reference operator[](const json_pointer& ptr) const; [`string_t`](string_t.md) using [`object_comparator_t`](object_comparator_t.md). This can also be a string view (C++17). +## Iterator invalidation + +For the non-const versions 1. and 4., when passing an **array** index that does not exist, it is created and filled with +a `#!json null` value before a reference to it is returned. For this, a reallocation can happen, in which case all +iterators (including the [`end()`](end.md) iterator) and all references to the elements are invalidated. + +For [`ordered_json`](../ordered_json.md), also passing an **object key** to the non-const versions 2., 3., and 4., a +reallocation can happen which again invalidates all iterators and all references. + ## Parameters `idx` (in) diff --git a/external/json/docs/mkdocs/docs/api/basic_json/operator_gt.md b/external/json/docs/mkdocs/docs/api/basic_json/operator_gt.md index 9516656e..486da5fd 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/operator_gt.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/operator_gt.md @@ -17,7 +17,7 @@ bool operator>(ScalarType lhs, const const_reference rhs) noexcept; // (2) operand is `NaN` and the other operand is either `NaN` or any other number. - Otherwise, returns the result of `#!cpp !(lhs <= rhs)` (see [**operator<=**](operator_le.md)). -2. Compares wether a JSON value is greater than a scalar or a scalar is greater than a JSON value by +2. Compares whether a JSON value is greater than a scalar or a scalar is greater than a JSON value by converting the scalar to a JSON value and comparing both JSON values according to 1. ## Template parameters diff --git a/external/json/docs/mkdocs/docs/api/basic_json/operator_le.md b/external/json/docs/mkdocs/docs/api/basic_json/operator_le.md index 7b648e03..c6144bb4 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/operator_le.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/operator_le.md @@ -17,7 +17,7 @@ bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; // (2) operand is `NaN` and the other operand is either `NaN` or any other number. - Otherwise, returns the result of `#!cpp !(rhs < lhs)` (see [**operator<**](operator_lt.md)). -1. Compares wether a JSON value is less than or equal to a scalar or a scalar is less than or equal +1. Compares whether a JSON value is less than or equal to a scalar or a scalar is less than or equal to a JSON value by converting the scalar to a JSON value and comparing both JSON values according to 1. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/operator_lt.md b/external/json/docs/mkdocs/docs/api/basic_json/operator_lt.md index b5d191ec..118d817c 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/operator_lt.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/operator_lt.md @@ -27,7 +27,7 @@ bool operator<(ScalarType lhs, const const_reference rhs) noexcept; // (2) 7. binary For instance, any boolean value is considered less than any string. -2. Compares wether a JSON value is less than a scalar or a scalar is less than a JSON value by converting +2. Compares whether a JSON value is less than a scalar or a scalar is less than a JSON value by converting the scalar to a JSON value and comparing both JSON values according to 1. ## Template parameters diff --git a/external/json/docs/mkdocs/docs/api/basic_json/other_error.md b/external/json/docs/mkdocs/docs/api/basic_json/other_error.md index 9a83340a..251c0f3d 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/other_error.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/other_error.md @@ -8,26 +8,36 @@ This exception is thrown in case of errors that cannot be classified with the ot Exceptions have ids 5xx (see [list of other errors](../../home/exceptions.md#further-exceptions)). -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error -class basic_json::other_error #FFFF00 {} + style json_other_error fill:#CCCCFF ``` ## Member functions diff --git a/external/json/docs/mkdocs/docs/api/basic_json/out_of_range.md b/external/json/docs/mkdocs/docs/api/basic_json/out_of_range.md index 6c1f0dfb..0c216411 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/out_of_range.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/out_of_range.md @@ -9,26 +9,36 @@ instance in case of array indices or nonexisting object keys. Exceptions have ids 4xx (see [list of out-of-range errors](../../home/exceptions.md#out-of-range)). -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error -class basic_json::out_of_range #FFFF00 {} + style json_out_of_range fill:#CCCCFF ``` ## Member functions diff --git a/external/json/docs/mkdocs/docs/api/basic_json/parse.md b/external/json/docs/mkdocs/docs/api/basic_json/parse.md index 49838ad1..69d412f9 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/parse.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/parse.md @@ -28,9 +28,9 @@ static basic_json parse(IteratorType first, IteratorType last, : A compatible input, for instance: - an `std::istream` object - - a `FILE` pointer (must not be null) + - a `FILE` pointer (throws if null) - a C-style array of characters - - a pointer to a null-terminated string of single byte characters + - a pointer to a null-terminated string of single byte characters (throws if null) - a `std::string` - an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of iterators. @@ -73,10 +73,11 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va ## Exceptions -- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token. -- Throws [`parse_error.102`](../../home/exceptions.md#jsonexceptionparse_error102) if to_unicode fails or surrogate +- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or + empty input like a null `FILE*` or `char*` pointer. +- Throws [`parse_error.102`](../../home/exceptions.md#jsonexceptionparse_error102) if `to_unicode` fails or surrogate error. -- Throws [`parse_error.103`](../../home/exceptions.md#jsonexceptionparse_error103) if to_unicode fails. +- Throws [`parse_error.103`](../../home/exceptions.md#jsonexceptionparse_error103) if `to_unicode` fails. ## Complexity @@ -86,12 +87,7 @@ super-linear complexity. ## Notes -(1) A UTF-8 byte order mark is silently ignored. - -!!! danger "Runtime assertion" - - The precondition that a passed `#!cpp FILE` pointer must not be null is enforced with a - [runtime assertion](../../features/assertions.md). +A UTF-8 byte order mark is silently ignored. ## Examples @@ -203,6 +199,7 @@ super-linear complexity. - Added in version 1.0.0. - Overload for contiguous containers (1) added in version 2.0.3. - Ignoring comments via `ignore_comments` added in version 3.9.0. +- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.11.4. !!! warning "Deprecation" diff --git a/external/json/docs/mkdocs/docs/api/basic_json/parse_error.md b/external/json/docs/mkdocs/docs/api/basic_json/parse_error.md index af3e1f0b..87b54b4c 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/parse_error.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/parse_error.md @@ -11,24 +11,36 @@ Member `byte` holds the byte index of the last read character in the input file Exceptions have ids 1xx (see [list of parse errors](../../home/exceptions.md#parse-errors)). -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error #FFFF00 { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error + + style json_parse_error fill:#CCCCFF ``` ## Member functions diff --git a/external/json/docs/mkdocs/docs/api/basic_json/push_back.md b/external/json/docs/mkdocs/docs/api/basic_json/push_back.md index 5c7d20dd..e0610393 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/push_back.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/push_back.md @@ -27,6 +27,15 @@ void push_back(initializer_list_t init); `init` is converted into an object element and added using `push_back(const typename object_t::value_type&)`. Otherwise, `init` is converted to a JSON value and added using `push_back(basic_json&&)`. +## Iterator invalidation + +For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including +the [`end()`](end.md) iterator) and all references to the elements are invalidated. Otherwise, only the +[`end()`](end.md) iterator is invalidated. + +For [`ordered_json`](../ordered_json.md), also adding an element to an **object** can yield a reallocation which again +invalidates all iterators and all references. + ## Parameters `val` (in) @@ -99,6 +108,11 @@ All functions can throw the following exception: --8<-- "examples/push_back__initializer_list.output" ``` +## See also + +- [emplace_back](emplace_back.md) add a value to an array +- [operator+=](operator+=.md) add a value to an array/object + ## Version history 1. Since version 1.0.0. diff --git a/external/json/docs/mkdocs/docs/api/basic_json/type_error.md b/external/json/docs/mkdocs/docs/api/basic_json/type_error.md index cda54c08..4d590556 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/type_error.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/type_error.md @@ -9,26 +9,36 @@ does not match the expected semantics. Exceptions have ids 3xx (see [list of type errors](../../home/exceptions.md#type-errors)). -```plantuml -std::exception <|-- basic_json::exception -basic_json::exception <|-- basic_json::parse_error -basic_json::exception <|-- basic_json::invalid_iterator -basic_json::exception <|-- basic_json::type_error -basic_json::exception <|-- basic_json::out_of_range -basic_json::exception <|-- basic_json::other_error +```mermaid +classDiagram + direction LR + + class std_exception ["std::exception"] { + <> + } -interface std::exception {} + class json_exception ["basic_json::exception"] { + +const int id + +const char* what() const + } + + class json_parse_error ["basic_json::parse_error"] { + +const std::size_t byte + } -class basic_json::exception { - + const int id - + const char* what() const -} + class json_invalid_iterator ["basic_json::invalid_iterator"] + class json_type_error ["basic_json::type_error"] + class json_out_of_range ["basic_json::out_of_range"] + class json_other_error ["basic_json::other_error"] -class basic_json::parse_error { - + const std::size_t byte -} + std_exception <|-- json_exception + json_exception <|-- json_parse_error + json_exception <|-- json_invalid_iterator + json_exception <|-- json_type_error + json_exception <|-- json_out_of_range + json_exception <|-- json_other_error -class basic_json::type_error #FFFF00 {} + style json_type_error fill:#CCCCFF ``` ## Member functions diff --git a/external/json/docs/mkdocs/docs/api/basic_json/update.md b/external/json/docs/mkdocs/docs/api/basic_json/update.md index a594cf9d..bfe785d7 100644 --- a/external/json/docs/mkdocs/docs/api/basic_json/update.md +++ b/external/json/docs/mkdocs/docs/api/basic_json/update.md @@ -17,6 +17,11 @@ recursively merges objects with common keys. The function is motivated by Python's [dict.update](https://docs.python.org/3.6/library/stdtypes.html#dict.update) function. +## Iterator invalidation + +For [`ordered_json`](../ordered_json.md), adding a value to an object can yield a reallocation, in which case all +iterators (including the `end()` iterator) and all references to the elements are invalidated. + ## Parameters `j` (in) @@ -139,4 +144,4 @@ function. ## Version history - Added in version 3.0.0. -- Added `merge_objects` parameter in 3.10.4. +- Added `merge_objects` parameter in 3.10.5. diff --git a/external/json/docs/mkdocs/docs/api/macros/index.md b/external/json/docs/mkdocs/docs/api/macros/index.md index ae9eb204..d37df592 100644 --- a/external/json/docs/mkdocs/docs/api/macros/index.md +++ b/external/json/docs/mkdocs/docs/api/macros/index.md @@ -42,7 +42,6 @@ header. See also the [macro overview page](../../features/macros.md). - [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums - [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions - ## Comparison behavior - [**JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON**](json_use_legacy_discarded_value_comparison.md) - @@ -50,6 +49,20 @@ header. See also the [macro overview page](../../features/macros.md). ## Serialization/deserialization macros +- Enum: [**NLOHMANN_JSON_SERIALIZE_ENUM**](nlohmann_json_serialize_enum.md) +- Class/struct: + - Do you need to serialize private variables? + - Yes? Do you only need serialization? + - Yes? `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE` + - No? Allow deserialization of JSON values with missing values? + - Yes? `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` + - No? `NLOHMANN_DEFINE_TYPE_INTRUSIVE` + - No? Do you only need serialization? + - Yes? `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE` + - No? Allow deserialization of JSON values with missing values? + - Yes? `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` + - No? `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` + - [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**
**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**
**NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, member...)**][DefInt] \- serialization/deserialization of types _with_ access to private variables diff --git a/external/json/docs/mkdocs/docs/api/macros/json_diagnostic_positions.md b/external/json/docs/mkdocs/docs/api/macros/json_diagnostic_positions.md new file mode 100644 index 00000000..d7d4ddd4 --- /dev/null +++ b/external/json/docs/mkdocs/docs/api/macros/json_diagnostic_positions.md @@ -0,0 +1,61 @@ +# JSON_DIAGNOSTIC_POSITIONS + +```cpp +#define JSON_DIAGNOSTIC_POSITIONS /* value */ +``` + +This macro enables position diagnostics for generated JSON objects. + +When enabled, two new properties: `start_pos()` and `end_pos()` are added to `nlohmann::basic_json` objects and fields. `start_pos()` returns the start +position of that JSON object/field in the original string the object was parsed from. Likewise, `end_pos()` returns the end position of that JSON +object/field in the original string the object was parsed from. + +`start_pos()` returns the first character of a given element in the original JSON string, while `end_pos()` returns the character following the last +character. For objects and arrays, the first and last characters correspond to the opening or closing braces/brackets, respectively. For fields, the first +and last character represent the opening and closing quotes or the first and last character of the field's numerical or predefined value +(true/false/null), respectively. + +Given the above, `end_pos() - start_pos()` for an object or field provides the length of the string representation for that object or field, including the +opening or closing braces, brackets, or quotes. + +`start_pos()` and `end_pos()` are only set if the JSON object was parsed using `parse()`. For all other cases, `std::string::npos` will be returned. + +Note that enabling this macro increases the size of every JSON value by two `std::size_t` fields and adds +slight runtime overhead. + +## Default definition + +The default value is `0` (position diagnostics are switched off). + +```cpp +#define JSON_DIAGNOSTIC_POSITIONS 0 +``` + +When the macro is not defined, the library will define it to its default value. + +## Notes + +!!! hint "CMake option" + + Diagnostic messages can also be controlled with the CMake option + [`JSON_Diagnostic_Positions`](../../integration/cmake.md#json_diagnostic_positions) (`OFF` by default) + which defines `JSON_DIAGNOSTIC_POSITIONS` accordingly. + +## Examples + +??? example "Example 1: retrieving positions" + + ```cpp + --8<-- "examples/diagnostic_positions.cpp" + ``` + + Output: + + ``` + --8<-- "examples/diagnostic_positions.output" + ``` + + The output shows the start/end positions of all the objects and fields in the JSON string. + +## Version history + diff --git a/external/json/docs/mkdocs/docs/api/macros/json_has_static_rtti.md b/external/json/docs/mkdocs/docs/api/macros/json_has_static_rtti.md index 78087831..33d0703a 100644 --- a/external/json/docs/mkdocs/docs/api/macros/json_has_static_rtti.md +++ b/external/json/docs/mkdocs/docs/api/macros/json_has_static_rtti.md @@ -28,4 +28,4 @@ When the macro is not defined, the library will define it to its default value. ## Version history -- Added in version ?. +- Added in version 3.11.3. diff --git a/external/json/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md b/external/json/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md index 557dfa29..4d962c2e 100644 --- a/external/json/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md +++ b/external/json/docs/mkdocs/docs/api/macros/json_use_implicit_conversions.md @@ -27,7 +27,7 @@ By default, implicit conversions are enabled. !!! hint "CMake option" Implicit conversions can also be controlled with the CMake option - [`JSON_ImplicitConversions`](../../integration/cmake.md#json_legacydiscardedvaluecomparison) + [`JSON_ImplicitConversions`](../../integration/cmake.md#json_implicitconversions) (`ON` by default) which defines `JSON_USE_IMPLICIT_CONVERSIONS` accordingly. ## Examples diff --git a/external/json/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md b/external/json/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md index bc1d1434..65f3f176 100644 --- a/external/json/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md +++ b/external/json/docs/mkdocs/docs/api/macros/json_use_legacy_discarded_value_comparison.md @@ -56,7 +56,7 @@ When the macro is not defined, the library will define it to its default value. !!! hint "CMake option" Legacy comparison can also be controlled with the CMake option - [`JSON_LegacyDiscardedValueComparison`](../../integration/cmake.md#json_legacydiscardedvaluecomparison) + [`JSON_LegacyDiscardedValueComparison`](../../integration/cmake.md#json_implicitconversions) (`OFF` by default) which defines `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON` accordingly. ## Examples diff --git a/external/json/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md b/external/json/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md new file mode 100644 index 00000000..f09a7478 --- /dev/null +++ b/external/json/docs/mkdocs/docs/api/macros/nlohmann_define_derived_type.md @@ -0,0 +1,137 @@ +

NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT, + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, + NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE

+ +```cpp +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(type, base_type, member...) // (1) +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(type, base_type, member...) // (2) +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...) // (3) + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(type, base_type, member...) // (4) +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, base_type, member...) // (5) +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...) // (6) +``` + +These macros can be used to simplify the serialization/deserialization of derived 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. + +- Macros 1, 2 and 3 are to be defined **inside** the class/struct to create code for. +Like [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), they can access private members. +- Macros 4, 5 and 6 are to be defined **outside** the class/struct to create code for, but **inside** its namespace. +Like [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md), +they **cannot** access private members. + +The first parameter is the name of the derived class/struct, +the second parameter is the name of the base class/struct and all remaining parameters name the members. +The base type **must** be already serializable/deserializable. + +- Macros 1 and 3 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. +- Macros 2 and 4 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 + +`base_type` (in) +: name of the base type (class, struct) `type` is derived from + +`member` (in) +: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list + +## Default definition + +Macros 1 and 2 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&); +``` + +Macros 4 and 5 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&); +``` + +Macros 3 and 6 add one function to the namespace which take care of the serialization only: + +```cpp +void to_json(nlohmann::json&, const type&); +``` + +In first two cases cases they call the `to_json`/`from_json` functions of the base type +before serializing/deserializing the members of the derived type: + +```cpp +class A { /* ... */ }; +class B : public A { /* ... */ }; + +void to_json(nlohmann::json& j, const B& b) { + nlohmann::to_json(j, static_cast(b)); + // ... +} + +void from_json(const nlohmann::json& j, B& b) { + nlohmann::from_json(j, static_cast(b)); + // ... +} +``` + +In the third case only `to_json` will be called: + +```cpp +class A { /* ... */ }; +class B : public A { /* ... */ }; + +void to_json(nlohmann::json& j, const B& b) { + nlohmann::to_json(j, static_cast(b)); + // ... +} +``` + +## Notes + +!!! info "Prerequisites" + + - Macros 1, 2 and 3 have the same prerequisites of NLOHMANN_DEFINE_TYPE_INTRUSIVE. + - Macros 4, 5 and 6 have the same prerequisites of NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE. + - Serialization/deserialization of base types must be defined. + +!!! warning "Implementation limits" + + - See Implementation limits for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE. + +## Examples + +Example of `NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE` usage: + +```cpp +class A { + double Aa; + double Ab; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(A, Aa, Ab) +}; + +class B : public A { + int Ba; + int Bb; + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(B, A, Ba, Bb) +}; +``` + +## See also + +- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md) + for similar macros that can be defined _inside_ a non-derived type. +- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md) + for similar macros that can be defined _outside_ a non-derived type. +- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview. + +## Version history + +1. Added in version 3.11.x. diff --git a/external/json/docs/mkdocs/docs/api/operator_literal_json.md b/external/json/docs/mkdocs/docs/api/operator_literal_json.md index bc2b2cfc..a3a4bd28 100644 --- a/external/json/docs/mkdocs/docs/api/operator_literal_json.md +++ b/external/json/docs/mkdocs/docs/api/operator_literal_json.md @@ -17,7 +17,7 @@ using namespace nlohmann; ``` This is suggested to ease migration to the next major version release of the library. See -['JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. +[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. ## Parameters diff --git a/external/json/docs/mkdocs/docs/api/operator_literal_json_pointer.md b/external/json/docs/mkdocs/docs/api/operator_literal_json_pointer.md index 0e12440e..423678c7 100644 --- a/external/json/docs/mkdocs/docs/api/operator_literal_json_pointer.md +++ b/external/json/docs/mkdocs/docs/api/operator_literal_json_pointer.md @@ -16,7 +16,7 @@ using namespace nlohmann::literals::json_literals; using namespace nlohmann; ``` This is suggested to ease migration to the next major version release of the library. See -['JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. +[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. ## Parameters diff --git a/external/json/docs/mkdocs/docs/api/ordered_json.md b/external/json/docs/mkdocs/docs/api/ordered_json.md index 7cfd9f4d..f4062d13 100644 --- a/external/json/docs/mkdocs/docs/api/ordered_json.md +++ b/external/json/docs/mkdocs/docs/api/ordered_json.md @@ -6,6 +6,13 @@ using ordered_json = basic_json; This type preserves the insertion order of object keys. +## Iterator invalidation + +The type is based on [`ordered_map`](ordered_map.md) which in turn uses a `std::vector` to store object elements. +Therefore, adding object elements can yield a reallocation in which case all iterators (including the +[`end()`](basic_json/end.md) iterator) and all references to the elements are invalidated. Also, any iterator or +reference after the insertion point will point to the same index which is now a different value. + ## Examples ??? example diff --git a/external/json/docs/mkdocs/docs/api/ordered_map.md b/external/json/docs/mkdocs/docs/api/ordered_map.md index 160b85c2..ca493416 100644 --- a/external/json/docs/mkdocs/docs/api/ordered_map.md +++ b/external/json/docs/mkdocs/docs/api/ordered_map.md @@ -23,6 +23,11 @@ A minimal map-like container that preserves insertion order for use within [`nlo `Allocator` : allocator type +## Iterator invalidation + +The type uses a `std::vector` to store object elements. Therefore, adding elements can yield a reallocation in which +case all iterators (including the `end()` iterator) and all references to the elements are invalidated. + ## Member types - **key_type** - key type (`Key`) diff --git a/external/json/docs/mkdocs/docs/features/arbitrary_types.md b/external/json/docs/mkdocs/docs/features/arbitrary_types.md index 9b54fcb3..449671c9 100644 --- a/external/json/docs/mkdocs/docs/features/arbitrary_types.md +++ b/external/json/docs/mkdocs/docs/features/arbitrary_types.md @@ -75,7 +75,7 @@ Likewise, when calling `template get()` or `get_to(your_type&)`, the 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. +* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [#1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. * When using `template 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()`](../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. @@ -265,7 +265,7 @@ struct bad_serializer } template - static void to_json(const BasicJsonType& j, T& value) { + static void from_json(const BasicJsonType& j, T& value) { // this calls BasicJsonType::json_serializer::from_json(j, value); // if BasicJsonType::json_serializer == bad_serializer ... oops! value = j.template template get(); // oops! diff --git a/external/json/docs/mkdocs/docs/features/assertions.md b/external/json/docs/mkdocs/docs/features/assertions.md index 2bad62e8..32b4e019 100644 --- a/external/json/docs/mkdocs/docs/features/assertions.md +++ b/external/json/docs/mkdocs/docs/features/assertions.md @@ -103,29 +103,38 @@ behavior and yields a runtime assertion. Assertion failed: (m_object != nullptr), function operator++, file iter_impl.hpp, line 368. ``` -### Reading from a null `FILE` pointer +## Changes -Reading from a null `#!cpp FILE` pointer is undefined behavior and yields a runtime assertion. This can happen when -calling `#!cpp std::fopen` on a nonexistent file. +### Reading from a null `FILE` or `char` pointer -??? example "Example 4: Uninitialized iterator" +Reading from a null `#!cpp FILE` or `#!cpp char` pointer in C++ is undefined behavior. Until version 3.11.4, this +library asserted that the pointer was not `nullptr` using a runtime assertion. If assertions were disabled, this would +result in undefined behavior. Since version 3.11.4, this library checks for `nullptr` and throws a +[`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) to prevent the undefined behavior. + +??? example "Example 4: Reading from null pointer" The following code will trigger an assertion at runtime: ```cpp + #include #include using json = nlohmann::json; int main() { - std::FILE* f = std::fopen("nonexistent_file.json", "r"); - json j = json::parse(f); + std::FILE* f = std::fopen("nonexistent_file.json", "r"); + try { + json j = json::parse(f); + } catch (std::exception& e) { + std::cerr << e.what() << std::endl; + } } ``` Output: ``` - Assertion failed: (m_file != nullptr), function file_input_adapter, file input_adapters.hpp, line 55. + [json.exception.parse_error.101] parse error: attempting to parse an empty input; check that your input string or stream contains the expected JSON ``` diff --git a/external/json/docs/mkdocs/docs/features/binary_values.md b/external/json/docs/mkdocs/docs/features/binary_values.md index 5ad6433c..4a15a2ee 100644 --- a/external/json/docs/mkdocs/docs/features/binary_values.md +++ b/external/json/docs/mkdocs/docs/features/binary_values.md @@ -10,17 +10,19 @@ serialized JSON text if they have been created manually or via a binary format. ## API for binary values -```plantuml -class json::binary_t { - -- setters -- +```mermaid +classDiagram + +class binary_t ["json::binary_t"] { +void set_subtype(std::uint64_t subtype) +void clear_subtype() - -- getters -- +std::uint64_t subtype() const +bool has_subtype() const } -"std::vector" <|-- json::binary_t +class vector ["std::vector"] + +vector <|-- binary_t ``` By default, binary values are stored as `std::vector`. This type can be changed by providing a template diff --git a/external/json/docs/mkdocs/docs/features/comments.md b/external/json/docs/mkdocs/docs/features/comments.md index 61266d9c..e99cceb4 100644 --- a/external/json/docs/mkdocs/docs/features/comments.md +++ b/external/json/docs/mkdocs/docs/features/comments.md @@ -5,9 +5,9 @@ This library does not support comments *by default*. It does so for three reason 1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript. 2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012: - > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. + > I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't. - > Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser. + > Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser. 3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this. diff --git a/external/json/docs/mkdocs/docs/features/iterators.md b/external/json/docs/mkdocs/docs/features/iterators.md index ce627e01..ca303cb4 100644 --- a/external/json/docs/mkdocs/docs/features/iterators.md +++ b/external/json/docs/mkdocs/docs/features/iterators.md @@ -100,7 +100,7 @@ for (auto& [key, val] : j_object.items()) !!! warning - Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See for more information. + Using `items()` on temporary objects is dangerous. Make sure the object's lifetime exceeds the iteration. See [#2040](https://github.com/nlohmann/json/issues/2040) for more information. ### Reverse iteration order diff --git a/external/json/docs/mkdocs/docs/features/json_pointer.md b/external/json/docs/mkdocs/docs/features/json_pointer.md index 04aeca50..4fd58f20 100644 --- a/external/json/docs/mkdocs/docs/features/json_pointer.md +++ b/external/json/docs/mkdocs/docs/features/json_pointer.md @@ -71,10 +71,10 @@ auto j = json::parse(R"({ })"); // access values -auto val = j["/"_json_pointer]; // {"array":["A","B","C"],...} +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 +auto val2 = j.at(json::json_pointer("/nested/three/1")); // false +auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0 ``` ## Flatten / unflatten diff --git a/external/json/docs/mkdocs/docs/features/macros.md b/external/json/docs/mkdocs/docs/features/macros.md index 926741b0..2fea87c1 100644 --- a/external/json/docs/mkdocs/docs/features/macros.md +++ b/external/json/docs/mkdocs/docs/features/macros.md @@ -100,6 +100,13 @@ When defined to `0`, implicit conversions are switched off. By default, implicit See [full documentation of `JSON_USE_IMPLICIT_CONVERSIONS`](../api/macros/json_use_implicit_conversions.md). +## `NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(type, base_type, member...)` +## `NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(type, base_type, member...)` +## `NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...)` +## `NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(type, base_type, member...)` +## `NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, base_type, member...)` +## `NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, base_type, member...)` + ## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as diff --git a/external/json/docs/mkdocs/docs/features/namespace.md b/external/json/docs/mkdocs/docs/features/namespace.md index 8cee2ccf..460cb3be 100644 --- a/external/json/docs/mkdocs/docs/features/namespace.md +++ b/external/json/docs/mkdocs/docs/features/namespace.md @@ -30,15 +30,16 @@ nlohmann::json_abi_diag_v3_11_2 Several incompatibilities have been observed. Amongst the most common ones is linking code compiled with different definitions of [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This is illustrated in the diagram below. -```plantuml -[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=0] as [json] -[**nlohmann_json (v3.10.5)**\nJSON_DIAGNOSTICS=1] as [json_diag] -[**some_library**] as [library] -[**application**] as [app] - -[library] ..|> [json] -[app] ..|> [json_diag] -[app] ..|>[library] +```mermaid +graph + json["nlohmann_json (v3.10.5)
JSON_DIAGNOSTICS=0"] + json_diag["nlohmann_json (v3.10.5)
JSON_DIAGNOSTICS=1"] + library["some library"] + app["application"] + + library --> json + app --> json_diag + app --> library ``` In releases prior to 3.11.0, mixing any version of the JSON library with different `JSON_DIAGNOSTICS` settings would diff --git a/external/json/docs/mkdocs/docs/features/parsing/sax_interface.md b/external/json/docs/mkdocs/docs/features/parsing/sax_interface.md index 0796a55f..5a9c83a7 100644 --- a/external/json/docs/mkdocs/docs/features/parsing/sax_interface.md +++ b/external/json/docs/mkdocs/docs/features/parsing/sax_interface.md @@ -2,27 +2,30 @@ The library uses a SAX-like interface with the following functions: -```plantuml -interface json::sax_t { - + {abstract} bool null() +```mermaid +classDiagram - + {abstract} bool boolean(bool val) - - + {abstract} bool number_integer(number_integer_t val) - + {abstract} bool number_unsigned(number_unsigned_t val) - - + {abstract} bool number_float(number_float_t val, const string_t& s) - - + {abstract} bool string(string_t& val) - + {abstract} bool binary(binary_t& val) - - + {abstract} bool start_object(std::size_t elements) - + {abstract} bool end_object() - + {abstract} bool start_array(std::size_t elements) - + {abstract} bool end_array() - + {abstract} bool key(string_t& val) - - + {abstract} bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) +class sax_t ["json::sax_t"] { + <> + +bool null()* + + +bool boolean(bool val)* + + +bool number_integer(number_integer_t val)* + +bool number_unsigned(number_unsigned_t val)* + + +bool number_float(number_float_t val, const string_t& s)* + + +bool string(string_t& val)* + +bool binary(binary_t& val)* + + +bool start_object(std::size_t elements)* + +bool end_object()* + +bool start_array(std::size_t elements)* + +bool end_array()* + +bool key(string_t& val)* + + +bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex)* } ``` diff --git a/external/json/docs/mkdocs/docs/features/types/index.md b/external/json/docs/mkdocs/docs/features/types/index.md index d9dfcc29..1a2a8119 100644 --- a/external/json/docs/mkdocs/docs/features/types/index.md +++ b/external/json/docs/mkdocs/docs/features/types/index.md @@ -19,8 +19,11 @@ Note there are three different types for numbers - when parsing JSON text, the b ## Storage -```plantuml -enum value_t { +```mermaid +classDiagram + +class value_t { + <> null object array @@ -33,7 +36,8 @@ enum value_t { discarded } -class json_value << (U,orchid) >> { +class json_value { + <> object_t* object array_t* array string_t* string @@ -45,17 +49,15 @@ class json_value << (U,orchid) >> { } class basic_json { - -- type and value -- - value_t m_type - json_value m_value - -- derived types -- - + typedef object_t - + typedef array_t - + typedef binary_t - + typedef boolean_t - + typedef number_integer_t - + typedef number_unsigned_t - + typedef number_float_t + -value_t m_type + -json_value m_value + +typedef object_t + +typedef array_t + +typedef binary_t + +typedef boolean_t + +typedef number_integer_t + +typedef number_unsigned_t + +typedef number_float_t } basic_json .. json_value diff --git a/external/json/docs/mkdocs/docs/home/customers.md b/external/json/docs/mkdocs/docs/home/customers.md new file mode 100644 index 00000000..67c5a62d --- /dev/null +++ b/external/json/docs/mkdocs/docs/home/customers.md @@ -0,0 +1,159 @@ +# Customers + +The library is used in multiple projects, applications, operating systems, etc. The list below is not exhaustive, but +the result of an internet search. If you know further customers of the library, [please let me know](mailto:mail@nlohmann.me). + +[![](../images/customers.png)](../images/customers.png) + +## Space Exploration + +- [**Peregrine Lunar Lander Flight 01**](https://en.wikipedia.org/wiki/Peregrine_Mission_One) - The library was utilized for payload management in the **Peregrine Moon Lander**, developed by **Astrobotic Technology** and launched as part of NASA's **Commercial Lunar Payload Services (CLPS)** program. After six days in orbit, the spacecraft was intentionally redirected into Earth's atmosphere, where it burned up over the Pacific Ocean on **January 18, 2024**. + +## Automotive + +- [**Alexa Auto SDK**](https://github.com/alexa/alexa-auto-sdk), a software development kit enabling the integration of Alexa into automotive systems +- [**Apollo**](https://github.com/ApolloAuto/apollo), a framework for building autonomous driving systems +- [**Automotive Grade Linux (AGL)**](https://download.automotivelinux.org/AGL/release/jellyfish/latest/qemux86-64/deploy/licenses/nlohmann-json/): a collaborative open-source platform for automotive software development +- [**Genesis Motor** (infotainment)](http://webmanual.genesis.com/ccIC/AVNT/JW/KOR/English/reference010.html), a luxury automotive brand +- [**Hyundai** (infotainment)](https://www.hyundai.com/wsvc/ww/download.file.do?id=/content/hyundai/ww/data/opensource/data/GN7-2022/licenseCode/info), a global automotive brand +- [**Kia** (infotainment)](http://webmanual.kia.com/PREM_GEN6/AVNT/RJPE/KOR/Korean/reference010.html), a global automotive brand +- [**Mercedes-Benz Operating System (MB.OS)**](https://group.mercedes-benz.com/careers/about-us/mercedes-benz-operating-system/), a core component of the vehicle software ecosystem from Mercedes-Benz +- [**Rivian** (infotainment)](https://assets.ctfassets.net/2md5qhoeajym/3cwyo4eoufk4yingUwusFt/ded2c47da620fdfc99c88c7156d2c1d8/In-Vehicle_OSS_Attribution_2024__11-24_.pdf), an electric vehicle manufacturer +- [**Suzuki** (infotainment)](https://www.globalsuzuki.com/motorcycle/ipc/oss/oss_48KA_00.pdf), a global automotive and motorcycle manufacturer + +## Gaming and Entertainment + +- [**Assassin's Creed: Mirage**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a stealth-action game set in the Middle East, focusing on the journey of a young assassin with classic parkour and stealth mechanics +- [**Chasm: The Rift**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a first-person shooter blending horror and adventure, where players navigate dark realms and battle monsters +- [**College Football 25**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a college football simulation game featuring gameplay that mimics real-life college teams and competitions +- [**Concepts**](https://concepts.app/en/licenses): a digital sketching app designed for creative professionals, offering flexible drawing tools for illustration, design, and brainstorming +- [**Depthkit**](https://www.depthkit.tv/third-party-licenses): a tool for creating and capturing volumetric video, enabling immersive 3D experiences and interactive content +- [**immersivetech**](https://immersitech.io/open-source-third-party-software/): a technology company focused on immersive experiences, providing tools and solutions for virtual and augmented reality applications +- [**LOOT**](https://loot.readthedocs.io/_/downloads/en/0.13.0/pdf/), a tool for optimizing the load order of game plugins, commonly used in The Elder Scrolls and Fallout series +- [**Madden NFL 25**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a sports simulation game capturing the excitement of American football with realistic gameplay and team management features +- [**Marne**](https://marne.io/licenses), an unofficial private server platform for hosting custom Battlefield 1 game experiences +- [**Minecraft**](https://www.minecraft.net/zh-hant/attribution), a popular sandbox video game +- [**NHL 22**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a hockey simulation game offering realistic gameplay, team management, and various modes to enhance the hockey experience +- [**Pixelpart**](https://pixelpart.net/documentation/book/third-party.html): a 2D animation and video compositing software that allows users to create animated graphics and visual effects with a focus on simplicity and ease of use +- [**Red Dead Redemption II**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): an open-world action-adventure game following an outlaw's story in the late 1800s, emphasizing deep storytelling and immersive gameplay +- [**Tactics Ogre: Reborn**](https://www.square-enix-games.com/en_US/documents/tactics-ogre-reborn-pc-installer-software-and-associated-plug-ins-disclosure), a tactical role-playing game featuring strategic battles and deep storytelling elements +- [**Throne and Liberty**](https://www.amazon.com/gp/help/customer/display.html?nodeId=T7fLNw5oAevCMtJFPj&pop-up=1), an MMORPG that offers an expansive fantasy world with dynamic gameplay and immersive storytelling +- [**Unity Vivox**](https://docs.unity3d.com/Packages/com.unity.services.vivox@15.1/license/Third%20Party%20Notices.html), a communication service that enables voice and text chat functionality in multiplayer games developed with Unity +- [**Zool: Redimensioned**](https://www.mobygames.com/person/1195889/niels-lohmann/credits/): a modern reimagining of the classic platformer featuring fast-paced gameplay and vibrant environments + +## Consumer Electronics + +- [**Audinate**](https://www.audinate.com/legal/software-licensing/dante-av-h-open-source-licenses/): a provider of networked audio solutions specializing in Dante technology, which facilitates high-quality digital audio transport over IP networks +- [**Cisco Webex Desk Camera**](https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/CiscoWebexDeskCamera-23-1622100417.pdf), a video camera designed for professional-quality video conferencing and remote collaboration +- [**Philips Hue Personal Wireless Lighting**](http://2ak5ape.257.cz/): a smart lighting system for customizable and wireless home illumination +- [**Ray-Ban Meta Smart glasses**](https://www.meta.com/de/en/legal/smart-glasses/third-party-notices-android/03/), a pair of smart glasses designed for capturing photos and videos with integrated connectivity and social features +- [**Siemens SINEMA Remote Connect**](https://cache.industry.siemens.com/dl/files/790/109793790/att_1054961/v2/OSS_SINEMA-RC_86.pdf), a remote connectivity solution for monitoring and managing industrial networks and devices securely +- [**Sony PlayStation 4**](https://doc.dl.playstation.net/doc/ps4-oss/index.html), a gaming console developed by Sony that offers a wide range of games and multimedia entertainment features +- [**Sony Virtual Webcam Driver for Remote Camera**](https://helpguide.sony.net/rc/vwd/v1/zh-cn/print.pdf), a software driver that enables the use of Sony cameras as virtual webcams for video conferencing and streaming + +## Operating Systems + +- [**Apple iOS and macOS**](https://www.apple.com/macos), a family of operating systems developed by Apple, including iOS for mobile devices and macOS for desktop computers +- [**Google Fuchsia**](https://fuchsia.googlesource.com/third_party/json/), an open-source operating system developed by Google, designed to be secure, updatable, and adaptable across various devices +- [**SerenityOS**](https://github.com/SerenityOS/serenity), an open-source operating system that aims to provide a simple and beautiful user experience with a focus on simplicity and elegance +- [**Yocto**](http://ftp.emacinc.com/openembedded-sw/kirkstone-icop-5.15-kirkstone-6.0/archive-2024-10/pn8m-090t-ppc/licenses/nlohmann-json/): a Linux-based build system for creating custom operating systems and software distributions, tailored for embedded devices and IoT applications + +## Development Tools and IDEs + +- [**Accentize SpectralBalance**](https://www.accentize.com/products/SpectralBalanceManual.pdf), an adaptive speech analysis tool designed to enhance audio quality by optimizing frequency balance in recordings +- [**Arm Compiler for Linux**](https://documentation-service.arm.com/static/66558e9d876c8d213b7843e4), a software development toolchain for compiling and optimizing applications on Arm-based Linux systems +- [**BBEdit**](https://s3.amazonaws.com/BBSW-download/BBEdit_15.1.2_User_Manual.pdf), a professional text and code editor for macOS +- [**CoderPad**](https://coderpad.io), a collaborative coding platform that enables real-time code interviews and assessments for developers; the library is included in every CoderPad instance and can be accessed with a simple `#include "json.hpp"` +- [**Compiler Explorer**](https://godbolt.org), a web-based tool that allows users to write, compile, and visualize the assembly output of code in various programming languages; the library is readily available and accessible with the directive `#include `. +- [**GitHub CodeQL**](https://github.com/github/codeql), a code analysis tool used for identifying security vulnerabilities and bugs in software through semantic queries +- [**Hex-Rays**](https://docs.hex-rays.com/user-guide/user-interface/licenses): a reverse engineering toolset for analyzing and decompiling binaries, primarily used for security research and vulnerability analysis +- [**ImHex**](https://github.com/WerWolv/ImHex), a hex editor designed for reverse engineering, providing advanced features for data analysis and manipulation +- [**Intel GPA Framework**](https://intel.github.io/gpasdk-doc/src/licenses.html), a suite of cross-platform tools for capturing, analyzing, and optimizing graphics applications across different APIs +- [**Meta Yoga**](https://github.com/facebook/yoga), a layout engine that facilitates flexible and efficient user interface design across multiple platforms +- [**MKVToolNix**](https://mkvtoolnix.download/doc/README.md), a set of tools for creating, editing, and inspecting MKV (Matroska) multimedia container files +- [**NVIDIA Nsight Compute**](https://docs.nvidia.com/nsight-compute/2022.2/pdf/CopyrightAndLicenses.pdf), a performance analysis tool for CUDA applications that provides detailed insights into GPU performance metrics +- [**Notepad++**](https://github.com/notepad-plus-plus/notepad-plus-plus), a free source code editor that supports various programming languages +- [**OpenRGB**](https://gitlab.com/CalcProgrammer1/OpenRGB), an open source RGB lighting control that doesn't depend on manufacturer software +- [**OpenTelemetry C++**](https://github.com/open-telemetry/opentelemetry-cpp): a library for collecting and exporting observability data in C++, enabling developers to implement distributed tracing and metrics in their application +- [**Qt Creator**](https://doc.qt.io/qtcreator/qtcreator-attribution-json-nlohmann.html), an IDE for developing applications using the Qt application framework +- [**Scanbot SDK**](https://docs.scanbot.io/barcode-scanner-sdk/web/third-party-libraries/): a software development kit (SDK) that provides tools for integrating advanced document scanning and barcode scanning capabilities into applications + +## Machine Learning and AI + +- [**Apple Core ML Tools**](https://github.com/apple/coremltools), a set of tools for converting and configuring machine learning models for deployment in Apple's Core ML framework +- [**Avular Mobile Robotics**](https://www.avular.com/licenses/nlohmann-json-3.9.1.txt): a platform for developing and deploying mobile robotics solutions +- [**Google gemma.cpp**](https://github.com/google/gemma.cpp), a lightweight C++ inference engine designed for running AI models from the Gemma family +- [**llama.cpp**](https://github.com/ggerganov/llama.cpp), a C++ library designed for efficient inference of large language models (LLMs), enabling streamlined integration into applications +- [**Mozilla llamafile**](https://github.com/Mozilla-Ocho/llamafile), a tool designed for distributing and executing large language models (LLMs) efficiently using a single file format +- [**NVIDIA ACE**](https://docs.nvidia.com/ace/latest/index.html), a suite of real-time AI solutions designed for the development of interactive avatars and digital human applications, enabling scalable and sophisticated user interactions +- [**Peer**](https://support.peer.inc/hc/en-us/articles/17261335054235-Licenses): a platform offering personalized AI assistants for interactive learning and creative collaboration +- [**stable-diffusion.cpp**](https://github.com/leejet/stable-diffusion.cpp): a C++ implementation of the Stable Diffusion image generation model +- [**TanvasTouch**](https://tanvas.co/tanvastouch-sdk-third-party-acknowledgments): a software development kit (SDK) that enables developers to create tactile experiences on touchscreens, allowing users to feel textures and physical sensations in a digital environment +- [**TensorFlow**](https://github.com/tensorflow/tensorflow), a machine learning framework that facilitates the development and training of models, supporting data serialization and efficient data exchange between components + +## Scientific Research and Analysis + +- [**BLACK**](https://www.black-sat.org/en/stable/installation/linux.html), a bounded linear temporal logic (LTL) satisfiability checker +- [**CERN Atlas Athena**](https://gitlab.cern.ch/atlas/athena/-/blob/main/Control/PerformanceMonitoring/PerfMonComps/src/PerfMonMTSvc.h), a software framework used in the ATLAS experiment at the Large Hadron Collider (LHC) for performance monitoring +- [**KAMERA**](https://github.com/Kitware/kamera): a platform for synchronized data collection and real-time deep learning to map marine species like polar bears and seals, aiding Arctic ecosystem research +- [**KiCad**](https://gitlab.com/kicad/code/kicad/-/tree/master/thirdparty/nlohmann_json): a free and open-source software suite for electronic design automation +- [**MeVisLab**](https://mevislabdownloads.mevis.de/docs/current/MeVis/ThirdParty/Documentation/Publish/ThirdPartyReference/index.html): a software framework for medical image processing and visualization. +- [**OpenPMD API**](https://openpmd-api.readthedocs.io/en/0.8.0-alpha/backends/json.html): a versatile programming interface for accessing and managing scientific data, designed to facilitate the efficient storage, retrieval, and sharing of simulation data across various applications and platforms +- [**ParaView**](https://github.com/Kitware/ParaView): an open-source tool for large-scale data visualization and analysis across various scientific domains +- [**QGIS**](https://gitlab.b-data.ch/qgis/qgis/-/blob/backport-57658-to-release-3_34/external/nlohmann/json.hpp): a free and open-source geographic information system (GIS) application that allows users to create, edit, visualize, and analyze geospatial data across a variety of formats +- [**VTK**](https://github.com/Kitware/VTK): a software library for 3D computer graphics, image processing, and visualization +- [**VolView**](https://github.com/Kitware/VolView): a lightweight application for interactive visualization and analysis of 3D medical imaging data. + +## Business and Productivity Software + +- [**ArcGIS PRO**](https://www.esri.com/content/dam/esrisites/en-us/media/legal/open-source-acknowledgements/arcgis-pro-2-8-attribution-report.html), a desktop geographic information system (GIS) application developed by Esri for mapping and spatial analysis +- [**Autodesk Desktop**](https://damassets.autodesk.net/content/dam/autodesk/www/Company/legal-notices-trademarks/autodesk-desktop-platform-components/internal-autodesk-components-web-page-2023.pdf), a software platform developed by Autodesk for creating and managing desktop applications and services +- [**Check Point**](https://www.checkpoint.com/about-us/copyright-and-trademarks/): a cybersecurity company specializing in threat prevention and network security solutions, offering a range of products designed to protect enterprises from cyber threats and ensure data integrity +- [**Microsoft Office for Mac**](https://officecdnmac.microsoft.com/pr/legal/mac/OfficeforMacAttributions.html), a suite of productivity applications developed by Microsoft for macOS, including tools for word processing, spreadsheets, and presentations +- [**Nexthink Infinity**](https://docs.nexthink.com/legal/services-terms/experience-open-source-software-licenses/infinity-2022.8-software-licenses): a digital employee experience management platform for monitoring and improving IT performance +- [**Sophos Connect Client**](https://docs.sophos.com/nsg/licenses/SophosConnect/SophosConnectAttribution.html): a secure VPN client from Sophos that allows remote users to connect to their corporate network, ensuring secure access to resources and data +- [**Stonebranch**](https://stonebranchdocs.atlassian.net/wiki/spaces/UA77/pages/799545647/Licenses+for+Third-Party+Libraries): a cloud-based cybersecurity solution that integrates backup, disaster recovery, and cybersecurity features to protect data and ensure business continuity for organizations +- [**Tablecruncher**](https://tablecruncher.com/): a data analysis tool that allows users to import, analyze, and visualize spreadsheet data, offering interactive features for better insights and decision-making +- [**magicplan**](https://help.magicplan.app/acknowledgments), a mobile application for creating floor plans and interior designs using augmented reality + +## Databases and Big Data + +- [**ADIOS2**](https://code.ornl.gov/ecpcitest/adios2/-/tree/pr4285_FFSUpstream/thirdparty/nlohmann_json?ref_type=heads): a data management framework designed for high-performance input and output operations +- [**Cribl Stream**](https://docs.cribl.io/stream/third-party-current-list/): a real-time data processing platform that enables organizations to collect, route, and transform observability data, enhancing visibility and insights into their systems +- [**DB Browser for SQLite**](https://github.com/sqlitebrowser/sqlitebrowser), a visual open-source tool for creating, designing, and editing SQLite database files +- [**MySQL Connector/C++**](https://docs.oracle.com/cd/E17952_01/connector-cpp-9.1-license-com-en/license-opentelemetry-cpp-com.html), a C++ library for connecting and interacting with MySQL databases +- [**MySQL NDB Cluster**](https://downloads.mysql.com/docs/licenses/cluster-9.0-com-en.pdf), a distributed database system that provides high availability and scalability for MySQL databases +- [**PrestoDB**](https://github.com/prestodb/presto), a distributed SQL query engine designed for large-scale data analytics, originally developed by Facebook +- [**ROOT Data Analysis Framework**](https://root.cern/doc/v614/classnlohmann_1_1basic__json.html), an open-source data analysis framework widely used in high-energy physics and other fields for data processing and visualization + +## Simulation and Modeling + +- [**Arcturus HoloSuite**](https://www.datocms-assets.com/104353/1698904597-holosuite-third-party-software-credits-and-attributions-2.pdf), a software toolset for capturing, editing, and streaming volumetric video, featuring advanced compression technologies for high-quality 3D content creation +- [**azul**](https://pure.tudelft.nl/ws/files/85338589/tgis.12673.pdf), a fast and efficient 3D city model viewer designed for visualizing urban environments and spatial data +- [**Blender**](https://projects.blender.org/blender/blender/search?q=nlohmann), a free and open-source 3D creation suite for modeling, animation, rendering, and more +- [**cpplot**](https://cpplot.readthedocs.io/en/latest/library_api/function_eigen_8h_1ac080eac0541014c5892a55e41bf785e6.html), a library for creating interactive graphs and charts in C++, which can be viewed in web browsers +- [**NVIDIA Omniverse**](https://docs.omniverse.nvidia.com/composer/latest/common/product-licenses/usd-explorer/usd-explorer-2023.2.0-licenses-manifest.html), a platform for 3D content creation and collaboration that enables real-time simulations and interactive experiences across various industries +- [**Pixar Renderman**](https://rmanwiki-26.pixar.com/space/REN26/19662083/Legal+Notice), a photorealistic 3D rendering software developed by Pixar, widely used in the film industry for creating high-quality visual effects and animations +- [**ROS - Robot Operating System**](http://docs.ros.org/en/noetic/api/behaviortree_cpp/html/json_8hpp_source.html), a set of software libraries and tools that assist in developing robot applications +- [**UBS**](https://www.ubs.com/), a multinational financial services and banking company +- [**GAMS**](https://www.gams.com/47/docs/THIRDPARTY.html): a high-performance mathematical modeling system for optimization and decision support +- [**M-Star**](https://docs.mstarcfd.com/3_Licensing/thirdparty-licenses.html): a computational fluid dynamics software for simulating and analyzing fluid flow +- [**MapleSim CAD Toolbox**](https://www.maplesoft.com/support/help/MapleSim/view.aspx?path=CADToolbox/copyright): a software extension for MapleSim that integrates CAD models, allowing users to import, manipulate, and analyze 3D CAD data within the MapleSim environment for enhanced modeling and simulation +- [**Kitware SMTK**](https://github.com/Kitware/SMTK): a software toolkit for managing simulation models and workflows in scientific and engineering applications + +## Enterprise and Cloud Applications + +- [**Acronis Cyber Protect Cloud**](https://care.acronis.com/s/article/59533-Third-party-software-used-in-Acronis-Cyber-Protect-Cloud?language=en_US): an all-in-one data protection solution that combines backup, disaster recovery, and cybersecurity to safeguard business data from threats like ransomware +- [**Baereos**](https://gitlab.tiger-computing.co.uk/packages/bareos/-/blob/tiger/bullseye/third-party/CLI11/examples/json.cpp): a backup solution that provides data protection and recovery options for various environments, including physical and virtual systems +- [**Bitdefender Home Scanner**](https://www.bitdefender.de/site/Main/view/home-scanner-open-source.html), a tool from Bitdefender that scans devices for malware and security threats, providing a safeguard against potential online dangers +- [**Citrix Provisioning**](https://docs.citrix.com/en-us/provisioning/2203-ltsr/downloads/pvs-third-party-notices-2203.pdf): a solution that streamlines the delivery of virtual desktops and applications by allowing administrators to manage and provision resources efficiently across multiple environments +- [**Citrix Virtual Apps and Desktops**](https://docs.citrix.com/en-us/citrix-virtual-apps-desktops/2305/downloads/third-party-notices-apps-and-desktops.pdf), a solution from Citrix that delivers virtual apps and desktops +- [**Cyberarc**](https://docs.cyberark.com/Downloads/Legal/Privileged%20Session%20Manager%20for%20SSH%20Third-Party%20Notices.pdf): a security solution that specializes in privileged access management, enabling organizations to control and monitor access to critical systems and data, thereby enhancing overall cybersecurity posture +- [**Egnyte Desktop**](https://helpdesk.egnyte.com/hc/en-us/articles/360007071732-Third-Party-Software-Acknowledgements): a secure cloud storage solution designed for businesses, enabling file sharing, collaboration, and data management across teams while ensuring compliance and data protection +- [**Ethereum Solidity**](https://github.com/ethereum/solidity), a high-level, object-oriented programming language designed for implementing smart contracts on the Ethereum platform +- [**Inciga**](https://fossies.org/linux/icinga2/third-party/nlohmann_json/json.hpp): a monitoring tool for IT infrastructure, designed to provide insights into system performance and availability through customizable dashboards and alerts +- [**Intel Accelerator Management Daemon for VMware ESXi**](https://downloadmirror.intel.com/772507/THIRD-PARTY.txt): a management tool designed for monitoring and controlling Intel hardware accelerators within VMware ESXi environments, optimizing performance and resource allocation +- [**Juniper Identity Management Service**](https://www.juniper.net/documentation/us/en/software/jims/jims-guide/jims-guide.pdf) +- [**Microsoft Azure IoT SDK**](https://library.e.abb.com/public/2779c5f85f30484192eb3cb3f666a201/IP%20Gateway%20Open%20License%20Declaration_9AKK108467A4095_Rev_C.pdf), a collection of tools and libraries to help developers connect, build, and deploy Internet of Things (IoT) solutions on the Azure cloud platform +- [**Microsoft WinGet**](https://github.com/microsoft/winget-cli), a command-line utility included in the Windows Package Manager +- [**Pointr**](https://docs-dev.pointr.tech/docs/8.x/Developer%20Portal/Open%20Source%20Licenses/): a platform for indoor positioning and navigation solutions, offering tools and SDKs for developers to create location-based applications diff --git a/external/json/docs/mkdocs/docs/home/design_goals.md b/external/json/docs/mkdocs/docs/home/design_goals.md index b80551fe..b3a0b2b9 100644 --- a/external/json/docs/mkdocs/docs/home/design_goals.md +++ b/external/json/docs/mkdocs/docs/home/design_goals.md @@ -2,7 +2,7 @@ There are myriads of [JSON](https://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: -- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples), and you'll know what I mean. +- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. - **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. diff --git a/external/json/docs/mkdocs/docs/home/exceptions.md b/external/json/docs/mkdocs/docs/home/exceptions.md index a0fee9e3..f6e586c6 100644 --- a/external/json/docs/mkdocs/docs/home/exceptions.md +++ b/external/json/docs/mkdocs/docs/home/exceptions.md @@ -6,24 +6,33 @@ All exceptions inherit from class `json::exception` (which in turn inherits from `std::exception`). It is used as the base class for all exceptions thrown by the `basic_json` class. This class can hence be used as "wildcard" to catch exceptions. -```plantuml -std::exception <|-- json::exception -json::exception <|-- json::parse_error -json::exception <|-- json::invalid_iterator -json::exception <|-- json::type_error -json::exception <|-- json::out_of_range -json::exception <|-- json::other_error +``` mermaid +classDiagram + direction LR + class `std::exception` { + <> + } -interface std::exception {} + class `json::exception` { + +const int id + +const char* what() const + } -class json::exception { - + const int id - + const char* what() const -} + class `json::parse_error` { + +const std::size_t byte + } -class json::parse_error { - + const std::size_t byte -} + class `json::invalid_iterator` + class `json::type_error` + class `json::out_of_range` + class `json::other_error` + + `std::exception` <|-- `json::exception` + `json::exception` <|-- `json::parse_error` + `json::exception` <|-- `json::invalid_iterator` + `json::exception` <|-- `json::type_error` + `json::exception` <|-- `json::out_of_range` + `json::exception` <|-- `json::other_error` ``` ### Switch off exceptions diff --git a/external/json/docs/mkdocs/docs/home/license.md b/external/json/docs/mkdocs/docs/home/license.md index baef2f51..391d77a4 100644 --- a/external/json/docs/mkdocs/docs/home/license.md +++ b/external/json/docs/mkdocs/docs/home/license.md @@ -1,10 +1,10 @@ # License - + The class is licensed under the [MIT License](https://opensource.org/licenses/MIT): -Copyright © 2013-2022 [Niels Lohmann](https://nlohmann.me) +Copyright © 2013-2024 [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/external/json/docs/mkdocs/docs/home/sponsors.md b/external/json/docs/mkdocs/docs/home/sponsors.md index 9097049d..7e3ef028 100644 --- a/external/json/docs/mkdocs/docs/home/sponsors.md +++ b/external/json/docs/mkdocs/docs/home/sponsors.md @@ -2,6 +2,11 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann). +## Priority Sponsor + +- [Martti Laine](https://github.com/codeclown) +- [Paul Harrington](https://github.com/phrrngtn) + ## Named Sponsors - [Michael Hartmann](https://github.com/reFX-Mike) @@ -9,5 +14,6 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl - [Steve Sperandeo](https://github.com/homer6) - [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe) - [Steve Wagner](https://github.com/ciroque) +- [Lion Yang](https://github.com/LionNatsu) Thanks everyone! diff --git a/external/json/docs/mkdocs/docs/images/customers.png b/external/json/docs/mkdocs/docs/images/customers.png new file mode 100644 index 00000000..e122f508 Binary files /dev/null and b/external/json/docs/mkdocs/docs/images/customers.png differ diff --git a/external/json/docs/mkdocs/docs/integration/bazel/BUILD b/external/json/docs/mkdocs/docs/integration/bazel/BUILD new file mode 100644 index 00000000..ec223f14 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/bazel/BUILD @@ -0,0 +1,5 @@ +cc_binary( + name = "main", + srcs = ["example.cpp"], + deps = ["@nlohmann_json//:json"], +) diff --git a/external/json/docs/mkdocs/docs/integration/bazel/WORKSPACE b/external/json/docs/mkdocs/docs/integration/bazel/WORKSPACE new file mode 100644 index 00000000..57ef2e10 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/bazel/WORKSPACE @@ -0,0 +1,7 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "nlohmann_json", + urls = ["https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz"], + strip_prefix = "json-3.11.3", +) diff --git a/external/json/docs/mkdocs/docs/integration/bazel/example.cpp b/external/json/docs/mkdocs/docs/integration/bazel/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/bazel/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/cget/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/cget/CMakeLists.txt new file mode 100644 index 00000000..e3fda5b9 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/cget/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(json_example) + +find_package(nlohmann_json REQUIRED) + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/cget/example.cpp b/external/json/docs/mkdocs/docs/integration/cget/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/cget/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/cmake.md b/external/json/docs/mkdocs/docs/integration/cmake.md index 545f53f3..df020319 100644 --- a/external/json/docs/mkdocs/docs/integration/cmake.md +++ b/external/json/docs/mkdocs/docs/integration/cmake.md @@ -119,9 +119,7 @@ automatically download a release as a dependency at configure type. ) ``` - 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 - . + However, the repository download size is quite large. ## CMake Options @@ -137,6 +135,9 @@ Enable CI build targets. The exact targets are used during the several CI steps Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This option is `OFF` by default. +### `JSON_Diagnostic_Positions` +Enable position diagnostics by defining macro [`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md). This option is off by default. + ### `JSON_DisableEnumSerialization` Disable default `enum` serialization by defining the macro diff --git a/external/json/docs/mkdocs/docs/integration/conan/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/conan/CMakeLists.txt index fd3e9ca7..e3fda5b9 100644 --- a/external/json/docs/mkdocs/docs/integration/conan/CMakeLists.txt +++ b/external/json/docs/mkdocs/docs/integration/conan/CMakeLists.txt @@ -1,9 +1,7 @@ +cmake_minimum_required(VERSION 3.15) project(json_example) -cmake_minimum_required(VERSION 2.8.12) -add_definitions("-std=c++11") -include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) -conan_basic_setup() +find_package(nlohmann_json REQUIRED) add_executable(json_example example.cpp) -target_link_libraries(json_example ${CONAN_LIBS}) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/conan/Conanfile.txt b/external/json/docs/mkdocs/docs/integration/conan/Conanfile.txt index a8a3e703..6dcd6141 100644 --- a/external/json/docs/mkdocs/docs/integration/conan/Conanfile.txt +++ b/external/json/docs/mkdocs/docs/integration/conan/Conanfile.txt @@ -1,5 +1,6 @@ [requires] -nlohmann_json/3.7.3 +nlohmann_json/3.11.3 [generators] -cmake +CMakeToolchain +CMakeDeps diff --git a/external/json/docs/mkdocs/docs/integration/conan/example.cpp b/external/json/docs/mkdocs/docs/integration/conan/example.cpp index e5a31be4..1a7ac4de 100644 --- a/external/json/docs/mkdocs/docs/integration/conan/example.cpp +++ b/external/json/docs/mkdocs/docs/integration/conan/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/external/json/docs/mkdocs/docs/integration/cpm/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/cpm/CMakeLists.txt new file mode 100644 index 00000000..c4f63401 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/cpm/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.15) +project(json_example) + +include(${CMAKE_SOURCE_DIR}/cmake/CPM.cmake) + +CPMAddPackage("gh:nlohmann/json@3.11.3") + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/cpm/example.cpp b/external/json/docs/mkdocs/docs/integration/cpm/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/cpm/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/homebrew/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/homebrew/CMakeLists.txt new file mode 100644 index 00000000..12f4ae1f --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/homebrew/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(json_example) + +find_package(nlohmann_json CONFIG REQUIRED) + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/homebrew/example.cpp b/external/json/docs/mkdocs/docs/integration/homebrew/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/homebrew/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/hunter/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/hunter/CMakeLists.txt new file mode 100644 index 00000000..4acc3258 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/hunter/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.15) + +include("cmake/HunterGate.cmake") +HunterGate( + URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz" + SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3" +) + +project(json_example) + +hunter_add_package(nlohmann_json) +find_package(nlohmann_json CONFIG REQUIRED) + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/hunter/example.cpp b/external/json/docs/mkdocs/docs/integration/hunter/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/hunter/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/macports/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/macports/CMakeLists.txt new file mode 100644 index 00000000..12f4ae1f --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/macports/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(json_example) + +find_package(nlohmann_json CONFIG REQUIRED) + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/macports/example.cpp b/external/json/docs/mkdocs/docs/integration/macports/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/macports/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/meson/example.cpp b/external/json/docs/mkdocs/docs/integration/meson/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/meson/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/meson/meson.build b/external/json/docs/mkdocs/docs/integration/meson/meson.build new file mode 100644 index 00000000..ec6d2343 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/meson/meson.build @@ -0,0 +1,12 @@ +project('json_example', 'cpp', + version: '1.0', + default_options: ['cpp_std=c++11'] +) + +dependency_json = dependency('nlohmann_json', required: true) + +executable('json_example', + sources: ['example.cpp'], + dependencies: [dependency_json], + install: true +) diff --git a/external/json/docs/mkdocs/docs/integration/nuget/nuget-package-content.png b/external/json/docs/mkdocs/docs/integration/nuget/nuget-package-content.png new file mode 100644 index 00000000..cc975b98 Binary files /dev/null and b/external/json/docs/mkdocs/docs/integration/nuget/nuget-package-content.png differ diff --git a/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-changes.png b/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-changes.png new file mode 100644 index 00000000..eb2a520a Binary files /dev/null and b/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-changes.png differ diff --git a/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-makefile.png b/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-makefile.png new file mode 100644 index 00000000..74657f26 Binary files /dev/null and b/external/json/docs/mkdocs/docs/integration/nuget/nuget-project-makefile.png differ diff --git a/external/json/docs/mkdocs/docs/integration/nuget/nuget-search-package.png b/external/json/docs/mkdocs/docs/integration/nuget/nuget-search-package.png new file mode 100644 index 00000000..da4c6e6d Binary files /dev/null and b/external/json/docs/mkdocs/docs/integration/nuget/nuget-search-package.png differ diff --git a/external/json/docs/mkdocs/docs/integration/nuget/nuget-select-package.png b/external/json/docs/mkdocs/docs/integration/nuget/nuget-select-package.png new file mode 100644 index 00000000..b80ebc7b Binary files /dev/null and b/external/json/docs/mkdocs/docs/integration/nuget/nuget-select-package.png differ diff --git a/external/json/docs/mkdocs/docs/integration/package_managers.md b/external/json/docs/mkdocs/docs/integration/package_managers.md index c9a273a5..964e8f8b 100644 --- a/external/json/docs/mkdocs/docs/integration/package_managers.md +++ b/external/json/docs/mkdocs/docs/integration/package_managers.md @@ -14,61 +14,178 @@ When executed, this program should create output similar to ## Homebrew -If you are using OS X and [Homebrew](http://brew.sh), just type +!!! abstract "Summary" + + formula: [**`nlohmann-json`**](https://formulae.brew.sh/formula/nlohmann-json) + + - :octicons-tag-24: Availalbe versions: current version and development version (with `--HEAD` parameter) + - :octicons-rocket-24: The formula is updated with every release. + - :octicons-person-24: Maintainer: Niels Lohmann + - :octicons-file-24: File issues at the [Homebrew issue tracker](https://github.com/Homebrew/homebrew-core/issues) + - :octicons-question-24: [Homebrew website](https://brew.sh) + +If you are using [Homebrew](http://brew.sh), you can install the library with ```sh brew install nlohmann-json ``` -and you're set. If you want the bleeding edge rather than the latest release, use +The header can be used directly in your code or via CMake. -```sh -brew install nlohmann-json --HEAD -``` - -instead. See [nlohmann-json](https://formulae.brew.sh/formula/nlohmann-json) for more information. - -??? example +??? example "Example: Raw compilation" 1. Create the following file: ```cpp title="example.cpp" - --8<-- "integration/example.cpp" + --8<-- "integration/homebrew/example.cpp" ``` - 2. Install the package + 2. Install the package: ```sh brew install nlohmann-json ``` - 3. Determine the include path, which defaults to `/usr/local/Cellar/nlohmann-json/$version/include`, where `$version` is the version of the library, e.g. `3.7.3`. The path of the library can be determined with + 3. Compile the code and pass the Homebrew prefix to the include path such that the library can be found: ```sh - brew list nlohmann-json + c++ example.cpp -I$(brew --prefix nlohmann-json)/include -std=c++11 -o example ``` - 4. Compile the code. For instance, the code can be compiled using Clang with +??? example "Example: CMake" + + 1. Create the following files: + + ```cpp title="example.cpp" + --8<-- "integration/homebrew/example.cpp" + ``` + + ```cmake title="CMakeLists.txt" + --8<-- "integration/homebrew/CMakeLists.txt" + ``` + + 2. Install the package: ```sh - clang++ example.cpp -I/usr/local/Cellar/nlohmann-json/3.7.3/include -std=c++11 -o example + brew install nlohmann-json ``` -:material-update: The [formula](https://formulae.brew.sh/formula/nlohmann-json) is updated automatically. + 3. Compile the code and pass the Homebrew prefix to CMake to find installed packages via `#!cmake find_package`: + + ```sh + CMAKE_PREFIX_PATH=$(brew --prefix) cmake -S . -B build + cmake --build build + ``` ## 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. +!!! abstract "Summary" -The provided `meson.build` can also be used as an alternative to cmake for installing `nlohmann_json` system-wide in which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` pkg-config dependency. In Meson, it is preferred to use the [`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than using the subproject directly. + wrap: **`nlohmann_json`** + + - :octicons-tag-24: Availalbe versions: current version and select older versions (see + [WrapDB](https://mesonbuild.com/Wrapdb-projects.html)) + - :octicons-rocket-24: The package is update automatically from file + [`meson.build`](https://github.com/nlohmann/json/blob/develop/meson.build). + - :octicons-file-24: File issues at the [library issue tracker](https://github.com/nlohmann/json/issues) + - :octicons-question-24: [Meson website](https://mesonbuild.com/index.html) + +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://mesonbuild.com/Wrapdb-projects.html), or simply +use + +```shell +meson wrap install nlohmann_json +``` + +Please see the Meson project for any issues regarding the packaging. + +The provided `meson.build` can also be used as an alternative to CMake for installing `nlohmann_json` system-wide in +which case a pkg-config file is installed. To use it, simply have your build system require the `nlohmann_json` +pkg-config dependency. In Meson, it is preferred to use the +[`dependency()`](https://mesonbuild.com/Reference-manual.html#dependency) object with a subproject fallback, rather than +using the subproject directly. + +??? example "Example: Wrap" + + 1. Create the following files: + + ```ini title="meson.build" + --8<-- "integration/meson/meson.build" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/meson/example.cpp" + ``` + + 2. Use the Meson WrapDB to fetch the nlohmann/json wrap: + + ```shell + mkdir subprojects + meson wrap install nlohmann_json + ``` + + 3. Build: + + ```shell + meson setup build + meson compile -C build + ``` ## Bazel -This repository provides a [Bazel](https://bazel.build/) `WORKSPACE.bazel` and a corresponding `BUILD.bazel` file. Therefore, this repository can be referenced by workspace rules such as `http_archive`, `git_repository`, or `local_repository` from other Bazel workspaces. To use the library you only need to depend on the target `@nlohmann_json//:json` (e.g. via `deps` attribute). +!!! abstract "Summary" + + use `http_archive`, `git_repository`, or `local_repository` + + - :octicons-tag-24: Any version, as version is specified in `WORKSPACE` file + - :octicons-file-24: File issues at the [library issue tracker](https://github.com/nlohmann/json/issues) + - :octicons-question-24: [Bazel website](https://bazel.build) + +This repository provides a [Bazel](https://bazel.build/) `WORKSPACE.bazel` and a corresponding `BUILD.bazel` file. Therefore, this +repository can be referenced by workspace rules such as `http_archive`, `git_repository`, or `local_repository` from +other Bazel workspaces. To use the library you only need to depend on the target `@nlohmann_json//:json` (e.g., via +`deps` attribute). + +??? example + + 1. Create the following files: + + ```ini title="BUILD" + --8<-- "integration/bazel/BUILD" + ``` + + ```ini title="WORKSPACE" + --8<-- "integration/bazel/WORKSPACE" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/bazel/example.cpp" + ``` + + 2. Build and run: + + ```shell + bazel build //:main + bazel run //:main + ``` ## Conan -If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `nlohmann_json/x.y.z` to your `conanfile`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/conan-io/conan-center-index/issues) if you experience problems with the packages. +!!! abstract "Summary" + + recipe: [**`nlohmann_json`**](https://conan.io/center/recipes/nlohmann_json) + + - :octicons-tag-24: Availalbe versions: current version and older versions (see + [Conan Center](https://conan.io/center/recipes/nlohmann_json)) + - :octicons-rocket-24: The package is update automatically via + [this recipe](https://github.com/conan-io/conan-center-index/tree/master/recipes/nlohmann_json). + - :octicons-file-24: File issues at the [Conan Center issue tracker](https://github.com/conan-io/conan-center-index/issues) + - :octicons-question-24: [Conan website](https://conan.io) + +If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `nlohmann_json/x.y.z` to your `conanfile`'s +requires, where `x.y.z` is the release version you want to use. ??? example @@ -86,33 +203,147 @@ If you are using [Conan](https://www.conan.io/) to manage your dependencies, mer --8<-- "integration/conan/example.cpp" ``` - 2. Build: + 2. Call Conan: ```sh - mkdir build - cd build - conan install .. - cmake .. - cmake --build . + conan install . --output-folder=build --build=missing ``` -:material-update: The [package](https://conan.io/center/nlohmann_json) is updated automatically. + 3. Build: + + ```sh + cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" -DCMAKE_BUILD_TYPE=Release + cmake --build build + ``` ## 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. +!!! abstract "Summary" + + package: [**`nlohmann-json`**](https://packages.spack.io/package.html?name=nlohmann-json) + + - :octicons-tag-24: Availalbe versions: current version and older versions (see + [Spack package](https://packages.spack.io/package.html?name=nlohmann-json)) + - :octicons-rocket-24: The package is updated with every release. + - :octicons-person-24: Maintainer: [Axel Huebl](https://github.com/ax3l) + - :octicons-file-24: File issues at the [Spack issue tracker](https://github.com/spack/spack/issues) + - :octicons-question-24: [Spack website](https://spack.io) + +If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the +[`nlohmann-json` package](https://packages.spack.io/package.html?name=nlohmann-json) via + +```shell +spack install nlohmann-json +``` + +Please see the [Spack project](https://github.com/spack/spack) for any issues regarding the packaging. + +??? example + + 1. Create the following files: + + ```cmake title="CMakeLists.txt" + --8<-- "integration/spack/CMakeLists.txt" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/spack/example.cpp" + ``` + + 2. Install the library: + + ```sh + spack install nlohmann-json + ``` + + 3. Load the environment for your Spack-installed packages: + + ```sh + spack load nlohmann-json + ``` + + 4. Build the project with CMake: + + ```sh + cmake -S . -B build -DCMAKE_PREFIX_PATH=$(spack location -i nlohmann-json) + cmake --build build + ``` ## Hunter -If you are using [hunter](https://github.com/cpp-pm/hunter) on your project for external dependencies, then you can use the [nlohmann_json package](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging. +!!! abstract "Summary" + + package: [**`nlohmann_json`**](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html) + + - :octicons-tag-24: Availalbe versions: current version and older versions (see + [Hunter package](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html)) + - :octicons-rocket-24: The package is updated with every release. + - :octicons-file-24: File issues at the [Hunter issue tracker](https://github.com/cpp-pm/hunter/issues) + - :octicons-question-24: [Hunter website](https://hunter.readthedocs.io/en/latest/) + +If you are using [Hunter](https://github.com/cpp-pm/hunter) on your project for external dependencies, then you can use +the [nlohmann_json package](https://hunter.readthedocs.io/en/latest/packages/pkg/nlohmann_json.html) via + +```cmake +hunter_add_package(nlohmann_json) +``` + +Please see the Hunter project for any issues regarding the packaging. + +??? example + + 1. Create the following files: + + ```cmake title="CMakeLists.txt" + --8<-- "integration/hunter/CMakeLists.txt" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/hunter/example.cpp" + ``` + + 2. Download required files + + ```shell + mkdir cmake + wget https://raw.githubusercontent.com/cpp-pm/gate/master/cmake/HunterGate.cmake -O cmake/HunterGate.cmake + ``` + + 3. Build the project with CMake: + + ```shell + cmake -S . -B build + cmake --build build + ``` ## Buckaroo -If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. Please file issues [here](https://github.com/buckaroo-pm/nlohmann-json). There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example). +If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example). + +!!! warning + + The module is outdated as the respective [repository](https://github.com/buckaroo-pm/nlohmann-json) has not been + updated in years. ## vcpkg -If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can install the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json) with `vcpkg install nlohmann-json` and follow the then displayed descriptions. Please see the vcpkg project for any issues regarding the packaging. +!!! abstract "Summary" + + package: [**`nlohmann-json`**](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json) + + - :octicons-tag-24: Availalbe versions: current version + - :octicons-rocket-24: The package is updated with every release. + - :octicons-file-24: File issues at the [vcpkg issue tracker](https://github.com/microsoft/vcpkg/issues) + - :octicons-question-24: [vcpkg website](https://vcpkg.io/) + +If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can +install the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json) with + +```shell +vcpkg install nlohmann-json +``` + +and follow the then displayed descriptions. Please see the vcpkg project for any issues regarding the packaging. ??? example @@ -135,19 +366,60 @@ If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project fo 3. Build: ```sh - mkdir build - cd build - cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake - cmake --build . + cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake + cmake --build build ``` - Note you need to adjust `/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake` to your system. - ## cget -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`). +!!! abstract "Summary" -:material-update: cget reads directly from the [GitHub repository](https://github.com/nlohmann/json) and is always up-to-date. + package: [**`nlohmann/json`**](https://github.com/pfultz2/cget-recipes/blob/master/recipes/nlohmann/json/package.txt) + + - :octicons-tag-24: Availalbe versions: current version and older versions + - :octicons-rocket-24: The package is updated with every release. + - :octicons-file-24: File issues at the [cget issue tracker](https://github.com/pfultz2/cget-recipes/issues) + - :octicons-question-24: [cget website](https://cget.readthedocs.io/) + +If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest `master` version with + +```shell +cget install nlohmann/json +``` + +A specific version can be installed with `cget install nlohmann/json@v3.11.3`. Also, the multiple header version can be +installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`). + +??? example + + 1. Create the following files: + + ```cmake title="CMakeLists.txt" + --8<-- "integration/vcpkg/CMakeLists.txt" + ``` + + ```cpp title="example.cpp" + --8<-- "integration/vcpkg/example.cpp" + ``` + + 2. Initialize cget + + ```shell + cget init + ``` + + 3. Install the library + + ```shell + cget install nlohmann/json + ``` + + 4. Build + + ```shell + cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cget/cget/cget.cmake + cmake --build build + ``` ## CocoaPods @@ -155,7 +427,136 @@ If you are using [CocoaPods](https://cocoapods.org), you can use the library by ## NuGet -If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/). Please check [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) on how to use the package. Please file issues [here](https://github.com/hnkb/nlohmann-json-nuget/issues). +!!! abstract "Summary" + + package: [**`nlohmann.json`**](https://www.nuget.org/packages/nlohmann.json/) + + - :octicons-tag-24: Availalbe versions: current and previous versions + - :octicons-rocket-24: The package is updated with every release. + - :octicons-person-24: Maintainer: [Hani Kaabi](https://github.com/hnkb) + - :octicons-file-24: File issues at the [maintainer's issue tracker](https://github.com/hnkb/nlohmann-json-nuget/issues) + - :octicons-question-24: [NuGet website](https://www.nuget.org) + +If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/) +with + +```shell +dotnet add package nlohmann.json +``` + +??? example + + Probably the easiest way to use NuGet packages is through Visual Studio graphical interface. Just right-click on a + project (any C++ project would do) in “Solution Explorer” and select “Manage NuGet Packages…” + + ![](nuget/nuget-search-package.png) + + Now you can click on “Browse” tab and find the package you like to install. + + ![](nuget/nuget-select-package.png) + + Most of the packages in NuGet gallery are .NET packages and would not be useful in a C++ project. Microsoft + recommends adding “native” and “nativepackage” tags to C++ NuGet packages to distinguish them, but even adding + “native” to search query would still show many .NET-only packages in the list. + + Nevertheless, after finding the package you want, just click on “Install” button and accept confirmation dialogs. + After the package is successfully added to the projects, you should be able to just build and execute the project + without the need for making any more changes to build settings. + + !!! note + + A few notes: + + - NuGet packages are installed per project and not system-wide. The header and binaries for the package are only + available to the project it is added to, and not other projects (obviously unless we add the package to those + projects as well) + - One of the many great things about your elegant work is that it is a header-only library, which makes + deployment very straightforward. In case of libraries which need binary deployment (`.lib`, `.dll` and `.pdb` + for debug info) the different binaries for each supported compiler version must be added to the NuGet package. + Some library creators cram binary versions for all supported Visual C++ compiler versions in the same package, + so a single package will support all compilers. Some others create a different package for each compiler + version (and you usually see things like “v140” or “vc141” in package name to clarify which VC++ compiler this + package supports). + - Packages can have dependency to other packages, and in this case, NuGet will install all dependencies as well + as the requested package recursively. + + **What happens behind the scenes** + + After you add a NuGet package, three changes occur in the project source directory. Of course, we could make these + changes manually instead of using GUI: + + ![](nuget/nuget-project-changes.png) + + 1. A `packages.config` file will be created (or updated to include the package name if one such file already + exists). This file contains a list of the packages required by this project (name and minimum version) and must + be added to the project source code repository, so if you move the source code to a new machine, MSBuild/NuGet + knows which packages it has to restore (which it does automatically before each build). + + ```xml + + + + + ``` + + 2. A `packages` folder which contains actual files in the packages (these are header and binary files required for + a successful build, plus a few metadata files). In case of this library for example, it contains `json.hpp`: + + ![](nuget/nuget-package-content.png) + + !!! note + + This directory should not be added to the project source code repository, as it will be restored before each + build by MSBuild/NuGet. If you go ahead and delete this folder, then build the project again, it will + magically re-appear! + + 3. Project MSBuild makefile (which for Visual C++ projects has a .vcxproj extension) will be updated to include + settings from the package. + + ![](nuget/nuget-project-makefile.png) + + The important bit for us here is line 170, which tells MSBuild to import settings from + `packages\nlohmann.json.3.5.0\build\native\nlohmann.json.targets` file. This is a file the package creator + created and added to the package (you can see it is one of the two files I created in this repository, the other + just contains package attributes like name and version number). What does it contain? + + For our header-only repository, the only setting we need is to add our include directory to the list of + `AdditionalIncludeDirectories`: + + ```xml + + + + + $(MSBuildThisFileDirectory)include;%(AdditionalIncludeDirectories) + + + + ``` + + For libraries with binary files, we will need to add `.lib` files to linker inputs and add settings to copy + `.dll` and other redistributable files to output directory, if needed. + + There are other changes to the makefile as well: + + - Lines 165-167 add the `packages.config` as one of project files (so it is shown in Solution Explorer tree + view). It is added as None (no build action) and removing it wouldn’t affect build. + + - Lines 172-177 check to ensure the required packages are present. This will display a build error if package + directory is empty (for example when NuGet cannot restore packages because Internet connection is down). + Again, if you omit this section, the only change in build would be a more cryptic error message if build + fails. + + !!! note + + Changes to .vcxproj makefile should also be added to project source code repository. + + As you can see, the mechanism NuGet uses to modify project settings is through MSBuild makefiles, so using NuGet + with other build systems and compilers (like CMake) as a dependency manager is either impossible or more problematic + than useful. + +Please refer to [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) for +more information. ## Conda @@ -169,9 +570,67 @@ If you are using [MSYS2](http://www.msys2.org/), you can use the [mingw-w64-nloh ## 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. +!!! abstract "Summary" -:material-update: The [package](https://ports.macports.org/port/nlohmann-json/) is updated automatically. + port: [**`nlohmann-json`**](https://ports.macports.org/port/nlohmann-json/) + + - :octicons-tag-24: Availalbe versions: current version + - :octicons-rocket-24: The port is updated with every release. + - :octicons-file-24: File issues at the [MacPorts issue tracker](https://trac.macports.org/newticket?port=nlohmann-json) + - :octicons-question-24: [MacPorts website](https://www.macports.org) + +If you are using [MacPorts](https://ports.macports.org), execute + +```shell +sudo port install nlohmann-json +``` + +to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) package. + +??? example "Example: Raw compilation" + + 1. Create the following file: + + ```cpp title="example.cpp" + --8<-- "integration/macports/example.cpp" + ``` + + 2. Install the package: + + ```sh + sudo port install nlohmann-json + ``` + + 3. Compile the code and pass the Homebrew prefix to the include path such that the library can be found: + + ```sh + c++ example.cpp -I/opt/local/include -std=c++11 -o example + ``` + +??? example "Example: CMake" + + 1. Create the following files: + + ```cpp title="example.cpp" + --8<-- "integration/homebrew/example.cpp" + ``` + + ```cmake title="CMakeLists.txt" + --8<-- "integration/homebrew/CMakeLists.txt" + ``` + + 2. Install the package: + + ```sh + sudo port install nlohmann-json + ``` + + 3. Compile the code: + + ```sh + cmake -S . -B build + cmake --build build + ``` ## build2 @@ -188,11 +647,44 @@ If you are using [`wsjcpp`](http://wsjcpp.org), you can use the command `wsjcpp ## 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: +!!! abstract "Summary" + + package: **`gh:nlohmann/json`** + + - :octicons-tag-24: Availalbe versions: current and previous versions + - :octicons-rocket-24: The package is updated with every release. + - :octicons-file-24: File issues at the [CPM.cmake issue tracker](https://github.com/cpm-cmake/CPM.cmake/issues) + - :octicons-question-24: [CPM.cmake website](https://github.com/cpm-cmake/CPM.cmake) + +If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), add the +[CPM.cmake script](https://github.com/TheLartians/CPM.cmake#adding-cpm) and the following snippet to your CMake project: ```cmake -CPMAddPackage( - NAME nlohmann_json - GITHUB_REPOSITORY nlohmann/json - VERSION 3.9.1) +CPMAddPackage("gh:nlohmann/json@3.11.3") ``` + +??? example + + 1. Create the following files: + + ```cpp title="example.cpp" + --8<-- "integration/cpm/example.cpp" + ``` + + ```cmake title="CMakeLists.txt" + --8<-- "integration/cpm/CMakeLists.txt" + ``` + + 2. Download CPM.cmake + + ```shell + mkdir -p cmake + wget -O cmake/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake + ``` + + 3. Build + + ```shell + cmake -S . -B build + cmake --build build + ``` diff --git a/external/json/docs/mkdocs/docs/integration/spack/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/spack/CMakeLists.txt new file mode 100644 index 00000000..e3fda5b9 --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/spack/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(json_example) + +find_package(nlohmann_json REQUIRED) + +add_executable(json_example example.cpp) +target_link_libraries(json_example PRIVATE nlohmann_json::nlohmann_json) diff --git a/external/json/docs/mkdocs/docs/integration/spack/example.cpp b/external/json/docs/mkdocs/docs/integration/spack/example.cpp new file mode 100644 index 00000000..1a7ac4de --- /dev/null +++ b/external/json/docs/mkdocs/docs/integration/spack/example.cpp @@ -0,0 +1,10 @@ +#include +#include +#include + +using json = nlohmann::json; + +int main() +{ + std::cout << std::setw(4) << json::meta() << std::endl; +} diff --git a/external/json/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt b/external/json/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt index d31f4e83..12f4ae1f 100644 --- a/external/json/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt +++ b/external/json/docs/mkdocs/docs/integration/vcpkg/CMakeLists.txt @@ -1,5 +1,5 @@ +cmake_minimum_required(VERSION 3.15) project(json_example) -cmake_minimum_required(VERSION 2.8.12) find_package(nlohmann_json CONFIG REQUIRED) diff --git a/external/json/docs/mkdocs/docs/integration/vcpkg/example.cpp b/external/json/docs/mkdocs/docs/integration/vcpkg/example.cpp index e5a31be4..1a7ac4de 100644 --- a/external/json/docs/mkdocs/docs/integration/vcpkg/example.cpp +++ b/external/json/docs/mkdocs/docs/integration/vcpkg/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/external/json/docs/mkdocs/mkdocs.yml b/external/json/docs/mkdocs/mkdocs.yml index 5e66db59..7b094153 100644 --- a/external/json/docs/mkdocs/mkdocs.yml +++ b/external/json/docs/mkdocs/mkdocs.yml @@ -9,7 +9,7 @@ repo_url: https://github.com/nlohmann/json edit_uri: edit/develop/docs/mkdocs/docs # Copyright -copyright: Copyright © 2013 - 2023 Niels Lohmann +copyright: Copyright © 2013 - 2024 Niels Lohmann # Configuration theme: @@ -30,7 +30,8 @@ theme: toggle: icon: material/brightness-4 name: Switch to light mode - + icon: + repo: fontawesome/brands/github font: text: Roboto code: JetBrains Mono @@ -41,6 +42,8 @@ theme: - navigation.indexes - navigation.top - content.tabs.link + - content.action.edit + - content.action.view nav: - Home: @@ -51,6 +54,7 @@ nav: - home/exceptions.md - home/releases.md - home/design_goals.md + - home/customers.md - home/sponsors.md - Features: - features/arbitrary_types.md @@ -281,10 +285,18 @@ nav: - 'JSON_USE_GLOBAL_UDLS': api/macros/json_use_global_udls.md - 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md - 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON': api/macros/json_use_legacy_discarded_value_comparison.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE': api/macros/nlohmann_define_derived_type.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_derived_type.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_derived_type.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_derived_type.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_derived_type.md + - 'NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_derived_type.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_INTRUSIVE_ONLY_SERIALIZE': 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_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_type_non_intrusive.md - 'NLOHMANN_JSON_NAMESPACE': api/macros/nlohmann_json_namespace.md - 'NLOHMANN_JSON_NAMESPACE_BEGIN': api/macros/nlohmann_json_namespace_begin.md - 'NLOHMANN_JSON_NAMESPACE_END': api/macros/nlohmann_json_namespace_begin.md @@ -299,8 +311,6 @@ extra: social: - icon: fontawesome/brands/github link: https://github.com/nlohmann - - icon: fontawesome/brands/twitter - link: https://twitter.com/nlohmann - icon: fontawesome/brands/linkedin link: https://www.linkedin.com/in/nielslohmann/ - icon: fontawesome/brands/xing @@ -332,7 +342,11 @@ markdown_extensions: - pymdownx.magiclink - pymdownx.mark #- pymdownx.smartsymbols - - pymdownx.superfences + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.tasklist: custom_checkbox: true - pymdownx.tabbed: @@ -341,23 +355,21 @@ markdown_extensions: - pymdownx.snippets: base_path: docs check_paths: true - - plantuml_markdown: - format: svg plugins: - - search: - separator: '[\s\-\.]' - lang: en - - minify: - minify_html: true - - git-revision-date-localized - - redirects: - redirect_maps: - 'api/basic_json/operator_gtgt.md': api/operator_gtgt.md - 'api/basic_json/operator_ltlt.md': api/operator_ltlt.md - 'api/basic_json/operator_literal_json.md': api/operator_literal_json.md - 'api/basic_json/operator_literal_json_pointer.md': api/operator_literal_json_pointer.md - 'api/json_pointer/operator_string.md': api/json_pointer/operator_string_t.md + - search: + separator: '[\s\-\.]' + lang: en + - minify: + minify_html: true + - git-revision-date-localized + - redirects: + redirect_maps: + 'api/basic_json/operator_gtgt.md': api/operator_gtgt.md + 'api/basic_json/operator_ltlt.md': api/operator_ltlt.md + 'api/basic_json/operator_literal_json.md': api/operator_literal_json.md + 'api/basic_json/operator_literal_json_pointer.md': api/operator_literal_json_pointer.md + 'api/json_pointer/operator_string.md': api/json_pointer/operator_string_t.md extra_css: - css/custom.css diff --git a/external/json/docs/mkdocs/requirements.txt b/external/json/docs/mkdocs/requirements.txt index b397d545..45aa14ab 100644 --- a/external/json/docs/mkdocs/requirements.txt +++ b/external/json/docs/mkdocs/requirements.txt @@ -1,49 +1,6 @@ -Babel==2.13.1 -certifi==2023.7.22 -charset-normalizer==3.3.1 -click==8.1.7 -csscompressor==0.9.5 -future==0.18.3 -ghp-import==2.1.0 -gitdb==4.0.11 -GitPython==3.1.40 -htmlmin==0.1.12 -httplib2==0.22.0 -idna==3.4 -importlib-metadata==6.8.0 -Jinja2==3.1.2 -joblib==1.3.2 -jsmin==3.0.1 -livereload==2.6.3 -lunr==0.7.0.post1 -Markdown==3.5 -markdown-include==0.8.1 -MarkupSafe==2.1.3 -mergedeep==1.3.4 -mkdocs==1.5.3 -mkdocs-git-revision-date-localized-plugin==1.2.1 -mkdocs-material==9.4.7 -mkdocs-material-extensions==1.3 -mkdocs-minify-plugin==0.7.1 -mkdocs-redirects==1.2.1 -mkdocs-simple-hooks==0.1.5 -nltk==3.8.1 -packaging==23.2 -plantuml==0.3.0 -plantuml-markdown==3.9.2 -Pygments==2.16.1 -pymdown-extensions==10.3.1 -pyparsing==3.1.1 -python-dateutil==2.8.2 -pytz==2023.3.post1 -PyYAML==6.0.1 -pyyaml_env_tag==0.1 -regex==2023.10.3 -requests==2.31.0 -six==1.16.0 -smmap==5.0.1 -tornado==6.3.3 -tqdm==4.66.1 -urllib3==2.0.7 -watchdog==3.0.0 -zipp==3.17.0 +mkdocs==1.6.1 # documentation framework +mkdocs-git-revision-date-localized-plugin==1.3.0 # plugin "git-revision-date-localized" +mkdocs-material==9.5.49 # theme for mkdocs +mkdocs-material-extensions==1.3.1 # extensions +mkdocs-minify-plugin==0.8.0 # plugin "minify" +mkdocs-redirects==1.2.2 # plugin "redirects" diff --git a/external/json/include/nlohmann/adl_serializer.hpp b/external/json/include/nlohmann/adl_serializer.hpp index 56a606c0..a441ad4d 100644 --- a/external/json/include/nlohmann/adl_serializer.hpp +++ b/external/json/include/nlohmann/adl_serializer.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/byte_container_with_subtype.hpp b/external/json/include/nlohmann/byte_container_with_subtype.hpp index 91382cd6..08ac658c 100644 --- a/external/json/include/nlohmann/byte_container_with_subtype.hpp +++ b/external/json/include/nlohmann/byte_container_with_subtype.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/abi_macros.hpp b/external/json/include/nlohmann/detail/abi_macros.hpp index f48b9eb1..baa2762d 100644 --- a/external/json/include/nlohmann/detail/abi_macros.hpp +++ b/external/json/include/nlohmann/detail/abi_macros.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -26,6 +26,10 @@ #define JSON_DIAGNOSTICS 0 #endif +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif @@ -36,6 +40,12 @@ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #endif +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #else @@ -47,14 +57,15 @@ #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ diff --git a/external/json/include/nlohmann/detail/conversions/from_json.hpp b/external/json/include/nlohmann/detail/conversions/from_json.hpp index aa2f0cbf..362383a9 100644 --- a/external/json/include/nlohmann/detail/conversions/from_json.hpp +++ b/external/json/include/nlohmann/detail/conversions/from_json.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -13,6 +13,9 @@ #include // forward_list #include // inserter, front_inserter, end #include // map +#ifdef JSON_HAS_CPP_17 + #include // optional +#endif #include // string #include // tuple, make_tuple #include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible @@ -43,6 +46,24 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) n = nullptr; } +#ifdef JSON_HAS_CPP_17 +#ifndef JSON_USE_IMPLICIT_CONVERSIONS +template +void from_json(const BasicJsonType& j, std::optional& opt) +{ + if (j.is_null()) + { + opt = std::nullopt; + } + else + { + opt.emplace(j.template get()); + } +} + +#endif // JSON_USE_IMPLICIT_CONVERSIONS +#endif // JSON_HAS_CPP_17 + // overloads for basic_json template parameters template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic::value&& @@ -190,6 +211,54 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines } } +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + arr[i1][i2] = j.at(i1).at(i2).template get(); + } + } +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + for (std::size_t i3 = 0; i3 < N3; ++i3) + { + arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get(); + } + } + } +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + for (std::size_t i3 = 0; i3 < N3; ++i3) + { + for (std::size_t i4 = 0; i4 < N4; ++i4) + { + arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get(); + } + } + } + } +} + template inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { @@ -275,7 +344,7 @@ void()) template < typename BasicJsonType, typename T, std::size_t... Idx > std::array from_json_inplace_array_impl(BasicJsonType&& j, - identity_tag> /*unused*/, index_sequence /*unused*/) + identity_tag> /*unused*/, index_sequence /*unused*/) { return { { std::forward(j).at(Idx).template get()... } }; } diff --git a/external/json/include/nlohmann/detail/conversions/to_chars.hpp b/external/json/include/nlohmann/detail/conversions/to_chars.hpp index e10741c9..b6514d12 100644 --- a/external/json/include/nlohmann/detail/conversions/to_chars.hpp +++ b/external/json/include/nlohmann/detail/conversions/to_chars.hpp @@ -4,7 +4,7 @@ // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2009 Florian Loitsch -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -239,10 +239,10 @@ boundaries compute_boundaries(FloatType value) // v- m- v m+ v+ const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1); const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) + ? diyfp((4 * v.f) - 1, v.e - 2) // (B) + : diyfp((2 * v.f) - 1, v.e - 1); // (A) // Determine the normalized w+ = m+. const diyfp w_plus = diyfp::normalize(m_plus); @@ -472,7 +472,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e) JSON_ASSERT(e >= -1500); JSON_ASSERT(e <= 1500); const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + const int k = ((f * 78913) / (1 << 18)) + static_cast(f > 0); const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; JSON_ASSERT(index >= 0); @@ -950,15 +950,15 @@ inline char* append_exponent(char* buf, int e) } else if (k < 100) { - *buf++ = static_cast('0' + k / 10); + *buf++ = static_cast('0' + (k / 10)); k %= 10; *buf++ = static_cast('0' + k); } else { - *buf++ = static_cast('0' + k / 100); + *buf++ = static_cast('0' + (k / 100)); k %= 100; - *buf++ = static_cast('0' + k / 10); + *buf++ = static_cast('0' + (k / 10)); k %= 10; *buf++ = static_cast('0' + k); } diff --git a/external/json/include/nlohmann/detail/conversions/to_json.hpp b/external/json/include/nlohmann/detail/conversions/to_json.hpp index e39b7797..ec20cd7d 100644 --- a/external/json/include/nlohmann/detail/conversions/to_json.hpp +++ b/external/json/include/nlohmann/detail/conversions/to_json.hpp @@ -3,11 +3,16 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once +#include // JSON_HAS_CPP_17 +#ifdef JSON_HAS_CPP_17 + #include // optional +#endif + #include // copy #include // begin, end #include // string @@ -18,7 +23,6 @@ #include // vector #include -#include #include #include #include @@ -260,6 +264,22 @@ struct external_constructor // to_json // ///////////// +#ifdef JSON_HAS_CPP_17 +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::optional& opt) +{ + if (opt.has_value()) + { + j = *opt; + } + else + { + j = nullptr; + } +} +#endif + template::value, int> = 0> inline void to_json(BasicJsonType& j, T b) noexcept @@ -320,7 +340,8 @@ template::type; - external_constructor::construct(j, static_cast(e)); + static constexpr value_t integral_value_t = std::is_unsigned::value ? value_t::number_unsigned : value_t::number_integer; + external_constructor::construct(j, static_cast(e)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION diff --git a/external/json/include/nlohmann/detail/exceptions.hpp b/external/json/include/nlohmann/detail/exceptions.hpp index 5974d7be..1fabeb16 100644 --- a/external/json/include/nlohmann/detail/exceptions.hpp +++ b/external/json/include/nlohmann/detail/exceptions.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -25,6 +25,18 @@ #include #include +// With -Wweak-vtables, Clang will complain about the exception classes as they +// have no out-of-line virtual method definitions and their vtable will be +// emitted in every translation unit. This issue cannot be fixed with a +// header-only library as there is no implementation file to move these +// functions to. As a result, we suppress this warning here to avoid client +// code to stumble over this. See https://github.com/nlohmann/json/issues/4087 +// for a discussion. +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wweak-vtables" +#endif + NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -255,3 +267,7 @@ class other_error : public exception } // namespace detail NLOHMANN_JSON_NAMESPACE_END + +#if defined(__clang__) + #pragma clang diagnostic pop +#endif diff --git a/external/json/include/nlohmann/detail/hash.hpp b/external/json/include/nlohmann/detail/hash.hpp index 4464e8e6..cfe4ccba 100644 --- a/external/json/include/nlohmann/detail/hash.hpp +++ b/external/json/include/nlohmann/detail/hash.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/input/binary_reader.hpp b/external/json/include/nlohmann/detail/input/binary_reader.hpp index a6e100e7..75babd55 100644 --- a/external/json/include/nlohmann/detail/input/binary_reader.hpp +++ b/external/json/include/nlohmann/detail/input/binary_reader.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -20,6 +20,9 @@ #include // char_traits, string #include // make_pair, move #include // vector +#ifdef __cpp_lib_byteswap + #include //byteswap +#endif #include #include @@ -62,7 +65,7 @@ static inline bool little_endianness(int num = 1) noexcept /*! @brief deserialization of CBOR, MessagePack, and UBJSON values */ -template> +template> class binary_reader { using number_integer_t = typename BasicJsonType::number_integer_t; @@ -169,7 +172,7 @@ class binary_reader std::int32_t document_size{}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -391,7 +394,7 @@ class binary_reader std::int32_t document_size{}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } @@ -651,7 +654,7 @@ class binary_reader } case 0x9F: // array (indefinite length) - return get_cbor_array(static_cast(-1), tag_handler); + return get_cbor_array(detail::unknown_size(), tag_handler); // map (0x00..0x17 pairs of data items follow) case 0xA0: @@ -705,7 +708,7 @@ class binary_reader } case 0xBF: // map (indefinite length) - return get_cbor_object(static_cast(-1), tag_handler); + return get_cbor_object(detail::unknown_size(), tag_handler); case 0xC6: // tagged item case 0xC7: @@ -1093,7 +1096,7 @@ class binary_reader } /*! - @param[in] len the length of the array or static_cast(-1) for an + @param[in] len the length of the array or detail::unknown_size() for an array of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed @@ -1106,7 +1109,7 @@ class binary_reader return false; } - if (len != static_cast(-1)) + if (len != detail::unknown_size()) { for (std::size_t i = 0; i < len; ++i) { @@ -1131,7 +1134,7 @@ class binary_reader } /*! - @param[in] len the length of the object or static_cast(-1) for an + @param[in] len the length of the object or detail::unknown_size() for an object of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed @@ -1147,7 +1150,7 @@ class binary_reader if (len != 0) { string_t key; - if (len != static_cast(-1)) + if (len != detail::unknown_size()) { for (std::size_t i = 0; i < len; ++i) { @@ -2565,7 +2568,7 @@ class binary_reader } else { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } @@ -2643,7 +2646,7 @@ class binary_reader } else { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -2754,6 +2757,29 @@ class binary_reader return current = ia.get_character(); } + /*! + @brief get_to read into a primitive type + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns false instead + + @return bool, whether the read was successful + */ + template + bool get_to(T& dest, const input_format_t format, const char* context) + { + auto new_chars_read = ia.get_elements(&dest); + chars_read += new_chars_read; + if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T))) + { + // in case of failure, advance position by 1 to report failing location + ++chars_read; + sax->parse_error(chars_read, "", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + return false; + } + return true; + } + /*! @return character read from the input after ignoring all 'N' entries */ @@ -2768,6 +2794,28 @@ class binary_reader return current; } + template + static void byte_swap(NumberType& number) + { + constexpr std::size_t sz = sizeof(number); +#ifdef __cpp_lib_byteswap + if constexpr (sz == 1) + { + return; + } + if constexpr(std::is_integral_v) + { + number = std::byteswap(number); + return; + } +#endif + auto* ptr = reinterpret_cast(&number); + for (std::size_t i = 0; i < sz / 2; ++i) + { + std::swap(ptr[i], ptr[sz - i - 1]); + } + } + /* @brief read a number from the input @@ -2786,29 +2834,16 @@ class binary_reader template bool get_number(const input_format_t format, NumberType& result) { - // step 1: read input into array with system's byte order - std::array vec{}; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) + // read in the original format + + if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; - } - - // reverse byte order prior to conversion if necessary - if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } + return false; + } + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) + { + byte_swap(result); } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); return true; } @@ -2947,7 +2982,7 @@ class binary_reader } private: - static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); + static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size(); /// input adapter InputAdapterType ia; diff --git a/external/json/include/nlohmann/detail/input/input_adapters.hpp b/external/json/include/nlohmann/detail/input/input_adapters.hpp index 33fca3e4..1fb132d3 100644 --- a/external/json/include/nlohmann/detail/input/input_adapters.hpp +++ b/external/json/include/nlohmann/detail/input/input_adapters.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -23,6 +23,7 @@ #include // istream #endif // JSON_NO_IO +#include #include #include #include @@ -67,6 +68,13 @@ class file_input_adapter return std::fgetc(m_file); } + // returns the number of characters successfully read + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + return fread(dest, 1, sizeof(T) * count, m_file); + } + private: /// the file pointer to read from std::FILE* m_file; @@ -126,6 +134,17 @@ class input_stream_adapter return res; } + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + auto res = static_cast(sb->sgetn(reinterpret_cast(dest), static_cast(count * sizeof(T)))); + if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T))) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + private: /// the associated input stream std::istream* is = nullptr; @@ -157,6 +176,26 @@ class iterator_input_adapter return char_traits::eof(); } + // for general iterators, we cannot really do something better than falling back to processing the range one-by-one + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + auto* ptr = reinterpret_cast(dest); + for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index) + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + ptr[read_index] = static_cast(*current); + std::advance(current, 1); + } + else + { + return read_index; + } + } + return count * sizeof(T); + } + private: IteratorType current; IteratorType end; @@ -320,6 +359,13 @@ class wide_string_input_adapter return utf8_bytes[utf8_bytes_index++]; } + // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here + template + std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1) + { + JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr)); + } + private: BaseInputAdapter base_adapter; @@ -416,10 +462,17 @@ typename container_input_adapter_factory_impl::container_input_adapter_factory::create(container); } +// specialization for std::string +using string_input_adapter_type = decltype(input_adapter(std::declval())); + #ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { + if (file == nullptr) + { + JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); + } return file_input_adapter(file); } @@ -446,9 +499,13 @@ template < typename CharT, int >::type = 0 > contiguous_bytes_input_adapter input_adapter(CharT b) { + if (b == nullptr) + { + JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); + } auto length = std::strlen(reinterpret_cast(b)); const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); + return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck] } template diff --git a/external/json/include/nlohmann/detail/input/json_sax.hpp b/external/json/include/nlohmann/detail/input/json_sax.hpp index c772521c..2386d8ef 100644 --- a/external/json/include/nlohmann/detail/input/json_sax.hpp +++ b/external/json/include/nlohmann/detail/input/json_sax.hpp @@ -3,20 +3,21 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include #include // string +#include // enable_if_t #include // move #include // vector #include +#include #include #include - NLOHMANN_JSON_NAMESPACE_BEGIN /*! @@ -144,6 +145,11 @@ struct json_sax namespace detail { +constexpr std::size_t unknown_size() +{ + return (std::numeric_limits::max)(); +} + /*! @brief SAX implementation to create a JSON value from SAX events @@ -157,7 +163,7 @@ constructor contains the parsed value. @tparam BasicJsonType the JSON type */ -template +template class json_sax_dom_parser { public: @@ -166,14 +172,15 @@ class json_sax_dom_parser using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; + using lexer_t = lexer; /*! @param[in,out] r reference to a JSON value that is manipulated while parsing @param[in] allow_exceptions_ whether parse errors yield exceptions */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr) + : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) {} // make class move-only @@ -229,7 +236,18 @@ class json_sax_dom_parser { ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the object here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the object, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) { JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); } @@ -252,6 +270,14 @@ class json_sax_dom_parser JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(ref_stack.back()->is_object()); +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing brace, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; @@ -261,7 +287,16 @@ class json_sax_dom_parser { ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the array here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) { JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); } @@ -274,6 +309,14 @@ class json_sax_dom_parser JSON_ASSERT(!ref_stack.empty()); JSON_ASSERT(ref_stack.back()->is_array()); +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing bracket, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + ref_stack.back()->set_parents(); ref_stack.pop_back(); return true; @@ -298,6 +341,75 @@ class json_sax_dom_parser } private: + +#if JSON_DIAGNOSTIC_POSITIONS + void handle_diagnostic_positions_for_json_value(BasicJsonType& v) + { + if (m_lexer_ref) + { + // Lexer has read past the current field value, so set the end position to the current position. + // The start position will be set below based on the length of the string representation + // of the value. + v.end_position = m_lexer_ref->get_position(); + + switch (v.type()) + { + case value_t::boolean: + { + // 4 and 5 are the string length of "true" and "false" + v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5); + break; + } + + case value_t::null: + { + // 4 is the string length of "null" + v.start_position = v.end_position - 4; + break; + } + + case value_t::string: + { + // include the length of the quotes, which is 2 + v.start_position = v.end_position - v.m_data.m_value.string->size() - 2; + break; + } + + // As we handle the start and end positions for values created during parsing, + // we do not expect the following value type to be called. Regardless, set the positions + // in case this is created manually or through a different constructor. Exclude from lcov + // since the exact condition of this switch is esoteric. + // LCOV_EXCL_START + case value_t::discarded: + { + v.end_position = std::string::npos; + v.start_position = v.end_position; + break; + } + // LCOV_EXCL_STOP + case value_t::binary: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + { + v.start_position = v.end_position - m_lexer_ref->get_string().size(); + break; + } + case value_t::object: + case value_t::array: + { + // object and array are handled in start_object() and start_array() handlers + // skip setting the values here. + break; + } + default: // LCOV_EXCL_LINE + // Handle all possible types discretely, default handler should never be reached. + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE + } + } + } +#endif + /*! @invariant If the ref stack is empty, then the passed value will be the new root. @@ -311,6 +423,11 @@ class json_sax_dom_parser if (ref_stack.empty()) { root = BasicJsonType(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(root); +#endif + return &root; } @@ -319,12 +436,22 @@ class json_sax_dom_parser if (ref_stack.back()->is_array()) { ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back()); +#endif + return &(ref_stack.back()->m_data.m_value.array->back()); } JSON_ASSERT(ref_stack.back()->is_object()); JSON_ASSERT(object_element); *object_element = BasicJsonType(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(*object_element); +#endif + return object_element; } @@ -338,9 +465,11 @@ class json_sax_dom_parser bool errored = false; /// whether to throw exceptions in case of errors const bool allow_exceptions = true; + /// the lexer reference to obtain the current position + lexer_t* m_lexer_ref = nullptr; }; -template +template class json_sax_dom_callback_parser { public: @@ -351,11 +480,13 @@ class json_sax_dom_callback_parser using binary_t = typename BasicJsonType::binary_t; using parser_callback_t = typename BasicJsonType::parser_callback_t; using parse_event_t = typename BasicJsonType::parse_event_t; + using lexer_t = lexer; json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) + parser_callback_t cb, + const bool allow_exceptions_ = true, + lexer_t* lexer_ = nullptr) + : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) { keep_stack.push_back(true); } @@ -418,12 +549,26 @@ class json_sax_dom_callback_parser auto val = handle_value(BasicJsonType::value_t::object, true); ref_stack.push_back(val.second); - // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + if (ref_stack.back()) { - JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); - } +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the object here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the object, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + // check object limit + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + } + } return true; } @@ -452,9 +597,23 @@ class json_sax_dom_callback_parser { // discard object *ref_stack.back() = discarded; + +#if JSON_DIAGNOSTIC_POSITIONS + // Set start/end positions for discarded object. + handle_diagnostic_positions_for_json_value(*ref_stack.back()); +#endif } else { + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing brace, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + ref_stack.back()->set_parents(); } } @@ -488,10 +647,25 @@ class json_sax_dom_callback_parser auto val = handle_value(BasicJsonType::value_t::array, true); ref_stack.push_back(val.second); - // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) + if (ref_stack.back()) { - JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the array here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the array, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + // check array limit + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + } } return true; @@ -506,12 +680,26 @@ class json_sax_dom_callback_parser keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); if (keep) { + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing bracket, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + ref_stack.back()->set_parents(); } else { // discard array *ref_stack.back() = discarded; + +#if JSON_DIAGNOSTIC_POSITIONS + // Set start/end positions for discarded array. + handle_diagnostic_positions_for_json_value(*ref_stack.back()); +#endif } } @@ -548,6 +736,71 @@ class json_sax_dom_callback_parser } private: + +#if JSON_DIAGNOSTIC_POSITIONS + void handle_diagnostic_positions_for_json_value(BasicJsonType& v) + { + if (m_lexer_ref) + { + // Lexer has read past the current field value, so set the end position to the current position. + // The start position will be set below based on the length of the string representation + // of the value. + v.end_position = m_lexer_ref->get_position(); + + switch (v.type()) + { + case value_t::boolean: + { + // 4 and 5 are the string length of "true" and "false" + v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5); + break; + } + + case value_t::null: + { + // 4 is the string length of "null" + v.start_position = v.end_position - 4; + break; + } + + case value_t::string: + { + // include the length of the quotes, which is 2 + v.start_position = v.end_position - v.m_data.m_value.string->size() - 2; + break; + } + + case value_t::discarded: + { + v.end_position = std::string::npos; + v.start_position = v.end_position; + break; + } + + case value_t::binary: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + { + v.start_position = v.end_position - m_lexer_ref->get_string().size(); + break; + } + + case value_t::object: + case value_t::array: + { + // object and array are handled in start_object() and start_array() handlers + // skip setting the values here. + break; + } + default: // LCOV_EXCL_LINE + // Handle all possible types discretely, default handler should never be reached. + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE + } + } + } +#endif + /*! @param[in] v value to add to the JSON value we build during parsing @param[in] skip_callback whether we should skip calling the callback @@ -578,6 +831,10 @@ class json_sax_dom_callback_parser // create value auto value = BasicJsonType(std::forward(v)); +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(value); +#endif + // check callback const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); @@ -632,9 +889,9 @@ class json_sax_dom_callback_parser /// stack to model hierarchy of values std::vector ref_stack {}; /// stack to manage which values to keep - std::vector keep_stack {}; + std::vector keep_stack {}; // NOLINT(readability-redundant-member-init) /// stack to manage which object keys to keep - std::vector key_keep_stack {}; + std::vector key_keep_stack {}; // NOLINT(readability-redundant-member-init) /// helper to hold the reference for the next object element BasicJsonType* object_element = nullptr; /// whether a syntax error occurred @@ -645,6 +902,8 @@ class json_sax_dom_callback_parser const bool allow_exceptions = true; /// a discarded value for the callback BasicJsonType discarded = BasicJsonType::value_t::discarded; + /// the lexer reference to obtain the current position + lexer_t* m_lexer_ref = nullptr; }; template @@ -692,7 +951,7 @@ class json_sax_acceptor return true; } - bool start_object(std::size_t /*unused*/ = static_cast(-1)) + bool start_object(std::size_t /*unused*/ = detail::unknown_size()) { return true; } @@ -707,7 +966,7 @@ class json_sax_acceptor return true; } - bool start_array(std::size_t /*unused*/ = static_cast(-1)) + bool start_array(std::size_t /*unused*/ = detail::unknown_size()) { return true; } diff --git a/external/json/include/nlohmann/detail/input/lexer.hpp b/external/json/include/nlohmann/detail/input/lexer.hpp index 4b3bf77d..6696b5a8 100644 --- a/external/json/include/nlohmann/detail/input/lexer.hpp +++ b/external/json/include/nlohmann/detail/input/lexer.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -967,7 +967,7 @@ class lexer : public lexer_base locale's decimal point is used instead of `.` to work with the locale-dependent converters. */ - token_type scan_number() // lgtm [cpp/use-of-goto] + token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated. { // reset token_buffer to store the number's bytes reset(); @@ -1049,6 +1049,7 @@ scan_number_zero: case '.': { add(decimal_point_char); + decimal_point_position = token_buffer.size() - 1; goto scan_number_decimal1; } @@ -1085,6 +1086,7 @@ scan_number_any1: case '.': { add(decimal_point_char); + decimal_point_position = token_buffer.size() - 1; goto scan_number_decimal1; } @@ -1256,7 +1258,7 @@ scan_number_done: // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) + if (errno != ERANGE) { value_unsigned = static_cast(x); if (value_unsigned == x) @@ -1272,7 +1274,7 @@ scan_number_done: // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) + if (errno != ERANGE) { value_integer = static_cast(x); if (value_integer == x) @@ -1322,6 +1324,7 @@ scan_number_done: { token_buffer.clear(); token_string.clear(); + decimal_point_position = std::string::npos; token_string.push_back(char_traits::to_char_type(current)); } @@ -1430,6 +1433,11 @@ scan_number_done: /// return current string value (implicitly resets the token; useful only once) string_t& get_string() { + // translate decimal points from locale back to '.' (#4084) + if (decimal_point_char != '.' && decimal_point_position != std::string::npos) + { + token_buffer[decimal_point_position] = '.'; + } return token_buffer; } @@ -1627,6 +1635,8 @@ scan_number_done: /// the decimal point const char_int_type decimal_point_char = '.'; + /// the position of the decimal point in the input + std::size_t decimal_point_position = std::string::npos; }; } // namespace detail diff --git a/external/json/include/nlohmann/detail/input/parser.hpp b/external/json/include/nlohmann/detail/input/parser.hpp index bdf85ba2..c856d116 100644 --- a/external/json/include/nlohmann/detail/input/parser.hpp +++ b/external/json/include/nlohmann/detail/input/parser.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -69,10 +69,10 @@ class parser public: /// a parser reading from an input adapter explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions_ = true, const bool skip_comments = false) - : callback(cb) + : callback(std::move(cb)) , m_lexer(std::move(adapter), skip_comments) , allow_exceptions(allow_exceptions_) { @@ -94,7 +94,7 @@ class parser { if (callback) { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); // in strict mode, input must be completely read @@ -122,7 +122,7 @@ class parser } else { - json_sax_dom_parser sdp(result, allow_exceptions); + json_sax_dom_parser sdp(result, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); // in strict mode, input must be completely read @@ -194,7 +194,7 @@ class parser { case token_type::begin_object: { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -239,7 +239,7 @@ class parser case token_type::begin_array: { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } diff --git a/external/json/include/nlohmann/detail/input/position_t.hpp b/external/json/include/nlohmann/detail/input/position_t.hpp index 8ac7c78c..42a57df2 100644 --- a/external/json/include/nlohmann/detail/input/position_t.hpp +++ b/external/json/include/nlohmann/detail/input/position_t.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/iterators/internal_iterator.hpp b/external/json/include/nlohmann/detail/iterators/internal_iterator.hpp index 2991ee69..00f67fe9 100644 --- a/external/json/include/nlohmann/detail/iterators/internal_iterator.hpp +++ b/external/json/include/nlohmann/detail/iterators/internal_iterator.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/iterators/iter_impl.hpp b/external/json/include/nlohmann/detail/iterators/iter_impl.hpp index 44470913..b7c72119 100644 --- a/external/json/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/external/json/include/nlohmann/detail/iterators/iter_impl.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -463,7 +463,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > bool operator==(const IterImpl& other) const @@ -474,7 +474,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } - JSON_ASSERT(m_object != nullptr); + // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 + if (m_object == nullptr) + { + return true; + } switch (m_object->m_data.m_type) { @@ -499,7 +503,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > bool operator!=(const IterImpl& other) const @@ -509,7 +513,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator<(const iter_impl& other) const { @@ -519,7 +523,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } - JSON_ASSERT(m_object != nullptr); + // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 + if (m_object == nullptr) + { + // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false + return false; + } switch (m_object->m_data.m_type) { @@ -544,7 +553,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator<=(const iter_impl& other) const { @@ -553,7 +562,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator>(const iter_impl& other) const { @@ -562,7 +571,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized. */ bool operator>=(const iter_impl& other) const { diff --git a/external/json/include/nlohmann/detail/iterators/iteration_proxy.hpp b/external/json/include/nlohmann/detail/iterators/iteration_proxy.hpp index 76293de2..227c8ea5 100644 --- a/external/json/include/nlohmann/detail/iterators/iteration_proxy.hpp +++ b/external/json/include/nlohmann/detail/iterators/iteration_proxy.hpp @@ -3,14 +3,13 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include // size_t -#include // input_iterator_tag -#include // string, to_string +#include // forward_iterator_tag #include // tuple_size, get, tuple_element #include // move @@ -20,19 +19,13 @@ #include #include +#include #include NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} template class iteration_proxy_value { public: @@ -40,7 +33,7 @@ template class iteration_proxy_value using value_type = iteration_proxy_value; using pointer = value_type *; using reference = value_type &; - using iterator_category = std::input_iterator_tag; + using iterator_category = std::forward_iterator_tag; using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: @@ -220,7 +213,7 @@ namespace std #endif template class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) - : public std::integral_constant {}; + : public std::integral_constant {}; template class tuple_element> // NOLINT(cert-dcl58-cpp) diff --git a/external/json/include/nlohmann/detail/iterators/iterator_traits.hpp b/external/json/include/nlohmann/detail/iterators/iterator_traits.hpp index 84cc27a8..2863c421 100644 --- a/external/json/include/nlohmann/detail/iterators/iterator_traits.hpp +++ b/external/json/include/nlohmann/detail/iterators/iterator_traits.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -43,7 +43,7 @@ struct iterator_traits template struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types + : iterator_types { }; diff --git a/external/json/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/external/json/include/nlohmann/detail/iterators/json_reverse_iterator.hpp index 006d5499..c3ac11da 100644 --- a/external/json/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +++ b/external/json/include/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/iterators/primitive_iterator.hpp b/external/json/include/nlohmann/detail/iterators/primitive_iterator.hpp index 0b6e8499..bb4a4cb0 100644 --- a/external/json/include/nlohmann/detail/iterators/primitive_iterator.hpp +++ b/external/json/include/nlohmann/detail/iterators/primitive_iterator.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/json_custom_base_class.hpp b/external/json/include/nlohmann/detail/json_custom_base_class.hpp index d1e29162..d526e629 100644 --- a/external/json/include/nlohmann/detail/json_custom_base_class.hpp +++ b/external/json/include/nlohmann/detail/json_custom_base_class.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/json_pointer.hpp b/external/json/include/nlohmann/detail/json_pointer.hpp index 4fdcd9ad..28588127 100644 --- a/external/json/include/nlohmann/detail/json_pointer.hpp +++ b/external/json/include/nlohmann/detail/json_pointer.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/json_ref.hpp b/external/json/include/nlohmann/detail/json_ref.hpp index b8bb6a76..2cd58e71 100644 --- a/external/json/include/nlohmann/detail/json_ref.hpp +++ b/external/json/include/nlohmann/detail/json_ref.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/macro_scope.hpp b/external/json/include/nlohmann/detail/macro_scope.hpp index 97127a64..987c8a2c 100644 --- a/external/json/include/nlohmann/detail/macro_scope.hpp +++ b/external/json/include/nlohmann/detail/macro_scope.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -216,7 +216,9 @@ template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ static const std::pair m[] = __VA_ARGS__; \ auto it = std::find_if(std::begin(m), std::end(m), \ [e](const std::pair& ej_pair) -> bool \ @@ -228,7 +230,9 @@ template \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ static const std::pair m[] = __VA_ARGS__; \ auto it = std::find_if(std::begin(m), std::end(m), \ [&j](const std::pair& ej_pair) -> bool \ @@ -391,7 +395,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); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; /*! @brief macro @@ -402,10 +406,20 @@ 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__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +*/ #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) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.x +*/ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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__)) } @@ -418,13 +432,55 @@ 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_ONLY_SERIALIZE(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__)) } - +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +*/ #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) { const 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_ONLY_SERIALIZE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(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__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + // inspired from https://stackoverflow.com/a/26745591 // allows to call any std function as if (e.g. with begin): // using std::begin; begin(x); diff --git a/external/json/include/nlohmann/detail/macro_unscope.hpp b/external/json/include/nlohmann/detail/macro_unscope.hpp index c6620d1e..256df809 100644 --- a/external/json/include/nlohmann/detail/macro_unscope.hpp +++ b/external/json/include/nlohmann/detail/macro_unscope.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/call_std/begin.hpp b/external/json/include/nlohmann/detail/meta/call_std/begin.hpp index 364cc89d..ee5b1abd 100644 --- a/external/json/include/nlohmann/detail/meta/call_std/begin.hpp +++ b/external/json/include/nlohmann/detail/meta/call_std/begin.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/call_std/end.hpp b/external/json/include/nlohmann/detail/meta/call_std/end.hpp index 463f0706..45edb2f3 100644 --- a/external/json/include/nlohmann/detail/meta/call_std/end.hpp +++ b/external/json/include/nlohmann/detail/meta/call_std/end.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/cpp_future.hpp b/external/json/include/nlohmann/detail/meta/cpp_future.hpp index 412b5aa7..78644aa5 100644 --- a/external/json/include/nlohmann/detail/meta/cpp_future.hpp +++ b/external/json/include/nlohmann/detail/meta/cpp_future.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-FileCopyrightText: 2018 The Abseil Authors // SPDX-License-Identifier: MIT @@ -162,7 +162,7 @@ struct static_const #endif template -inline constexpr std::array make_array(Args&& ... args) +constexpr std::array make_array(Args&& ... args) { return std::array {{static_cast(std::forward(args))...}}; } diff --git a/external/json/include/nlohmann/detail/meta/detected.hpp b/external/json/include/nlohmann/detail/meta/detected.hpp index 1db9bf9c..13422fd3 100644 --- a/external/json/include/nlohmann/detail/meta/detected.hpp +++ b/external/json/include/nlohmann/detail/meta/detected.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/identity_tag.hpp b/external/json/include/nlohmann/detail/meta/identity_tag.hpp index 269deffb..d6b6059d 100644 --- a/external/json/include/nlohmann/detail/meta/identity_tag.hpp +++ b/external/json/include/nlohmann/detail/meta/identity_tag.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/is_sax.hpp b/external/json/include/nlohmann/detail/meta/is_sax.hpp index 4e02bc14..e36257a3 100644 --- a/external/json/include/nlohmann/detail/meta/is_sax.hpp +++ b/external/json/include/nlohmann/detail/meta/is_sax.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/meta/std_fs.hpp b/external/json/include/nlohmann/detail/meta/std_fs.hpp index fd180396..70c0ac98 100644 --- a/external/json/include/nlohmann/detail/meta/std_fs.hpp +++ b/external/json/include/nlohmann/detail/meta/std_fs.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -19,7 +19,7 @@ namespace std_fs = std::experimental::filesystem; } // namespace detail NLOHMANN_JSON_NAMESPACE_END #elif JSON_HAS_FILESYSTEM -#include +#include // NOLINT(build/c++17) NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { diff --git a/external/json/include/nlohmann/detail/meta/type_traits.hpp b/external/json/include/nlohmann/detail/meta/type_traits.hpp index e1b000dc..8bae7609 100644 --- a/external/json/include/nlohmann/detail/meta/type_traits.hpp +++ b/external/json/include/nlohmann/detail/meta/type_traits.hpp @@ -3,16 +3,16 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include // numeric_limits +#include // char_traits +#include // tuple #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval -#include // tuple -#include // char_traits #include #include @@ -211,7 +211,7 @@ struct char_traits : std::char_traits static constexpr int_type eof() noexcept { - return static_cast(EOF); + return static_cast(std::char_traits::eof()); } }; @@ -235,7 +235,7 @@ struct char_traits : std::char_traits static constexpr int_type eof() noexcept { - return static_cast(EOF); + return static_cast(std::char_traits::eof()); } }; @@ -261,19 +261,19 @@ struct is_default_constructible : std::is_default_constructible {}; template struct is_default_constructible> - : conjunction, is_default_constructible> {}; + : conjunction, is_default_constructible> {}; template struct is_default_constructible> - : conjunction, is_default_constructible> {}; + : conjunction, is_default_constructible> {}; template struct is_default_constructible> - : conjunction...> {}; + : conjunction...> {}; template struct is_default_constructible> - : conjunction...> {}; + : conjunction...> {}; template struct is_constructible : std::is_constructible {}; @@ -471,8 +471,8 @@ is_detected::value&& // special case for types like std::filesystem::path whose iterator's value_type are themselves // c.f. https://github.com/nlohmann/json/pull/3073 !std::is_same>::value&& - is_complete_type < - detected_t>::value >> +is_complete_type < +detected_t>::value >> { using value_type = range_value_t; @@ -595,12 +595,12 @@ using is_usable_as_key_type = typename std::conditional < template> using is_usable_as_basic_json_key_type = typename std::conditional < - is_usable_as_key_type::value - && !is_json_iterator_of::value, - std::true_type, - std::false_type >::type; + is_usable_as_key_type::value + && !is_json_iterator_of::value, + std::true_type, + std::false_type >::type; template using detect_erase_with_key_type = decltype(std::declval().erase(std::declval())); @@ -734,7 +734,7 @@ struct value_in_range_of_impl1 }; template -inline constexpr bool value_in_range_of(T val) +constexpr bool value_in_range_of(T val) { return value_in_range_of_impl1::test(val); } @@ -750,7 +750,7 @@ namespace impl { template -inline constexpr bool is_c_string() +constexpr bool is_c_string() { using TUnExt = typename std::remove_extent::type; using TUnCVExt = typename std::remove_cv::type; @@ -778,7 +778,7 @@ namespace impl { template -inline constexpr bool is_transparent() +constexpr bool is_transparent() { return is_detected::value; } diff --git a/external/json/include/nlohmann/detail/meta/void_t.hpp b/external/json/include/nlohmann/detail/meta/void_t.hpp index 99615c7c..59b97a29 100644 --- a/external/json/include/nlohmann/detail/meta/void_t.hpp +++ b/external/json/include/nlohmann/detail/meta/void_t.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/output/binary_writer.hpp b/external/json/include/nlohmann/detail/output/binary_writer.hpp index f475d57b..70dd752e 100644 --- a/external/json/include/nlohmann/detail/output/binary_writer.hpp +++ b/external/json/include/nlohmann/detail/output/binary_writer.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -612,7 +612,7 @@ class binary_writer case value_t::binary: { // step 0: determine if the binary type has a set subtype to - // determine whether or not to use the ext or fixext types + // determine whether to use the ext or fixext types const bool use_ext = j.m_data.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length diff --git a/external/json/include/nlohmann/detail/output/output_adapters.hpp b/external/json/include/nlohmann/detail/output/output_adapters.hpp index 626f7c0c..72cd7d36 100644 --- a/external/json/include/nlohmann/detail/output/output_adapters.hpp +++ b/external/json/include/nlohmann/detail/output/output_adapters.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/output/serializer.hpp b/external/json/include/nlohmann/detail/output/serializer.hpp index ed20b0d9..b42a3104 100644 --- a/external/json/include/nlohmann/detail/output/serializer.hpp +++ b/external/json/include/nlohmann/detail/output/serializer.hpp @@ -3,8 +3,8 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -643,7 +643,7 @@ class serializer @param[in] x unsigned integer number to count its digits @return number of decimal digits */ - inline unsigned int count_digits(number_unsigned_t x) noexcept + unsigned int count_digits(number_unsigned_t x) noexcept { unsigned int n_digits = 1; for (;;) @@ -926,7 +926,7 @@ class serializer ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte); - const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + const std::size_t index = 256u + (static_cast(state) * 16u) + static_cast(type); JSON_ASSERT(index < utf8d.size()); state = utf8d[index]; return state; @@ -952,7 +952,7 @@ class serializer * absolute values of INT_MIN and INT_MAX are usually not the same. See * #1708 for details. */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept + number_unsigned_t remove_sign(number_integer_t x) noexcept { JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) return static_cast(-(x + 1)) + 1; diff --git a/external/json/include/nlohmann/detail/string_concat.hpp b/external/json/include/nlohmann/detail/string_concat.hpp index f49e8d21..b086ebc7 100644 --- a/external/json/include/nlohmann/detail/string_concat.hpp +++ b/external/json/include/nlohmann/detail/string_concat.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/string_escape.hpp b/external/json/include/nlohmann/detail/string_escape.hpp index 7f1b5c56..dadab25b 100644 --- a/external/json/include/nlohmann/detail/string_escape.hpp +++ b/external/json/include/nlohmann/detail/string_escape.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/detail/string_utils.hpp b/external/json/include/nlohmann/detail/string_utils.hpp new file mode 100644 index 00000000..0ac28c65 --- /dev/null +++ b/external/json/include/nlohmann/detail/string_utils.hpp @@ -0,0 +1,37 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-License-Identifier: MIT + +#pragma once + +#include // size_t +#include // string, to_string + +#include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +void int_to_string(StringType& target, std::size_t value) +{ + // For ADL + using std::to_string; + target = to_string(value); +} + +template +StringType to_string(std::size_t value) +{ + StringType result; + int_to_string(result, value); + return result; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END diff --git a/external/json/include/nlohmann/detail/value_t.hpp b/external/json/include/nlohmann/detail/value_t.hpp index 07688fe8..9fdbfe8e 100644 --- a/external/json/include/nlohmann/detail/value_t.hpp +++ b/external/json/include/nlohmann/detail/value_t.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/include/nlohmann/json.hpp b/external/json/include/nlohmann/json.hpp index 95d6bf1d..9b3b5950 100644 --- a/external/json/include/nlohmann/json.hpp +++ b/external/json/include/nlohmann/json.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /****************************************************************************\ @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -114,9 +115,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec friend class ::nlohmann::detail::binary_writer; template friend class ::nlohmann::detail::binary_reader; - template + template friend class ::nlohmann::detail::json_sax_dom_parser; - template + template friend class ::nlohmann::detail::json_sax_dom_callback_parser; friend class ::nlohmann::detail::exception; @@ -137,7 +138,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); + std::move(cb), allow_exceptions, ignore_comments); } private: @@ -750,10 +751,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j, std::size_t old_capacity = static_cast(-1)) + reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size()) { #if JSON_DIAGNOSTICS - if (old_capacity != static_cast(-1)) + if (old_capacity != detail::unknown_size()) { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); @@ -847,6 +848,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < detail::is_basic_json::value&& !std::is_same::value, int > = 0 > basic_json(const BasicJsonType& val) +#if JSON_DIAGNOSTIC_POSITIONS + : start_position(val.start_pos()), + end_position(val.end_pos()) +#endif { using other_boolean_t = typename BasicJsonType::boolean_t; using other_number_float_t = typename BasicJsonType::number_float_t; @@ -893,6 +898,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } JSON_ASSERT(m_data.m_type == val.type()); + set_parents(); assert_invariant(); } @@ -1029,7 +1035,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class InputIT, typename std::enable_if < std::is_same::value || std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) + basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param) { JSON_ASSERT(first.m_object != nullptr); JSON_ASSERT(last.m_object != nullptr); @@ -1144,6 +1150,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) : json_base_class_t(other) +#if JSON_DIAGNOSTIC_POSITIONS + , start_position(other.start_position) + , end_position(other.end_position) +#endif { m_data.m_type = other.m_data.m_type; // check of passed value is valid @@ -1213,15 +1223,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept : json_base_class_t(std::forward(other)), - m_data(std::move(other.m_data)) + m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check +#if JSON_DIAGNOSTIC_POSITIONS + , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check + , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check +#endif { // check that passed value is valid - other.assert_invariant(false); + other.assert_invariant(false); // cppcheck-suppress[accessForwarded] // invalidate payload other.m_data.m_type = value_t::null; other.m_data.m_value = {}; +#if JSON_DIAGNOSTIC_POSITIONS + other.start_position = std::string::npos; + other.end_position = std::string::npos; +#endif + set_parents(); assert_invariant(); } @@ -1242,6 +1261,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec using std::swap; swap(m_data.m_type, other.m_data.m_type); swap(m_data.m_value, other.m_data.m_value); + +#if JSON_DIAGNOSTIC_POSITIONS + swap(start_position, other.start_position); + swap(end_position, other.end_position); +#endif + json_base_class_t::operator=(std::move(other)); set_parents(); @@ -1463,13 +1488,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) @@ -1948,7 +1973,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // create better exception explanation JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); - } + } // cppcheck-suppress[missingReturn] } else { @@ -1971,7 +1996,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // create better exception explanation JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); - } + } // cppcheck-suppress[missingReturn] } else { @@ -2116,7 +2141,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief access specified object element /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ - reference operator[](typename object_t::key_type key) + reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param) { // implicitly convert null value to an empty object if (is_null()) @@ -2426,7 +2451,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class IteratorType, detail::enable_if_t < std::is_same::value || std::is_same::value, int > = 0 > - IteratorType erase(IteratorType pos) + IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param) { // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) @@ -2496,7 +2521,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class IteratorType, detail::enable_if_t < std::is_same::value || std::is_same::value, int > = 0 > - IteratorType erase(IteratorType first, IteratorType last) + IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param) { // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) @@ -3263,7 +3288,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, Args&& ... args) + iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param) { iterator result(this); JSON_ASSERT(m_data.m_value.array != nullptr); @@ -3282,7 +3307,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, const basic_json& val) + iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) @@ -3302,14 +3327,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, basic_json&& val) + iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param) { return insert(pos, val); } /// @brief inserts copies of element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) @@ -3329,7 +3354,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts range of elements into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) + iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) @@ -3360,7 +3385,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts elements from initializer list into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, initializer_list_t ilist) + iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) @@ -3380,7 +3405,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts range of elements into object /// @sa https://json.nlohmann.me/api/basic_json/insert/ - void insert(const_iterator first, const_iterator last) + void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) { // insert only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) @@ -3401,6 +3426,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + set_parents(); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -3412,7 +3438,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief updates a JSON object from another object, overwriting existing keys /// @sa https://json.nlohmann.me/api/basic_json/update/ - void update(const_iterator first, const_iterator last, bool merge_objects = false) + void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param) { // implicitly convert null value to an empty object if (is_null()) @@ -4013,12 +4039,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(detail::input_adapter(std::forward(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded] return result; } @@ -4028,24 +4054,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(IteratorType first, IteratorType last, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved] return result; } JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved] return result; } @@ -4224,6 +4250,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec basic_json* m_parent = nullptr; #endif +#if JSON_DIAGNOSTIC_POSITIONS + /// the start position of the value + std::size_t start_position = std::string::npos; + /// the end position of the value + std::size_t end_position = std::string::npos; + public: + constexpr std::size_t start_pos() const noexcept + { + return start_position; + } + + constexpr std::size_t end_pos() const noexcept + { + return end_position; + } +#endif + ////////////////////////////////////////// // binary serialization/deserialization // ////////////////////////////////////////// @@ -4365,9 +4408,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4381,9 +4424,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4406,10 +4449,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4422,9 +4465,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4437,9 +4480,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4460,10 +4503,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4476,9 +4519,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4491,9 +4534,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4514,10 +4557,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4530,9 +4573,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4545,9 +4588,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4560,9 +4603,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4575,9 +4618,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -4598,10 +4641,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } /// @} @@ -4702,7 +4745,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // the valid JSON Patch operations enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - const auto get_op = [](const std::string & op) + const auto get_op = [](const string_t& op) { if (op == "add") { @@ -4733,7 +4776,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec }; // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) + const auto operation_add = [&result](json_pointer & ptr, const basic_json & val) { // adding to the root of the target document means replacing it if (ptr.empty()) @@ -4839,15 +4882,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec for (const auto& val : json_patch) { // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, + const auto get_value = [&val](const string_t& op, + const string_t& member, bool string_type) -> basic_json & { // find value auto it = val.m_data.m_value.object->find(member); // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); + const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable) // check if desired value is present if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) @@ -4874,8 +4917,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); json_pointer ptr(path); switch (get_op(op)) @@ -4901,7 +4944,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case patch_operations::move: { - const auto from_path = get_value("move", "from", true).template get(); + const auto from_path = get_value("move", "from", true).template get(); json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -4918,7 +4961,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case patch_operations::copy: { - const auto from_path = get_value("copy", "from", true).template get(); + const auto from_path = get_value("copy", "from", true).template get(); const json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -4978,7 +5021,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/diff/ JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") + const string_t& path = "") { // the patch basic_json result(value_t::array); @@ -5008,7 +5051,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec while (i < source.size() && i < target.size()) { // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); + auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', detail::to_string(i))); result.insert(result.end(), temp_diff.begin(), temp_diff.end()); ++i; } @@ -5025,7 +5068,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result.insert(result.begin() + end_index, object( { {"op", "remove"}, - {"path", detail::concat(path, '/', std::to_string(i))} + {"path", detail::concat(path, '/', detail::to_string(i))} })); ++i; } @@ -5036,7 +5079,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result.push_back( { {"op", "add"}, - {"path", detail::concat(path, "/-")}, + {"path", detail::concat(path, "/-")}, {"value", target[i]} }); ++i; @@ -5051,7 +5094,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec for (auto it = source.cbegin(); it != source.cend(); ++it) { // escape the key name to be used in a JSON patch - const auto path_key = detail::concat(path, '/', detail::escape(it.key())); + const auto path_key = detail::concat(path, '/', detail::escape(it.key())); if (target.find(it.key()) != target.end()) { @@ -5075,7 +5118,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (source.find(it.key()) == source.end()) { // found a key that is not in this -> add it - const auto path_key = detail::concat(path, '/', detail::escape(it.key())); + const auto path_key = detail::concat(path, '/', detail::escape(it.key())); result.push_back( { {"op", "add"}, {"path", path_key}, diff --git a/external/json/include/nlohmann/json_fwd.hpp b/external/json/include/nlohmann/json_fwd.hpp index 32bde590..d796cfd7 100644 --- a/external/json/include/nlohmann/json_fwd.hpp +++ b/external/json/include/nlohmann/json_fwd.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ diff --git a/external/json/include/nlohmann/ordered_map.hpp b/external/json/include/nlohmann/ordered_map.hpp index 39e4a50a..f87abd7a 100644 --- a/external/json/include/nlohmann/ordered_map.hpp +++ b/external/json/include/nlohmann/ordered_map.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once @@ -26,7 +26,7 @@ NLOHMANN_JSON_NAMESPACE_BEGIN /// for use within nlohmann::basic_json template , class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> + struct ordered_map : std::vector, Allocator> { using key_type = Key; using mapped_type = T; @@ -341,7 +341,7 @@ template , template using require_input_iter = typename std::enable_if::iterator_category, - std::input_iterator_tag>::value>::type; + std::input_iterator_tag>::value>::type; template> void insert(InputIt first, InputIt last) diff --git a/external/json/include/nlohmann/thirdparty/hedley/hedley.hpp b/external/json/include/nlohmann/thirdparty/hedley/hedley.hpp index a1dc64f6..4e4ef888 100644 --- a/external/json/include/nlohmann/thirdparty/hedley/hedley.hpp +++ b/external/json/include/nlohmann/thirdparty/hedley/hedley.hpp @@ -5,8 +5,8 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson // SPDX-License-Identifier: MIT /* Hedley - https://nemequ.github.io/hedley diff --git a/external/json/include/nlohmann/thirdparty/hedley/hedley_undef.hpp b/external/json/include/nlohmann/thirdparty/hedley/hedley_undef.hpp index c0aee2bb..c07df895 100644 --- a/external/json/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +++ b/external/json/include/nlohmann/thirdparty/hedley/hedley_undef.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/nlohmann_json.natvis b/external/json/nlohmann_json.natvis index a831ea04..fbe4221f 100644 --- a/external/json/nlohmann_json.natvis +++ b/external/json/nlohmann_json.natvis @@ -7,21 +7,21 @@ - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) @@ -37,21 +37,21 @@ - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) @@ -65,30 +65,30 @@ - - - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) - + {second} second @@ -97,21 +97,21 @@ - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) @@ -125,30 +125,30 @@ - - - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) - + {second} second @@ -157,21 +157,21 @@ - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) @@ -185,30 +185,30 @@ - - - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) - + {second} second @@ -217,21 +217,21 @@ - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) @@ -245,30 +245,30 @@ - - - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + + + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) - + {second} second diff --git a/external/json/single_include/nlohmann/json.hpp b/external/json/single_include/nlohmann/json.hpp index 8b72ea65..9314724f 100644 --- a/external/json/single_include/nlohmann/json.hpp +++ b/external/json/single_include/nlohmann/json.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /****************************************************************************\ @@ -37,7 +37,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -50,7 +50,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -73,6 +73,10 @@ #define JSON_DIAGNOSTICS 0 #endif +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif @@ -83,6 +87,12 @@ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #endif +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #else @@ -94,14 +104,15 @@ #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ @@ -152,7 +163,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -162,6 +173,9 @@ #include // forward_list #include // inserter, front_inserter, end #include // map +#ifdef JSON_HAS_CPP_17 + #include // optional +#endif #include // string #include // tuple, make_tuple #include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible @@ -175,7 +189,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -195,7 +209,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -211,7 +225,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -223,7 +237,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -236,7 +250,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -323,8 +337,8 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson // SPDX-License-Identifier: MIT /* Hedley - https://nemequ.github.io/hedley @@ -2568,7 +2582,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP template \ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ static const std::pair m[] = __VA_ARGS__; \ auto it = std::find_if(std::begin(m), std::end(m), \ [e](const std::pair& ej_pair) -> bool \ @@ -2580,7 +2596,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP template \ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ { \ + /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ static const std::pair m[] = __VA_ARGS__; \ auto it = std::find_if(std::begin(m), std::end(m), \ [&j](const std::pair& ej_pair) -> bool \ @@ -2743,7 +2761,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #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); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; /*! @brief macro @@ -2754,10 +2772,20 @@ JSON_HEDLEY_DIAGNOSTIC_POP 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__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +*/ #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) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE +@since version 3.11.x +*/ #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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__)) } @@ -2770,13 +2798,55 @@ JSON_HEDLEY_DIAGNOSTIC_POP 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_ONLY_SERIALIZE(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__)) } - +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT +@since version 3.11.0 +*/ #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) { const 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_ONLY_SERIALIZE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(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__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + +/*! +@brief macro +@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE +@since version 3.11.x +*/ +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(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::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + // inspired from https://stackoverflow.com/a/26745591 // allows to call any std function as if (e.g. with begin): // using std::begin; begin(x); @@ -2942,7 +3012,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3017,7 +3087,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3059,7 +3129,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-FileCopyrightText: 2018 The Abseil Authors // SPDX-License-Identifier: MIT @@ -3219,7 +3289,7 @@ struct static_const #endif template -inline constexpr std::array make_array(Args&& ... args) +constexpr std::array make_array(Args&& ... args) { return std::array {{static_cast(std::forward(args))...}}; } @@ -3233,16 +3303,16 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include // numeric_limits +#include // char_traits +#include // tuple #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval -#include // tuple -#include // char_traits // #include // __ _____ _____ _____ @@ -3250,7 +3320,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3293,7 +3363,7 @@ struct iterator_traits template struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types + : iterator_types { }; @@ -3318,7 +3388,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3338,7 +3408,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3362,7 +3432,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -3624,7 +3694,7 @@ struct char_traits : std::char_traits static constexpr int_type eof() noexcept { - return static_cast(EOF); + return static_cast(std::char_traits::eof()); } }; @@ -3648,7 +3718,7 @@ struct char_traits : std::char_traits static constexpr int_type eof() noexcept { - return static_cast(EOF); + return static_cast(std::char_traits::eof()); } }; @@ -3674,19 +3744,19 @@ struct is_default_constructible : std::is_default_constructible {}; template struct is_default_constructible> - : conjunction, is_default_constructible> {}; + : conjunction, is_default_constructible> {}; template struct is_default_constructible> - : conjunction, is_default_constructible> {}; + : conjunction, is_default_constructible> {}; template struct is_default_constructible> - : conjunction...> {}; + : conjunction...> {}; template struct is_default_constructible> - : conjunction...> {}; + : conjunction...> {}; template struct is_constructible : std::is_constructible {}; @@ -3884,8 +3954,8 @@ is_detected::value&& // special case for types like std::filesystem::path whose iterator's value_type are themselves // c.f. https://github.com/nlohmann/json/pull/3073 !std::is_same>::value&& - is_complete_type < - detected_t>::value >> +is_complete_type < +detected_t>::value >> { using value_type = range_value_t; @@ -4008,12 +4078,12 @@ using is_usable_as_key_type = typename std::conditional < template> using is_usable_as_basic_json_key_type = typename std::conditional < - is_usable_as_key_type::value - && !is_json_iterator_of::value, - std::true_type, - std::false_type >::type; + is_usable_as_key_type::value + && !is_json_iterator_of::value, + std::true_type, + std::false_type >::type; template using detect_erase_with_key_type = decltype(std::declval().erase(std::declval())); @@ -4147,7 +4217,7 @@ struct value_in_range_of_impl1 }; template -inline constexpr bool value_in_range_of(T val) +constexpr bool value_in_range_of(T val) { return value_in_range_of_impl1::test(val); } @@ -4163,7 +4233,7 @@ namespace impl { template -inline constexpr bool is_c_string() +constexpr bool is_c_string() { using TUnExt = typename std::remove_extent::type; using TUnCVExt = typename std::remove_cv::type; @@ -4191,7 +4261,7 @@ namespace impl { template -inline constexpr bool is_transparent() +constexpr bool is_transparent() { return is_detected::value; } @@ -4213,7 +4283,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -4358,6 +4428,18 @@ inline OutStringType concat(Args && ... args) NLOHMANN_JSON_NAMESPACE_END +// With -Wweak-vtables, Clang will complain about the exception classes as they +// have no out-of-line virtual method definitions and their vtable will be +// emitted in every translation unit. This issue cannot be fixed with a +// header-only library as there is no implementation file to move these +// functions to. As a result, we suppress this warning here to avoid client +// code to stumble over this. See https://github.com/nlohmann/json/issues/4087 +// for a discussion. +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wweak-vtables" +#endif + NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -4589,6 +4671,10 @@ class other_error : public exception } // namespace detail NLOHMANN_JSON_NAMESPACE_END +#if defined(__clang__) + #pragma clang diagnostic pop +#endif + // #include // #include @@ -4599,7 +4685,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -4623,7 +4709,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -4640,7 +4726,7 @@ namespace std_fs = std::experimental::filesystem; } // namespace detail NLOHMANN_JSON_NAMESPACE_END #elif JSON_HAS_FILESYSTEM -#include +#include // NOLINT(build/c++17) NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -4670,6 +4756,24 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n) n = nullptr; } +#ifdef JSON_HAS_CPP_17 +#ifndef JSON_USE_IMPLICIT_CONVERSIONS +template +void from_json(const BasicJsonType& j, std::optional& opt) +{ + if (j.is_null()) + { + opt = std::nullopt; + } + else + { + opt.emplace(j.template get()); + } +} + +#endif // JSON_USE_IMPLICIT_CONVERSIONS +#endif // JSON_HAS_CPP_17 + // overloads for basic_json template parameters template < typename BasicJsonType, typename ArithmeticType, enable_if_t < std::is_arithmetic::value&& @@ -4817,6 +4921,54 @@ auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines } } +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + arr[i1][i2] = j.at(i1).at(i2).template get(); + } + } +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + for (std::size_t i3 = 0; i3 < N3; ++i3) + { + arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get(); + } + } + } +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +-> decltype(j.template get(), void()) +{ + for (std::size_t i1 = 0; i1 < N1; ++i1) + { + for (std::size_t i2 = 0; i2 < N2; ++i2) + { + for (std::size_t i3 = 0; i3 < N3; ++i3) + { + for (std::size_t i4 = 0; i4 < N4; ++i4) + { + arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get(); + } + } + } + } +} + template inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { @@ -4902,7 +5054,7 @@ void()) template < typename BasicJsonType, typename T, std::size_t... Idx > std::array from_json_inplace_array_impl(BasicJsonType&& j, - identity_tag> /*unused*/, index_sequence /*unused*/) + identity_tag> /*unused*/, index_sequence /*unused*/) { return { { std::forward(j).at(Idx).template get()... } }; } @@ -5129,11 +5281,17 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT +// #include +// JSON_HAS_CPP_17 +#ifdef JSON_HAS_CPP_17 + #include // optional +#endif + #include // copy #include // begin, end #include // string @@ -5149,14 +5307,13 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include // size_t -#include // input_iterator_tag -#include // string, to_string +#include // forward_iterator_tag #include // tuple_size, get, tuple_element #include // move @@ -5168,6 +5325,46 @@ NLOHMANN_JSON_NAMESPACE_END // #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t +#include // string, to_string + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +void int_to_string(StringType& target, std::size_t value) +{ + // For ADL + using std::to_string; + target = to_string(value); +} + +template +StringType to_string(std::size_t value) +{ + StringType result; + int_to_string(result, value); + return result; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + // #include @@ -5175,13 +5372,6 @@ NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} template class iteration_proxy_value { public: @@ -5189,7 +5379,7 @@ template class iteration_proxy_value using value_type = iteration_proxy_value; using pointer = value_type *; using reference = value_type &; - using iterator_category = std::input_iterator_tag; + using iterator_category = std::forward_iterator_tag; using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; private: @@ -5369,7 +5559,7 @@ namespace std #endif template class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) - : public std::integral_constant {}; + : public std::integral_constant {}; template class tuple_element> // NOLINT(cert-dcl58-cpp) @@ -5390,8 +5580,6 @@ class tuple_element> inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy> = true; #endif -// #include - // #include // #include @@ -5637,6 +5825,22 @@ struct external_constructor // to_json // ///////////// +#ifdef JSON_HAS_CPP_17 +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::optional& opt) +{ + if (opt.has_value()) + { + j = *opt; + } + else + { + j = nullptr; + } +} +#endif + template::value, int> = 0> inline void to_json(BasicJsonType& j, T b) noexcept @@ -5697,7 +5901,8 @@ template::type; - external_constructor::construct(j, static_cast(e)); + static constexpr value_t integral_value_t = std::is_unsigned::value ? value_t::number_unsigned : value_t::number_integer; + external_constructor::construct(j, static_cast(e)); } #endif // JSON_DISABLE_ENUM_SERIALIZATION @@ -5870,7 +6075,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -5982,7 +6187,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6115,7 +6320,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6132,6 +6337,9 @@ NLOHMANN_JSON_NAMESPACE_END #include // char_traits, string #include // make_pair, move #include // vector +#ifdef __cpp_lib_byteswap + #include //byteswap +#endif // #include @@ -6141,7 +6349,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6161,6 +6369,8 @@ NLOHMANN_JSON_NAMESPACE_END #include // istream #endif // JSON_NO_IO +// #include + // #include // #include @@ -6208,6 +6418,13 @@ class file_input_adapter return std::fgetc(m_file); } + // returns the number of characters successfully read + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + return fread(dest, 1, sizeof(T) * count, m_file); + } + private: /// the file pointer to read from std::FILE* m_file; @@ -6267,6 +6484,17 @@ class input_stream_adapter return res; } + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + auto res = static_cast(sb->sgetn(reinterpret_cast(dest), static_cast(count * sizeof(T)))); + if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T))) + { + is->clear(is->rdstate() | std::ios::eofbit); + } + return res; + } + private: /// the associated input stream std::istream* is = nullptr; @@ -6298,6 +6526,26 @@ class iterator_input_adapter return char_traits::eof(); } + // for general iterators, we cannot really do something better than falling back to processing the range one-by-one + template + std::size_t get_elements(T* dest, std::size_t count = 1) + { + auto* ptr = reinterpret_cast(dest); + for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index) + { + if (JSON_HEDLEY_LIKELY(current != end)) + { + ptr[read_index] = static_cast(*current); + std::advance(current, 1); + } + else + { + return read_index; + } + } + return count * sizeof(T); + } + private: IteratorType current; IteratorType end; @@ -6461,6 +6709,13 @@ class wide_string_input_adapter return utf8_bytes[utf8_bytes_index++]; } + // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here + template + std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1) + { + JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr)); + } + private: BaseInputAdapter base_adapter; @@ -6557,10 +6812,17 @@ typename container_input_adapter_factory_impl::container_input_adapter_factory::create(container); } +// specialization for std::string +using string_input_adapter_type = decltype(input_adapter(std::declval())); + #ifndef JSON_NO_IO // Special cases with fast paths inline file_input_adapter input_adapter(std::FILE* file) { + if (file == nullptr) + { + JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); + } return file_input_adapter(file); } @@ -6587,9 +6849,13 @@ template < typename CharT, int >::type = 0 > contiguous_bytes_input_adapter input_adapter(CharT b) { + if (b == nullptr) + { + JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); + } auto length = std::strlen(reinterpret_cast(b)); const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); + return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck] } template @@ -6638,739 +6904,26 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include #include // string +#include // enable_if_t #include // move #include // vector // #include -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -/*! -@brief SAX interface - -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. -Each function is called in different situations while the input is parsed. The -boolean return value informs the parser whether to continue processing the -input. -*/ -template -struct json_sax -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @brief a null value was read - @return whether parsing should proceed - */ - virtual bool null() = 0; - - /*! - @brief a boolean value was read - @param[in] val boolean value - @return whether parsing should proceed - */ - virtual bool boolean(bool val) = 0; - - /*! - @brief an integer number was read - @param[in] val integer value - @return whether parsing should proceed - */ - virtual bool number_integer(number_integer_t val) = 0; - - /*! - @brief an unsigned integer number was read - @param[in] val unsigned integer value - @return whether parsing should proceed - */ - virtual bool number_unsigned(number_unsigned_t val) = 0; - - /*! - @brief a floating-point number was read - @param[in] val floating-point value - @param[in] s raw token value - @return whether parsing should proceed - */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; - - /*! - @brief a string value was read - @param[in] val string value - @return whether parsing should proceed - @note It is safe to move the passed string value. - */ - virtual bool string(string_t& val) = 0; - - /*! - @brief a binary value was read - @param[in] val binary value - @return whether parsing should proceed - @note It is safe to move the passed binary value. - */ - virtual bool binary(binary_t& val) = 0; - - /*! - @brief the beginning of an object was read - @param[in] elements number of object elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_object(std::size_t elements) = 0; - - /*! - @brief an object key was read - @param[in] val object key - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool key(string_t& val) = 0; - - /*! - @brief the end of an object was read - @return whether parsing should proceed - */ - virtual bool end_object() = 0; - - /*! - @brief the beginning of an array was read - @param[in] elements number of array elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_array(std::size_t elements) = 0; - - /*! - @brief the end of an array was read - @return whether parsing should proceed - */ - virtual bool end_array() = 0; - - /*! - @brief a parse error occurred - @param[in] position the position in the input where the error occurs - @param[in] last_token the last read token - @param[in] ex an exception object describing the error - @return whether parsing should proceed (must return false) - */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; - - json_sax() = default; - json_sax(const json_sax&) = default; - json_sax(json_sax&&) noexcept = default; - json_sax& operator=(const json_sax&) = default; - json_sax& operator=(json_sax&&) noexcept = default; - virtual ~json_sax() = default; -}; - -namespace detail -{ -/*! -@brief SAX implementation to create a JSON value from SAX events - -This class implements the @ref json_sax interface and processes the SAX events -to create a JSON value which makes it basically a DOM parser. The structure or -hierarchy of the JSON value is managed by the stack `ref_stack` which contains -a pointer to the respective array or object for each recursion depth. - -After successful parsing, the value that is passed by reference to the -constructor contains the parsed value. - -@tparam BasicJsonType the JSON type -*/ -template -class json_sax_dom_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @param[in,out] r reference to a JSON value that is manipulated while - parsing - @param[in] allow_exceptions_ whether parse errors yield exceptions - */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) - {} - - // make class move-only - json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~json_sax_dom_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); - } - - return true; - } - - bool key(string_t& val) - { - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(ref_stack.back()->is_object()); - - // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); - return true; - } - - bool end_object() - { - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(ref_stack.back()->is_object()); - - ref_stack.back()->set_parents(); - ref_stack.pop_back(); - return true; - } - - bool start_array(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - - if (JSON_HEDLEY_UNLIKELY(len != static_cast(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); - } - - return true; - } - - bool end_array() - { - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(ref_stack.back()->is_array()); - - ref_stack.back()->set_parents(); - ref_stack.pop_back(); - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) - { - if (ref_stack.empty()) - { - root = BasicJsonType(std::forward(v)); - return &root; - } - - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_data.m_value.array->back()); - } - - JSON_ASSERT(ref_stack.back()->is_object()); - JSON_ASSERT(object_element); - *object_element = BasicJsonType(std::forward(v)); - return object_element; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -template -class json_sax_dom_callback_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using parser_callback_t = typename BasicJsonType::parser_callback_t; - using parse_event_t = typename BasicJsonType::parse_event_t; - - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) - { - keep_stack.push_back(true); - } - - // make class move-only - json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) - ~json_sax_dom_callback_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::object, true); - ref_stack.push_back(val.second); - - // 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, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); - } - - return true; - } - - bool key(string_t& val) - { - BasicJsonType k = BasicJsonType(val); - - // check callback for key - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); - key_keep_stack.push_back(keep); - - // add discarded value at given key and store the reference for later - if (keep && ref_stack.back()) - { - object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); - } - - return true; - } - - bool end_object() - { - if (ref_stack.back()) - { - if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { - // discard object - *ref_stack.back() = discarded; - } - else - { - ref_stack.back()->set_parents(); - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { - // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { - ref_stack.back()->erase(it); - break; - } - } - } - - return true; - } - - bool start_array(std::size_t len) - { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::array, true); - ref_stack.push_back(val.second); - - // 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, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); - } - - return true; - } - - bool end_array() - { - bool keep = true; - - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (keep) - { - ref_stack.back()->set_parents(); - } - else - { - // discard array - *ref_stack.back() = discarded; - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { - ref_stack.back()->m_data.m_value.array->pop_back(); - } - - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @param[in] v value to add to the JSON value we build during parsing - @param[in] skip_callback whether we should skip calling the callback - function; this is required after start_array() and - start_object() SAX events, because otherwise we would call the - callback function with an empty array or object, respectively. - - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - - @return pair of boolean (whether value should be kept) and pointer (to the - passed value in the ref_stack hierarchy; nullptr if not kept) - */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) - { - JSON_ASSERT(!keep_stack.empty()); - - // do not handle this value if we know it would be added to a discarded - // container - if (!keep_stack.back()) - { - return {false, nullptr}; - } - - // create value - auto value = BasicJsonType(std::forward(v)); - - // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); - - // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; - } - - if (ref_stack.empty()) - { - root = std::move(value); - return {true, & root}; - } - - // skip this value if we already decided to skip the parent - // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; - } - - // we now only expect arrays and objects - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - // array - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); - return {true, & (ref_stack.back()->m_data.m_value.array->back())}; - } - - // object - JSON_ASSERT(ref_stack.back()->is_object()); - // check if we should store an element for the current key - JSON_ASSERT(!key_keep_stack.empty()); - const bool store_element = key_keep_stack.back(); - key_keep_stack.pop_back(); - - if (!store_element) - { - return {false, nullptr}; - } - - JSON_ASSERT(object_element); - *object_element = std::move(value); - return {true, object_element}; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// stack to manage which values to keep - std::vector keep_stack {}; - /// stack to manage which object keys to keep - std::vector key_keep_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// callback function - const parser_callback_t callback = nullptr; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; - /// a discarded value for the callback - BasicJsonType discarded = BasicJsonType::value_t::discarded; -}; - -template -class json_sax_acceptor -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - bool null() - { - return true; - } - - bool boolean(bool /*unused*/) - { - return true; - } - - bool number_integer(number_integer_t /*unused*/) - { - return true; - } - - bool number_unsigned(number_unsigned_t /*unused*/) - { - return true; - } - - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) - { - return true; - } - - bool string(string_t& /*unused*/) - { - return true; - } - - bool binary(binary_t& /*unused*/) - { - return true; - } - - bool start_object(std::size_t /*unused*/ = static_cast(-1)) - { - return true; - } - - bool key(string_t& /*unused*/) - { - return true; - } - - bool end_object() - { - return true; - } - - bool start_array(std::size_t /*unused*/ = static_cast(-1)) - { - return true; - } - - bool end_array() - { - return true; - } - - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) - { - return false; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -8338,7 +7891,7 @@ class lexer : public lexer_base locale's decimal point is used instead of `.` to work with the locale-dependent converters. */ - token_type scan_number() // lgtm [cpp/use-of-goto] + token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated. { // reset token_buffer to store the number's bytes reset(); @@ -8420,6 +7973,7 @@ scan_number_zero: case '.': { add(decimal_point_char); + decimal_point_position = token_buffer.size() - 1; goto scan_number_decimal1; } @@ -8456,6 +8010,7 @@ scan_number_any1: case '.': { add(decimal_point_char); + decimal_point_position = token_buffer.size() - 1; goto scan_number_decimal1; } @@ -8627,7 +8182,7 @@ scan_number_done: // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) + if (errno != ERANGE) { value_unsigned = static_cast(x); if (value_unsigned == x) @@ -8643,7 +8198,7 @@ scan_number_done: // we checked the number format before JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - if (errno == 0) + if (errno != ERANGE) { value_integer = static_cast(x); if (value_integer == x) @@ -8693,6 +8248,7 @@ scan_number_done: { token_buffer.clear(); token_string.clear(); + decimal_point_position = std::string::npos; token_string.push_back(char_traits::to_char_type(current)); } @@ -8801,6 +8357,11 @@ scan_number_done: /// return current string value (implicitly resets the token; useful only once) string_t& get_string() { + // translate decimal points from locale back to '.' (#4084) + if (decimal_point_char != '.' && decimal_point_position != std::string::npos) + { + token_buffer[decimal_point_position] = '.'; + } return token_buffer; } @@ -8998,6 +8559,8 @@ scan_number_done: /// the decimal point const char_int_type decimal_point_char = '.'; + /// the position of the decimal point in the input + std::size_t decimal_point_position = std::string::npos; }; } // namespace detail @@ -9005,13 +8568,986 @@ NLOHMANN_JSON_NAMESPACE_END // #include +// #include + +NLOHMANN_JSON_NAMESPACE_BEGIN + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief a floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string value was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string value. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief a binary value was read + @param[in] val binary value + @return whether parsing should proceed + @note It is safe to move the passed binary value. + */ + virtual bool binary(binary_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + json_sax() = default; + json_sax(const json_sax&) = default; + json_sax(json_sax&&) noexcept = default; + json_sax& operator=(const json_sax&) = default; + json_sax& operator=(json_sax&&) noexcept = default; + virtual ~json_sax() = default; +}; + +namespace detail +{ +constexpr std::size_t unknown_size() +{ + return (std::numeric_limits::max)(); +} + +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using lexer_t = lexer; + + /*! + @param[in,out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr) + : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the object here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the object, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool key(string_t& val) + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_object()); + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing brace, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the array here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + } + + return true; + } + + bool end_array() + { + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(ref_stack.back()->is_array()); + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing bracket, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + + ref_stack.back()->set_parents(); + ref_stack.pop_back(); + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + +#if JSON_DIAGNOSTIC_POSITIONS + void handle_diagnostic_positions_for_json_value(BasicJsonType& v) + { + if (m_lexer_ref) + { + // Lexer has read past the current field value, so set the end position to the current position. + // The start position will be set below based on the length of the string representation + // of the value. + v.end_position = m_lexer_ref->get_position(); + + switch (v.type()) + { + case value_t::boolean: + { + // 4 and 5 are the string length of "true" and "false" + v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5); + break; + } + + case value_t::null: + { + // 4 is the string length of "null" + v.start_position = v.end_position - 4; + break; + } + + case value_t::string: + { + // include the length of the quotes, which is 2 + v.start_position = v.end_position - v.m_data.m_value.string->size() - 2; + break; + } + + // As we handle the start and end positions for values created during parsing, + // we do not expect the following value type to be called. Regardless, set the positions + // in case this is created manually or through a different constructor. Exclude from lcov + // since the exact condition of this switch is esoteric. + // LCOV_EXCL_START + case value_t::discarded: + { + v.end_position = std::string::npos; + v.start_position = v.end_position; + break; + } + // LCOV_EXCL_STOP + case value_t::binary: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + { + v.start_position = v.end_position - m_lexer_ref->get_string().size(); + break; + } + case value_t::object: + case value_t::array: + { + // object and array are handled in start_object() and start_array() handlers + // skip setting the values here. + break; + } + default: // LCOV_EXCL_LINE + // Handle all possible types discretely, default handler should never be reached. + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE + } + } + } +#endif + + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(root); +#endif + + return &root; + } + + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back()); +#endif + + return &(ref_stack.back()->m_data.m_value.array->back()); + } + + JSON_ASSERT(ref_stack.back()->is_object()); + JSON_ASSERT(object_element); + *object_element = BasicJsonType(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(*object_element); +#endif + + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// the lexer reference to obtain the current position + lexer_t* m_lexer_ref = nullptr; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + using lexer_t = lexer; + + json_sax_dom_callback_parser(BasicJsonType& r, + parser_callback_t cb, + const bool allow_exceptions_ = true, + lexer_t* lexer_ = nullptr) + : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool binary(binary_t& val) + { + handle_value(std::move(val)); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + if (ref_stack.back()) + { + +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the object here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the object, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + // check object limit + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back())); + } + } + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep && ref_stack.back()) + { + object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back()) + { + if (!callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + +#if JSON_DIAGNOSTIC_POSITIONS + // Set start/end positions for discarded object. + handle_diagnostic_positions_for_json_value(*ref_stack.back()); +#endif + } + else + { + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing brace, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + + ref_stack.back()->set_parents(); + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + if (ref_stack.back()) + { + +#if JSON_DIAGNOSTIC_POSITIONS + // Manually set the start position of the array here. + // Ensure this is after the call to handle_value to ensure correct start position. + if (m_lexer_ref) + { + // Lexer has read the first character of the array, so + // subtract 1 from the position to get the correct start position. + ref_stack.back()->start_position = m_lexer_ref->get_position() - 1; + } +#endif + + // check array limit + if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back())); + } + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (keep) + { + +#if JSON_DIAGNOSTIC_POSITIONS + if (m_lexer_ref) + { + // Lexer's position is past the closing bracket, so set that as the end position. + ref_stack.back()->end_position = m_lexer_ref->get_position(); + } +#endif + + ref_stack.back()->set_parents(); + } + else + { + // discard array + *ref_stack.back() = discarded; + +#if JSON_DIAGNOSTIC_POSITIONS + // Set start/end positions for discarded array. + handle_diagnostic_positions_for_json_value(*ref_stack.back()); +#endif + } + } + + JSON_ASSERT(!ref_stack.empty()); + JSON_ASSERT(!keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->pop_back(); + } + + return true; + } + + template + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const Exception& ex) + { + errored = true; + static_cast(ex); + if (allow_exceptions) + { + JSON_THROW(ex); + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + +#if JSON_DIAGNOSTIC_POSITIONS + void handle_diagnostic_positions_for_json_value(BasicJsonType& v) + { + if (m_lexer_ref) + { + // Lexer has read past the current field value, so set the end position to the current position. + // The start position will be set below based on the length of the string representation + // of the value. + v.end_position = m_lexer_ref->get_position(); + + switch (v.type()) + { + case value_t::boolean: + { + // 4 and 5 are the string length of "true" and "false" + v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5); + break; + } + + case value_t::null: + { + // 4 is the string length of "null" + v.start_position = v.end_position - 4; + break; + } + + case value_t::string: + { + // include the length of the quotes, which is 2 + v.start_position = v.end_position - v.m_data.m_value.string->size() - 2; + break; + } + + case value_t::discarded: + { + v.end_position = std::string::npos; + v.start_position = v.end_position; + break; + } + + case value_t::binary: + case value_t::number_integer: + case value_t::number_unsigned: + case value_t::number_float: + { + v.start_position = v.end_position - m_lexer_ref->get_string().size(); + break; + } + + case value_t::object: + case value_t::array: + { + // object and array are handled in start_object() and start_array() handlers + // skip setting the values here. + break; + } + default: // LCOV_EXCL_LINE + // Handle all possible types discretely, default handler should never be reached. + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE + } + } + } +#endif + + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + JSON_ASSERT(!keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (!keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + +#if JSON_DIAGNOSTIC_POSITIONS + handle_diagnostic_positions_for_json_value(value); +#endif + + // check callback + const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (!keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, & root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (!ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); + return {true, & (ref_stack.back()->m_data.m_value.array->back())}; + } + + // object + JSON_ASSERT(ref_stack.back()->is_object()); + // check if we should store an element for the current key + JSON_ASSERT(!key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (!store_element) + { + return {false, nullptr}; + } + + JSON_ASSERT(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; // NOLINT(readability-redundant-member-init) + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; // NOLINT(readability-redundant-member-init) + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; + /// the lexer reference to obtain the current position + lexer_t* m_lexer_ref = nullptr; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using binary_t = typename BasicJsonType::binary_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool binary(binary_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = detail::unknown_size()) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = detail::unknown_size()) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -9207,7 +9743,7 @@ static inline bool little_endianness(int num = 1) noexcept /*! @brief deserialization of CBOR, MessagePack, and UBJSON values */ -template> +template> class binary_reader { using number_integer_t = typename BasicJsonType::number_integer_t; @@ -9314,7 +9850,7 @@ class binary_reader std::int32_t document_size{}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -9536,7 +10072,7 @@ class binary_reader std::int32_t document_size{}; get_number(input_format_t::bson, document_size); - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } @@ -9796,7 +10332,7 @@ class binary_reader } case 0x9F: // array (indefinite length) - return get_cbor_array(static_cast(-1), tag_handler); + return get_cbor_array(detail::unknown_size(), tag_handler); // map (0x00..0x17 pairs of data items follow) case 0xA0: @@ -9850,7 +10386,7 @@ class binary_reader } case 0xBF: // map (indefinite length) - return get_cbor_object(static_cast(-1), tag_handler); + return get_cbor_object(detail::unknown_size(), tag_handler); case 0xC6: // tagged item case 0xC7: @@ -10238,7 +10774,7 @@ class binary_reader } /*! - @param[in] len the length of the array or static_cast(-1) for an + @param[in] len the length of the array or detail::unknown_size() for an array of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed @@ -10251,7 +10787,7 @@ class binary_reader return false; } - if (len != static_cast(-1)) + if (len != detail::unknown_size()) { for (std::size_t i = 0; i < len; ++i) { @@ -10276,7 +10812,7 @@ class binary_reader } /*! - @param[in] len the length of the object or static_cast(-1) for an + @param[in] len the length of the object or detail::unknown_size() for an object of indefinite size @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed @@ -10292,7 +10828,7 @@ class binary_reader if (len != 0) { string_t key; - if (len != static_cast(-1)) + if (len != detail::unknown_size()) { for (std::size_t i = 0; i < len; ++i) { @@ -11710,7 +12246,7 @@ class binary_reader } else { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } @@ -11788,7 +12324,7 @@ class binary_reader } else { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -11899,6 +12435,29 @@ class binary_reader return current = ia.get_character(); } + /*! + @brief get_to read into a primitive type + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns false instead + + @return bool, whether the read was successful + */ + template + bool get_to(T& dest, const input_format_t format, const char* context) + { + auto new_chars_read = ia.get_elements(&dest); + chars_read += new_chars_read; + if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T))) + { + // in case of failure, advance position by 1 to report failing location + ++chars_read; + sax->parse_error(chars_read, "", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); + return false; + } + return true; + } + /*! @return character read from the input after ignoring all 'N' entries */ @@ -11913,6 +12472,28 @@ class binary_reader return current; } + template + static void byte_swap(NumberType& number) + { + constexpr std::size_t sz = sizeof(number); +#ifdef __cpp_lib_byteswap + if constexpr (sz == 1) + { + return; + } + if constexpr(std::is_integral_v) + { + number = std::byteswap(number); + return; + } +#endif + auto* ptr = reinterpret_cast(&number); + for (std::size_t i = 0; i < sz / 2; ++i) + { + std::swap(ptr[i], ptr[sz - i - 1]); + } + } + /* @brief read a number from the input @@ -11931,29 +12512,16 @@ class binary_reader template bool get_number(const input_format_t format, NumberType& result) { - // step 1: read input into array with system's byte order - std::array vec{}; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) + // read in the original format + + if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number"))) { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; - } - - // reverse byte order prior to conversion if necessary - if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } + return false; + } + if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) + { + byte_swap(result); } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); return true; } @@ -12092,7 +12660,7 @@ class binary_reader } private: - static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); + static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size(); /// input adapter InputAdapterType ia; @@ -12163,7 +12731,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12237,10 +12805,10 @@ class parser public: /// a parser reading from an input adapter explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions_ = true, const bool skip_comments = false) - : callback(cb) + : callback(std::move(cb)) , m_lexer(std::move(adapter), skip_comments) , allow_exceptions(allow_exceptions_) { @@ -12262,7 +12830,7 @@ class parser { if (callback) { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); // in strict mode, input must be completely read @@ -12290,7 +12858,7 @@ class parser } else { - json_sax_dom_parser sdp(result, allow_exceptions); + json_sax_dom_parser sdp(result, allow_exceptions, &m_lexer); sax_parse_internal(&sdp); // in strict mode, input must be completely read @@ -12362,7 +12930,7 @@ class parser { case token_type::begin_object: { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) { return false; } @@ -12407,7 +12975,7 @@ class parser case token_type::begin_array: { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast(-1)))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) { return false; } @@ -12692,7 +13260,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12705,7 +13273,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12864,7 +13432,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -13331,7 +13899,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > bool operator==(const IterImpl& other) const @@ -13342,7 +13910,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } - JSON_ASSERT(m_object != nullptr); + // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 + if (m_object == nullptr) + { + return true; + } switch (m_object->m_data.m_type) { @@ -13367,7 +13939,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ template < typename IterImpl, detail::enable_if_t < (std::is_same::value || std::is_same::value), std::nullptr_t > = nullptr > bool operator!=(const IterImpl& other) const @@ -13377,7 +13949,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator<(const iter_impl& other) const { @@ -13387,7 +13959,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object)); } - JSON_ASSERT(m_object != nullptr); + // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493 + if (m_object == nullptr) + { + // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false + return false; + } switch (m_object->m_data.m_type) { @@ -13412,7 +13989,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator<=(const iter_impl& other) const { @@ -13421,7 +13998,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized. */ bool operator>(const iter_impl& other) const { @@ -13430,7 +14007,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci /*! @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. + @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized. */ bool operator>=(const iter_impl& other) const { @@ -13626,7 +14203,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -13761,7 +14338,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -13803,7 +14380,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14798,7 +15375,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14880,6 +15457,8 @@ NLOHMANN_JSON_NAMESPACE_END // #include +// #include + // #include // #include @@ -14890,7 +15469,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14916,7 +15495,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -15651,7 +16230,7 @@ class binary_writer case value_t::binary: { // step 0: determine if the binary type has a set subtype to - // determine whether or not to use the ext or fixext types + // determine whether to use the ext or fixext types const bool use_ext = j.m_data.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length @@ -16884,8 +17463,8 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -16910,7 +17489,7 @@ NLOHMANN_JSON_NAMESPACE_END // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2009 Florian Loitsch -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -17146,10 +17725,10 @@ boundaries compute_boundaries(FloatType value) // v- m- v m+ v+ const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1); const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) + ? diyfp((4 * v.f) - 1, v.e - 2) // (B) + : diyfp((2 * v.f) - 1, v.e - 1); // (A) // Determine the normalized w+ = m+. const diyfp w_plus = diyfp::normalize(m_plus); @@ -17379,7 +17958,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e) JSON_ASSERT(e >= -1500); JSON_ASSERT(e <= 1500); const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + const int k = ((f * 78913) / (1 << 18)) + static_cast(f > 0); const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; JSON_ASSERT(index >= 0); @@ -17857,15 +18436,15 @@ inline char* append_exponent(char* buf, int e) } else if (k < 100) { - *buf++ = static_cast('0' + k / 10); + *buf++ = static_cast('0' + (k / 10)); k %= 10; *buf++ = static_cast('0' + k); } else { - *buf++ = static_cast('0' + k / 100); + *buf++ = static_cast('0' + (k / 100)); k %= 100; - *buf++ = static_cast('0' + k / 10); + *buf++ = static_cast('0' + (k / 10)); k %= 10; *buf++ = static_cast('0' + k); } @@ -18651,7 +19230,7 @@ class serializer @param[in] x unsigned integer number to count its digits @return number of decimal digits */ - inline unsigned int count_digits(number_unsigned_t x) noexcept + unsigned int count_digits(number_unsigned_t x) noexcept { unsigned int n_digits = 1; for (;;) @@ -18934,7 +19513,7 @@ class serializer ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte); - const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + const std::size_t index = 256u + (static_cast(state) * 16u) + static_cast(type); JSON_ASSERT(index < utf8d.size()); state = utf8d[index]; return state; @@ -18960,7 +19539,7 @@ class serializer * absolute values of INT_MIN and INT_MAX are usually not the same. See * #1708 for details. */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept + number_unsigned_t remove_sign(number_integer_t x) noexcept { JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) return static_cast(-(x + 1)) + 1; @@ -19005,7 +19584,7 @@ NLOHMANN_JSON_NAMESPACE_END // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -19030,7 +19609,7 @@ NLOHMANN_JSON_NAMESPACE_BEGIN /// for use within nlohmann::basic_json template , class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> + struct ordered_map : std::vector, Allocator> { using key_type = Key; using mapped_type = T; @@ -19345,7 +19924,7 @@ template , template using require_input_iter = typename std::enable_if::iterator_category, - std::input_iterator_tag>::value>::type; + std::input_iterator_tag>::value>::type; template> void insert(InputIt first, InputIt last) @@ -19416,9 +19995,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec friend class ::nlohmann::detail::binary_writer; template friend class ::nlohmann::detail::binary_reader; - template + template friend class ::nlohmann::detail::json_sax_dom_parser; - template + template friend class ::nlohmann::detail::json_sax_dom_callback_parser; friend class ::nlohmann::detail::exception; @@ -19439,7 +20018,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ) { return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); + std::move(cb), allow_exceptions, ignore_comments); } private: @@ -20052,10 +20631,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return it; } - reference set_parent(reference j, std::size_t old_capacity = static_cast(-1)) + reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size()) { #if JSON_DIAGNOSTICS - if (old_capacity != static_cast(-1)) + if (old_capacity != detail::unknown_size()) { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); @@ -20135,8 +20714,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape) - JSONSerializer::to_json(std::declval(), - std::forward(val)))) + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); set_parents(); @@ -20149,6 +20728,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::enable_if_t < detail::is_basic_json::value&& !std::is_same::value, int > = 0 > basic_json(const BasicJsonType& val) +#if JSON_DIAGNOSTIC_POSITIONS + : start_position(val.start_pos()), + end_position(val.end_pos()) +#endif { using other_boolean_t = typename BasicJsonType::boolean_t; using other_number_float_t = typename BasicJsonType::number_float_t; @@ -20195,6 +20778,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } JSON_ASSERT(m_data.m_type == val.type()); + set_parents(); assert_invariant(); } @@ -20331,7 +20915,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class InputIT, typename std::enable_if < std::is_same::value || std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) + basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param) { JSON_ASSERT(first.m_object != nullptr); JSON_ASSERT(last.m_object != nullptr); @@ -20446,6 +21030,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) : json_base_class_t(other) +#if JSON_DIAGNOSTIC_POSITIONS + , start_position(other.start_position) + , end_position(other.end_position) +#endif { m_data.m_type = other.m_data.m_type; // check of passed value is valid @@ -20515,15 +21103,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept : json_base_class_t(std::forward(other)), - m_data(std::move(other.m_data)) + m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check +#if JSON_DIAGNOSTIC_POSITIONS + , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check + , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check +#endif { // check that passed value is valid - other.assert_invariant(false); + other.assert_invariant(false); // cppcheck-suppress[accessForwarded] // invalidate payload other.m_data.m_type = value_t::null; other.m_data.m_value = {}; +#if JSON_DIAGNOSTIC_POSITIONS + other.start_position = std::string::npos; + other.end_position = std::string::npos; +#endif + set_parents(); assert_invariant(); } @@ -20544,6 +21141,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec using std::swap; swap(m_data.m_type, other.m_data.m_type); swap(m_data.m_value, other.m_data.m_value); + +#if JSON_DIAGNOSTIC_POSITIONS + swap(start_position, other.start_position); + swap(end_position, other.end_position); +#endif + json_base_class_t::operator=(std::move(other)); set_parents(); @@ -20765,13 +21368,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) @@ -20906,7 +21509,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) + JSONSerializer::from_json(std::declval(), std::declval()))) { auto ret = ValueType(); JSONSerializer::from_json(*this, ret); @@ -20948,7 +21551,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_non_default_from_json::value, int > = 0 > ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { return JSONSerializer::from_json(*this); } @@ -21098,7 +21701,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::has_from_json::value, int > = 0 > ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) + JSONSerializer::from_json(std::declval(), v))) { JSONSerializer::from_json(*this, v); return v; @@ -21250,7 +21853,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // create better exception explanation JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); - } + } // cppcheck-suppress[missingReturn] } else { @@ -21273,7 +21876,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // create better exception explanation JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); - } + } // cppcheck-suppress[missingReturn] } else { @@ -21418,7 +22021,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief access specified object element /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/ - reference operator[](typename object_t::key_type key) + reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param) { // implicitly convert null value to an empty object if (is_null()) @@ -21728,7 +22331,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class IteratorType, detail::enable_if_t < std::is_same::value || std::is_same::value, int > = 0 > - IteratorType erase(IteratorType pos) + IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param) { // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) @@ -21798,7 +22401,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template < class IteratorType, detail::enable_if_t < std::is_same::value || std::is_same::value, int > = 0 > - IteratorType erase(IteratorType first, IteratorType last) + IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param) { // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) @@ -22565,7 +23168,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @note: This uses std::distance to support GCC 4.8, /// see https://github.com/nlohmann/json/pull/1257 template - iterator insert_iterator(const_iterator pos, Args&& ... args) + iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param) { iterator result(this); JSON_ASSERT(m_data.m_value.array != nullptr); @@ -22584,7 +23187,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, const basic_json& val) + iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) @@ -22604,14 +23207,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, basic_json&& val) + iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param) { return insert(pos, val); } /// @brief inserts copies of element into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) + iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) @@ -22631,7 +23234,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts range of elements into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) + iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) @@ -22662,7 +23265,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts elements from initializer list into array /// @sa https://json.nlohmann.me/api/basic_json/insert/ - iterator insert(const_iterator pos, initializer_list_t ilist) + iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param) { // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) @@ -22682,7 +23285,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief inserts range of elements into object /// @sa https://json.nlohmann.me/api/basic_json/insert/ - void insert(const_iterator first, const_iterator last) + void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param) { // insert only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) @@ -22703,6 +23306,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + set_parents(); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -22714,7 +23318,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief updates a JSON object from another object, overwriting existing keys /// @sa https://json.nlohmann.me/api/basic_json/update/ - void update(const_iterator first, const_iterator last, bool merge_objects = false) + void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param) { // implicitly convert null value to an empty object if (is_null()) @@ -23315,12 +23919,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(detail::input_adapter(std::forward(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded] return result; } @@ -23330,24 +23934,24 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json parse(IteratorType first, IteratorType last, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved] return result; } JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, + parser_callback_t cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false) { basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); + parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved] return result; } @@ -23526,6 +24130,23 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec basic_json* m_parent = nullptr; #endif +#if JSON_DIAGNOSTIC_POSITIONS + /// the start position of the value + std::size_t start_position = std::string::npos; + /// the end position of the value + std::size_t end_position = std::string::npos; + public: + constexpr std::size_t start_pos() const noexcept + { + return start_position; + } + + constexpr std::size_t end_pos() const noexcept + { + return end_position; + } +#endif + ////////////////////////////////////////// // binary serialization/deserialization // ////////////////////////////////////////// @@ -23667,9 +24288,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23683,9 +24304,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23708,10 +24329,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); + const bool res = binary_reader(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23724,9 +24345,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23739,9 +24360,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23762,10 +24383,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23778,9 +24399,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23793,9 +24414,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23816,10 +24437,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23832,9 +24453,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23847,9 +24468,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23862,9 +24483,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23877,9 +24498,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } @@ -23900,10 +24521,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const bool allow_exceptions = true) { basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); auto ia = i.get(); + detail::json_sax_dom_parser sdp(result, allow_exceptions); // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) - const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); + const bool res = binary_reader(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved] return res ? result : basic_json(value_t::discarded); } /// @} @@ -24004,7 +24625,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // the valid JSON Patch operations enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - const auto get_op = [](const std::string & op) + const auto get_op = [](const string_t& op) { if (op == "add") { @@ -24035,7 +24656,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec }; // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) + const auto operation_add = [&result](json_pointer & ptr, const basic_json & val) { // adding to the root of the target document means replacing it if (ptr.empty()) @@ -24141,15 +24762,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec for (const auto& val : json_patch) { // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, + const auto get_value = [&val](const string_t& op, + const string_t& member, bool string_type) -> basic_json & { // find value auto it = val.m_data.m_value.object->find(member); // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); + const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable) // check if desired value is present if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) @@ -24176,8 +24797,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); + const auto op = get_value("op", "op", true).template get(); + const auto path = get_value(op, "path", true).template get(); json_pointer ptr(path); switch (get_op(op)) @@ -24203,7 +24824,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case patch_operations::move: { - const auto from_path = get_value("move", "from", true).template get(); + const auto from_path = get_value("move", "from", true).template get(); json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -24220,7 +24841,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case patch_operations::copy: { - const auto from_path = get_value("copy", "from", true).template get(); + const auto from_path = get_value("copy", "from", true).template get(); const json_pointer from_ptr(from_path); // the "from" location must exist - use at() @@ -24280,7 +24901,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/diff/ JSON_HEDLEY_WARN_UNUSED_RESULT static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") + const string_t& path = "") { // the patch basic_json result(value_t::array); @@ -24310,7 +24931,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec while (i < source.size() && i < target.size()) { // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i))); + auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', detail::to_string(i))); result.insert(result.end(), temp_diff.begin(), temp_diff.end()); ++i; } @@ -24327,7 +24948,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result.insert(result.begin() + end_index, object( { {"op", "remove"}, - {"path", detail::concat(path, '/', std::to_string(i))} + {"path", detail::concat(path, '/', detail::to_string(i))} })); ++i; } @@ -24338,7 +24959,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result.push_back( { {"op", "add"}, - {"path", detail::concat(path, "/-")}, + {"path", detail::concat(path, "/-")}, {"value", target[i]} }); ++i; @@ -24353,7 +24974,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec for (auto it = source.cbegin(); it != source.cend(); ++it) { // escape the key name to be used in a JSON patch - const auto path_key = detail::concat(path, '/', detail::escape(it.key())); + const auto path_key = detail::concat(path, '/', detail::escape(it.key())); if (target.find(it.key()) != target.end()) { @@ -24377,7 +24998,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (source.find(it.key()) == source.end()) { // found a key that is not in this -> add it - const auto path_key = detail::concat(path, '/', detail::escape(it.key())); + const auto path_key = detail::concat(path, '/', detail::escape(it.key())); result.push_back( { {"op", "add"}, {"path", path_key}, @@ -24561,7 +25182,7 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -24606,7 +25227,7 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT diff --git a/external/json/single_include/nlohmann/json_fwd.hpp b/external/json/single_include/nlohmann/json_fwd.hpp index 29a6036d..1df3928d 100644 --- a/external/json/single_include/nlohmann/json_fwd.hpp +++ b/external/json/single_include/nlohmann/json_fwd.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -21,7 +21,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT @@ -44,6 +44,10 @@ #define JSON_DIAGNOSTICS 0 #endif +#ifndef JSON_DIAGNOSTIC_POSITIONS + #define JSON_DIAGNOSTIC_POSITIONS 0 +#endif + #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif @@ -54,6 +58,12 @@ #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS #endif +#if JSON_DIAGNOSTIC_POSITIONS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS +#endif + #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #else @@ -65,14 +75,15 @@ #endif // Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) #define NLOHMANN_JSON_ABI_TAGS \ NLOHMANN_JSON_ABI_TAGS_CONCAT( \ NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) // Construct the namespace version component #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ diff --git a/external/json/tests/abi/config/config.hpp b/external/json/tests/abi/config/config.hpp index 8762b2a6..1e0f41e8 100644 --- a/external/json/tests/abi/config/config.hpp +++ b/external/json/tests/abi/config/config.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/tests/abi/config/custom.cpp b/external/json/tests/abi/config/custom.cpp index 9e5bb898..64644c56 100644 --- a/external/json/tests/abi/config/custom.cpp +++ b/external/json/tests/abi/config/custom.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/abi/config/default.cpp b/external/json/tests/abi/config/default.cpp index d54ca6ff..f210ae95 100644 --- a/external/json/tests/abi/config/default.cpp +++ b/external/json/tests/abi/config/default.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -24,6 +24,10 @@ TEST_CASE("default namespace") expected += "_diag"; #endif +#if JSON_DIAGNOSTIC_POSITIONS + expected += "_dp"; +#endif + #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON expected += "_ldvcmp"; #endif diff --git a/external/json/tests/abi/config/noversion.cpp b/external/json/tests/abi/config/noversion.cpp index 2a7c277d..c76ec11b 100644 --- a/external/json/tests/abi/config/noversion.cpp +++ b/external/json/tests/abi/config/noversion.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -25,6 +25,10 @@ TEST_CASE("default namespace without version component") expected += "_diag"; #endif +#if JSON_DIAGNOSTIC_POSITIONS + expected += "_dp"; +#endif + #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON expected += "_ldvcmp"; #endif diff --git a/external/json/tests/abi/diag/diag.cpp b/external/json/tests/abi/diag/diag.cpp index 286f75db..7cc95bfd 100644 --- a/external/json/tests/abi/diag/diag.cpp +++ b/external/json/tests/abi/diag/diag.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/abi/diag/diag.hpp b/external/json/tests/abi/diag/diag.hpp index 1d4d49e9..030df752 100644 --- a/external/json/tests/abi/diag/diag.hpp +++ b/external/json/tests/abi/diag/diag.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/tests/abi/diag/diag_off.cpp b/external/json/tests/abi/diag/diag_off.cpp index cd0d178f..63d8ab96 100644 --- a/external/json/tests/abi/diag/diag_off.cpp +++ b/external/json/tests/abi/diag/diag_off.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #undef JSON_DIAGNOSTICS diff --git a/external/json/tests/abi/diag/diag_on.cpp b/external/json/tests/abi/diag/diag_on.cpp index 197a2c0c..7bdca137 100644 --- a/external/json/tests/abi/diag/diag_on.cpp +++ b/external/json/tests/abi/diag/diag_on.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #undef JSON_DIAGNOSTICS diff --git a/external/json/tests/abi/inline_ns/use_current.cpp b/external/json/tests/abi/inline_ns/use_current.cpp index cb07dd33..ba2b5495 100644 --- a/external/json/tests/abi/inline_ns/use_current.cpp +++ b/external/json/tests/abi/inline_ns/use_current.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/abi/inline_ns/use_v3_10_5.cpp b/external/json/tests/abi/inline_ns/use_v3_10_5.cpp index 7a427539..79cf658d 100644 --- a/external/json/tests/abi/inline_ns/use_v3_10_5.cpp +++ b/external/json/tests/abi/inline_ns/use_v3_10_5.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/abi/main.cpp b/external/json/tests/abi/main.cpp index 0a4805e7..523cda91 100644 --- a/external/json/tests/abi/main.cpp +++ b/external/json/tests/abi/main.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN diff --git a/external/json/tests/benchmarks/src/benchmarks.cpp b/external/json/tests/benchmarks/src/benchmarks.cpp index 0210b9fe..40be5ec2 100644 --- a/external/json/tests/benchmarks/src/benchmarks.cpp +++ b/external/json/tests/benchmarks/src/benchmarks.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include @@ -140,6 +140,46 @@ BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/si BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json"); BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json"); +////////////////////////////////////////////////////////////////////////////// +// Parse Msgpack +////////////////////////////////////////////////////////////////////////////// + +static void FromMsgpack(benchmark::State& state, const char* filename) +{ + std::ifstream f(filename); + std::string str((std::istreambuf_iterator(f)), std::istreambuf_iterator()); + auto bytes = json::to_msgpack(json::parse(str)); + std::ofstream o("test.msgpack"); + o.write((char*)bytes.data(), bytes.size()); + o.flush(); + o.close(); + for (auto _ : state) + { + state.PauseTiming(); + auto* j = new json(); + auto file = fopen("test.msgpack", "rb"); + state.ResumeTiming(); + + *j = json::from_msgpack(file); + + state.PauseTiming(); + fclose(file); + delete j; + state.ResumeTiming(); + } + + state.SetBytesProcessed(state.iterations() * bytes.size()); +} + +BENCHMARK_CAPTURE(FromMsgpack, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json"); +BENCHMARK_CAPTURE(FromMsgpack, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json"); +BENCHMARK_CAPTURE(FromMsgpack, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json"); +BENCHMARK_CAPTURE(FromMsgpack, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json"); +BENCHMARK_CAPTURE(FromMsgpack, floats, TEST_DATA_DIRECTORY "/regression/floats.json"); +BENCHMARK_CAPTURE(FromMsgpack, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json"); +BENCHMARK_CAPTURE(FromMsgpack, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json"); +BENCHMARK_CAPTURE(FromMsgpack, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json"); + ////////////////////////////////////////////////////////////////////////////// // serialize binary CBOR ////////////////////////////////////////////////////////////////////////////// diff --git a/external/json/tests/cmake_add_subdirectory/project/main.cpp b/external/json/tests/cmake_add_subdirectory/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_add_subdirectory/project/main.cpp +++ b/external/json/tests/cmake_add_subdirectory/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_fetch_content/project/main.cpp b/external/json/tests/cmake_fetch_content/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_fetch_content/project/main.cpp +++ b/external/json/tests/cmake_fetch_content/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_fetch_content2/project/main.cpp b/external/json/tests/cmake_fetch_content2/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_fetch_content2/project/main.cpp +++ b/external/json/tests/cmake_fetch_content2/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_import/project/main.cpp b/external/json/tests/cmake_import/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_import/project/main.cpp +++ b/external/json/tests/cmake_import/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_import_minver/project/main.cpp b/external/json/tests/cmake_import_minver/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_import_minver/project/main.cpp +++ b/external/json/tests/cmake_import_minver/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_target_include_directories/project/Bar.cpp b/external/json/tests/cmake_target_include_directories/project/Bar.cpp index 83a14bc8..adcdc87c 100644 --- a/external/json/tests/cmake_target_include_directories/project/Bar.cpp +++ b/external/json/tests/cmake_target_include_directories/project/Bar.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "Bar.hpp" diff --git a/external/json/tests/cmake_target_include_directories/project/Bar.hpp b/external/json/tests/cmake_target_include_directories/project/Bar.hpp index a56257c3..ddfb9e75 100644 --- a/external/json/tests/cmake_target_include_directories/project/Bar.hpp +++ b/external/json/tests/cmake_target_include_directories/project/Bar.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cmake_target_include_directories/project/Foo.cpp b/external/json/tests/cmake_target_include_directories/project/Foo.cpp index 42e950e7..c3ffe11e 100644 --- a/external/json/tests/cmake_target_include_directories/project/Foo.cpp +++ b/external/json/tests/cmake_target_include_directories/project/Foo.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "Foo.hpp" diff --git a/external/json/tests/cmake_target_include_directories/project/Foo.hpp b/external/json/tests/cmake_target_include_directories/project/Foo.hpp index 18fe9763..a26dead0 100644 --- a/external/json/tests/cmake_target_include_directories/project/Foo.hpp +++ b/external/json/tests/cmake_target_include_directories/project/Foo.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/tests/cmake_target_include_directories/project/main.cpp b/external/json/tests/cmake_target_include_directories/project/main.cpp index 6db94486..ebdde5c8 100644 --- a/external/json/tests/cmake_target_include_directories/project/main.cpp +++ b/external/json/tests/cmake_target_include_directories/project/main.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/cuda_example/json_cuda.cu b/external/json/tests/cuda_example/json_cuda.cu index 65759666..02084a79 100644 --- a/external/json/tests/cuda_example/json_cuda.cu +++ b/external/json/tests/cuda_example/json_cuda.cu @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include diff --git a/external/json/tests/src/fuzzer-driver_afl.cpp b/external/json/tests/src/fuzzer-driver_afl.cpp index ae3aefe1..79767bae 100644 --- a/external/json/tests/src/fuzzer-driver_afl.cpp +++ b/external/json/tests/src/fuzzer-driver_afl.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_bjdata.cpp b/external/json/tests/src/fuzzer-parse_bjdata.cpp index 30f1ddd0..b5a209ea 100644 --- a/external/json/tests/src/fuzzer-parse_bjdata.cpp +++ b/external/json/tests/src/fuzzer-parse_bjdata.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_bson.cpp b/external/json/tests/src/fuzzer-parse_bson.cpp index fa2a221d..0b02323b 100644 --- a/external/json/tests/src/fuzzer-parse_bson.cpp +++ b/external/json/tests/src/fuzzer-parse_bson.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_cbor.cpp b/external/json/tests/src/fuzzer-parse_cbor.cpp index db92aca8..2bdf2348 100644 --- a/external/json/tests/src/fuzzer-parse_cbor.cpp +++ b/external/json/tests/src/fuzzer-parse_cbor.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_json.cpp b/external/json/tests/src/fuzzer-parse_json.cpp index be04e803..d06c0626 100644 --- a/external/json/tests/src/fuzzer-parse_json.cpp +++ b/external/json/tests/src/fuzzer-parse_json.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_msgpack.cpp b/external/json/tests/src/fuzzer-parse_msgpack.cpp index 0106b405..7737a8a5 100644 --- a/external/json/tests/src/fuzzer-parse_msgpack.cpp +++ b/external/json/tests/src/fuzzer-parse_msgpack.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/fuzzer-parse_ubjson.cpp b/external/json/tests/src/fuzzer-parse_ubjson.cpp index 2830bef7..f2331865 100644 --- a/external/json/tests/src/fuzzer-parse_ubjson.cpp +++ b/external/json/tests/src/fuzzer-parse_ubjson.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT /* diff --git a/external/json/tests/src/make_test_data_available.hpp b/external/json/tests/src/make_test_data_available.hpp index a2ffefa8..06f49986 100644 --- a/external/json/tests/src/make_test_data_available.hpp +++ b/external/json/tests/src/make_test_data_available.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/tests/src/test_utils.hpp b/external/json/tests/src/test_utils.hpp index dbb0a9b1..25af71c0 100644 --- a/external/json/tests/src/test_utils.hpp +++ b/external/json/tests/src/test_utils.hpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once diff --git a/external/json/tests/src/unit-32bit.cpp b/external/json/tests/src/unit-32bit.cpp index 22a2ad28..93a54a97 100644 --- a/external/json/tests/src/unit-32bit.cpp +++ b/external/json/tests/src/unit-32bit.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -23,7 +23,7 @@ struct trait_test_arg static constexpr bool max_in_range = MaxInRange; }; -TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) +TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) // NOLINT(readability-math-missing-parentheses) { using nlohmann::detail::value_in_range_of; diff --git a/external/json/tests/src/unit-algorithms.cpp b/external/json/tests/src/unit-algorithms.cpp index 3fb1640d..871f0409 100644 --- a/external/json/tests/src/unit-algorithms.cpp +++ b/external/json/tests/src/unit-algorithms.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-allocator.cpp b/external/json/tests/src/unit-allocator.cpp index 399c8bfa..cf401a02 100644 --- a/external/json/tests/src/unit-allocator.cpp +++ b/external/json/tests/src/unit-allocator.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-alt-string.cpp b/external/json/tests/src/unit-alt-string.cpp index 7efe2e2e..164ff5e4 100644 --- a/external/json/tests/src/unit-alt-string.cpp +++ b/external/json/tests/src/unit-alt-string.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-FileCopyrightText: 2018 Vitaliy Manushkin // SPDX-License-Identifier: MIT @@ -16,8 +16,8 @@ /* forward declarations */ class alt_string; -bool operator<(const char* op1, const alt_string& op2) noexcept; -void int_to_string(alt_string& target, std::size_t value); +bool operator<(const char* op1, const alt_string& op2) noexcept; // NOLINT(misc-use-internal-linkage) +void int_to_string(alt_string& target, std::size_t value); // NOLINT(misc-use-internal-linkage) /* * This is virtually a string class. @@ -28,17 +28,28 @@ class alt_string public: using value_type = std::string::value_type; - static constexpr auto npos = static_cast(-1); + static constexpr auto npos = (std::numeric_limits::max)(); alt_string(const char* str): str_impl(str) {} alt_string(const char* str, std::size_t count): str_impl(str, count) {} alt_string(size_t count, char chr): str_impl(count, chr) {} alt_string() = default; - template - alt_string& append(TParams&& ...params) + alt_string& append(char ch) { - str_impl.append(std::forward(params)...); + str_impl.push_back(ch); + return *this; + } + + alt_string& append(const alt_string& str) + { + str_impl.append(str.str_impl); + return *this; + } + + alt_string& append(const char* s, std::size_t length) + { + str_impl.append(s, length); return *this; } @@ -157,8 +168,13 @@ class alt_string return *this; } + void reserve( std::size_t new_cap = 0 ) + { + str_impl.reserve(new_cap); + } + private: - std::string str_impl {}; + std::string str_impl {}; // NOLINT(readability-redundant-member-init) friend bool operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept; }; @@ -319,4 +335,28 @@ TEST_CASE("alternative string type") CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]); CHECK(j.at(alt_json::json_pointer("/foo/1")) == j["foo"][1]); } + + SECTION("patch") + { + alt_json const patch1 = alt_json::parse(R"([{ "op": "add", "path": "/a/b", "value": [ "foo", "bar" ] }])"); + alt_json const doc1 = alt_json::parse(R"({ "a": { "foo": 1 } })"); + + CHECK_NOTHROW(doc1.patch(patch1)); + alt_json doc1_ans = alt_json::parse(R"( + { + "a": { + "foo": 1, + "b": [ "foo", "bar" ] + } + } + )"); + CHECK(doc1.patch(patch1) == doc1_ans); + } + + SECTION("diff") + { + alt_json const j1 = {"foo", "bar", "baz"}; + alt_json const j2 = {"foo", "bam"}; + CHECK(alt_json::diff(j1, j2).dump() == "[{\"op\":\"replace\",\"path\":\"/1\",\"value\":\"bam\"},{\"op\":\"remove\",\"path\":\"/2\"}]"); + } } diff --git a/external/json/tests/src/unit-assert_macro.cpp b/external/json/tests/src/unit-assert_macro.cpp index 55eb3b9e..ce336285 100644 --- a/external/json/tests/src/unit-assert_macro.cpp +++ b/external/json/tests/src/unit-assert_macro.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-binary_formats.cpp b/external/json/tests/src/unit-binary_formats.cpp index b41a6fec..b8ca315d 100644 --- a/external/json/tests/src/unit-binary_formats.cpp +++ b/external/json/tests/src/unit-binary_formats.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-bjdata.cpp b/external/json/tests/src/unit-bjdata.cpp index 9f247fe6..cf770e5f 100644 --- a/external/json/tests/src/unit-bjdata.cpp +++ b/external/json/tests/src/unit-bjdata.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -109,7 +109,7 @@ struct trait_test_arg static constexpr bool max_in_range = MaxInRange; }; -TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) +TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) // NOLINT(readability-math-missing-parentheses) { using nlohmann::detail::value_in_range_of; @@ -339,13 +339,13 @@ TEST_CASE("BJData") std::vector const numbers { -32769, - -100000, - -1000000, - -10000000, - -100000000, - -1000000000, - -2147483647 - 1, // https://stackoverflow.com/a/29356002/266378 - }; + -100000, + -1000000, + -10000000, + -100000000, + -1000000000, + -2147483647 - 1, // https://stackoverflow.com/a/29356002/266378 + }; for (const auto i : numbers) { CAPTURE(i) @@ -573,7 +573,7 @@ TEST_CASE("BJData") // check individual bytes CHECK(result[0] == 'I'); - auto const restored = static_cast(static_cast(result[2]) * 256 + static_cast(result[1])); + auto const restored = static_cast((static_cast(result[2]) * 256) + static_cast(result[1])); CHECK(restored == i); // roundtrip @@ -613,7 +613,7 @@ TEST_CASE("BJData") // check individual bytes CHECK(result[0] == 'u'); - auto const restored = static_cast(static_cast(result[2]) * 256 + static_cast(result[1])); + auto const restored = static_cast((static_cast(result[2]) * 256) + static_cast(result[1])); CHECK(restored == i); // roundtrip @@ -905,7 +905,7 @@ TEST_CASE("BJData") // check individual bytes CHECK(result[0] == 'I'); - auto const restored = static_cast(static_cast(result[2]) * 256 + static_cast(result[1])); + auto const restored = static_cast((static_cast(result[2]) * 256) + static_cast(result[1])); CHECK(restored == i); // roundtrip @@ -944,7 +944,7 @@ TEST_CASE("BJData") // check individual bytes CHECK(result[0] == 'u'); - auto const restored = static_cast(static_cast(result[2]) * 256 + static_cast(result[1])); + auto const restored = static_cast((static_cast(result[2]) * 256) + static_cast(result[1])); CHECK(restored == i); // roundtrip diff --git a/external/json/tests/src/unit-bson.cpp b/external/json/tests/src/unit-bson.cpp index 13216f2f..96188108 100644 --- a/external/json/tests/src/unit-bson.cpp +++ b/external/json/tests/src/unit-bson.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -621,7 +621,7 @@ TEST_CASE("BSON input/output_adapters") { SECTION("std::ostringstream") { - std::basic_ostringstream ss; + std::basic_ostringstream ss; json::to_bson(json_representation, ss); json j3 = json::from_bson(ss.str()); CHECK(json_representation == j3); diff --git a/external/json/tests/src/unit-byte_container_with_subtype.cpp b/external/json/tests/src/unit-byte_container_with_subtype.cpp index 4116076b..227655e8 100644 --- a/external/json/tests/src/unit-byte_container_with_subtype.cpp +++ b/external/json/tests/src/unit-byte_container_with_subtype.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-capacity.cpp b/external/json/tests/src/unit-capacity.cpp index 61203cc2..9f8e9ffb 100644 --- a/external/json/tests/src/unit-capacity.cpp +++ b/external/json/tests/src/unit-capacity.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-cbor.cpp b/external/json/tests/src/unit-cbor.cpp index be94d2f6..b505cb92 100644 --- a/external/json/tests/src/unit-cbor.cpp +++ b/external/json/tests/src/unit-cbor.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -14,7 +14,6 @@ using nlohmann::json; #include #include #include -#include #include #include #include "make_test_data_available.hpp" @@ -241,13 +240,13 @@ TEST_CASE("CBOR") const std::vector numbers { -65537, - -100000, - -1000000, - -10000000, - -100000000, - -1000000000, - -4294967296, - }; + -100000, + -1000000, + -10000000, + -100000000, + -1000000000, + -4294967296, + }; for (const auto i : numbers) { CAPTURE(i) @@ -317,7 +316,7 @@ TEST_CASE("CBOR") // check individual bytes CHECK(result[0] == 0x39); - const auto restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + const auto restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == positive); CHECK(-1 - restored == i); @@ -505,7 +504,7 @@ TEST_CASE("CBOR") // check individual bytes CHECK(result[0] == 0x19); - const auto restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + const auto restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -744,7 +743,7 @@ TEST_CASE("CBOR") // check individual bytes CHECK(result[0] == 0x19); - const auto restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + const auto restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -990,7 +989,7 @@ TEST_CASE("CBOR") { 0xfa, 0xff, 0x7f, 0xff, 0xff }; - // the same with lowest float + // the same with the lowest float const auto result = json::to_cbor(j); CHECK(result == expected); // roundtrip @@ -1632,7 +1631,7 @@ TEST_CASE("CBOR") }; json j; - auto cbp = nlohmann::detail::json_sax_dom_callback_parser(j, callback, true); + auto cbp = nlohmann::detail::json_sax_dom_callback_parser(j, callback, true); CHECK(json::sax_parse(input, &cbp, json::input_format_t::cbor)); CHECK(j.at("foo").is_binary()); CHECK(binary_seen); @@ -1881,7 +1880,7 @@ TEST_CASE("single CBOR roundtrip") { SECTION("std::ostringstream") { - std::basic_ostringstream ss; + std::basic_ostringstream ss; json::to_cbor(j1, ss); json j3 = json::from_cbor(ss.str()); CHECK(j1 == j3); diff --git a/external/json/tests/src/unit-class_const_iterator.cpp b/external/json/tests/src/unit-class_const_iterator.cpp index 003ce889..6b5f989c 100644 --- a/external/json/tests/src/unit-class_const_iterator.cpp +++ b/external/json/tests/src/unit-class_const_iterator.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-class_iterator.cpp b/external/json/tests/src/unit-class_iterator.cpp index 296ffa3f..ef49665e 100644 --- a/external/json/tests/src/unit-class_iterator.cpp +++ b/external/json/tests/src/unit-class_iterator.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-class_lexer.cpp b/external/json/tests/src/unit-class_lexer.cpp index ac029253..dba0cb2e 100644 --- a/external/json/tests/src/unit-class_lexer.cpp +++ b/external/json/tests/src/unit-class_lexer.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -23,7 +23,7 @@ json::lexer::token_type scan_string(const char* s, const bool ignore_comments) } } // namespace -std::string get_error_message(const char* s, bool ignore_comments = false); +std::string get_error_message(const char* s, bool ignore_comments = false); // NOLINT(misc-use-internal-linkage) std::string get_error_message(const char* s, const bool ignore_comments) { auto ia = nlohmann::detail::input_adapter(s); diff --git a/external/json/tests/src/unit-class_parser.cpp b/external/json/tests/src/unit-class_parser.cpp index f766842a..b48b8000 100644 --- a/external/json/tests/src/unit-class_parser.cpp +++ b/external/json/tests/src/unit-class_parser.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -75,7 +75,7 @@ class SaxEventLogger bool start_object(std::size_t elements) { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_object()"); } @@ -100,7 +100,7 @@ class SaxEventLogger bool start_array(std::size_t elements) { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_array()"); } @@ -124,7 +124,7 @@ class SaxEventLogger return false; } - std::vector events {}; + std::vector events {}; // NOLINT(readability-redundant-member-init) bool errored = false; }; @@ -219,7 +219,7 @@ json parser_helper(const std::string& s) CHECK(j_nothrow == j); json j_sax; - nlohmann::detail::json_sax_dom_parser sdp(j_sax); + nlohmann::detail::json_sax_dom_parser sdp(j_sax); json::sax_parse(s, &sdp); CHECK(j_sax == j); @@ -828,7 +828,7 @@ TEST_CASE("parser class") // for ranges in range of IEEE 754-2008 binary64 (double precision) // this does not accommodate 64 bit integers without loss of accuracy. // As 64 bit integers are now widely used in software, it is desirable - // to expand support to to the full 64 bit (signed and unsigned) range + // to expand support to the full 64 bit (signed and unsigned) range // i.e. -(2**63) -> (2**64)-1. // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1)) diff --git a/external/json/tests/src/unit-class_parser_diagnostic_positions.cpp b/external/json/tests/src/unit-class_parser_diagnostic_positions.cpp new file mode 100644 index 00000000..3b796a16 --- /dev/null +++ b/external/json/tests/src/unit-class_parser_diagnostic_positions.cpp @@ -0,0 +1,1957 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" +#define JSON_TESTS_PRIVATE +#ifdef JSON_DIAGNOSTIC_POSITIONS + #undef JSON_DIAGNOSTIC_POSITIONS +#endif + +#define JSON_DIAGNOSTIC_POSITIONS 1 +#include +using nlohmann::json; + +#ifdef JSON_TEST_NO_GLOBAL_UDLS + using namespace nlohmann::literals; // NOLINT(google-build-using-namespace) +#endif + +#include + +namespace +{ +class SaxEventLogger +{ + public: + bool null() + { + events.emplace_back("null()"); + return true; + } + + bool boolean(bool val) + { + events.emplace_back(val ? "boolean(true)" : "boolean(false)"); + return true; + } + + bool number_integer(json::number_integer_t val) + { + events.push_back("number_integer(" + std::to_string(val) + ")"); + return true; + } + + bool number_unsigned(json::number_unsigned_t val) + { + events.push_back("number_unsigned(" + std::to_string(val) + ")"); + return true; + } + + bool number_float(json::number_float_t /*unused*/, const std::string& s) + { + events.push_back("number_float(" + s + ")"); + return true; + } + + bool string(std::string& val) + { + events.push_back("string(" + val + ")"); + return true; + } + + bool binary(json::binary_t& val) + { + std::string binary_contents = "binary("; + std::string comma_space; + for (auto b : val) + { + binary_contents.append(comma_space); + binary_contents.append(std::to_string(static_cast(b))); + comma_space = ", "; + } + binary_contents.append(")"); + events.push_back(binary_contents); + return true; + } + + bool start_object(std::size_t elements) + { + if (elements == (std::numeric_limits::max)()) + { + events.emplace_back("start_object()"); + } + else + { + events.push_back("start_object(" + std::to_string(elements) + ")"); + } + return true; + } + + bool key(std::string& val) + { + events.push_back("key(" + val + ")"); + return true; + } + + bool end_object() + { + events.emplace_back("end_object()"); + return true; + } + + bool start_array(std::size_t elements) + { + if (elements == (std::numeric_limits::max)()) + { + events.emplace_back("start_array()"); + } + else + { + events.push_back("start_array(" + std::to_string(elements) + ")"); + } + return true; + } + + bool end_array() + { + events.emplace_back("end_array()"); + return true; + } + + bool parse_error(std::size_t position, const std::string& /*unused*/, const json::exception& /*unused*/) + { + errored = true; + events.push_back("parse_error(" + std::to_string(position) + ")"); + return false; + } + + std::vector events {}; // NOLINT(readability-redundant-member-init) + bool errored = false; +}; + +class SaxCountdown : public nlohmann::json::json_sax_t +{ + public: + explicit SaxCountdown(const int count) : events_left(count) + {} + + bool null() override + { + return events_left-- > 0; + } + + bool boolean(bool /*val*/) override + { + return events_left-- > 0; + } + + bool number_integer(json::number_integer_t /*val*/) override + { + return events_left-- > 0; + } + + bool number_unsigned(json::number_unsigned_t /*val*/) override + { + return events_left-- > 0; + } + + bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override + { + return events_left-- > 0; + } + + bool string(std::string& /*val*/) override + { + return events_left-- > 0; + } + + bool binary(json::binary_t& /*val*/) override + { + return events_left-- > 0; + } + + bool start_object(std::size_t /*elements*/) override + { + return events_left-- > 0; + } + + bool key(std::string& /*val*/) override + { + return events_left-- > 0; + } + + bool end_object() override + { + return events_left-- > 0; + } + + bool start_array(std::size_t /*elements*/) override + { + return events_left-- > 0; + } + + bool end_array() override + { + return events_left-- > 0; + } + + bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override + { + return false; + } + + private: + int events_left = 0; +}; + +json parser_helper(const std::string& s); +bool accept_helper(const std::string& s); +void comments_helper(const std::string& s); + +json parser_helper(const std::string& s) +{ + json j; + json::parser(nlohmann::detail::input_adapter(s)).parse(true, j); + + // if this line was reached, no exception occurred + // -> check if result is the same without exceptions + json j_nothrow; + CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow)); + CHECK(j_nothrow == j); + + json j_sax; + nlohmann::detail::json_sax_dom_parser sdp(j_sax); + json::sax_parse(s, &sdp); + CHECK(j_sax == j); + + comments_helper(s); + + return j; +} + +bool accept_helper(const std::string& s) +{ + CAPTURE(s) + + // 1. parse s without exceptions + json j; + CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j)); + const bool ok_noexcept = !j.is_discarded(); + + // 2. accept s + const bool ok_accept = json::parser(nlohmann::detail::input_adapter(s)).accept(true); + + // 3. check if both approaches come to the same result + CHECK(ok_noexcept == ok_accept); + + // 4. parse with SAX (compare with relaxed accept result) + SaxEventLogger el; + CHECK_NOTHROW(json::sax_parse(s, &el, json::input_format_t::json, false)); + CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == !el.errored); + + // 5. parse with simple callback + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept + { + return true; + }; + json const j_cb = json::parse(s, cb, false); + const bool ok_noexcept_cb = !j_cb.is_discarded(); + + // 6. check if this approach came to the same result + CHECK(ok_noexcept == ok_noexcept_cb); + + // 7. check if comments are properly ignored + if (ok_accept) + { + comments_helper(s); + } + + // 8. return result + return ok_accept; +} + +void comments_helper(const std::string& s) +{ + json _; + + // parse/accept with default parser + CHECK_NOTHROW(_ = json::parse(s)); + CHECK(json::accept(s)); + + // parse/accept while skipping comments + CHECK_NOTHROW(_ = json::parse(s, nullptr, false, true)); + CHECK(json::accept(s, true)); + + std::vector json_with_comments; + + // start with a comment + json_with_comments.push_back(std::string("// this is a comment\n") + s); + json_with_comments.push_back(std::string("/* this is a comment */") + s); + // end with a comment + json_with_comments.push_back(s + "// this is a comment"); + json_with_comments.push_back(s + "/* this is a comment */"); + + // check all strings + for (const auto& json_with_comment : json_with_comments) + { + CAPTURE(json_with_comment) + CHECK_THROWS_AS(_ = json::parse(json_with_comment), json::parse_error); + CHECK(!json::accept(json_with_comment)); + + CHECK_NOTHROW(_ = json::parse(json_with_comment, nullptr, true, true)); + CHECK(json::accept(json_with_comment, true)); + } +} + +/** + * Validates that the generated JSON object is the same as expected + * Validates that the start position and end position match the start and end of the string + * + * This check assumes that there is no whitespace around the json object in the original string. + */ +void validate_generated_json_and_start_end_pos_helper(const std::string& original_string, const json& j, const json& check) +{ + CHECK(j == check); + CHECK(j.start_pos() == 0); + CHECK(j.end_pos() == original_string.size()); +} + +/** + * Parses the root object from the given root string and validates that the start and end positions for the nested object are correct. + * + * This checks that whitespace around the nested object is included in the start and end positions of the root object. + */ +void validate_start_end_pos_for_nested_obj_helper(const std::string& nested_type_json_str, const std::string& root_type_json_str, const json& expected_json, const json::parser_callback_t& cb = nullptr) +{ + json j; + + // 1. If callback is provided, use callback version of parse() + if (cb) + { + j = json::parse(root_type_json_str, cb); + } + else + { + j = json::parse(root_type_json_str); + } + + // 2. Check if the generated JSON is as expected + // Assumptions: The root_type_json_str does not have any whitespace around the json object + validate_generated_json_and_start_end_pos_helper(root_type_json_str, j, expected_json); + + // 3. Get the nested object + const auto& nested = j["nested"]; + // 4. Check if the start and end positions are generated correctly for nested objects and arrays + CHECK(nested_type_json_str == root_type_json_str.substr(nested.start_pos(), nested.end_pos() - nested.start_pos())); +} + +} // namespace + +TEST_CASE("parser class") +{ + SECTION("parse") + { + SECTION("null") + { + CHECK(parser_helper("null") == json(nullptr)); + } + + SECTION("true") + { + CHECK(parser_helper("true") == json(true)); + } + + SECTION("false") + { + CHECK(parser_helper("false") == json(false)); + } + + SECTION("array") + { + SECTION("empty array") + { + CHECK(parser_helper("[]") == json(json::value_t::array)); + CHECK(parser_helper("[ ]") == json(json::value_t::array)); + } + + SECTION("nonempty array") + { + CHECK(parser_helper("[true, false, null]") == json({true, false, nullptr})); + } + } + + SECTION("object") + { + SECTION("empty object") + { + CHECK(parser_helper("{}") == json(json::value_t::object)); + CHECK(parser_helper("{ }") == json(json::value_t::object)); + } + + SECTION("nonempty object") + { + CHECK(parser_helper("{\"\": true, \"one\": 1, \"two\": null}") == json({{"", true}, {"one", 1}, {"two", nullptr}})); + } + } + + SECTION("string") + { + // empty string + CHECK(parser_helper("\"\"") == json(json::value_t::string)); + + SECTION("errors") + { + // error: tab in string + CHECK_THROWS_WITH_AS(parser_helper("\"\t\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"'", json::parse_error&); + // error: newline in string + CHECK_THROWS_WITH_AS(parser_helper("\"\n\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\r\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"'", json::parse_error&); + // error: backspace in string + CHECK_THROWS_WITH_AS(parser_helper("\"\b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"'", json::parse_error&); + // improve code coverage + CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&); + // unescaped control characters + CHECK_THROWS_WITH_AS(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'", json::parse_error&); // NOLINT(bugprone-string-literal-with-embedded-nul) + CHECK_THROWS_WITH_AS(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0001 (SOH) must be escaped to \\u0001; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0002 (STX) must be escaped to \\u0002; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0003 (ETX) must be escaped to \\u0003; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0004 (EOT) must be escaped to \\u0004; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0005 (ENQ) must be escaped to \\u0005; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0006 (ACK) must be escaped to \\u0006; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0007 (BEL) must be escaped to \\u0007; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000B (VT) must be escaped to \\u000B; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000E (SO) must be escaped to \\u000E; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000F (SI) must be escaped to \\u000F; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0010 (DLE) must be escaped to \\u0010; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0011 (DC1) must be escaped to \\u0011; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0012 (DC2) must be escaped to \\u0012; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0013 (DC3) must be escaped to \\u0013; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0014 (DC4) must be escaped to \\u0014; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0015 (NAK) must be escaped to \\u0015; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0016 (SYN) must be escaped to \\u0016; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0017 (ETB) must be escaped to \\u0017; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0018 (CAN) must be escaped to \\u0018; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0019 (EM) must be escaped to \\u0019; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001A (SUB) must be escaped to \\u001A; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001B (ESC) must be escaped to \\u001B; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001C (FS) must be escaped to \\u001C; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001D (GS) must be escaped to \\u001D; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001E (RS) must be escaped to \\u001E; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001F (US) must be escaped to \\u001F; last read: '\"'", json::parse_error&); + + SECTION("additional test for null byte") + { + // The test above for the null byte is wrong, because passing + // a string to the parser only reads int until it encounters + // a null byte. This test inserts the null byte later on and + // uses an iterator range. + std::string s = "\"1\""; + s[1] = '\0'; + json _; + CHECK_THROWS_WITH_AS(_ = json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"'", json::parse_error&); + } + } + + SECTION("escaped") + { + // quotation mark "\"" + auto r1 = R"("\"")"_json; + CHECK(parser_helper("\"\\\"\"") == r1); + // reverse solidus "\\" + auto r2 = R"("\\")"_json; + CHECK(parser_helper("\"\\\\\"") == r2); + // solidus + CHECK(parser_helper("\"\\/\"") == R"("/")"_json); + // backspace + CHECK(parser_helper("\"\\b\"") == json("\b")); + // formfeed + CHECK(parser_helper("\"\\f\"") == json("\f")); + // newline + CHECK(parser_helper("\"\\n\"") == json("\n")); + // carriage return + CHECK(parser_helper("\"\\r\"") == json("\r")); + // horizontal tab + CHECK(parser_helper("\"\\t\"") == json("\t")); + + CHECK(parser_helper("\"\\u0001\"").get() == "\x01"); + CHECK(parser_helper("\"\\u000a\"").get() == "\n"); + CHECK(parser_helper("\"\\u00b0\"").get() == "°"); + CHECK(parser_helper("\"\\u0c00\"").get() == "ఀ"); + CHECK(parser_helper("\"\\ud000\"").get() == "퀀"); + CHECK(parser_helper("\"\\u000E\"").get() == "\x0E"); + CHECK(parser_helper("\"\\u00F0\"").get() == "ð"); + CHECK(parser_helper("\"\\u0100\"").get() == "Ā"); + CHECK(parser_helper("\"\\u2000\"").get() == " "); + CHECK(parser_helper("\"\\uFFFF\"").get() == "￿"); + CHECK(parser_helper("\"\\u20AC\"").get() == "€"); + CHECK(parser_helper("\"€\"").get() == "€"); + CHECK(parser_helper("\"🎈\"").get() == "🎈"); + + CHECK(parser_helper("\"\\ud80c\\udc60\"").get() == "\xf0\x93\x81\xa0"); + CHECK(parser_helper("\"\\ud83c\\udf1e\"").get() == "🌞"); + } + } + + SECTION("number") + { + SECTION("integers") + { + SECTION("without exponent") + { + CHECK(parser_helper("-128") == json(-128)); + CHECK(parser_helper("-0") == json(-0)); + CHECK(parser_helper("0") == json(0)); + CHECK(parser_helper("128") == json(128)); + } + + SECTION("with exponent") + { + CHECK(parser_helper("0e1") == json(0e1)); + CHECK(parser_helper("0E1") == json(0e1)); + + CHECK(parser_helper("10000E-4") == json(10000e-4)); + CHECK(parser_helper("10000E-3") == json(10000e-3)); + CHECK(parser_helper("10000E-2") == json(10000e-2)); + CHECK(parser_helper("10000E-1") == json(10000e-1)); + CHECK(parser_helper("10000E0") == json(10000e0)); + CHECK(parser_helper("10000E1") == json(10000e1)); + CHECK(parser_helper("10000E2") == json(10000e2)); + CHECK(parser_helper("10000E3") == json(10000e3)); + CHECK(parser_helper("10000E4") == json(10000e4)); + + CHECK(parser_helper("10000e-4") == json(10000e-4)); + CHECK(parser_helper("10000e-3") == json(10000e-3)); + CHECK(parser_helper("10000e-2") == json(10000e-2)); + CHECK(parser_helper("10000e-1") == json(10000e-1)); + CHECK(parser_helper("10000e0") == json(10000e0)); + CHECK(parser_helper("10000e1") == json(10000e1)); + CHECK(parser_helper("10000e2") == json(10000e2)); + CHECK(parser_helper("10000e3") == json(10000e3)); + CHECK(parser_helper("10000e4") == json(10000e4)); + + CHECK(parser_helper("-0e1") == json(-0e1)); + CHECK(parser_helper("-0E1") == json(-0e1)); + CHECK(parser_helper("-0E123") == json(-0e123)); + + // numbers after exponent + CHECK(parser_helper("10E0") == json(10e0)); + CHECK(parser_helper("10E1") == json(10e1)); + CHECK(parser_helper("10E2") == json(10e2)); + CHECK(parser_helper("10E3") == json(10e3)); + CHECK(parser_helper("10E4") == json(10e4)); + CHECK(parser_helper("10E5") == json(10e5)); + CHECK(parser_helper("10E6") == json(10e6)); + CHECK(parser_helper("10E7") == json(10e7)); + CHECK(parser_helper("10E8") == json(10e8)); + CHECK(parser_helper("10E9") == json(10e9)); + CHECK(parser_helper("10E+0") == json(10e0)); + CHECK(parser_helper("10E+1") == json(10e1)); + CHECK(parser_helper("10E+2") == json(10e2)); + CHECK(parser_helper("10E+3") == json(10e3)); + CHECK(parser_helper("10E+4") == json(10e4)); + CHECK(parser_helper("10E+5") == json(10e5)); + CHECK(parser_helper("10E+6") == json(10e6)); + CHECK(parser_helper("10E+7") == json(10e7)); + CHECK(parser_helper("10E+8") == json(10e8)); + CHECK(parser_helper("10E+9") == json(10e9)); + CHECK(parser_helper("10E-1") == json(10e-1)); + CHECK(parser_helper("10E-2") == json(10e-2)); + CHECK(parser_helper("10E-3") == json(10e-3)); + CHECK(parser_helper("10E-4") == json(10e-4)); + CHECK(parser_helper("10E-5") == json(10e-5)); + CHECK(parser_helper("10E-6") == json(10e-6)); + CHECK(parser_helper("10E-7") == json(10e-7)); + CHECK(parser_helper("10E-8") == json(10e-8)); + CHECK(parser_helper("10E-9") == json(10e-9)); + } + + SECTION("edge cases") + { + // From RFC8259, Section 6: + // Note that when such software is used, numbers that are + // integers and are in the range [-(2**53)+1, (2**53)-1] + // are interoperable in the sense that implementations will + // agree exactly on their numeric values. + + // -(2**53)+1 + CHECK(parser_helper("-9007199254740991").get() == -9007199254740991); + // (2**53)-1 + CHECK(parser_helper("9007199254740991").get() == 9007199254740991); + } + + SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64-bit integers) + { + // While RFC8259, Section 6 specifies a preference for support + // for ranges in range of IEEE 754-2008 binary64 (double precision) + // this does not accommodate 64-bit integers without loss of accuracy. + // As 64-bit integers are now widely used in software, it is desirable + // to expand support to the full 64 bit (signed and unsigned) range + // i.e. -(2**63) -> (2**64)-1. + + // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1)) + CHECK(parser_helper("-9223372036854775808").get() == -9223372036854775807 - 1); + // (2**63)-1 + CHECK(parser_helper("9223372036854775807").get() == 9223372036854775807); + // (2**64)-1 + CHECK(parser_helper("18446744073709551615").get() == 18446744073709551615u); + } + } + + SECTION("floating-point") + { + SECTION("without exponent") + { + CHECK(parser_helper("-128.5") == json(-128.5)); + CHECK(parser_helper("0.999") == json(0.999)); + CHECK(parser_helper("128.5") == json(128.5)); + CHECK(parser_helper("-0.0") == json(-0.0)); + } + + SECTION("with exponent") + { + CHECK(parser_helper("-128.5E3") == json(-128.5E3)); + CHECK(parser_helper("-128.5E-3") == json(-128.5E-3)); + CHECK(parser_helper("-0.0e1") == json(-0.0e1)); + CHECK(parser_helper("-0.0E1") == json(-0.0e1)); + } + } + + SECTION("overflow") + { + // overflows during parsing yield an exception + CHECK_THROWS_WITH_AS(parser_helper("1.18973e+4932").empty(), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'", json::out_of_range&); + } + + SECTION("invalid numbers") + { + // numbers must not begin with "+" + CHECK_THROWS_AS(parser_helper("+1"), json::parse_error&); + CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&); + + CHECK_THROWS_WITH_AS(parser_helper("01"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected number literal; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-01"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - unexpected number literal; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("--1"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1."), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1E"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1E-"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '1E-'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1.E1"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.E'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-1E"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-1E'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0E#"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0E-#"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0E-#'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0#"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: '-0#'; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0.0:"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ':'; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0.0Z"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '-0.0Z'; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0E123:"), + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - unexpected ':'; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0e0-:"), + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'; expected end of input", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0e-:"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0e-:'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0f"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '-0f'; expected end of input", json::parse_error&); + } + } + } + + SECTION("accept") + { + SECTION("null") + { + CHECK(accept_helper("null")); + } + + SECTION("true") + { + CHECK(accept_helper("true")); + } + + SECTION("false") + { + CHECK(accept_helper("false")); + } + + SECTION("array") + { + SECTION("empty array") + { + CHECK(accept_helper("[]")); + CHECK(accept_helper("[ ]")); + } + + SECTION("nonempty array") + { + CHECK(accept_helper("[true, false, null]")); + } + } + + SECTION("object") + { + SECTION("empty object") + { + CHECK(accept_helper("{}")); + CHECK(accept_helper("{ }")); + } + + SECTION("nonempty object") + { + CHECK(accept_helper("{\"\": true, \"one\": 1, \"two\": null}")); + } + } + + SECTION("string") + { + // empty string + CHECK(accept_helper("\"\"")); + + SECTION("errors") + { + // error: tab in string + CHECK(accept_helper("\"\t\"") == false); + // error: newline in string + CHECK(accept_helper("\"\n\"") == false); + CHECK(accept_helper("\"\r\"") == false); + // error: backspace in string + CHECK(accept_helper("\"\b\"") == false); + // improve code coverage + CHECK(accept_helper("\uFF01") == false); + CHECK(accept_helper("[-4:1,]") == false); + // unescaped control characters + CHECK(accept_helper("\"\x00\"") == false); // NOLINT(bugprone-string-literal-with-embedded-nul) + CHECK(accept_helper("\"\x01\"") == false); + CHECK(accept_helper("\"\x02\"") == false); + CHECK(accept_helper("\"\x03\"") == false); + CHECK(accept_helper("\"\x04\"") == false); + CHECK(accept_helper("\"\x05\"") == false); + CHECK(accept_helper("\"\x06\"") == false); + CHECK(accept_helper("\"\x07\"") == false); + CHECK(accept_helper("\"\x08\"") == false); + CHECK(accept_helper("\"\x09\"") == false); + CHECK(accept_helper("\"\x0a\"") == false); + CHECK(accept_helper("\"\x0b\"") == false); + CHECK(accept_helper("\"\x0c\"") == false); + CHECK(accept_helper("\"\x0d\"") == false); + CHECK(accept_helper("\"\x0e\"") == false); + CHECK(accept_helper("\"\x0f\"") == false); + CHECK(accept_helper("\"\x10\"") == false); + CHECK(accept_helper("\"\x11\"") == false); + CHECK(accept_helper("\"\x12\"") == false); + CHECK(accept_helper("\"\x13\"") == false); + CHECK(accept_helper("\"\x14\"") == false); + CHECK(accept_helper("\"\x15\"") == false); + CHECK(accept_helper("\"\x16\"") == false); + CHECK(accept_helper("\"\x17\"") == false); + CHECK(accept_helper("\"\x18\"") == false); + CHECK(accept_helper("\"\x19\"") == false); + CHECK(accept_helper("\"\x1a\"") == false); + CHECK(accept_helper("\"\x1b\"") == false); + CHECK(accept_helper("\"\x1c\"") == false); + CHECK(accept_helper("\"\x1d\"") == false); + CHECK(accept_helper("\"\x1e\"") == false); + CHECK(accept_helper("\"\x1f\"") == false); + } + + SECTION("escaped") + { + // quotation mark "\"" + auto r1 = R"("\"")"_json; + CHECK(accept_helper("\"\\\"\"")); + // reverse solidus "\\" + auto r2 = R"("\\")"_json; + CHECK(accept_helper("\"\\\\\"")); + // solidus + CHECK(accept_helper("\"\\/\"")); + // backspace + CHECK(accept_helper("\"\\b\"")); + // formfeed + CHECK(accept_helper("\"\\f\"")); + // newline + CHECK(accept_helper("\"\\n\"")); + // carriage return + CHECK(accept_helper("\"\\r\"")); + // horizontal tab + CHECK(accept_helper("\"\\t\"")); + + CHECK(accept_helper("\"\\u0001\"")); + CHECK(accept_helper("\"\\u000a\"")); + CHECK(accept_helper("\"\\u00b0\"")); + CHECK(accept_helper("\"\\u0c00\"")); + CHECK(accept_helper("\"\\ud000\"")); + CHECK(accept_helper("\"\\u000E\"")); + CHECK(accept_helper("\"\\u00F0\"")); + CHECK(accept_helper("\"\\u0100\"")); + CHECK(accept_helper("\"\\u2000\"")); + CHECK(accept_helper("\"\\uFFFF\"")); + CHECK(accept_helper("\"\\u20AC\"")); + CHECK(accept_helper("\"€\"")); + CHECK(accept_helper("\"🎈\"")); + + CHECK(accept_helper("\"\\ud80c\\udc60\"")); + CHECK(accept_helper("\"\\ud83c\\udf1e\"")); + } + } + + SECTION("number") + { + SECTION("integers") + { + SECTION("without exponent") + { + CHECK(accept_helper("-128")); + CHECK(accept_helper("-0")); + CHECK(accept_helper("0")); + CHECK(accept_helper("128")); + } + + SECTION("with exponent") + { + CHECK(accept_helper("0e1")); + CHECK(accept_helper("0E1")); + + CHECK(accept_helper("10000E-4")); + CHECK(accept_helper("10000E-3")); + CHECK(accept_helper("10000E-2")); + CHECK(accept_helper("10000E-1")); + CHECK(accept_helper("10000E0")); + CHECK(accept_helper("10000E1")); + CHECK(accept_helper("10000E2")); + CHECK(accept_helper("10000E3")); + CHECK(accept_helper("10000E4")); + + CHECK(accept_helper("10000e-4")); + CHECK(accept_helper("10000e-3")); + CHECK(accept_helper("10000e-2")); + CHECK(accept_helper("10000e-1")); + CHECK(accept_helper("10000e0")); + CHECK(accept_helper("10000e1")); + CHECK(accept_helper("10000e2")); + CHECK(accept_helper("10000e3")); + CHECK(accept_helper("10000e4")); + + CHECK(accept_helper("-0e1")); + CHECK(accept_helper("-0E1")); + CHECK(accept_helper("-0E123")); + } + + SECTION("edge cases") + { + // From RFC8259, Section 6: + // Note that when such software is used, numbers that are + // integers and are in the range [-(2**53)+1, (2**53)-1] + // are interoperable in the sense that implementations will + // agree exactly on their numeric values. + + // -(2**53)+1 + CHECK(accept_helper("-9007199254740991")); + // (2**53)-1 + CHECK(accept_helper("9007199254740991")); + } + + SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64-bit integers) + { + // While RFC8259, Section 6 specifies a preference for support + // for ranges in range of IEEE 754-2008 binary64 (double precision) + // this does not accommodate 64 bit integers without loss of accuracy. + // As 64 bit integers are now widely used in software, it is desirable + // to expand support to the full 64 bit (signed and unsigned) range + // i.e. -(2**63) -> (2**64)-1. + + // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1)) + CHECK(accept_helper("-9223372036854775808")); + // (2**63)-1 + CHECK(accept_helper("9223372036854775807")); + // (2**64)-1 + CHECK(accept_helper("18446744073709551615")); + } + } + + SECTION("floating-point") + { + SECTION("without exponent") + { + CHECK(accept_helper("-128.5")); + CHECK(accept_helper("0.999")); + CHECK(accept_helper("128.5")); + CHECK(accept_helper("-0.0")); + } + + SECTION("with exponent") + { + CHECK(accept_helper("-128.5E3")); + CHECK(accept_helper("-128.5E-3")); + CHECK(accept_helper("-0.0e1")); + CHECK(accept_helper("-0.0E1")); + } + } + + SECTION("overflow") + { + // overflows during parsing + CHECK(!accept_helper("1.18973e+4932")); + } + + SECTION("invalid numbers") + { + CHECK(accept_helper("01") == false); + CHECK(accept_helper("--1") == false); + CHECK(accept_helper("1.") == false); + CHECK(accept_helper("1E") == false); + CHECK(accept_helper("1E-") == false); + CHECK(accept_helper("1.E1") == false); + CHECK(accept_helper("-1E") == false); + CHECK(accept_helper("-0E#") == false); + CHECK(accept_helper("-0E-#") == false); + CHECK(accept_helper("-0#") == false); + CHECK(accept_helper("-0.0:") == false); + CHECK(accept_helper("-0.0Z") == false); + CHECK(accept_helper("-0E123:") == false); + CHECK(accept_helper("-0e0-:") == false); + CHECK(accept_helper("-0e-:") == false); + CHECK(accept_helper("-0f") == false); + + // numbers must not begin with "+" + CHECK(accept_helper("+1") == false); + CHECK(accept_helper("+0") == false); + } + } + } + + SECTION("parse errors") + { + // unexpected end of number + CHECK_THROWS_WITH_AS(parser_helper("0."), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("--"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-0."), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after '.'; last read: '-0.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-."), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("-:"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("0.:"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.:'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("e."), + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'e'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1e."), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1e/"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e/'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1e:"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e:'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1E."), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E.'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1E/"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E/'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("1E:"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'", json::parse_error&); + + // unexpected end of null + CHECK_THROWS_WITH_AS(parser_helper("n"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'n'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("nu"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'nu'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("nul"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nul'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("nulk"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulk'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("nulm"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulm'", json::parse_error&); + + // unexpected end of true + CHECK_THROWS_WITH_AS(parser_helper("t"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 't'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("tr"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'tr'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("tru"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'tru'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("trud"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'trud'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("truf"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'truf'", json::parse_error&); + + // unexpected end of false + CHECK_THROWS_WITH_AS(parser_helper("f"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'f'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("fa"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'fa'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("fal"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'fal'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("fals"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'fals'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("falsd"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsd'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("falsf"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsf'", json::parse_error&); + + // missing/unexpected end of array + CHECK_THROWS_WITH_AS(parser_helper("["), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("[1"), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("[1,"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("[1,]"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("]"), + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal", json::parse_error&); + + // missing/unexpected end of object + CHECK_THROWS_WITH_AS(parser_helper("{"), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected end of input; expected string literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("{\"foo\""), + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing object separator - unexpected end of input; expected ':'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":"), + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":}"), + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":1,}"), + "[json.exception.parse_error.101] parse error at line 1, column 10: syntax error while parsing object key - unexpected '}'; expected string literal", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("}"), + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal", json::parse_error&); + + // missing/unexpected end of string + CHECK_THROWS_WITH_AS(parser_helper("\""), + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\\""), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: missing closing quote; last read: '\"\\\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u\""), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u0\""), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u01\""), + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u012\""), + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012\"'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u"), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u0"), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u01"), + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01'", json::parse_error&); + CHECK_THROWS_WITH_AS(parser_helper("\"\\u012"), + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012'", json::parse_error&); + + // invalid escapes + for (int c = 1; c < 128; ++c) + { + auto s = std::string("\"\\") + std::string(1, static_cast(c)) + "\""; + + switch (c) + { + // valid escapes + case ('"'): + case ('\\'): + case ('/'): + case ('b'): + case ('f'): + case ('n'): + case ('r'): + case ('t'): + { + CHECK_NOTHROW(parser_helper(s)); + break; + } + + // \u must be followed with four numbers, so we skip it here + case ('u'): + { + break; + } + + // any other combination of backslash and character is invalid + default: + { + CHECK_THROWS_AS(parser_helper(s), json::parse_error&); + // only check error message if c is not a control character + if (c > 0x1f) + { + CHECK_THROWS_WITH_STD_STR(parser_helper(s), + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast(c)) + "'"); + } + break; + } + } + } + + // invalid \uxxxx escapes + { + // check whether character is a valid hex character + const auto valid = [](int c) + { + switch (c) + { + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + case ('9'): + case ('a'): + case ('b'): + case ('c'): + case ('d'): + case ('e'): + case ('f'): + case ('A'): + case ('B'): + case ('C'): + case ('D'): + case ('E'): + case ('F'): + { + return true; + } + + default: + { + return false; + } + } + }; + + for (int c = 1; c < 128; ++c) + { + std::string const s = "\"\\u"; + + // create a string with the iterated character at each position + auto s1 = s + "000" + std::string(1, static_cast(c)) + "\""; + auto s2 = s + "00" + std::string(1, static_cast(c)) + "0\""; + auto s3 = s + "0" + std::string(1, static_cast(c)) + "00\""; + auto s4 = s + std::string(1, static_cast(c)) + "000\""; + + if (valid(c)) + { + CAPTURE(s1) + CHECK_NOTHROW(parser_helper(s1)); + CAPTURE(s2) + CHECK_NOTHROW(parser_helper(s2)); + CAPTURE(s3) + CHECK_NOTHROW(parser_helper(s3)); + CAPTURE(s4) + CHECK_NOTHROW(parser_helper(s4)); + } + else + { + CAPTURE(s1) + CHECK_THROWS_AS(parser_helper(s1), json::parse_error&); + // only check error message if c is not a control character + if (c > 0x1f) + { + CHECK_THROWS_WITH_STD_STR(parser_helper(s1), + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'"); + } + + CAPTURE(s2) + CHECK_THROWS_AS(parser_helper(s2), json::parse_error&); + // only check error message if c is not a control character + if (c > 0x1f) + { + CHECK_THROWS_WITH_STD_STR(parser_helper(s2), + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'"); + } + + CAPTURE(s3) + CHECK_THROWS_AS(parser_helper(s3), json::parse_error&); + // only check error message if c is not a control character + if (c > 0x1f) + { + CHECK_THROWS_WITH_STD_STR(parser_helper(s3), + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'"); + } + + CAPTURE(s4) + CHECK_THROWS_AS(parser_helper(s4), json::parse_error&); + // only check error message if c is not a control character + if (c > 0x1f) + { + CHECK_THROWS_WITH_STD_STR(parser_helper(s4), + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'"); + } + } + } + } + + json _; + + // missing part of a surrogate pair + CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\""), "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'", json::parse_error&); + // invalid surrogate pair + CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\uD80C\""), + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'", json::parse_error&); + CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\u0000\""), + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'", json::parse_error&); + CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\uFFFF\""), + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'", json::parse_error&); + } + + SECTION("parse errors (accept)") + { + // unexpected end of number + CHECK(accept_helper("0.") == false); + CHECK(accept_helper("-") == false); + CHECK(accept_helper("--") == false); + CHECK(accept_helper("-0.") == false); + CHECK(accept_helper("-.") == false); + CHECK(accept_helper("-:") == false); + CHECK(accept_helper("0.:") == false); + CHECK(accept_helper("e.") == false); + CHECK(accept_helper("1e.") == false); + CHECK(accept_helper("1e/") == false); + CHECK(accept_helper("1e:") == false); + CHECK(accept_helper("1E.") == false); + CHECK(accept_helper("1E/") == false); + CHECK(accept_helper("1E:") == false); + + // unexpected end of null + CHECK(accept_helper("n") == false); + CHECK(accept_helper("nu") == false); + CHECK(accept_helper("nul") == false); + + // unexpected end of true + CHECK(accept_helper("t") == false); + CHECK(accept_helper("tr") == false); + CHECK(accept_helper("tru") == false); + + // unexpected end of false + CHECK(accept_helper("f") == false); + CHECK(accept_helper("fa") == false); + CHECK(accept_helper("fal") == false); + CHECK(accept_helper("fals") == false); + + // missing/unexpected end of array + CHECK(accept_helper("[") == false); + CHECK(accept_helper("[1") == false); + CHECK(accept_helper("[1,") == false); + CHECK(accept_helper("[1,]") == false); + CHECK(accept_helper("]") == false); + + // missing/unexpected end of object + CHECK(accept_helper("{") == false); + CHECK(accept_helper("{\"foo\"") == false); + CHECK(accept_helper("{\"foo\":") == false); + CHECK(accept_helper("{\"foo\":}") == false); + CHECK(accept_helper("{\"foo\":1,}") == false); + CHECK(accept_helper("}") == false); + + // missing/unexpected end of string + CHECK(accept_helper("\"") == false); + CHECK(accept_helper("\"\\\"") == false); + CHECK(accept_helper("\"\\u\"") == false); + CHECK(accept_helper("\"\\u0\"") == false); + CHECK(accept_helper("\"\\u01\"") == false); + CHECK(accept_helper("\"\\u012\"") == false); + CHECK(accept_helper("\"\\u") == false); + CHECK(accept_helper("\"\\u0") == false); + CHECK(accept_helper("\"\\u01") == false); + CHECK(accept_helper("\"\\u012") == false); + + // unget of newline + CHECK(parser_helper("\n123\n") == 123); + + // invalid escapes + for (int c = 1; c < 128; ++c) + { + auto s = std::string("\"\\") + std::string(1, static_cast(c)) + "\""; + + switch (c) + { + // valid escapes + case ('"'): + case ('\\'): + case ('/'): + case ('b'): + case ('f'): + case ('n'): + case ('r'): + case ('t'): + { + CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept()); + break; + } + + // \u must be followed with four numbers, so we skip it here + case ('u'): + { + break; + } + + // any other combination of backslash and character is invalid + default: + { + CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept() == false); + break; + } + } + } + + // invalid \uxxxx escapes + { + // check whether character is a valid hex character + const auto valid = [](int c) + { + switch (c) + { + case ('0'): + case ('1'): + case ('2'): + case ('3'): + case ('4'): + case ('5'): + case ('6'): + case ('7'): + case ('8'): + case ('9'): + case ('a'): + case ('b'): + case ('c'): + case ('d'): + case ('e'): + case ('f'): + case ('A'): + case ('B'): + case ('C'): + case ('D'): + case ('E'): + case ('F'): + { + return true; + } + + default: + { + return false; + } + } + }; + + for (int c = 1; c < 128; ++c) + { + std::string const s = "\"\\u"; + + // create a string with the iterated character at each position + const auto s1 = s + "000" + std::string(1, static_cast(c)) + "\""; + const auto s2 = s + "00" + std::string(1, static_cast(c)) + "0\""; + const auto s3 = s + "0" + std::string(1, static_cast(c)) + "00\""; + const auto s4 = s + std::string(1, static_cast(c)) + "000\""; + + if (valid(c)) + { + CAPTURE(s1) + CHECK(json::parser(nlohmann::detail::input_adapter(s1)).accept()); + CAPTURE(s2) + CHECK(json::parser(nlohmann::detail::input_adapter(s2)).accept()); + CAPTURE(s3) + CHECK(json::parser(nlohmann::detail::input_adapter(s3)).accept()); + CAPTURE(s4) + CHECK(json::parser(nlohmann::detail::input_adapter(s4)).accept()); + } + else + { + CAPTURE(s1) + CHECK(json::parser(nlohmann::detail::input_adapter(s1)).accept() == false); + + CAPTURE(s2) + CHECK(json::parser(nlohmann::detail::input_adapter(s2)).accept() == false); + + CAPTURE(s3) + CHECK(json::parser(nlohmann::detail::input_adapter(s3)).accept() == false); + + CAPTURE(s4) + CHECK(json::parser(nlohmann::detail::input_adapter(s4)).accept() == false); + } + } + } + + // missing part of a surrogate pair + CHECK(accept_helper("\"\\uD80C\"") == false); + // invalid surrogate pair + CHECK(accept_helper("\"\\uD80C\\uD80C\"") == false); + CHECK(accept_helper("\"\\uD80C\\u0000\"") == false); + CHECK(accept_helper("\"\\uD80C\\uFFFF\"") == false); + } + + SECTION("tests found by mutate++") + { + // test case to make sure no comma precedes the first key + CHECK_THROWS_WITH_AS(parser_helper("{,\"key\": false}"), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected ','; expected string literal", json::parse_error&); + // test case to make sure an object is properly closed + CHECK_THROWS_WITH_AS(parser_helper("[{\"key\": false true]"), "[json.exception.parse_error.101] parse error at line 1, column 19: syntax error while parsing object - unexpected true literal; expected '}'", json::parse_error&); + + // test case to make sure the callback is properly evaluated after reading a key + { + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t event, json& /*unused*/) noexcept + { + return event != json::parse_event_t::key; + }; + + json x = json::parse("{\"key\": false}", cb); + CHECK(x == json::object()); + } + } + + SECTION("callback function") + { + const auto* s_object = R"( + { + "foo": 2, + "bar": { + "baz": 1 + } + } + )"; + + const auto* s_array = R"( + [1,2,[3,4,5],4,5] + )"; + + const auto* structured_array = R"( + [ + 1, + { + "foo": "bar" + }, + { + "qux": "baz" + } + ] + )"; + + SECTION("filter nothing") + { + json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + { + return true; + }); + + CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}})); + + json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + { + return true; + }); + + CHECK (j_array == json({1, 2, {3, 4, 5}, 4, 5})); + } + + SECTION("filter everything") + { + json const j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + { + return false; + }); + + // the top-level object will be discarded, leaving a null + CHECK (j_object.is_null()); + + json const j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + { + return false; + }); + + // the top-level array will be discarded, leaving a null + CHECK (j_array.is_null()); + } + + SECTION("filter specific element") + { + json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t event, const json & j) noexcept + { + // filter all number(2) elements + return event != json::parse_event_t::value || j != json(2); + }); + + CHECK (j_object == json({{"bar", {{"baz", 1}}}})); + + json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t event, const json & j) noexcept + { + return event != json::parse_event_t::value || j != json(2); + }); + + CHECK (j_array == json({1, {3, 4, 5}, 4, 5})); + } + + SECTION("filter object in array") + { + json j_filtered1 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json & parsed) + { + return !(e == json::parse_event_t::object_end && parsed.contains("foo")); + }); + + // the specified object will be discarded, and removed. + CHECK (j_filtered1.size() == 2); + CHECK (j_filtered1 == json({1, {{"qux", "baz"}}})); + + json j_filtered2 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json& /*parsed*/) noexcept + { + return e != json::parse_event_t::object_end; + }); + + // removed all objects in array. + CHECK (j_filtered2.size() == 1); + CHECK (j_filtered2 == json({1})); + } + + SECTION("filter specific events") + { + SECTION("first closing event") + { + { + json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept + { + static bool first = true; + if (e == json::parse_event_t::object_end && first) + { + first = false; + return false; + } + + return true; + }); + + // the first completed object will be discarded + CHECK (j_object == json({{"foo", 2}})); + } + + { + json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept + { + static bool first = true; + if (e == json::parse_event_t::array_end && first) + { + first = false; + return false; + } + + return true; + }); + + // the first completed array will be discarded + CHECK (j_array == json({1, 2, 4, 5})); + } + } + } + + SECTION("special cases") + { + // the following test cases cover the situation in which an empty + // object and array is discarded only after the closing character + // has been read + + json j_empty_object = json::parse("{}", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept + { + return e != json::parse_event_t::object_end; + }); + CHECK(j_empty_object == json()); + + json j_empty_array = json::parse("[]", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept + { + return e != json::parse_event_t::array_end; + }); + CHECK(j_empty_array == json()); + } + } + + SECTION("constructing from contiguous containers") + { + SECTION("from std::vector") + { + std::vector v = {'t', 'r', 'u', 'e'}; + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + + SECTION("from std::array") + { + std::array v { {'t', 'r', 'u', 'e'} }; + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + + SECTION("from array") + { + uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + + SECTION("from char literal") + { + CHECK(parser_helper("true") == json(true)); + } + + SECTION("from std::string") + { + std::string v = {'t', 'r', 'u', 'e'}; + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + + SECTION("from std::initializer_list") + { + std::initializer_list const v = {'t', 'r', 'u', 'e'}; + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + + SECTION("from std::valarray") + { + std::valarray v = {'t', 'r', 'u', 'e'}; + json j; + json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j); + CHECK(j == json(true)); + } + } + + SECTION("improve test coverage") + { + SECTION("parser with callback") + { + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept + { + return true; + }; + + CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded()); + + json _; + CHECK_THROWS_WITH_AS(_ = json::parse("{\"foo\": true:", cb), "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing object - unexpected ':'; expected '}'", json::parse_error&); + + CHECK_THROWS_WITH_AS(_ = json::parse("1.18973e+4932", cb), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'", json::out_of_range&); + } + + SECTION("SAX parser") + { + SECTION("} without value") + { + SaxCountdown s(1); + CHECK(json::sax_parse("{}", &s) == false); + } + + SECTION("} with value") + { + SaxCountdown s(3); + CHECK(json::sax_parse("{\"k1\": true}", &s) == false); + } + + SECTION("second key") + { + SaxCountdown s(3); + CHECK(json::sax_parse("{\"k1\": true, \"k2\": false}", &s) == false); + } + + SECTION("] without value") + { + SaxCountdown s(1); + CHECK(json::sax_parse("[]", &s) == false); + } + + SECTION("] with value") + { + SaxCountdown s(2); + CHECK(json::sax_parse("[1]", &s) == false); + } + + SECTION("float") + { + SaxCountdown s(0); + CHECK(json::sax_parse("3.14", &s) == false); + } + + SECTION("false") + { + SaxCountdown s(0); + CHECK(json::sax_parse("false", &s) == false); + } + + SECTION("null") + { + SaxCountdown s(0); + CHECK(json::sax_parse("null", &s) == false); + } + + SECTION("true") + { + SaxCountdown s(0); + CHECK(json::sax_parse("true", &s) == false); + } + + SECTION("unsigned") + { + SaxCountdown s(0); + CHECK(json::sax_parse("12", &s) == false); + } + + SECTION("integer") + { + SaxCountdown s(0); + CHECK(json::sax_parse("-12", &s) == false); + } + + SECTION("string") + { + SaxCountdown s(0); + CHECK(json::sax_parse("\"foo\"", &s) == false); + } + } + } + + SECTION("error messages for comments") + { + json _; + CHECK_THROWS_WITH_AS(_ = json::parse("/a", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid comment; expecting '/' or '*' after '/'; last read: '/a'", json::parse_error); + CHECK_THROWS_WITH_AS(_ = json::parse("/*", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid comment; missing closing '*/'; last read: '/*'", json::parse_error); + } + + // Macro for all test cases for start_pos and end_pos +#define SETUP_TESTCASES() \ + SECTION("with callback") \ + { \ + SECTION("filter nothing") \ + { \ + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept \ + { \ + return true; \ + }; \ + validate_start_end_pos_for_nested_obj_helper(nested_type_json_str, root_type_json_str, expected, cb); \ + } \ + SECTION("filter element") \ + { \ + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t event, json& j) noexcept \ + { \ + return (event != json::parse_event_t::key && event != json::parse_event_t::value) || j != json("a"); \ + }; \ + validate_start_end_pos_for_nested_obj_helper(nested_type_json_str, root_type_json_str, filteredExpected, cb); \ + } \ + } \ + SECTION("without callback") \ + { \ + validate_start_end_pos_for_nested_obj_helper(nested_type_json_str, root_type_json_str, expected); \ + } + + SECTION("retrieve start position and end position") + { + SECTION("for object") + { + // Create an object with spaces to test the start and end positions. Spaces will not be included in the + // JSON object, however, the start and end positions should include the spaces from the input JSON string. + const std::string nested_type_json_str = R"({ "a": 1,"b" : "test1"})"; + const std::string root_type_json_str = R"({ "nested": )" + nested_type_json_str + R"(, "anotherValue": "test2"})"; + auto expected = json({{"nested", {{"a", 1}, {"b", "test1"}}}, {"anotherValue", "test2"}}); + auto filteredExpected = expected; + filteredExpected["nested"].erase("a"); + + SETUP_TESTCASES() + } + + SECTION("for array") + { + const std::string nested_type_json_str = R"(["a", "test", 45])"; + const std::string root_type_json_str = R"({ "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", {"a", "test", 45}}, {"anotherValue", "test"}}); + auto filteredExpected = expected; + filteredExpected["nested"] = json({"test", 45}); + SETUP_TESTCASES() + } + + SECTION("for array with objects") + { + const std::string nested_type_json_str = R"([{"a": 1, "b": "test"}, {"c": 2, "d": "test2"}])"; + const std::string root_type_json_str = R"({ "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", {{{"a", 1}, {"b", "test"}}, {{"c", 2}, {"d", "test2"}}}}, {"anotherValue", "test"}}); + auto filteredExpected = expected; + filteredExpected["nested"][0].erase("a"); + SETUP_TESTCASES() + + auto j = json::parse(root_type_json_str); + auto nested_array = j["nested"]; + const auto& nested_obj = nested_array[0]; + CHECK(nested_type_json_str.substr(1, 21) == root_type_json_str.substr(nested_obj.start_pos(), nested_obj.end_pos() - nested_obj.start_pos())); + CHECK(nested_type_json_str.substr(24, 22) == root_type_json_str.substr(nested_array[1].start_pos(), nested_array[1].end_pos() - nested_array[1].start_pos())); + } + + SECTION("for two levels of nesting objects") + { + const std::string nested_type_json_str = R"({"nested2": {"b": "test"}})"; + const std::string root_type_json_str = R"({ "a": 2, "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"a", 2}, {"nested", {{"nested2", {{"b", "test"}}}}}, {"anotherValue", "test"}}); + auto filteredExpected = expected; + filteredExpected.erase("a"); + SETUP_TESTCASES() + + auto j = json::parse(root_type_json_str); + auto nested_obj = j["nested"]["nested2"]; + CHECK(nested_type_json_str.substr(12, 13) == root_type_json_str.substr(nested_obj.start_pos(), nested_obj.end_pos() - nested_obj.start_pos())); + } + + SECTION("for simple types") + { + SECTION("no nested") + { + SECTION("with callback") + { + json::parser_callback_t const cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept + { + return true; + }; + + // 1. string type + std::string json_str = R"("test")"; + auto j = json::parse(json_str, cb); + validate_generated_json_and_start_end_pos_helper(json_str, j, "test"); + + // 2. number type + json_str = R"(1)"; + j = json::parse(json_str, cb); + validate_generated_json_and_start_end_pos_helper(json_str, j, 1); + + // 3. boolean type + json_str = R"(true)"; + j = json::parse(json_str, cb); + validate_generated_json_and_start_end_pos_helper(json_str, j, true); + + // 4. null type + json_str = R"(null)"; + j = json::parse(json_str, cb); + validate_generated_json_and_start_end_pos_helper(json_str, j, nullptr); + } + + SECTION("without callback") + { + // 1. string type + std::string json_str = R"("test")"; + auto j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, "test"); + + // 2. number type + json_str = R"(1)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, 1); + + json_str = R"(1.001239923)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, 1.001239923); + + json_str = R"(1.123812389000000)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, 1.123812389); + + // 3. boolean type + json_str = R"(true)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, true); + + json_str = R"(false)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, false); + + // 4. null type + json_str = R"(null)"; + j = json::parse(json_str); + validate_generated_json_and_start_end_pos_helper(json_str, j, nullptr); + } + } + + SECTION("string type") + { + const std::string nested_type_json_str = R"("test")"; + const std::string root_type_json_str = R"({ "a": 1, "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", "test"}, {"anotherValue", "test"}, {"a", 1}}); + auto filteredExpected = expected; + filteredExpected.erase("a"); + SETUP_TESTCASES() + } + + SECTION("number type") + { + const std::string nested_type_json_str = R"(2)"; + const std::string root_type_json_str = R"({ "a": 1, "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", 2}, {"anotherValue", "test"}, {"a", 1}}); + auto filteredExpected = expected; + filteredExpected.erase("a"); + SETUP_TESTCASES() + } + + SECTION("boolean type") + { + const std::string nested_type_json_str = R"(true)"; + const std::string root_type_json_str = R"({ "a": 1, "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", true}, {"anotherValue", "test"}, {"a", 1}}); + auto filteredExpected = expected; + filteredExpected.erase("a"); + SETUP_TESTCASES() + } + + SECTION("null type") + { + const std::string nested_type_json_str = R"(null)"; + const std::string root_type_json_str = R"({ "a": 1, "nested": )" + nested_type_json_str + R"(, "anotherValue": "test" })"; + auto expected = json({{"nested", nullptr}, {"anotherValue", "test"}, {"a", 1}}); + auto filteredExpected = expected; + filteredExpected.erase("a"); + SETUP_TESTCASES() + } + } + SECTION("with leading whitespace and newlines around root JSON") + { + const std::string initial_whitespace = R"( + + )"; + const std::string nested_type_json_str = R"({ + "a": 1, + "nested": { + "b": "test" + }, + "anotherValue": "test" + })"; + const std::string end_whitespace = R"( + + )"; + const std::string root_type_json_str = initial_whitespace + nested_type_json_str + end_whitespace; + + auto expected = json({{"a", 1}, {"nested", {{"b", "test"}}}, {"anotherValue", "test"}}); + + auto j = json::parse(root_type_json_str); + + // 2. Check if the generated JSON is as expected + CHECK(j == expected); + + // 3. Check if the start and end positions do not include the surrounding whitespace + CHECK(j.start_pos() == initial_whitespace.size()); + CHECK(j.end_pos() == root_type_json_str.size() - end_whitespace.size()); + } + } +} diff --git a/external/json/tests/src/unit-comparison.cpp b/external/json/tests/src/unit-comparison.cpp index 7df20486..84d3e181 100644 --- a/external/json/tests/src/unit-comparison.cpp +++ b/external/json/tests/src/unit-comparison.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT // cmake/test.cmake selects the C++ standard versions with which to build a diff --git a/external/json/tests/src/unit-concepts.cpp b/external/json/tests/src/unit-concepts.cpp index e0429918..67d6a285 100644 --- a/external/json/tests/src/unit-concepts.cpp +++ b/external/json/tests/src/unit-concepts.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -20,7 +20,6 @@ TEST_CASE("concepts") // a, b: values of type X: json // TABLE 96 - Container Requirements - // X::value_type must return T CHECK((std::is_same::value)); diff --git a/external/json/tests/src/unit-constructor1.cpp b/external/json/tests/src/unit-constructor1.cpp index bbd57605..2a424715 100644 --- a/external/json/tests/src/unit-constructor1.cpp +++ b/external/json/tests/src/unit-constructor1.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-constructor2.cpp b/external/json/tests/src/unit-constructor2.cpp index 85a91ff9..18d0fdcc 100644 --- a/external/json/tests/src/unit-constructor2.cpp +++ b/external/json/tests/src/unit-constructor2.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-convenience.cpp b/external/json/tests/src/unit-convenience.cpp index 34bbb02c..04e5aaed 100644 --- a/external/json/tests/src/unit-convenience.cpp +++ b/external/json/tests/src/unit-convenience.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -55,7 +55,7 @@ struct alt_string_iter return *this; } - std::string impl{}; + std::string impl{}; // NOLINT(readability-redundant-member-init) }; struct alt_string_data @@ -91,7 +91,7 @@ struct alt_string_data return *this; } - std::string impl{}; + std::string impl{}; // NOLINT(readability-redundant-member-init) }; void check_escaped(const char* original, const char* escaped = "", bool ensure_ascii = false); diff --git a/external/json/tests/src/unit-conversions.cpp b/external/json/tests/src/unit-conversions.cpp index d7df0bee..93a31fc9 100644 --- a/external/json/tests/src/unit-conversions.cpp +++ b/external/json/tests/src/unit-conversions.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT // cmake/test.cmake selects the C++ standard versions with which to build a @@ -16,6 +15,11 @@ #include "doctest_compatibility.h" +// skip tests if JSON_DisableEnumSerialization=ON (#4384) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1) + #define SKIP_TESTS_FOR_ENUM_SERIALIZATION +#endif + #define JSON_TESTS_PRIVATE #include using nlohmann::json; @@ -32,6 +36,25 @@ using nlohmann::json; DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +#ifdef JSON_HAS_CPP_17 + #if __has_include() + #include + #elif __has_include() + #include + #endif +#endif + +#if defined(JSON_HAS_CPP_17) + #include +#endif + TEST_CASE("value conversion") { SECTION("get an object (explicit)") @@ -153,6 +176,7 @@ TEST_CASE("value conversion") } #if JSON_USE_IMPLICIT_CONVERSIONS + SECTION("get an object (implicit)") { const json::object_t o_reference = {{"object", json::object()}, @@ -344,6 +368,68 @@ TEST_CASE("value conversion") CHECK(std::equal(std::begin(nbs), std::end(nbs), std::begin(nbs2))); } + SECTION("built-in arrays: 2D") + { + const int nbs[][3] = {{0, 1, 2}, {3, 4, 5}}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int nbs2[][3] = {{0, 0, 0}, {0, 0, 0}}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + + const json j2 = nbs; + j2.get_to(nbs2); + CHECK(std::equal(std::begin(nbs[0]), std::end(nbs[1]), std::begin(nbs2[0]))); + } + + SECTION("built-in arrays: 3D") + { + // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + const int nbs[][2][3] = {\ + {{0, 1, 2}, {3, 4, 5}}, \ + {{10, 11, 12}, {13, 14, 15}}\ + }; + int nbs2[][2][3] = {\ + {{0, 0, 0}, {0, 0, 0}}, \ + {{0, 0, 0}, {0, 0, 0}}\ + }; + // NOLINTEND(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + + const json j2 = nbs; + j2.get_to(nbs2); + CHECK(std::equal(std::begin(nbs[0][0]), std::end(nbs[1][1]), std::begin(nbs2[0][0]))); + } + + SECTION("built-in arrays: 4D") + { + // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + const int nbs[][2][2][3] = {\ + { + \ + {{0, 1, 2}, {3, 4, 5}}, \ + {{10, 11, 12}, {13, 14, 15}}\ + }, \ + { + \ + {{20, 21, 22}, {23, 24, 25}}, \ + {{30, 31, 32}, {33, 34, 35}}\ + }\ + }; + int nbs2[][2][2][3] = {\ + { + \ + {{0, 0, 0}, {0, 0, 0}}, \ + {{0, 0, 0}, {0, 0, 0}}\ + }, \ + { + \ + {{0, 0, 0}, {0, 0, 0}}, \ + {{0, 0, 0}, {0, 0, 0}}\ + }\ + }; + // NOLINTEND(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + + const json j2 = nbs; + j2.get_to(nbs2); + CHECK(std::equal(std::begin(nbs[0][0][0]), std::end(nbs[1][1][1]), std::begin(nbs2[0][0][0]))); + } + SECTION("std::deque") { std::deque a{"previous", "value"}; @@ -1164,7 +1250,7 @@ TEST_CASE("value conversion") SECTION("non-const") { - const json j_const = j; + const json j_const = j; // NOLINT(performance-unnecessary-copy-initialization) const auto& b = j_const.get_binary(); CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary); } @@ -1263,6 +1349,7 @@ TEST_CASE("value conversion") } #endif +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION SECTION("get an enum") { enum c_enum { value_1, value_2 }; @@ -1271,6 +1358,7 @@ TEST_CASE("value conversion") CHECK(json(value_1).get() == value_1); CHECK(json(cpp_enum::value_1).get() == cpp_enum::value_1); } +#endif SECTION("more involved conversions") { @@ -1513,7 +1601,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(cards, {cards::karo, "karo"} }) -enum TaskState +enum TaskState // NOLINT(cert-int09-c,readability-enum-initial-value) { TS_STOPPED, TS_RUNNING, @@ -1569,4 +1657,72 @@ TEST_CASE("JSON to enum mapping") } } +#ifdef JSON_HAS_CPP_17 +#ifndef JSON_USE_IMPLICIT_CONVERSIONS +TEST_CASE("std::optional") +{ + SECTION("null") + { + json j_null; + std::optional opt_null; + + CHECK(json(opt_null) == j_null); + CHECK(j_null.get>() == std::nullopt); + } + + SECTION("string") + { + json j_string = "string"; + std::optional opt_string = "string"; + + CHECK(json(opt_string) == j_string); + CHECK(std::optional(j_string) == opt_string); + } + + SECTION("bool") + { + json j_bool = true; + std::optional opt_bool = true; + + CHECK(json(opt_bool) == j_bool); + CHECK(std::optional(j_bool) == opt_bool); + } + + SECTION("number") + { + json j_number = 1; + std::optional opt_int = 1; + + CHECK(json(opt_int) == j_number); + CHECK(j_number.get>() == opt_int); + } + + SECTION("array") + { + json j_array = {1, 2, nullptr}; + std::vector> opt_array = {{1, 2, std::nullopt}}; + + CHECK(json(opt_array) == j_array); + CHECK(j_array.get>>() == opt_array); + } + + SECTION("object") + { + json j_object = {{"one", 1}, {"two", 2}, {"zero", nullptr}}; + std::map> opt_object {{"one", 1}, {"two", 2}, {"zero", std::nullopt}}; + + CHECK(json(opt_object) == j_object); + CHECK(std::map>(j_object) == opt_object); + } +} +#endif +#endif + +#ifdef JSON_HAS_CPP_17 + #undef JSON_HAS_CPP_17 +#endif + +#ifdef JSON_HAS_CPP_14 + #undef JSON_HAS_CPP_14 +#endif DOCTEST_CLANG_SUPPRESS_WARNING_POP diff --git a/external/json/tests/src/unit-custom-base-class.cpp b/external/json/tests/src/unit-custom-base-class.cpp index 7d3c2eef..1128ff46 100644 --- a/external/json/tests/src/unit-custom-base-class.cpp +++ b/external/json/tests/src/unit-custom-base-class.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2019 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include @@ -283,8 +282,8 @@ TEST_CASE("JSON Visit Node") }; json.visit( - [&](const json_with_visitor_t::json_pointer & p, - const json_with_visitor_t& j) + [&](const json_with_visitor_t::json_pointer & p, + const json_with_visitor_t& j) { std::stringstream str; str << p.to_string() << " - " ; @@ -331,6 +330,6 @@ TEST_CASE("JSON Visit Node") CHECK(expected.count(str.str()) == 1); expected.erase(str.str()); } - ); + ); CHECK(expected.empty()); } diff --git a/external/json/tests/src/unit-deserialization.cpp b/external/json/tests/src/unit-deserialization.cpp index 3bc161f1..24ec83ff 100644 --- a/external/json/tests/src/unit-deserialization.cpp +++ b/external/json/tests/src/unit-deserialization.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -77,7 +76,7 @@ struct SaxEventLogger : public nlohmann::json_sax bool start_object(std::size_t elements) override { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_object()"); } @@ -102,7 +101,7 @@ struct SaxEventLogger : public nlohmann::json_sax bool start_array(std::size_t elements) override { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_array()"); } @@ -125,14 +124,14 @@ struct SaxEventLogger : public nlohmann::json_sax return false; } - std::vector events {}; + std::vector events {}; // NOLINT(readability-redundant-member-init) }; struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger { bool start_object(std::size_t elements) override { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_object()"); } @@ -157,7 +156,7 @@ struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger { bool start_array(std::size_t elements) override { - if (elements == static_cast(-1)) + if (elements == (std::numeric_limits::max)()) { events.emplace_back("start_array()"); } @@ -360,6 +359,10 @@ TEST_CASE("deserialization") "start_object()", "key(one)", "number_unsigned(1)", "end_object()", "parse_error(29)" })); + + const char* string = nullptr; + CHECK_THROWS_WITH_AS(_ = json::parse(string), "[json.exception.parse_error.101] parse error: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&); + CHECK_THROWS_WITH_AS(_ = json::parse(nullptr), "[json.exception.parse_error.101] parse error: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&); } SECTION("operator<<") @@ -583,7 +586,7 @@ TEST_CASE("deserialization") auto first = str.begin(); auto last = str.end(); json j; - json_sax_dom_parser sax(j, true); + json_sax_dom_parser sax(j, true); CHECK(json::sax_parse(proxy(first), proxy(last), &sax, input_format_t::json, false)); @@ -1131,13 +1134,15 @@ TEST_CASE("deserialization") } } -TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, - char, unsigned char, signed char, - wchar_t, - char16_t, char32_t, - std::uint8_t, std::int8_t, - std::int16_t, std::uint16_t, - std::int32_t, std::uint32_t) +// select the types to test - char8_t is only available in C++20 +#define TYPE_LIST(...) __VA_ARGS__ +#ifdef JSON_HAS_CPP_20 + #define ASCII_TYPES TYPE_LIST(char, wchar_t, char16_t, char32_t, char8_t) +#else + #define ASCII_TYPES TYPE_LIST(char, wchar_t, char16_t, char32_t) +#endif + +TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, ASCII_TYPES) // NOLINT(readability-math-missing-parentheses) { std::vector const v = {'t', 'r', 'u', 'e'}; CHECK(json::parse(v) == json(true)); @@ -1149,8 +1154,7 @@ TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, CHECK(l.events == std::vector({"boolean(true)"})); } -TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, - char, unsigned char, std::uint8_t) +TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, char, unsigned char, std::uint8_t) // NOLINT(readability-math-missing-parentheses) { // a star emoji std::vector const v = {'"', static_cast(0xe2u), static_cast(0xadu), static_cast(0x90u), static_cast(0xefu), static_cast(0xb8u), static_cast(0x8fu), '"'}; @@ -1162,8 +1166,7 @@ TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, CHECK(l.events.size() == 1); } -TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, - char16_t, std::uint16_t) +TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, char16_t) // NOLINT(readability-math-missing-parentheses) { // a star emoji std::vector const v = {static_cast('"'), static_cast(0x2b50), static_cast(0xfe0f), static_cast('"')}; @@ -1175,8 +1178,7 @@ TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, CHECK(l.events.size() == 1); } -TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T, - char32_t, std::uint32_t) +TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T, char32_t) // NOLINT(readability-math-missing-parentheses) { // a star emoji std::vector const v = {static_cast('"'), static_cast(0x2b50), static_cast(0xfe0f), static_cast('"')}; diff --git a/external/json/tests/src/unit-diagnostics.cpp b/external/json/tests/src/unit-diagnostics.cpp index 0e172b91..472d11e2 100644 --- a/external/json/tests/src/unit-diagnostics.cpp +++ b/external/json/tests/src/unit-diagnostics.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -243,4 +242,24 @@ TEST_CASE("Regression tests for extended diagnostics") json const j_arr_copy = j_arr; } } + + SECTION("Regression test for issue #3915 - JSON_DIAGNOSTICS trigger assertion") + { + json j = json::object(); + j["root"] = "root_str"; + + json jj = json::object(); + jj["child"] = json::object(); + + // If do not push anything in object, then no assert will be produced + jj["child"]["prop1"] = "prop1_value"; + + // Push all properties of child in parent + j.insert(jj.at("child").begin(), jj.at("child").end()); + + // Here assert is generated when construct new json + const json k(j); + + CHECK(k.dump() == "{\"prop1\":\"prop1_value\",\"root\":\"root_str\"}"); + } } diff --git a/external/json/tests/src/unit-disabled_exceptions.cpp b/external/json/tests/src/unit-disabled_exceptions.cpp index 4ad15514..ef64eeee 100644 --- a/external/json/tests/src/unit-disabled_exceptions.cpp +++ b/external/json/tests/src/unit-disabled_exceptions.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -20,10 +19,10 @@ using json = nlohmann::json; // for #2824 ///////////////////////////////////////////////////////////////////// -class sax_no_exception : public nlohmann::detail::json_sax_dom_parser +class sax_no_exception : public nlohmann::detail::json_sax_dom_parser { public: - explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser(j, false) {} + explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser(j, false) {} static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) { diff --git a/external/json/tests/src/unit-element_access1.cpp b/external/json/tests/src/unit-element_access1.cpp index 55a07ede..844e6a44 100644 --- a/external/json/tests/src/unit-element_access1.cpp +++ b/external/json/tests/src/unit-element_access1.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -55,7 +54,7 @@ TEST_CASE("element access 1") SECTION("null") { json j_nonarray(json::value_t::null); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with null", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with null", json::type_error&); @@ -64,7 +63,7 @@ TEST_CASE("element access 1") SECTION("boolean") { json j_nonarray(json::value_t::boolean); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with boolean", json::type_error&); @@ -73,7 +72,7 @@ TEST_CASE("element access 1") SECTION("string") { json j_nonarray(json::value_t::string); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with string", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with string", json::type_error&); @@ -82,7 +81,7 @@ TEST_CASE("element access 1") SECTION("object") { json j_nonarray(json::value_t::object); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with object", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with object", json::type_error&); @@ -91,7 +90,7 @@ TEST_CASE("element access 1") SECTION("number (integer)") { json j_nonarray(json::value_t::number_integer); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); @@ -100,7 +99,7 @@ TEST_CASE("element access 1") SECTION("number (unsigned)") { json j_nonarray(json::value_t::number_unsigned); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); @@ -109,7 +108,7 @@ TEST_CASE("element access 1") SECTION("number (floating-point)") { json j_nonarray(json::value_t::number_float); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const.at(0), "[json.exception.type_error.304] cannot use at() with number", json::type_error&); @@ -155,7 +154,7 @@ TEST_CASE("element access 1") SECTION("standard tests") { json j_nonarray(json::value_t::null); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_NOTHROW(j_nonarray[0]); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with null", json::type_error&); } @@ -171,7 +170,7 @@ TEST_CASE("element access 1") SECTION("boolean") { json j_nonarray(json::value_t::boolean); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&); } @@ -179,7 +178,7 @@ TEST_CASE("element access 1") SECTION("string") { json j_nonarray(json::value_t::string); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&); } @@ -187,7 +186,7 @@ TEST_CASE("element access 1") SECTION("object") { json j_nonarray(json::value_t::object); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&); } @@ -195,7 +194,7 @@ TEST_CASE("element access 1") SECTION("number (integer)") { json j_nonarray(json::value_t::number_integer); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); } @@ -203,7 +202,7 @@ TEST_CASE("element access 1") SECTION("number (unsigned)") { json j_nonarray(json::value_t::number_unsigned); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); } @@ -211,7 +210,7 @@ TEST_CASE("element access 1") SECTION("number (floating-point)") { json j_nonarray(json::value_t::number_float); - const json j_nonarray_const(j_nonarray); + const json j_nonarray_const(j_nonarray); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&); } diff --git a/external/json/tests/src/unit-element_access2.cpp b/external/json/tests/src/unit-element_access2.cpp index 8497fb94..739febc8 100644 --- a/external/json/tests/src/unit-element_access2.cpp +++ b/external/json/tests/src/unit-element_access2.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -17,7 +16,7 @@ // build test with C++14 // JSON_HAS_CPP_14 -TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json) +TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_json) // NOLINT(readability-math-missing-parentheses) { SECTION("object") { @@ -83,7 +82,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("null") { Json j_nonobject(Json::value_t::null); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with null", typename Json::type_error&); @@ -96,7 +95,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("boolean") { Json j_nonobject(Json::value_t::boolean); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with boolean", typename Json::type_error&); @@ -109,7 +108,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("string") { Json j_nonobject(Json::value_t::string); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with string", typename Json::type_error&); @@ -122,7 +121,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("array") { Json j_nonobject(Json::value_t::array); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with array", typename Json::type_error&); @@ -135,7 +134,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("number (integer)") { Json j_nonobject(Json::value_t::number_integer); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); @@ -148,7 +147,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("number (unsigned)") { Json j_nonobject(Json::value_t::number_unsigned); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); @@ -161,7 +160,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j SECTION("number (floating-point)") { Json j_nonobject(Json::value_t::number_float); - const Json j_nonobject_const(j_nonobject); + const Json j_nonobject_const(j_nonobject); // NOLINT(performance-unnecessary-copy-initialization) CHECK_THROWS_WITH_AS(j_nonobject.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); CHECK_THROWS_WITH_AS(j_nonobject_const.at("foo"), "[json.exception.type_error.304] cannot use at() with number", typename Json::type_error&); @@ -1456,7 +1455,7 @@ TEST_CASE_TEMPLATE("element access 2", Json, nlohmann::json, nlohmann::ordered_j } #if !defined(JSON_NOEXCEPTION) -TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nlohmann::ordered_json) +TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nlohmann::ordered_json) // NOLINT(readability-math-missing-parentheses) { SECTION("object") { @@ -1492,7 +1491,7 @@ TEST_CASE_TEMPLATE("element access 2 (throwing tests)", Json, nlohmann::json, nl #endif // TODO(falbrechtskirchinger) merge with the other test case; clean up -TEST_CASE_TEMPLATE("element access 2 (additional value() tests)", Json, nlohmann::json, nlohmann::ordered_json) +TEST_CASE_TEMPLATE("element access 2 (additional value() tests)", Json, nlohmann::json, nlohmann::ordered_json) // NOLINT(readability-math-missing-parentheses) { using string_t = typename Json::string_t; using number_integer_t = typename Json::number_integer_t; diff --git a/external/json/tests/src/unit-hash.cpp b/external/json/tests/src/unit-hash.cpp index 7c98a27c..a6e524c6 100644 --- a/external/json/tests/src/unit-hash.cpp +++ b/external/json/tests/src/unit-hash.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-inspection.cpp b/external/json/tests/src/unit-inspection.cpp index 0574094c..b7e73469 100644 --- a/external/json/tests/src/unit-inspection.cpp +++ b/external/json/tests/src/unit-inspection.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-items.cpp b/external/json/tests/src/unit-items.cpp index ef2dd74b..7544f01d 100644 --- a/external/json/tests/src/unit-items.cpp +++ b/external/json/tests/src/unit-items.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-iterators1.cpp b/external/json/tests/src/unit-iterators1.cpp index 24669a62..49361edc 100644 --- a/external/json/tests/src/unit-iterators1.cpp +++ b/external/json/tests/src/unit-iterators1.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-iterators2.cpp b/external/json/tests/src/unit-iterators2.cpp index ce8c95ba..85cd5bbf 100644 --- a/external/json/tests/src/unit-iterators2.cpp +++ b/external/json/tests/src/unit-iterators2.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT // cmake/test.cmake selects the C++ standard versions with which to build a diff --git a/external/json/tests/src/unit-iterators3.cpp b/external/json/tests/src/unit-iterators3.cpp new file mode 100644 index 00000000..49d3ed6e --- /dev/null +++ b/external/json/tests/src/unit-iterators3.cpp @@ -0,0 +1,35 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" + +#include +#include +#include + +#include +using nlohmann::json; + +#if (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +#ifdef JSON_HAS_CPP_14 +TEST_CASE_TEMPLATE("checking forward-iterators", T, // NOLINT(readability-math-missing-parentheses) + std::vector, std::string, nlohmann::json) +{ + auto it1 = typename T::iterator{}; + auto it2 = typename T::iterator{}; + CHECK(it1 == it2); + CHECK(it1 <= it2); + CHECK(it1 >= it2); + CHECK_FALSE(it1 != it2); + CHECK_FALSE(it1 < it2); + CHECK_FALSE(it1 > it2); +} +#endif diff --git a/external/json/tests/src/unit-json_patch.cpp b/external/json/tests/src/unit-json_patch.cpp index 0999393e..da0cf731 100644 --- a/external/json/tests/src/unit-json_patch.cpp +++ b/external/json/tests/src/unit-json_patch.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -1305,7 +1305,7 @@ TEST_CASE("JSON patch") const auto& doc = test["doc"]; const auto& patch = test["patch"]; - if (test.count("error") == 0) + if (test.count("error") == 0) // NOLINT(readability-container-contains) { // if an expected value is given, use it; use doc otherwise const auto& expected = test.value("expected", doc); diff --git a/external/json/tests/src/unit-json_pointer.cpp b/external/json/tests/src/unit-json_pointer.cpp index 79c67f99..beb24cc9 100644 --- a/external/json/tests/src/unit-json_pointer.cpp +++ b/external/json/tests/src/unit-json_pointer.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-large_json.cpp b/external/json/tests/src/unit-large_json.cpp index 9703a545..4ffc1d01 100644 --- a/external/json/tests/src/unit-large_json.cpp +++ b/external/json/tests/src/unit-large_json.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-locale-cpp.cpp b/external/json/tests/src/unit-locale-cpp.cpp new file mode 100644 index 00000000..529c95cc --- /dev/null +++ b/external/json/tests/src/unit-locale-cpp.cpp @@ -0,0 +1,161 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" + +#define JSON_TESTS_PRIVATE +#include +using nlohmann::json; + +#include + +struct ParserImpl final: public nlohmann::json_sax +{ + bool null() override + { + return true; + } + bool boolean(bool /*val*/) override + { + return true; + } + bool number_integer(json::number_integer_t /*val*/) override + { + return true; + } + bool number_unsigned(json::number_unsigned_t /*val*/) override + { + return true; + } + bool number_float(json::number_float_t /*val*/, const json::string_t& s) override + { + float_string_copy = s; + return true; + } + bool string(json::string_t& /*val*/) override + { + return true; + } + bool binary(json::binary_t& /*val*/) override + { + return true; + } + bool start_object(std::size_t /*val*/) override + { + return true; + } + bool key(json::string_t& /*val*/) override + { + return true; + } + bool end_object() override + { + return true; + } + bool start_array(std::size_t /*val*/) override + { + return true; + } + bool end_array() override + { + return true; + } + bool parse_error(std::size_t /*val*/, const std::string& /*val*/, const nlohmann::detail::exception& /*val*/) override + { + return false; + } + + ~ParserImpl() override; + + ParserImpl() + : float_string_copy("not set") + {} + + ParserImpl(const ParserImpl& other) + : float_string_copy(other.float_string_copy) + {} + + ParserImpl(ParserImpl&& other) noexcept + : float_string_copy(std::move(other.float_string_copy)) + {} + + ParserImpl& operator=(const ParserImpl& other) + { + if (this != &other) + { + float_string_copy = other.float_string_copy; + } + return *this; + } + + ParserImpl& operator=(ParserImpl&& other) noexcept + { + if (this != &other) + { + float_string_copy = std::move(other.float_string_copy); + } + return *this; + } + + json::string_t float_string_copy; +}; + +ParserImpl::~ParserImpl() = default; + +TEST_CASE("locale-dependent test (LC_NUMERIC=C)") +{ + WARN_MESSAGE(std::setlocale(LC_NUMERIC, "C") != nullptr, "could not set locale"); + + SECTION("check if locale is properly set") + { + std::array buffer = {}; + CHECK(std::snprintf(buffer.data(), buffer.size(), "%.2f", 12.34) == 5); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + CHECK(std::string(buffer.data()) == "12.34"); + } + + SECTION("parsing") + { + CHECK(json::parse("12.34").dump() == "12.34"); + } + + SECTION("SAX parsing") + { + ParserImpl sax {}; + json::sax_parse( "12.34", &sax ); + CHECK(sax.float_string_copy == "12.34"); + } +} + +TEST_CASE("locale-dependent test (LC_NUMERIC=de_DE)") +{ + if (std::setlocale(LC_NUMERIC, "de_DE") != nullptr) + { + SECTION("check if locale is properly set") + { + std::array buffer = {}; + CHECK(std::snprintf(buffer.data(), buffer.size(), "%.2f", 12.34) == 5); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) + CHECK(std::string(buffer.data()) == "12,34"); + } + + SECTION("parsing") + { + CHECK(json::parse("12.34").dump() == "12.34"); + } + + SECTION("SAX parsing") + { + ParserImpl sax{}; + json::sax_parse("12.34", &sax); + CHECK(sax.float_string_copy == "12.34"); + } + } + else + { + MESSAGE("locale de_DE is not usable"); + } +} diff --git a/external/json/tests/src/unit-merge_patch.cpp b/external/json/tests/src/unit-merge_patch.cpp index 6a8bcfe2..411ac28d 100644 --- a/external/json/tests/src/unit-merge_patch.cpp +++ b/external/json/tests/src/unit-merge_patch.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-meta.cpp b/external/json/tests/src/unit-meta.cpp index a522faab..50e6c891 100644 --- a/external/json/tests/src/unit-meta.cpp +++ b/external/json/tests/src/unit-meta.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-modifiers.cpp b/external/json/tests/src/unit-modifiers.cpp index fb686780..f113fa17 100644 --- a/external/json/tests/src/unit-modifiers.cpp +++ b/external/json/tests/src/unit-modifiers.cpp @@ -3,8 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// Copyright (c) 2013-2022 Niels Lohmann . -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-msgpack.cpp b/external/json/tests/src/unit-msgpack.cpp index 61162afa..a24f4996 100644 --- a/external/json/tests/src/unit-msgpack.cpp +++ b/external/json/tests/src/unit-msgpack.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -281,7 +281,7 @@ TEST_CASE("MessagePack") // check individual bytes CHECK(result[0] == 0xcd); - auto const restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + auto const restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -479,11 +479,11 @@ TEST_CASE("MessagePack") std::vector const numbers { -32769, - -65536, - -77777, - -1048576, - -2147483648LL, - }; + -65536, + -77777, + -1048576, + -2147483648LL, + }; for (auto i : numbers) { CAPTURE(i) @@ -671,7 +671,7 @@ TEST_CASE("MessagePack") // check individual bytes CHECK(result[0] == 0xcd); - auto const restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + auto const restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -1508,6 +1508,22 @@ TEST_CASE("MessagePack") CHECK(json::from_msgpack(std::vector({0xc4}), true, false).is_discarded()); } + SECTION("unexpected end inside int with stream") + { + json _; + const std::string data = {static_cast(0xd2u), static_cast(0x12u), static_cast(0x34u), static_cast(0x56u)}; + CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::istringstream(data, std::ios::binary)), + "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing MessagePack number: unexpected end of input", json::parse_error&); + } + SECTION("misuse wchar for binary") + { + json _; + // creates 0xd2 after UTF-8 decoding, triggers get_elements in wide_string_input_adapter for code coverage + const std::u32string data = {static_cast(0x0280)}; + CHECK_THROWS_WITH_AS(_ = json::from_msgpack(data), + "[json.exception.parse_error.112] parse error at byte 1: wide string type cannot be interpreted as binary data", json::parse_error&); + } + SECTION("unsupported bytes") { SECTION("concrete examples") @@ -1604,7 +1620,7 @@ TEST_CASE("single MessagePack roundtrip") { SECTION("std::ostringstream") { - std::basic_ostringstream ss; + std::basic_ostringstream ss; json::to_msgpack(j1, ss); json j3 = json::from_msgpack(ss.str()); CHECK(j1 == j3); diff --git a/external/json/tests/src/unit-no-mem-leak-on-adl-serialize.cpp b/external/json/tests/src/unit-no-mem-leak-on-adl-serialize.cpp index 37b10a91..23552178 100644 --- a/external/json/tests/src/unit-no-mem-leak-on-adl-serialize.cpp +++ b/external/json/tests/src/unit-no-mem-leak-on-adl-serialize.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-noexcept.cpp b/external/json/tests/src/unit-noexcept.cpp index bba230d0..8364e83a 100644 --- a/external/json/tests/src/unit-noexcept.cpp +++ b/external/json/tests/src/unit-noexcept.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -12,6 +12,11 @@ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") +// skip tests if JSON_DisableEnumSerialization=ON (#4384) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1) + #define SKIP_TESTS_FOR_ENUM_SERIALIZATION +#endif + #include using nlohmann::json; @@ -36,12 +41,16 @@ static_assert(noexcept(json{}), ""); static_assert(noexcept(nlohmann::to_json(std::declval(), 2)), ""); static_assert(noexcept(nlohmann::to_json(std::declval(), 2.5)), ""); static_assert(noexcept(nlohmann::to_json(std::declval(), true)), ""); -static_assert(noexcept(nlohmann::to_json(std::declval(), test{})), ""); -static_assert(noexcept(nlohmann::to_json(std::declval(), pod{})), ""); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION +static_assert(noexcept(nlohmann::to_json(std::declval(), test {})), ""); +#endif +static_assert(noexcept(nlohmann::to_json(std::declval(), pod {})), ""); static_assert(!noexcept(nlohmann::to_json(std::declval(), pod_bis{})), ""); static_assert(noexcept(json(2)), ""); -static_assert(noexcept(json(test{})), ""); -static_assert(noexcept(json(pod{})), ""); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION +static_assert(noexcept(json(test {})), ""); +#endif +static_assert(noexcept(json(pod {})), ""); static_assert(noexcept(std::declval().get()), ""); static_assert(!noexcept(std::declval().get()), ""); static_assert(noexcept(json(pod{})), ""); diff --git a/external/json/tests/src/unit-ordered_json.cpp b/external/json/tests/src/unit-ordered_json.cpp index d77d904b..982b7a3d 100644 --- a/external/json/tests/src/unit-ordered_json.cpp +++ b/external/json/tests/src/unit-ordered_json.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-ordered_map.cpp b/external/json/tests/src/unit-ordered_map.cpp index ceafea1e..3171177c 100644 --- a/external/json/tests/src/unit-ordered_map.cpp +++ b/external/json/tests/src/unit-ordered_map.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-pointer_access.cpp b/external/json/tests/src/unit-pointer_access.cpp index 4503a3b7..b5734559 100644 --- a/external/json/tests/src/unit-pointer_access.cpp +++ b/external/json/tests/src/unit-pointer_access.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -326,7 +326,7 @@ TEST_CASE("pointer access") CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); - CHECK(value.get_ptr() != nullptr); + CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() != nullptr); CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); @@ -355,7 +355,7 @@ TEST_CASE("pointer access") CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); - CHECK(value.get_ptr() != nullptr); + CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() != nullptr); CHECK(value.get_ptr() == nullptr); CHECK(value.get_ptr() == nullptr); diff --git a/external/json/tests/src/unit-readme.cpp b/external/json/tests/src/unit-readme.cpp index f2a571aa..66f9d9b0 100644 --- a/external/json/tests/src/unit-readme.cpp +++ b/external/json/tests/src/unit-readme.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -115,7 +115,7 @@ TEST_CASE("README" * doctest::skip()) auto j3 = json::parse(R"({"happy": true, "pi": 3.141})"); // explicit conversion to string - std::string const s = j.dump(); // {\"happy\":true,\"pi\":3.141} + std::string const s = j.dump(); // NOLINT(bugprone-unused-local-non-trivial-variable) // {\"happy\":true,\"pi\":3.141} // serialization with pretty printing // pass in the amount of spaces to indent @@ -152,7 +152,7 @@ TEST_CASE("README" * doctest::skip()) } // getter/setter - const auto tmp = j[0].get(); + const auto tmp = j[0].get(); // NOLINT(bugprone-unused-local-non-trivial-variable) j[1] = 42; bool foo{j.at(2)}; CHECK(foo == true); @@ -171,7 +171,7 @@ TEST_CASE("README" * doctest::skip()) // find an entry CHECK(o.find("foo") != o.end()); - if (o.find("foo") != o.end()) + if (o.find("foo") != o.end()) // NOLINT(readability-container-contains) { // there is an entry with key "foo" } @@ -237,7 +237,7 @@ TEST_CASE("README" * doctest::skip()) // strings std::string const s1 = "Hello, world!"; json const js = s1; - auto s2 = js.get(); + auto s2 = js.get(); // NOLINT(bugprone-unused-local-non-trivial-variable) // Booleans bool const b1 = true; @@ -253,7 +253,7 @@ TEST_CASE("README" * doctest::skip()) // etc. - std::string const vs = js.get(); + std::string const vs = js.get(); // NOLINT(bugprone-unused-local-non-trivial-variable) bool vb = jb.get(); CHECK(vb == true); int vi = jn.get(); diff --git a/external/json/tests/src/unit-reference_access.cpp b/external/json/tests/src/unit-reference_access.cpp index 3b46fe83..d63a470d 100644 --- a/external/json/tests/src/unit-reference_access.cpp +++ b/external/json/tests/src/unit-reference_access.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -215,8 +215,8 @@ TEST_CASE("reference access") "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number", json::type_error&); CHECK_THROWS_WITH_AS(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number", json::type_error&); - //CHECK_THROWS_WITH_AS(value.get_ref(), - // "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number", json::type_error&); + CHECK_THROWS_WITH_AS(value.get_ref(), + "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number", json::type_error&); CHECK_NOTHROW(value.get_ref()); CHECK_THROWS_WITH_AS(value.get_ref(), "[json.exception.type_error.303] incompatible ReferenceType for get_ref, actual type is number", json::type_error&); } diff --git a/external/json/tests/src/unit-regression1.cpp b/external/json/tests/src/unit-regression1.cpp index f5ef5d80..ecb970d2 100644 --- a/external/json/tests/src/unit-regression1.cpp +++ b/external/json/tests/src/unit-regression1.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -11,6 +11,11 @@ // for some reason including this after the json header leads to linker errors with VS 2017... #include +// skip tests if JSON_DisableEnumSerialization=ON (#4384) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1) + #define SKIP_TESTS_FOR_ENUM_SERIALIZATION +#endif + #define JSON_TESTS_PRIVATE #include using nlohmann::json; @@ -169,6 +174,7 @@ TEST_CASE("regression tests 1") } } +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION SECTION("pull request #71 - handle enum type") { enum { t = 0, u = 102}; @@ -191,6 +197,7 @@ TEST_CASE("regression tests 1") {"game_type", t} })); } +#endif SECTION("issue #76 - dump() / parse() not idempotent") { @@ -1328,10 +1335,10 @@ TEST_CASE("regression tests 1") { std::ifstream is; is.exceptions( - is.exceptions() - | std::ios_base::failbit - | std::ios_base::badbit - ); // handle different exceptions as 'file not found', 'permission denied' + is.exceptions() + | std::ios_base::failbit + | std::ios_base::badbit + ); // handle different exceptions as 'file not found', 'permission denied' is.open(TEST_DATA_DIRECTORY "/regression/working_file.json"); json _; @@ -1341,10 +1348,10 @@ TEST_CASE("regression tests 1") { std::ifstream is; is.exceptions( - is.exceptions() - | std::ios_base::failbit - | std::ios_base::badbit - ); // handle different exceptions as 'file not found', 'permission denied' + is.exceptions() + | std::ios_base::failbit + | std::ios_base::badbit + ); // handle different exceptions as 'file not found', 'permission denied' is.open(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json.cbor", std::ios_base::in | std::ios_base::binary); diff --git a/external/json/tests/src/unit-regression2.cpp b/external/json/tests/src/unit-regression2.cpp index fab9aae3..88a64a7b 100644 --- a/external/json/tests/src/unit-regression2.cpp +++ b/external/json/tests/src/unit-regression2.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT // cmake/test.cmake selects the C++ standard versions with which to build a @@ -90,18 +90,18 @@ struct Data : a(std::move(a_)) , b(std::move(b_)) {} - std::string a{}; - std::string b{}; + std::string a{}; // NOLINT(readability-redundant-member-init) + std::string b{}; // NOLINT(readability-redundant-member-init) }; -void from_json(const json& j, Data& data); +void from_json(const json& j, Data& data); // NOLINT(misc-use-internal-linkage) void from_json(const json& j, Data& data) { j["a"].get_to(data.a); j["b"].get_to(data.b); } -bool operator==(Data const& lhs, Data const& rhs); +bool operator==(Data const& lhs, Data const& rhs); // NOLINT(misc-use-internal-linkage) bool operator==(Data const& lhs, Data const& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; @@ -162,11 +162,11 @@ struct adl_serializer // for #2824 ///////////////////////////////////////////////////////////////////// -class sax_no_exception : public nlohmann::detail::json_sax_dom_parser +class sax_no_exception : public nlohmann::detail::json_sax_dom_parser { public: explicit sax_no_exception(json& j) - : nlohmann::detail::json_sax_dom_parser(j, false) + : nlohmann::detail::json_sax_dom_parser(j, false) {} static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) @@ -218,10 +218,10 @@ class Foo class FooBar { public: - Foo foo{}; + Foo foo{}; // NOLINT(readability-redundant-member-init) }; -inline void from_json(const nlohmann::json& j, FooBar& fb) +inline void from_json(const nlohmann::json& j, FooBar& fb) // NOLINT(misc-use-internal-linkage) { j.at("value").get_to(fb.foo.value); } @@ -233,23 +233,80 @@ inline void from_json(const nlohmann::json& j, FooBar& fb) struct for_3171_base // NOLINT(cppcoreguidelines-special-member-functions) { for_3171_base(const std::string& /*unused*/ = {}) {} - virtual ~for_3171_base() = default; + virtual ~for_3171_base(); + + for_3171_base(const for_3171_base& other) // NOLINT(hicpp-use-equals-default,modernize-use-equals-default) + : str(other.str) + {} + + for_3171_base& operator=(const for_3171_base& other) + { + if (this != &other) + { + str = other.str; + } + return *this; + } + + for_3171_base(for_3171_base&& other) noexcept + : str(std::move(other.str)) + {} + + for_3171_base& operator=(for_3171_base&& other) noexcept + { + if (this != &other) + { + str = std::move(other.str); + } + return *this; + } virtual void _from_json(const json& j) { j.at("str").get_to(str); } - std::string str{}; + std::string str{}; // NOLINT(readability-redundant-member-init) }; +for_3171_base::~for_3171_base() = default; + struct for_3171_derived : public for_3171_base { for_3171_derived() = default; + ~for_3171_derived() override; explicit for_3171_derived(const std::string& /*unused*/) { } + + for_3171_derived(const for_3171_derived& other) // NOLINT(hicpp-use-equals-default,modernize-use-equals-default) + : for_3171_base(other) + {} + + for_3171_derived& operator=(const for_3171_derived& other) + { + if (this != &other) + { + for_3171_base::operator=(other); // Call base class assignment operator + } + return *this; + } + + for_3171_derived(for_3171_derived&& other) noexcept + : for_3171_base(std::move(other)) + {} + + for_3171_derived& operator=(for_3171_derived&& other) noexcept + { + if (this != &other) + { + for_3171_base::operator=(std::move(other)); // Call base class move assignment operator + } + return *this; + } }; -inline void from_json(const json& j, for_3171_base& tb) +for_3171_derived::~for_3171_derived() = default; + +inline void from_json(const json& j, for_3171_base& tb) // NOLINT(misc-use-internal-linkage) { tb._from_json(j); } @@ -264,7 +321,7 @@ struct for_3312 std::string name; }; -inline void from_json(const json& j, for_3312& obj) +inline void from_json(const json& j, for_3312& obj) // NOLINT(misc-use-internal-linkage) { j.at("name").get_to(obj.name); } @@ -622,8 +679,8 @@ TEST_CASE("regression tests 2") // see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060 const json j{{"x", "test"}}; const std::string defval = "default value"; - auto val = j.value("x", defval); - auto val2 = j.value("y", defval); + auto val = j.value("x", defval); // NOLINT(bugprone-unused-local-non-trivial-variable) + auto val2 = j.value("y", defval); // NOLINT(bugprone-unused-local-non-trivial-variable) } SECTION("issue #2293 - eof doesn't cause parsing to stop") @@ -675,6 +732,7 @@ TEST_CASE("regression tests 2") } #ifdef JSON_HAS_CPP_20 +#ifndef _LIBCPP_VERSION // see https://github.com/nlohmann/json/issues/4490 #if __has_include() SECTION("issue #2546 - parsing containers of std::byte") { @@ -684,6 +742,7 @@ TEST_CASE("regression tests 2") CHECK(j.dump() == "\"Hello, world!\""); } #endif +#endif #endif SECTION("issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails") @@ -866,7 +925,7 @@ TEST_CASE("regression tests 2") CHECK(j.dump() == "[1,4]"); } - SECTION("issue #3343 - json and ordered_json are not interchangable") + SECTION("issue #3343 - json and ordered_json are not interchangeable") { json::object_t jobj({ { "product", "one" } }); ordered_json::object_t ojobj({{"product", "one"}}); diff --git a/external/json/tests/src/unit-serialization.cpp b/external/json/tests/src/unit-serialization.cpp index e8f0e7e5..201e5724 100644 --- a/external/json/tests/src/unit-serialization.cpp +++ b/external/json/tests/src/unit-serialization.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -165,7 +165,7 @@ TEST_CASE("serialization") } } -TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t) +TEST_CASE_TEMPLATE("serialization for extreme integer values", T, int32_t, uint32_t, int64_t, uint64_t) // NOLINT(readability-math-missing-parentheses) { SECTION("minimum") { diff --git a/external/json/tests/src/unit-testsuites.cpp b/external/json/tests/src/unit-testsuites.cpp index 5807934b..d32616bc 100644 --- a/external/json/tests/src/unit-testsuites.cpp +++ b/external/json/tests/src/unit-testsuites.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -163,7 +163,7 @@ TEST_CASE("compliance tests from nativejson-benchmark") TEST_DOUBLE("[2.2250738585072012e-308]", 2.2250738585072014e-308); - // More closer to normal/subnormal boundary + // Closer to normal/subnormal boundary // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308 TEST_DOUBLE("[2.22507385850720113605740979670913197593481954635164564e-308]", 2.2250738585072009e-308); @@ -312,7 +312,7 @@ TEST_CASE("test suite from json-test-suite") { SECTION("read all sample.json") { - // read a file with all unicode characters stored as single-character + // read a file with all Unicode characters stored as single-character // strings in a JSON array std::ifstream f(TEST_DATA_DIRECTORY "/json_testsuite/sample.json"); json j; diff --git a/external/json/tests/src/unit-to_chars.cpp b/external/json/tests/src/unit-to_chars.cpp index 6d32e065..d7c8de04 100644 --- a/external/json/tests/src/unit-to_chars.cpp +++ b/external/json/tests/src/unit-to_chars.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT // XXX: diff --git a/external/json/tests/src/unit-type_traits.cpp b/external/json/tests/src/unit-type_traits.cpp index 4c78aa99..c672b6b3 100644 --- a/external/json/tests/src/unit-type_traits.cpp +++ b/external/json/tests/src/unit-type_traits.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-ubjson.cpp b/external/json/tests/src/unit-ubjson.cpp index 06611c5f..a9d931cd 100644 --- a/external/json/tests/src/unit-ubjson.cpp +++ b/external/json/tests/src/unit-ubjson.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -450,7 +450,7 @@ TEST_CASE("UBJSON") // check individual bytes CHECK(result[0] == 'I'); - auto const restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + auto const restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -655,7 +655,7 @@ TEST_CASE("UBJSON") // check individual bytes CHECK(result[0] == 'I'); - auto const restored = static_cast(static_cast(result[1]) * 256 + static_cast(result[2])); + auto const restored = static_cast((static_cast(result[1]) * 256) + static_cast(result[2])); CHECK(restored == i); // roundtrip @@ -1617,7 +1617,7 @@ TEST_CASE("UBJSON") CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); json j; - nlohmann::detail::json_sax_dom_callback_parser scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + nlohmann::detail::json_sax_dom_callback_parser scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept { return true; }); @@ -1631,7 +1631,7 @@ TEST_CASE("UBJSON") CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); json j; - nlohmann::detail::json_sax_dom_callback_parser scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept + nlohmann::detail::json_sax_dom_callback_parser scp(j, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept { return true; }); diff --git a/external/json/tests/src/unit-udl.cpp b/external/json/tests/src/unit-udl.cpp index bb72ccbc..08378877 100644 --- a/external/json/tests/src/unit-udl.cpp +++ b/external/json/tests/src/unit-udl.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-udt.cpp b/external/json/tests/src/unit-udt.cpp index b138aa46..8e567a9e 100644 --- a/external/json/tests/src/unit-udt.cpp +++ b/external/json/tests/src/unit-udt.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -12,6 +12,11 @@ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") +// skip tests if JSON_DisableEnumSerialization=ON (#4384) +#if defined(JSON_DISABLE_ENUM_SERIALIZATION) && (JSON_DISABLE_ENUM_SERIALIZATION == 1) + #define SKIP_TESTS_FOR_ENUM_SERIALIZATION +#endif + #include using nlohmann::json; #ifdef JSON_TEST_NO_GLOBAL_UDLS @@ -52,27 +57,30 @@ struct address struct person { - age m_age{}; - name m_name{}; - country m_country{}; + age m_age{}; // NOLINT(readability-redundant-member-init) + name m_name{}; // NOLINT(readability-redundant-member-init) + country m_country{}; // NOLINT(readability-redundant-member-init) person() = default; person(const age& a, name n, const country& c) : m_age(a), m_name(std::move(n)), m_country(c) {} }; struct contact { - person m_person{}; - address m_address{}; + person m_person{}; // NOLINT(readability-redundant-member-init) + address m_address{}; // NOLINT(readability-redundant-member-init) contact() = default; contact(person p, address a) : m_person(std::move(p)), m_address(std::move(a)) {} }; +enum class book_id : std::uint64_t; + struct contact_book { - name m_book_name{}; - std::vector m_contacts{}; + name m_book_name{}; // NOLINT(readability-redundant-member-init) + book_id m_book_id{}; + std::vector m_contacts{}; // NOLINT(readability-redundant-member-init) contact_book() = default; - contact_book(name n, std::vector c) : m_book_name(std::move(n)), m_contacts(std::move(c)) {} + contact_book(name n, book_id i, std::vector c) : m_book_name(std::move(n)), m_book_id(i), m_contacts(std::move(c)) {} }; } // namespace udt @@ -129,7 +137,11 @@ static void to_json(nlohmann::json& j, const contact& c) static void to_json(nlohmann::json& j, const contact_book& cb) { - j = json{{"name", cb.m_book_name}, {"contacts", cb.m_contacts}}; + j = json{{"name", cb.m_book_name}, +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + {"id", cb.m_book_id}, +#endif + {"contacts", cb.m_contacts}}; } // operators @@ -161,8 +173,8 @@ static bool operator==(const contact& lhs, const contact& rhs) static bool operator==(const contact_book& lhs, const contact_book& rhs) { - return std::tie(lhs.m_book_name, lhs.m_contacts) == - std::tie(rhs.m_book_name, rhs.m_contacts); + return std::tie(lhs.m_book_name, lhs.m_book_id, lhs.m_contacts) == + std::tie(rhs.m_book_name, rhs.m_book_id, rhs.m_contacts); } } // namespace udt @@ -219,6 +231,9 @@ static void from_json(const nlohmann::json& j, contact& c) static void from_json(const nlohmann::json& j, contact_book& cb) { cb.m_book_name = j["name"].get(); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + cb.m_book_id = j["id"].get(); +#endif cb.m_contacts = j["contacts"].get>(); } } // namespace udt @@ -237,7 +252,8 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) const udt::person senior_programmer{{42}, {"王芳"}, udt::country::china}; const udt::address addr{"Paris"}; const udt::contact cpp_programmer{sfinae_addict, addr}; - const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}}; + const udt::book_id large_id{static_cast(static_cast(1) << 63)}; // verify large unsigned enums are handled correctly + const udt::contact_book book{{"C++"}, static_cast(42u), {cpp_programmer, {senior_programmer, addr}}}; SECTION("conversion to json via free-functions") { @@ -248,21 +264,36 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK(json("Paris") == json(addr)); CHECK(json(cpp_programmer) == R"({"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"})"_json); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + CHECK(json(large_id) == json(static_cast(1) << 63)); + CHECK(json(large_id) > 0u); + CHECK(to_string(json(large_id)) == "9223372036854775808"); + CHECK(json(large_id).is_number_unsigned()); +#endif +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + CHECK( + json(book) == + R"({"name":"C++", "id":42, "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); +#else CHECK( json(book) == R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json); +#endif } SECTION("conversion from json via free-functions") { const auto big_json = - R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; + R"({"name":"C++", "id":42, "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json; SECTION("via explicit calls to get") { const auto parsed_book = big_json.get(); const auto book_name = big_json["name"].get(); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + const auto book_id = big_json["id"].get(); +#endif const auto contacts = big_json["contacts"].get>(); const auto contact_json = big_json["contacts"].at(0); @@ -282,7 +313,10 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK(contact == cpp_programmer); CHECK(contacts == book.m_contacts); CHECK(book_name == udt::name{"C++"}); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + CHECK(book_id == book.m_book_id); CHECK(book == parsed_book); +#endif } SECTION("via explicit calls to get_to") @@ -303,6 +337,9 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) { const udt::contact_book parsed_book = big_json; const udt::name book_name = big_json["name"]; +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + const udt::book_id book_id = big_json["id"]; +#endif const std::vector contacts = big_json["contacts"]; const auto contact_json = big_json["contacts"].at(0); const udt::contact contact = contact_json; @@ -320,7 +357,10 @@ TEST_CASE("basic usage" * doctest::test_suite("udt")) CHECK(contact == cpp_programmer); CHECK(contacts == book.m_contacts); CHECK(book_name == udt::name{"C++"}); +#ifndef SKIP_TESTS_FOR_ENUM_SERIALIZATION + CHECK(book_id == static_cast(42u)); CHECK(book == parsed_book); +#endif } #endif } @@ -330,7 +370,7 @@ namespace udt { struct legacy_type { - std::string number{}; + std::string number{}; // NOLINT(readability-redundant-member-init) legacy_type() = default; legacy_type(std::string n) : number(std::move(n)) {} }; @@ -603,7 +643,7 @@ struct small_pod struct non_pod { - std::string s{}; + std::string s{}; // NOLINT(readability-redundant-member-init) non_pod() = default; non_pod(std::string S) : s(std::move(S)) {} }; diff --git a/external/json/tests/src/unit-udt_macro.cpp b/external/json/tests/src/unit-udt_macro.cpp index e2383f40..8a71d448 100644 --- a/external/json/tests/src/unit-udt_macro.cpp +++ b/external/json/tests/src/unit-udt_macro.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include @@ -18,7 +18,7 @@ namespace persons class person_with_private_data { private: - std::string name{}; + std::string name{}; // NOLINT(readability-redundant-member-init) int age = 0; json metadata = nullptr; @@ -38,10 +38,30 @@ class person_with_private_data NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata) }; +class derived_person_with_private_data : public person_with_private_data +{ + private: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_with_private_data& rhs) const + { + return person_with_private_data::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_with_private_data() = default; + derived_person_with_private_data(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_with_private_data(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(derived_person_with_private_data, person_with_private_data, hair_color) +}; + class person_with_private_data_2 { private: - std::string name{}; + std::string name{}; // NOLINT(readability-redundant-member-init) int age = 0; json metadata = nullptr; @@ -74,10 +94,35 @@ class person_with_private_data_2 NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person_with_private_data_2, age, name, metadata) }; +class derived_person_with_private_data_2 : public person_with_private_data_2 +{ + private: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_with_private_data_2& rhs) const + { + return person_with_private_data_2::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_with_private_data_2() = default; + derived_person_with_private_data_2(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_with_private_data_2(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + std::string getHairColor() const + { + return hair_color; + } + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(derived_person_with_private_data_2, person_with_private_data_2, hair_color) +}; + class person_without_private_data_1 { public: - std::string name{}; + std::string name{}; // NOLINT(readability-redundant-member-init) int age = 0; json metadata = nullptr; @@ -96,10 +141,30 @@ class person_without_private_data_1 NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_without_private_data_1, age, name, metadata) }; +class derived_person_without_private_data_1 : public person_without_private_data_1 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_1& rhs) const + { + return person_without_private_data_1::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_1() = default; + derived_person_without_private_data_1(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_1(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(derived_person_without_private_data_1, person_without_private_data_1, hair_color) +}; + class person_without_private_data_2 { public: - std::string name{}; + std::string name{}; // NOLINT(readability-redundant-member-init) int age = 0; json metadata = nullptr; @@ -118,10 +183,30 @@ class person_without_private_data_2 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata) +class derived_person_without_private_data_2 : public person_without_private_data_2 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_2& rhs) const + { + return person_without_private_data_2::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_2() = default; + derived_person_without_private_data_2(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_2(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} +}; + +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(derived_person_without_private_data_2, person_without_private_data_2, hair_color) + class person_without_private_data_3 { public: - std::string name{}; + std::string name{}; // NOLINT(readability-redundant-member-init) int age = 0; json metadata = nullptr; @@ -153,6 +238,31 @@ class person_without_private_data_3 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person_without_private_data_3, age, name, metadata) +class derived_person_without_private_data_3 : public person_without_private_data_3 +{ + public: + std::string hair_color{"blue"}; + + public: + bool operator==(const derived_person_without_private_data_3& rhs) const + { + return person_without_private_data_3::operator==(rhs) && hair_color == rhs.hair_color; + } + + derived_person_without_private_data_3() = default; + derived_person_without_private_data_3(std::string name_, int age_, json metadata_, std::string hair_color_) + : person_without_private_data_3(std::move(name_), age_, std::move(metadata_)) + , hair_color(std::move(hair_color_)) + {} + + std::string getHairColor() const + { + return hair_color; + } +}; + +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(derived_person_without_private_data_3, person_without_private_data_3, hair_color) + class person_with_private_alphabet { public: @@ -216,6 +326,19 @@ class person_with_private_alphabet NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_alphabet, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z) }; +class derived_person_with_private_alphabet : public person_with_private_alphabet +{ + public: + bool operator==(const derived_person_with_private_alphabet& other) const + { + return person_with_private_alphabet::operator==(other) && schwa == other.schwa; + } + + private: + int schwa = 0; + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(derived_person_with_private_alphabet, person_with_private_alphabet, schwa) +}; + class person_with_public_alphabet { public: @@ -317,9 +440,35 @@ class person_without_default_constructor_2 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(person_without_default_constructor_2, name, age) +class derived_person_only_serialize_public : public person_without_default_constructor_1 +{ + public: + std::string hair_color; + + derived_person_only_serialize_public(std::string name_, int age_, std::string hair_color_) + : person_without_default_constructor_1(std::move(name_), age_) + , hair_color(std::move(hair_color_)) + {} +}; + +NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_public, person_without_default_constructor_1, hair_color) + +class derived_person_only_serialize_private : person_without_default_constructor_1 +{ + private: + std::string hair_color; + public: + derived_person_only_serialize_private(std::string name_, int age_, std::string hair_color_) + : person_without_default_constructor_1(std::move(name_), age_) + , hair_color(std::move(hair_color_)) + {} + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(derived_person_only_serialize_private, person_without_default_constructor_1, hair_color) +}; + } // namespace persons -TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, // NOLINT(readability-math-missing-parentheses) persons::person_with_private_data, persons::person_without_private_data_1, persons::person_without_private_data_2) @@ -345,7 +494,33 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU } } -TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT", T, +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE", T, // NOLINT(readability-math-missing-parentheses) + persons::derived_person_with_private_data, + persons::derived_person_without_private_data_1, + persons::derived_person_without_private_data_2) +{ + SECTION("person") + { + // serialization + T p1("Erik", 1, {{"haircuts", 2}}, "red"); + CHECK(json(p1).dump() == "{\"age\":1,\"hair_color\":\"red\",\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check exception in case of missing field + json j = json(p1); + j.erase("age"); + CHECK_THROWS_WITH_AS(j.get(), "[json.exception.out_of_range.403] key 'age' not found", json::out_of_range); + } +} + +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT", T, // NOLINT(readability-math-missing-parentheses) persons::person_with_private_data_2, persons::person_without_private_data_3) { @@ -376,10 +551,53 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU CHECK(p3.getName() == ""); CHECK(p3.getAge() == 0); CHECK(p3.getMetadata() == nullptr); + + // check default value in case of empty json + const json j4; + T p4 = j4.get(); + CHECK(p4.getName() == ""); + CHECK(p4.getAge() == 0); + CHECK(p4.getMetadata() == nullptr); } } -TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, +TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT", T, // NOLINT(readability-math-missing-parentheses) + persons::derived_person_with_private_data_2, + persons::derived_person_without_private_data_3) +{ + SECTION("derived person with default values") + { + // serialization of default constructed object + T p0; + CHECK(json(p0).dump() == "{\"age\":0,\"hair_color\":\"blue\",\"metadata\":null,\"name\":\"\"}"); + + // serialization + T p1("Erik", 1, {{"haircuts", 2}}, "red"); + CHECK(json(p1).dump() == "{\"age\":1,\"hair_color\":\"red\",\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}"); + + // deserialization + auto p2 = json(p1).get(); + CHECK(p2 == p1); + + // roundtrip + CHECK(T(json(p1)) == p1); + CHECK(json(T(json(p1))) == json(p1)); + + // check default value in case of missing field + json j = json(p1); + j.erase("name"); + j.erase("age"); + j.erase("metadata"); + j.erase("hair_color"); + T p3 = j.get(); + CHECK(p3.getName() == ""); + CHECK(p3.getAge() == 0); + CHECK(p3.getMetadata() == nullptr); + CHECK(p3.getHairColor() == "blue"); + } +} + +TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T, // NOLINT(readability-math-missing-parentheses) persons::person_with_private_alphabet, persons::person_with_public_alphabet) { @@ -451,7 +669,7 @@ TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/priv } } -TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", T, +TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", T, // NOLINT(readability-math-missing-parentheses) persons::person_without_default_constructor_1, persons::person_without_default_constructor_2) { @@ -472,3 +690,25 @@ TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHM } } } + +TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE and NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE", T, // NOLINT(readability-math-missing-parentheses) + persons::derived_person_only_serialize_public, + persons::derived_person_only_serialize_private) +{ + SECTION("derived person only serialize") + { + { + // serialization of a single object + T person{"Erik", 1, "brown"}; + CHECK(json(person).dump() == "{\"age\":1,\"hair_color\":\"brown\",\"name\":\"Erik\"}"); + + // serialization of a container with objects + std::vector const two_persons + { + {"Erik", 1, "brown"}, + {"Kyle", 2, "black"} + }; + CHECK(json(two_persons).dump() == "[{\"age\":1,\"hair_color\":\"brown\",\"name\":\"Erik\"},{\"age\":2,\"hair_color\":\"black\",\"name\":\"Kyle\"}]"); + } + } +} diff --git a/external/json/tests/src/unit-unicode1.cpp b/external/json/tests/src/unit-unicode1.cpp index e4405c47..f812d669 100644 --- a/external/json/tests/src/unit-unicode1.cpp +++ b/external/json/tests/src/unit-unicode1.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" @@ -155,7 +155,7 @@ TEST_CASE("Unicode (1/5)" * doctest::skip()) SECTION("read all unicode characters") { - // read a file with all unicode characters stored as single-character + // read a file with all Unicode characters stored as single-character // strings in a JSON array std::ifstream f(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json"); json j; diff --git a/external/json/tests/src/unit-unicode2.cpp b/external/json/tests/src/unit-unicode2.cpp index ebc29db5..606de12e 100644 --- a/external/json/tests/src/unit-unicode2.cpp +++ b/external/json/tests/src/unit-unicode2.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-unicode3.cpp b/external/json/tests/src/unit-unicode3.cpp index dffb1cfa..b060f090 100644 --- a/external/json/tests/src/unit-unicode3.cpp +++ b/external/json/tests/src/unit-unicode3.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-unicode4.cpp b/external/json/tests/src/unit-unicode4.cpp index 6a0e0898..a6a67a02 100644 --- a/external/json/tests/src/unit-unicode4.cpp +++ b/external/json/tests/src/unit-unicode4.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-unicode5.cpp b/external/json/tests/src/unit-unicode5.cpp index 217d3b38..7cf2fc8c 100644 --- a/external/json/tests/src/unit-unicode5.cpp +++ b/external/json/tests/src/unit-unicode5.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-user_defined_input.cpp b/external/json/tests/src/unit-user_defined_input.cpp index 5483f6a0..e4460d56 100644 --- a/external/json/tests/src/unit-user_defined_input.cpp +++ b/external/json/tests/src/unit-user_defined_input.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-windows_h.cpp b/external/json/tests/src/unit-windows_h.cpp index 9c153585..8ae4c811 100644 --- a/external/json/tests/src/unit-windows_h.cpp +++ b/external/json/tests/src/unit-windows_h.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit-wstring.cpp b/external/json/tests/src/unit-wstring.cpp index 1aaa13ba..7394d25d 100644 --- a/external/json/tests/src/unit-wstring.cpp +++ b/external/json/tests/src/unit-wstring.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" diff --git a/external/json/tests/src/unit.cpp b/external/json/tests/src/unit.cpp index adb39dba..523cda91 100644 --- a/external/json/tests/src/unit.cpp +++ b/external/json/tests/src/unit.cpp @@ -3,7 +3,7 @@ // | | |__ | | | | | | version 3.11.3 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013 - 2024 Niels Lohmann // SPDX-License-Identifier: MIT #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN diff --git a/external/json/tools/astyle/.astylerc b/external/json/tools/astyle/.astylerc new file mode 100644 index 00000000..580a3fca --- /dev/null +++ b/external/json/tools/astyle/.astylerc @@ -0,0 +1,80 @@ +# Configuration for Artistic Style +# see https://astyle.sourceforge.net/astyle.html + +####################### +# Brace Style Options # +####################### + +# use Allman style for braces +--style=allman + +############### +# Tab Options # +############### + +# indent using 4 spaces +--indent=spaces=4 + +####################### +# Indentation Options # +####################### + +# indent access modifiers one half indent +--indent-modifiers + +# indent switch cases to the switch block +--indent-switches + +# indent preprocessor blocks +--indent-preproc-block + +# indent preprocessor defines +--indent-preproc-define + +# indent C++ comments +--indent-col1-comments + +################### +# Padding Options # +################### + +# insert space padding around operators +--pad-oper + +# insert space between if/for/while... and the following parentheses +--pad-header + +# attach the pointer to the variable type (left) +--align-pointer=type + +# attach the reference to the variable type (left) +--align-reference=type + +###################### +# Formatting Options # +###################### + +# add braces to unbraced one line conditional statements +--add-braces + +# convert tabs to spaces +--convert-tabs + +# closes whitespace between the ending angle brackets of template definitions +--close-templates + +################# +# Other Options # +################# + +# do not create backup files +--suffix=none + +# preserve the original file date +--preserve-date + +# display only the files that have been formatted +--formatted + +# for the linux (LF) line end style +--lineend=linux diff --git a/external/json/tools/astyle/requirements.txt b/external/json/tools/astyle/requirements.txt new file mode 100644 index 00000000..99458a86 --- /dev/null +++ b/external/json/tools/astyle/requirements.txt @@ -0,0 +1 @@ +astyle==3.4.13 diff --git a/external/json/tools/gdb_pretty_printer/nlohmann-json.py b/external/json/tools/gdb_pretty_printer/nlohmann-json.py index 299152ae..3984f592 100644 --- a/external/json/tools/gdb_pretty_printer/nlohmann-json.py +++ b/external/json/tools/gdb_pretty_printer/nlohmann-json.py @@ -17,16 +17,16 @@ def json_lookup_function(val): if m := ns_pattern.fullmatch(str(val.type.strip_typedefs().name)): name = m.group('name') if name and name.startswith('basic_json<') and name.endswith('>'): - m = ns_pattern.fullmatch(str(val['m_type'])) + m = ns_pattern.fullmatch(str(val["m_data"]['m_type'])) t = m.group('name') if t and t.startswith('detail::value_t::'): try: - union_val = val['m_value'][t.removeprefix('detail::value_t::')] + union_val = val["m_data"]['m_value'][t.removeprefix('detail::value_t::')] if union_val.type.code == gdb.TYPE_CODE_PTR: return gdb.default_visualizer(union_val.dereference()) else: return JsonValuePrinter(union_val) except Exception: - return JsonValuePrinter(val['m_type']) + return JsonValuePrinter(val["m_data"]['m_type']) gdb.pretty_printers.append(json_lookup_function) diff --git a/external/json/tools/generate_natvis/nlohmann_json.natvis.j2 b/external/json/tools/generate_natvis/nlohmann_json.natvis.j2 index d6b72893..c3eafa54 100644 --- a/external/json/tools/generate_natvis/nlohmann_json.natvis.j2 +++ b/external/json/tools/generate_natvis/nlohmann_json.natvis.j2 @@ -8,21 +8,21 @@ {% for ns in namespaces %} - null - {*(m_value.object)} - {*(m_value.array)} - {*(m_value.string)} - {m_value.boolean} - {m_value.number_integer} - {m_value.number_unsigned} - {m_value.number_float} - discarded + null + {*(m_data.m_value.object)} + {*(m_data.m_value.array)} + {*(m_data.m_value.string)} + {m_data.m_value.boolean} + {m_data.m_value.number_integer} + {m_data.m_value.number_unsigned} + {m_data.m_value.number_float} + discarded - - *(m_value.object),view(simple) + + *(m_data.m_value.object),view(simple) - - *(m_value.array),view(simple) + + *(m_data.m_value.array),view(simple) diff --git a/external/json/tools/serve_header/requirements.txt b/external/json/tools/serve_header/requirements.txt index d32eed3b..c399c52b 100644 --- a/external/json/tools/serve_header/requirements.txt +++ b/external/json/tools/serve_header/requirements.txt @@ -1,2 +1,2 @@ -PyYAML==6.0 -watchdog==2.1.7 +PyYAML==6.0.2 +watchdog==6.0.0