mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 04:00:31 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a32f61eb98 | ||
|
|
1d675cdb46 |
-17
@@ -1,17 +0,0 @@
|
|||||||
arm_container:
|
|
||||||
image: gcc:latest
|
|
||||||
|
|
||||||
check_task:
|
|
||||||
check_script:
|
|
||||||
# the gcc image ships an outdated CMake, so fetch a recent prebuilt binary
|
|
||||||
# instead of compiling CMake from source
|
|
||||||
- wget -q https://github.com/Kitware/CMake/releases/download/v4.3.4/cmake-4.3.4-linux-aarch64.tar.gz
|
|
||||||
- tar xfz cmake-4.3.4-linux-aarch64.tar.gz
|
|
||||||
- export PATH="$(pwd)/cmake-4.3.4-linux-aarch64/bin:$PATH"
|
|
||||||
- cmake --version
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake .. -DJSON_FastTests=ON
|
|
||||||
- make -j4
|
|
||||||
- cd tests
|
|
||||||
- ctest -j4
|
|
||||||
@@ -24,6 +24,10 @@ updates:
|
|||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
cooldown:
|
||||||
default-days: 7
|
default-days: 7
|
||||||
|
ignore:
|
||||||
|
# astyle is deliberately pinned (see tools/astyle/requirements.txt): newer versions
|
||||||
|
# reformat the code, and the pinned version defines the formatting CI enforces
|
||||||
|
- dependency-name: astyle
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /tools/generate_natvis
|
directory: /tools/generate_natvis
|
||||||
|
|||||||
@@ -30,14 +30,6 @@ environment:
|
|||||||
CMAKE_OPTIONS: ""
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
configuration: Release
|
|
||||||
platform: x86
|
|
||||||
name: with_win_header
|
|
||||||
CXX_FLAGS: "/W4 /WX"
|
|
||||||
CMAKE_OPTIONS: ""
|
|
||||||
GENERATOR: Visual Studio 14 2015
|
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
configuration: Release
|
configuration: Release
|
||||||
platform: x86
|
platform: x86
|
||||||
@@ -74,9 +66,6 @@ install:
|
|||||||
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
|
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
# for with_win_header build, inject the inclusion of Windows.h to the single-header library
|
|
||||||
- ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
|
|
||||||
- ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
|
|
||||||
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
|
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ jobs:
|
|||||||
run: cmake -S . -B build -DJSON_CI=On
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ci_infer
|
run: cmake --build build --target ci_infer
|
||||||
|
- name: Archive Infer report
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
|
with:
|
||||||
|
name: infer-report
|
||||||
|
path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
ci_static_analysis_ubuntu:
|
ci_static_analysis_ubuntu:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -97,13 +104,13 @@ jobs:
|
|||||||
|
|
||||||
ci_cmake_options:
|
ci_cmake_options:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ubuntu:focal
|
container: ubuntu:24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
|
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
|
||||||
steps:
|
steps:
|
||||||
- name: Install build-essential
|
- name: Install build-essential
|
||||||
run: apt-get update ; apt-get install -y build-essential unzip wget git libssl-dev
|
run: apt-get update ; apt-get install -y build-essential unzip wget git
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
@@ -407,3 +414,21 @@ jobs:
|
|||||||
run: cmake -S . -B build -DJSON_CI=On
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ${{ matrix.target }}
|
run: cmake --build build --target ${{ matrix.target }}
|
||||||
|
|
||||||
|
# Native Linux ARM64 runner with the latest GCC. The ubuntu-24.04-arm label is
|
||||||
|
# only available for public repositories.
|
||||||
|
ci_test_arm64:
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
container: gcc:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Get latest CMake and ninja
|
||||||
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
|
- name: Check that the job runs natively on arm64
|
||||||
|
run: uname -m && test "$(uname -m)" = aarch64
|
||||||
|
- name: Run CMake
|
||||||
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --target ci_test_compiler_default
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"_comment": "Used by the ci_infer CMake target (#5715 item 4b). fail-on-issue makes CI fail on Infer findings; disable-issue-type is a type-level baseline for the ~174 pre-existing findings (all PULSE_UNNECESSARY_COPY*/PULSE_RESOURCE_LEAK/PULSE_CONST_REFABLE, mostly in test code) triaged in run https://github.com/nlohmann/json/actions/runs/35829411620 on commit 1054b2097, so CI fails only on a NEW issue type. Remove an entry here once its findings have been fixed or explicitly accepted.",
|
||||||
|
"fail-on-issue": true,
|
||||||
|
"disable-issue-type": [
|
||||||
|
"PULSE_UNNECESSARY_COPY_ASSIGNMENT",
|
||||||
|
"PULSE_UNNECESSARY_COPY",
|
||||||
|
"PULSE_UNNECESSARY_COPY_INTERMEDIATE",
|
||||||
|
"PULSE_UNNECESSARY_COPY_OPTIONAL",
|
||||||
|
"PULSE_RESOURCE_LEAK",
|
||||||
|
"PULSE_CONST_REFABLE"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -33,17 +33,6 @@ Further documentation:
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> The folder `.github/workflows` is predetermined by GitHub.
|
> The folder `.github/workflows` is predetermined by GitHub.
|
||||||
|
|
||||||
### `.cirrus.yml`
|
|
||||||
|
|
||||||
Configuration file for the pipeline at [Cirrus CI](https://cirrus-ci.com/github/nlohmann/json).
|
|
||||||
|
|
||||||
Further documentation:
|
|
||||||
|
|
||||||
- [Writing tasks](https://cirrus-ci.org/guide/writing-tasks/)
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> The filename `.cirrus.yml` and position (root of the repository) are predetermined by Cirrus CI.
|
|
||||||
|
|
||||||
### `.github/external_ci/appveyor.yml`
|
### `.github/external_ci/appveyor.yml`
|
||||||
|
|
||||||
Configuration for the pipelines at [AppVeyor](https://ci.appveyor.com/project/nlohmann/json).
|
Configuration for the pipelines at [AppVeyor](https://ci.appveyor.com/project/nlohmann/json).
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ install_astyle:
|
|||||||
|
|
||||||
# call the Artistic Style pretty printer on all source files
|
# call the Artistic Style pretty printer on all source files
|
||||||
pretty: install_astyle
|
pretty: install_astyle
|
||||||
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp
|
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp docs/mkdocs/docs/examples/*.hpp
|
||||||
|
|
||||||
# create single header files and pretty print
|
# create single header files and pretty print
|
||||||
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE)
|
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
[](https://coveralls.io/github/nlohmann/json?branch=develop)
|
[](https://coveralls.io/github/nlohmann/json?branch=develop)
|
||||||
[](https://scan.coverity.com/projects/nlohmann-json)
|
[](https://scan.coverity.com/projects/nlohmann-json)
|
||||||
[](https://app.codacy.com/gh/nlohmann/json/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
[](https://app.codacy.com/gh/nlohmann/json/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
||||||
[](https://cirrus-ci.com/github/nlohmann/json)
|
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
|
||||||
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
|
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
|
||||||
[](https://json.nlohmann.me)
|
[](https://json.nlohmann.me)
|
||||||
|
|||||||
+107
-82
@@ -40,6 +40,14 @@ execute_process(COMMAND ${IWYU_TOOL} --version OUTPUT_VARIABLE IWYU_TOOL_VERSION
|
|||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
|
message(STATUS "🔖 include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
|
||||||
|
|
||||||
|
# CMake's CXX_INCLUDE_WHAT_YOU_USE launcher runs IWYU during the normal compile step (useful to see
|
||||||
|
# diagnostics inline), but CMake's own __run_co_compile wrapper does not propagate the launched
|
||||||
|
# tool's exit code to the build, so IWYU's own "-Xiwyu --error" cannot fail that step (verified: a
|
||||||
|
# deliberately-unused #include in a header still lets `cmake --build` finish with exit code 0).
|
||||||
|
# iwyu_tool.py, which ships with IWYU, reads compile_commands.json and does return a non-zero exit
|
||||||
|
# code for any analyzed file with findings; ci_single_binaries uses it to actually fail on findings.
|
||||||
|
find_program(IWYU_TOOL_PY NAMES iwyu_tool iwyu_tool.py iwyu-tool)
|
||||||
|
|
||||||
find_program(INFER_TOOL NAMES infer)
|
find_program(INFER_TOOL NAMES infer)
|
||||||
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
|
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
|
||||||
@@ -55,12 +63,6 @@ execute_process(COMMAND ${NINJA_TOOL} --version OUTPUT_VARIABLE NINJA_TOOL_VERSI
|
|||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
|
message(STATUS "🔖 Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
|
||||||
|
|
||||||
find_program(OCLINT_TOOL NAMES oclint-json-compilation-database)
|
|
||||||
find_program(OCLINT_VERSION_TOOL NAMES oclint)
|
|
||||||
execute_process(COMMAND ${OCLINT_VERSION_TOOL} --version OUTPUT_VARIABLE OCLINT_TOOL_VERSION ERROR_VARIABLE OCLINT_TOOL_VERSION)
|
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" OCLINT_TOOL_VERSION "${OCLINT_TOOL_VERSION}")
|
|
||||||
message(STATUS "🔖 OCLint ${OCLINT_TOOL_VERSION} (${OCLINT_TOOL})")
|
|
||||||
|
|
||||||
find_program(VALGRIND_TOOL NAMES valgrind)
|
find_program(VALGRIND_TOOL NAMES valgrind)
|
||||||
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
|
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
|
||||||
@@ -128,16 +130,16 @@ foreach(CXX_STANDARD 11 14 17 20 23 26)
|
|||||||
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# pass -stdlib=libc++ through CXXFLAGS: an explicit -DCMAKE_CXX_FLAGS would make CMake ignore CXXFLAGS
|
||||||
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
|
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS};-stdlib=libc++" ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||||
-DJSON_TestStandards=${CXX_STANDARD}
|
-DJSON_TestStandards=${CXX_STANDARD}
|
||||||
-DCMAKE_CXX_FLAGS="-stdlib=libc++"
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
|
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||||
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
|
||||||
)
|
)
|
||||||
endforeach()
|
endforeach()
|
||||||
@@ -376,13 +378,20 @@ add_custom_target(ci_test_clang_sanitizer
|
|||||||
# Check if header is amalgamated and sources are properly indented.
|
# Check if header is amalgamated and sources are properly indented.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
# Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
|
||||||
|
# (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
|
||||||
file(GLOB_RECURSE INDENT_FILES
|
file(GLOB_RECURSE INDENT_FILES
|
||||||
${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cu
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.cu
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.cu
|
||||||
)
|
)
|
||||||
|
list(FILTER INDENT_FILES EXCLUDE REGEX "/tests/thirdparty/|/tests/abi/include/nlohmann/")
|
||||||
|
|
||||||
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
||||||
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
||||||
@@ -391,6 +400,7 @@ add_custom_target(ci_test_amalgamation
|
|||||||
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
||||||
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
||||||
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
|
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
|
||||||
|
COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~
|
||||||
|
|
||||||
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
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/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
||||||
@@ -400,16 +410,18 @@ add_custom_target(ci_test_amalgamation
|
|||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
||||||
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
|
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
|
||||||
|
|
||||||
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
||||||
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
||||||
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
|
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
|
||||||
|
COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel
|
||||||
|
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${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
|
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
||||||
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
COMMENT "Check amalgamation and indentation"
|
COMMENT "Check amalgamation, formatting, and BUILD.bazel"
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -444,14 +456,14 @@ add_custom_target(ci_test_valgrind
|
|||||||
# Check code with Clang Static Analyzer.
|
# Check code with Clang Static Analyzer.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
set(CLANG_ANALYZER_CHECKS "fuchsia.HandleChecker,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.mpi.MPI-Checker,optin.osx.OSObjectCStyleCast,optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,optin.osx.cocoa.localizability.NonLocalizedStringChecker,optin.performance.GCDAntipattern,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,osx.API,osx.MIG,osx.NumberObjectConversion,osx.OSObjectRetainCount,osx.ObjCProperty,osx.SecKeychainAPI,osx.cocoa.AtSync,osx.cocoa.AutoreleaseWrite,osx.cocoa.ClassRelease,osx.cocoa.Dealloc,osx.cocoa.IncompatibleMethodTypes,osx.cocoa.Loops,osx.cocoa.MissingSuperCall,osx.cocoa.NSAutoreleasePool,osx.cocoa.NSError,osx.cocoa.NilArg,osx.cocoa.NonNilReturnValue,osx.cocoa.ObjCGenerics,osx.cocoa.RetainCount,osx.cocoa.RunLoopAutoreleaseLeak,osx.cocoa.SelfInit,osx.cocoa.SuperDealloc,osx.cocoa.UnusedIvars,osx.cocoa.VariadicMethodTypes,osx.coreFoundation.CFError,osx.coreFoundation.CFNumber,osx.coreFoundation.CFRetainRelease,osx.coreFoundation.containers.OutOfBounds,osx.coreFoundation.containers.PointerSizedValues,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
|
set(CLANG_ANALYZER_CHECKS "nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
|
||||||
|
|
||||||
add_custom_target(ci_clang_analyze
|
add_custom_target(ci_clang_analyze
|
||||||
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
-DJSON_BuildTests=ON
|
-DJSON_BuildTests=ON
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} -analyze-headers -o ${PROJECT_BINARY_DIR}/report ninja
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} --use-analyzer=${CLANG_TOOL} -analyze-headers --status-bugs -o ${PROJECT_BINARY_DIR}/report ninja
|
||||||
COMMENT "Check code with Clang Analyzer"
|
COMMENT "Check code with Clang Analyzer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -467,7 +479,7 @@ add_custom_target(ci_cppcheck
|
|||||||
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
|
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
|
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
|
||||||
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
|
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
|
||||||
--cppcheck-build-dir=cppcheck --check-level=exhaustive
|
--cppcheck-build-dir=cppcheck
|
||||||
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
|
-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
|
-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"
|
COMMENT "Check code with Cppcheck"
|
||||||
@@ -485,34 +497,6 @@ add_custom_target(ci_cpplint
|
|||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Check code with OCLint.
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
file(COPY ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp DESTINATION ${PROJECT_BINARY_DIR}/src_single)
|
|
||||||
file(RENAME ${PROJECT_BINARY_DIR}/src_single/json.hpp ${PROJECT_BINARY_DIR}/src_single/all.cpp)
|
|
||||||
file(APPEND "${PROJECT_BINARY_DIR}/src_single/all.cpp" "\n\nint main()\n{}\n")
|
|
||||||
|
|
||||||
add_executable(single_all ${PROJECT_BINARY_DIR}/src_single/all.cpp)
|
|
||||||
target_compile_features(single_all PRIVATE cxx_std_11)
|
|
||||||
|
|
||||||
add_custom_target(ci_oclint
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
||||||
-DJSON_BuildTests=OFF -DJSON_CI=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_oclint
|
|
||||||
COMMAND ${OCLINT_TOOL} -i ${PROJECT_BINARY_DIR}/build_oclint/src_single/all.cpp -p ${PROJECT_BINARY_DIR}/build_oclint --
|
|
||||||
-report-type html -enable-global-analysis --max-priority-1=0 --max-priority-2=1000 --max-priority-3=2000
|
|
||||||
--disable-rule=MultipleUnaryOperator
|
|
||||||
--disable-rule=DoubleNegative
|
|
||||||
--disable-rule=ShortVariableName
|
|
||||||
--disable-rule=GotoStatement
|
|
||||||
--disable-rule=LongLine
|
|
||||||
-o ${PROJECT_BINARY_DIR}/build_oclint/oclint_report.html
|
|
||||||
COMMENT "Check code with OCLint"
|
|
||||||
)
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Check code with Clang-Tidy.
|
# Check code with Clang-Tidy.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -527,29 +511,16 @@ add_custom_target(ci_clang_tidy
|
|||||||
COMMENT "Check code with Clang-Tidy"
|
COMMENT "Check code with Clang-Tidy"
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Check code with PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>.
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
add_custom_target(ci_pvs_studio
|
|
||||||
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
||||||
-DJSON_BuildTests=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_pvs_studio
|
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PVS_STUDIO_ANALYZER_TOOL} analyze -j 10
|
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PLOG_CONVERTER_TOOL} -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
|
||||||
COMMENT "Check code with PVS Studio"
|
|
||||||
)
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Check code with Infer <https://fbinfer.com> static analyzer.
|
# Check code with Infer <https://fbinfer.com> static analyzer.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
# .inferconfig (repository root) pins --fail-on-issue and the currently-triaged issue types that
|
||||||
|
# are disabled until they are addressed separately; see #5715 item 4b.
|
||||||
add_custom_target(ci_infer
|
add_custom_target(ci_infer
|
||||||
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
|
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run --project-root ${PROJECT_SOURCE_DIR} -- make
|
||||||
COMMENT "Check code with Infer"
|
COMMENT "Check code with Infer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -605,7 +576,13 @@ add_custom_target(ci_reproducible_tests
|
|||||||
# be compiled individually.
|
# be compiled individually.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
set(iwyu_path_and_options ${IWYU_TOOL} -Xiwyu --max_line_length=300)
|
set(iwyu_options -Xiwyu --error -Xiwyu --max_line_length=300)
|
||||||
|
set(iwyu_path_and_options ${IWYU_TOOL} ${iwyu_options})
|
||||||
|
|
||||||
|
# CMake needs to know the exact flags used to compile each src_single/*.cpp below to hand them to
|
||||||
|
# iwyu_tool.py; JSON_CI already implies a from-scratch configure, so enabling this project-wide has
|
||||||
|
# no downside here.
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
foreach(SRC_FILE ${SRC_FILES})
|
foreach(SRC_FILE ${SRC_FILES})
|
||||||
# get relative path of the header file
|
# get relative path of the header file
|
||||||
@@ -620,14 +597,34 @@ foreach(SRC_FILE ${SRC_FILES})
|
|||||||
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
||||||
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
|
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
|
||||||
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
|
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
|
||||||
# remember binary for ci_single_binaries target
|
# remember binary for ci_single_binaries
|
||||||
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
|
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
|
||||||
|
# json.hpp pulls together the whole library behind heavily templated, SFINAE-based code, and
|
||||||
|
# IWYU's suggestion for its one truly ambiguous symbol (a container-comparison "swap,
|
||||||
|
# operator!=") is not deterministic between runs (observed <set>, <unordered_map>, and <map>
|
||||||
|
# for the exact same source across otherwise-identical local and containerized builds). Keep
|
||||||
|
# reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it
|
||||||
|
# from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a
|
||||||
|
# nondeterministic suggestion for a header that already re-exports everything on purpose.
|
||||||
|
if(NOT RELATIVE_SRC_FILE STREQUAL "json")
|
||||||
|
list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp)
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(ci_single_binaries
|
if(IWYU_TOOL_PY)
|
||||||
|
add_custom_target(ci_single_binaries
|
||||||
|
DEPENDS ${single_binaries}
|
||||||
|
COMMAND ${IWYU_TOOL_PY} -p ${PROJECT_BINARY_DIR} ${single_binaries_tus} -- ${iwyu_options}
|
||||||
|
COMMENT "Check if headers are self-contained"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# iwyu_tool.py (ships with IWYU, e.g. as /usr/bin/iwyu_tool on Debian/Ubuntu) was not found;
|
||||||
|
# fall back to building the self-containment check without enforcing the IWYU findings.
|
||||||
|
add_custom_target(ci_single_binaries
|
||||||
DEPENDS ${single_binaries}
|
DEPENDS ${single_binaries}
|
||||||
COMMENT "Check if headers are self-contained"
|
COMMENT "Check if headers are self-contained"
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Benchmarks
|
# Benchmarks
|
||||||
@@ -649,10 +646,29 @@ add_custom_target(ci_benchmarks
|
|||||||
# we test the project with different CMake versions:
|
# we test the project with different CMake versions:
|
||||||
# - CMake 3.5 (the earliest supported)
|
# - CMake 3.5 (the earliest supported)
|
||||||
# - CMake 3.31.6 (the latest 3.x release)
|
# - CMake 3.31.6 (the latest 3.x release)
|
||||||
# - CMake 4.0.0 (the latest release)
|
# - CMake 4.0.0 (the first 4.x release)
|
||||||
|
# - the CMake version running this build (usually the latest release)
|
||||||
|
|
||||||
function(ci_get_cmake version var)
|
function(ci_get_cmake version var)
|
||||||
set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}/bin/cmake)
|
set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}/bin/cmake)
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$")
|
||||||
|
# Kitware publishes a prebuilt Linux x86_64 archive for every release; unpacking it is far
|
||||||
|
# cheaper than compiling all of CMake (including its own test helpers) from source.
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${${var}}
|
||||||
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-linux-x86_64.tar.gz
|
||||||
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-SHA-256.txt
|
||||||
|
# verify the archive against Kitware's published SHA-256 sums before unpacking it
|
||||||
|
COMMAND sh -c "grep ' cmake-${version}-linux-x86_64[.]tar[.]gz$' cmake-${version}-SHA-256.txt | sha256sum -c -"
|
||||||
|
COMMAND tar xfz cmake-${version}-linux-x86_64.tar.gz
|
||||||
|
COMMAND rm cmake-${version}-linux-x86_64.tar.gz cmake-${version}-SHA-256.txt
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -rf cmake-${version}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rename cmake-${version}-linux-x86_64 cmake-${version}
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
COMMENT "Download prebuilt CMake ${version}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# no prebuilt archive for this platform (e.g. macOS or Linux aarch64): build from source
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${${var}}
|
OUTPUT ${${var}}
|
||||||
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}.tar.gz
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}.tar.gz
|
||||||
@@ -662,8 +678,9 @@ function(ci_get_cmake version var)
|
|||||||
COMMAND cmake -S cmake-${version} -B cmake-${version} -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
COMMAND cmake -S cmake-${version} -B cmake-${version} -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
COMMAND cmake --build cmake-${version} --parallel 10
|
COMMAND cmake --build cmake-${version} --parallel 10
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
COMMENT "Download CMake ${version}"
|
COMMENT "Download and build CMake ${version} from source"
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
set(${var} ${${var}} PARENT_SCOPE)
|
set(${var} ${${var}} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@@ -673,30 +690,24 @@ ci_get_cmake(4.0.0 CMAKE_4_0_0_BINARY)
|
|||||||
|
|
||||||
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
|
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
|
||||||
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
||||||
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind)
|
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
|
||||||
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_31_6})
|
JSON_StrictNulHandling)
|
||||||
|
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
||||||
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
||||||
|
|
||||||
function(ci_add_cmake_flags_targets flag min_version)
|
function(ci_add_cmake_flags_targets flag min_version)
|
||||||
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
|
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
|
||||||
string(REPLACE . _ min_version_var ${min_version})
|
string(REPLACE . _ min_version_var ${min_version})
|
||||||
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
|
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
|
||||||
add_custom_target(${flag_target}_${min_version}_2
|
|
||||||
COMMENT "Check CMake flag ${flag} (CMake ${CMAKE_VERSION})"
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-Werror=dev
|
|
||||||
-D${flag}=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
|
|
||||||
)
|
|
||||||
add_custom_target(${flag_target}_${min_version_var}
|
add_custom_target(${flag_target}_${min_version_var}
|
||||||
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${min_version})"
|
COMMENT "Check CMake flag ${flag} (CMake ${min_version})"
|
||||||
COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
||||||
&& ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
|
&& ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
|
||||||
DEPENDS ${cmake_binary}
|
DEPENDS ${cmake_binary}
|
||||||
)
|
)
|
||||||
list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${flag_target}_${min_version_var})
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target}_${min_version_var})
|
||||||
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target} ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
|
||||||
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
|
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
|
||||||
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
|
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
@@ -713,6 +724,20 @@ foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
|||||||
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 4.0.0)
|
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 4.0.0)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
# check the same flags with the CMake version running this build
|
||||||
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
||||||
|
string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" flag_target)
|
||||||
|
add_custom_target(${flag_target}
|
||||||
|
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})"
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-Werror=dev
|
||||||
|
-D${JSON_CMAKE_FLAG}=ON
|
||||||
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
|
||||||
|
)
|
||||||
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target})
|
||||||
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(ci_cmake_flags
|
add_custom_target(ci_cmake_flags
|
||||||
DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
|
DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
|
||||||
COMMENT "Check CMake flags"
|
COMMENT "Check CMake flags"
|
||||||
@@ -871,6 +896,6 @@ add_custom_target(ci_test_build_documentation
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
add_custom_target(ci_clean
|
add_custom_target(ci_clean
|
||||||
COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* cmake-3.5.0-Darwin64 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
|
COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* ${PROJECT_BINARY_DIR}/cmake-3.5.0 ${PROJECT_BINARY_DIR}/cmake-3.31.6 ${PROJECT_BINARY_DIR}/cmake-4.0.0 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
|
||||||
COMMENT "Clean generated directories"
|
COMMENT "Clean generated directories"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ Thereby, `Target` is the current object; that is, the patch is applied to the cu
|
|||||||
|
|
||||||
Linear in the lengths of `apply_patch`.
|
Linear in the lengths of `apply_patch`.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
`apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
|
||||||
|
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
|
||||||
|
`#!cpp *this`.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
@@ -61,3 +67,5 @@ Linear in the lengths of `apply_patch`.
|
|||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.0.0.
|
- Added in version 3.0.0.
|
||||||
|
- Fixed use of freed or relocated memory when `apply_patch` is `#!cpp *this` or refers to a value contained in
|
||||||
|
`#!cpp *this`, in version 3.13.0.
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
|||||||
1. O(N*log(size() + N)), where N is the number of elements to insert.
|
1. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||||
2. O(N*log(size() + N)), where N is the number of elements to insert.
|
2. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
The argument `j` (or, for overload (2), the range `[first, last)`) may be `#!cpp *this` itself or refer to a value
|
||||||
|
contained in `#!cpp *this` (for example, a subobject returned by `#!cpp (*this)[key]`); it is read as it was when
|
||||||
|
`update()` was called, before any modification of `#!cpp *this`.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
@@ -155,3 +161,5 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
|||||||
|
|
||||||
- Added in version 3.0.0.
|
- Added in version 3.0.0.
|
||||||
- Added `merge_objects` parameter in 3.10.5.
|
- Added `merge_objects` parameter in 3.10.5.
|
||||||
|
- Fixed use of freed or relocated memory when the argument is `#!cpp *this` or refers to a value contained in
|
||||||
|
`#!cpp *this`, in version 3.13.0.
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
| GNU 14.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 14.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 16.1.0 | arm64 | Linux 6.1.100 | Cirrus CI |
|
| GNU 16.1.0 | arm64 | Ubuntu 24.04 | GitHub |
|
||||||
| icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
| icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||||
| icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub |
|
| icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub |
|
||||||
| nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
| nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||||
@@ -132,7 +132,8 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
[libstdc++](https://gcc.gnu.org/onlinedocs/libstdc++/) to detect subtle differences or incompatibilities.
|
[libstdc++](https://gcc.gnu.org/onlinedocs/libstdc++/) to detect subtle differences or incompatibilities.
|
||||||
- [x] The code checked with [Include What You Use (IWYU)](https://include-what-you-use.org) that all required standard
|
- [x] The code checked with [Include What You Use (IWYU)](https://include-what-you-use.org) that all required standard
|
||||||
headers are included.
|
headers are included.
|
||||||
- [x] On Windows, the library is compiled with `<Windows.h>` being included to detect and avoid common bugs.
|
- [x] On Windows, the library is compiled with `<Windows.h>` being included to detect and avoid common bugs (see
|
||||||
|
[`unit-windows_h.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-windows_h.cpp)).
|
||||||
- [x] The library is compiled with exceptions disabled to support alternative means of error handling.
|
- [x] The library is compiled with exceptions disabled to support alternative means of error handling.
|
||||||
|
|
||||||
## Stable public API
|
## Stable public API
|
||||||
|
|||||||
+89
-38
@@ -29,7 +29,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm> // all_of, find, for_each, none_of
|
#include <algorithm> // all_of, find, for_each, none_of
|
||||||
|
#include <cmath> // isnan
|
||||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
#include <functional> // hash, less
|
#include <functional> // hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
@@ -38,19 +40,28 @@
|
|||||||
#include <iterator> // make_move_iterator, random_access_iterator_tag
|
#include <iterator> // make_move_iterator, random_access_iterator_tag
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <memory> // unique_ptr
|
#include <memory> // unique_ptr
|
||||||
|
#include <set> // swap, operator!=
|
||||||
#include <stdexcept> // length_error
|
#include <stdexcept> // length_error
|
||||||
#include <string> // string, stoi, to_string
|
#include <string> // string, stoi, to_string
|
||||||
|
#include <type_traits> // enable_if_t, is_same, is_scalar, ...
|
||||||
|
#include <unordered_map> // swap (for the from_json(..., std::unordered_map&) overload)
|
||||||
#include <utility> // declval, forward, move, pair, swap
|
#include <utility> // declval, forward, move, pair, swap
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/adl_serializer.hpp>
|
// keep: json.hpp's own basic_json<> default template arguments need the complete definition of
|
||||||
|
// each of these, not only the forward declarations from json_fwd.hpp, so IWYU's suggestion to
|
||||||
|
// drop them (nothing in this file otherwise names the type) would break every downstream
|
||||||
|
// translation unit that relies on basic_json<>'s defaults actually being usable.
|
||||||
|
#include <nlohmann/adl_serializer.hpp> // IWYU pragma: keep
|
||||||
#include <nlohmann/byte_container_with_subtype.hpp>
|
#include <nlohmann/byte_container_with_subtype.hpp>
|
||||||
#include <nlohmann/detail/conversions/from_json.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/conversions/to_json.hpp>
|
#include <nlohmann/detail/conversions/from_json.hpp> // IWYU pragma: keep
|
||||||
|
#include <nlohmann/detail/conversions/to_json.hpp> // IWYU pragma: keep
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/hash.hpp>
|
#include <nlohmann/detail/hash.hpp>
|
||||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
|
#include <nlohmann/detail/input/json_sax.hpp>
|
||||||
#include <nlohmann/detail/input/lexer.hpp>
|
#include <nlohmann/detail/input/lexer.hpp>
|
||||||
#include <nlohmann/detail/input/parser.hpp>
|
#include <nlohmann/detail/input/parser.hpp>
|
||||||
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
||||||
@@ -62,6 +73,7 @@
|
|||||||
#include <nlohmann/detail/json_pointer.hpp>
|
#include <nlohmann/detail/json_pointer.hpp>
|
||||||
#include <nlohmann/detail/json_ref.hpp>
|
#include <nlohmann/detail/json_ref.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
#include <nlohmann/detail/string_escape.hpp>
|
#include <nlohmann/detail/string_escape.hpp>
|
||||||
#include <nlohmann/detail/string_utils.hpp>
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
@@ -73,7 +85,8 @@
|
|||||||
#include <nlohmann/detail/recursion_depth_limit.hpp>
|
#include <nlohmann/detail/recursion_depth_limit.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
#include <nlohmann/ordered_map.hpp>
|
#include <nlohmann/ordered_map.hpp> // IWYU pragma: keep
|
||||||
|
#include <nlohmann/thirdparty/hedley/hedley.hpp>
|
||||||
|
|
||||||
#if defined(JSON_HAS_CPP_17)
|
#if defined(JSON_HAS_CPP_17)
|
||||||
#if JSON_HAS_STATIC_RTTI
|
#if JSON_HAS_STATIC_RTTI
|
||||||
@@ -4402,25 +4415,26 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
||||||
void update(const_reference j, bool merge_objects = false)
|
void update(const_reference j, bool merge_objects = false)
|
||||||
{
|
{
|
||||||
update(j.begin(), j.end(), merge_objects);
|
prepare_update();
|
||||||
|
|
||||||
|
// passed value must be an object (checked here so a type_error names
|
||||||
|
// j, not the copy made below)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
|
{
|
||||||
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", j.type_name()), &j));
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy first: j may be *this or one of its descendants, and is
|
||||||
|
// iterated (and moved from) below to update *this
|
||||||
|
basic_json source = j;
|
||||||
|
update_from(source, merge_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief updates a JSON object from another object, overwriting existing keys
|
/// @brief updates a JSON object from another object, overwriting existing keys
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
||||||
void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
|
void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
|
||||||
{
|
{
|
||||||
// implicitly convert a null value to an empty object
|
prepare_update();
|
||||||
if (is_null())
|
|
||||||
{
|
|
||||||
m_data.m_type = value_t::object;
|
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
assert_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
|
||||||
{
|
|
||||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if range iterators belong to the same JSON object
|
// check if range iterators belong to the same JSON object
|
||||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||||
@@ -4434,7 +4448,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
update_members(first, last, merge_objects, 0);
|
// copy first: the range may belong to *this or one of its
|
||||||
|
// descendants, and is iterated (and moved from) below to update
|
||||||
|
// *this
|
||||||
|
basic_json source(first, last);
|
||||||
|
update_from(source, merge_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -4442,15 +4460,42 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// merge_patch_iteratively is merging into, and the members still to merge
|
/// merge_patch_iteratively is merging into, and the members still to merge
|
||||||
struct merge_frame
|
struct merge_frame
|
||||||
{
|
{
|
||||||
merge_frame(basic_json* target_, const_iterator position_, const_iterator last_) noexcept
|
merge_frame(basic_json* target_, iterator position_, iterator last_) noexcept
|
||||||
: target(target_), position(std::move(position_)), last(std::move(last_))
|
: target(target_), position(std::move(position_)), last(std::move(last_))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
basic_json* target;
|
basic_json* target;
|
||||||
const_iterator position;
|
iterator position;
|
||||||
const_iterator last;
|
iterator last;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief converts a null value to an empty object and checks that this
|
||||||
|
/// value is an object; called first by both @ref update overloads
|
||||||
|
void prepare_update()
|
||||||
|
{
|
||||||
|
// implicitly convert a null value to an empty object; create the
|
||||||
|
// object before setting the type, so a throwing allocation leaves
|
||||||
|
// this value null
|
||||||
|
if (is_null())
|
||||||
|
{
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
|
m_data.m_type = value_t::object;
|
||||||
|
assert_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||||
|
{
|
||||||
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief starts the @ref update_members loop over an already-copied @a
|
||||||
|
/// source; called by both @ref update overloads
|
||||||
|
void update_from(basic_json& source, const bool merge_objects)
|
||||||
|
{
|
||||||
|
update_members(source.begin(), source.end(), merge_objects, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief the members loop of @ref update, for this object and range
|
@brief the members loop of @ref update, for this object and range
|
||||||
|
|
||||||
@@ -4463,7 +4508,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
@param[in] depth nesting level of this object, counted from the object
|
@param[in] depth nesting level of this object, counted from the object
|
||||||
@ref update was called on
|
@ref update was called on
|
||||||
*/
|
*/
|
||||||
void update_members(const const_iterator& first, const const_iterator& last, const bool merge_objects, const std::size_t depth)
|
void update_members(const iterator& first, const iterator& last, const bool merge_objects, const std::size_t depth)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
||||||
{
|
{
|
||||||
@@ -4481,13 +4526,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// are overwritten as usual" behavior (see #5402).
|
// are overwritten as usual" behavior (see #5402).
|
||||||
if (it2 != m_data.m_value.object->end() && it2->second.is_object())
|
if (it2 != m_data.m_value.object->end() && it2->second.is_object())
|
||||||
{
|
{
|
||||||
it2->second.update_members(it.value().cbegin(), it.value().cend(), true, depth + 1);
|
it2->second.update_members(it.value().begin(), it.value().end(), true, depth + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set_parent() also repairs the other members, which ordered_json
|
// set_parent() also repairs the other members, which ordered_json
|
||||||
// relocates when adding a key makes its vector grow
|
// relocates when adding a key makes its vector grow
|
||||||
set_parent(m_data.m_value.object->operator[](it.key()) = it.value());
|
set_parent(m_data.m_value.object->operator[](it.key()) = std::move(it.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4501,7 +4546,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
version. Only reached for values nested deeper than @ref
|
version. Only reached for values nested deeper than @ref
|
||||||
detail::recursion_depth_limit.
|
detail::recursion_depth_limit.
|
||||||
*/
|
*/
|
||||||
void update_members_iteratively(const_iterator first, const_iterator last)
|
void update_members_iteratively(iterator first, iterator last)
|
||||||
{
|
{
|
||||||
std::vector<merge_frame> stack;
|
std::vector<merge_frame> stack;
|
||||||
|
|
||||||
@@ -4528,18 +4573,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it2 = target->m_data.m_value.object->find(first.key());
|
const auto it2 = target->m_data.m_value.object->find(first.key());
|
||||||
if (it2 != target->m_data.m_value.object->end() && it2->second.is_object())
|
if (it2 != target->m_data.m_value.object->end() && it2->second.is_object())
|
||||||
{
|
{
|
||||||
const basic_json& source = first.value();
|
basic_json& source = first.value();
|
||||||
++first;
|
++first;
|
||||||
stack.emplace_back(target, first, last);
|
stack.emplace_back(target, first, last);
|
||||||
target = &it2->second;
|
target = &it2->second;
|
||||||
first = source.cbegin();
|
first = source.begin();
|
||||||
last = source.cend();
|
last = source.end();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set_parent() also repairs the other members, which ordered_json
|
// set_parent() also repairs the other members, which ordered_json
|
||||||
// relocates when adding a key makes its vector grow
|
// relocates when adding a key makes its vector grow
|
||||||
target->set_parent(target->m_data.m_value.object->operator[](first.key()) = first.value());
|
target->set_parent(target->m_data.m_value.object->operator[](first.key()) = std::move(first.value()));
|
||||||
++first;
|
++first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6548,7 +6593,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
||||||
void merge_patch(const basic_json& apply_patch)
|
void merge_patch(const basic_json& apply_patch)
|
||||||
{
|
{
|
||||||
apply_merge_patch(apply_patch, 0);
|
// copy first: apply_patch may be *this or one of its descendants,
|
||||||
|
// and is iterated (and moved from) below to patch *this
|
||||||
|
basic_json patch = apply_patch;
|
||||||
|
apply_merge_patch(patch, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -6561,7 +6609,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
detail::recursion_depth_limit levels have been entered, @ref
|
detail::recursion_depth_limit levels have been entered, @ref
|
||||||
merge_patch_iteratively applies what is left without the call stack.
|
merge_patch_iteratively applies what is left without the call stack.
|
||||||
*/
|
*/
|
||||||
void apply_merge_patch(const basic_json& apply_patch, const std::size_t depth)
|
void apply_merge_patch(basic_json& apply_patch, const std::size_t depth)
|
||||||
{
|
{
|
||||||
if (apply_patch.is_object())
|
if (apply_patch.is_object())
|
||||||
{
|
{
|
||||||
@@ -6589,7 +6637,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*this = apply_patch;
|
*this = std::move(apply_patch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6602,12 +6650,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
recursive version. Only reached for patches nested deeper than @ref
|
recursive version. Only reached for patches nested deeper than @ref
|
||||||
detail::recursion_depth_limit.
|
detail::recursion_depth_limit.
|
||||||
*/
|
*/
|
||||||
void merge_patch_iteratively(const basic_json& apply_patch)
|
void merge_patch_iteratively(basic_json& apply_patch)
|
||||||
{
|
{
|
||||||
std::vector<merge_frame> stack;
|
std::vector<merge_frame> stack;
|
||||||
|
|
||||||
// patch `target` with `patch`, or start patching it member by member
|
// patch `target` with `patch`, or start patching it member by member
|
||||||
const auto apply = [&stack](basic_json & target, const basic_json & patch)
|
const auto apply = [&stack](basic_json & target, basic_json & patch)
|
||||||
{
|
{
|
||||||
if (patch.is_object())
|
if (patch.is_object())
|
||||||
{
|
{
|
||||||
@@ -6615,11 +6663,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
{
|
{
|
||||||
target = basic_json::object();
|
target = basic_json::object();
|
||||||
}
|
}
|
||||||
stack.emplace_back(&target, patch.cbegin(), patch.cend());
|
stack.emplace_back(&target, patch.begin(), patch.end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target = patch;
|
target = std::move(patch);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -6635,7 +6683,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const const_iterator member = frame.position;
|
const iterator member = frame.position;
|
||||||
++stack.back().position;
|
++stack.back().position;
|
||||||
if (member.value().is_null())
|
if (member.value().is_null())
|
||||||
{
|
{
|
||||||
@@ -6802,7 +6850,10 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_unscope.hpp>
|
// keep: undoes the macros defined via detail/macro_scope.hpp at the top of this file; removing it
|
||||||
|
// (nothing in this file *uses* a symbol from it) would leak JSON_* macros into every translation
|
||||||
|
// unit that includes this header.
|
||||||
|
#include <nlohmann/detail/macro_unscope.hpp> // IWYU pragma: keep
|
||||||
|
|
||||||
// End of GCC diagnostic pragmas for C++ modules support
|
// End of GCC diagnostic pragmas for C++ modules support
|
||||||
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L
|
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <string> // allocator, string
|
||||||
#include <string> // string
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -32,7 +31,7 @@ This serializer ignores the template arguments and uses ADL
|
|||||||
for serialization.
|
for serialization.
|
||||||
*/
|
*/
|
||||||
template<typename T = void, typename SFINAE = void>
|
template<typename T = void, typename SFINAE = void>
|
||||||
struct adl_serializer;
|
struct adl_serializer; // IWYU pragma: keep
|
||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
@@ -48,12 +47,12 @@ template<template<typename U, typename V, typename... Args> class ObjectType =
|
|||||||
adl_serializer,
|
adl_serializer,
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||||
template<typename RefStringType>
|
template<typename RefStringType>
|
||||||
class json_pointer;
|
class json_pointer; // IWYU pragma: keep
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief default specialization
|
@brief default specialization
|
||||||
@@ -64,7 +63,7 @@ using json = basic_json<>;
|
|||||||
/// @brief a minimal map-like container that preserves insertion order
|
/// @brief a minimal map-like container that preserves insertion order
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||||
struct ordered_map;
|
struct ordered_map; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief specialization that maintains the insertion order of object keys
|
/// @brief specialization that maintains the insertion order of object keys
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||||
|
|||||||
@@ -12,13 +12,14 @@
|
|||||||
#include <functional> // equal_to, less
|
#include <functional> // equal_to, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iterator> // input_iterator_tag, iterator_traits
|
#include <iterator> // input_iterator_tag, iterator_traits
|
||||||
#include <memory> // allocator
|
#include <new> // for operator new (placement new)
|
||||||
#include <stdexcept> // for out_of_range
|
#include <stdexcept> // for out_of_range
|
||||||
#include <tuple> // forward_as_tuple
|
#include <tuple> // forward_as_tuple
|
||||||
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
||||||
#include <utility> // forward, move, pair, piecewise_construct
|
#include <utility> // forward, move, pair, piecewise_construct
|
||||||
#include <vector> // vector
|
#include <vector> // vector, allocator
|
||||||
|
|
||||||
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm> // all_of, find, for_each, none_of
|
#include <algorithm> // all_of, find, for_each, none_of
|
||||||
|
#include <cmath> // isnan
|
||||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
#include <functional> // hash, less
|
#include <functional> // hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
@@ -38,11 +40,18 @@
|
|||||||
#include <iterator> // make_move_iterator, random_access_iterator_tag
|
#include <iterator> // make_move_iterator, random_access_iterator_tag
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <memory> // unique_ptr
|
#include <memory> // unique_ptr
|
||||||
|
#include <set> // swap, operator!=
|
||||||
#include <stdexcept> // length_error
|
#include <stdexcept> // length_error
|
||||||
#include <string> // string, stoi, to_string
|
#include <string> // string, stoi, to_string
|
||||||
|
#include <type_traits> // enable_if_t, is_same, is_scalar, ...
|
||||||
|
#include <unordered_map> // swap (for the from_json(..., std::unordered_map&) overload)
|
||||||
#include <utility> // declval, forward, move, pair, swap
|
#include <utility> // declval, forward, move, pair, swap
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
|
// keep: json.hpp's own basic_json<> default template arguments need the complete definition of
|
||||||
|
// each of these, not only the forward declarations from json_fwd.hpp, so IWYU's suggestion to
|
||||||
|
// drop them (nothing in this file otherwise names the type) would break every downstream
|
||||||
|
// translation unit that relies on basic_json<>'s defaults actually being usable.
|
||||||
// #include <nlohmann/adl_serializer.hpp>
|
// #include <nlohmann/adl_serializer.hpp>
|
||||||
// __ _____ _____ _____
|
// __ _____ _____ _____
|
||||||
// __| | __| | | | JSON for Modern C++
|
// __| | __| | | | JSON for Modern C++
|
||||||
@@ -3973,8 +3982,7 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <string> // allocator, string
|
||||||
#include <string> // string
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
// #include <nlohmann/detail/abi_macros.hpp>
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -3995,7 +4003,7 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
for serialization.
|
for serialization.
|
||||||
*/
|
*/
|
||||||
template<typename T = void, typename SFINAE = void>
|
template<typename T = void, typename SFINAE = void>
|
||||||
struct adl_serializer;
|
struct adl_serializer; // IWYU pragma: keep
|
||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
@@ -4011,12 +4019,12 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
adl_serializer,
|
adl_serializer,
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||||
template<typename RefStringType>
|
template<typename RefStringType>
|
||||||
class json_pointer;
|
class json_pointer; // IWYU pragma: keep
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief default specialization
|
@brief default specialization
|
||||||
@@ -4027,7 +4035,7 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
/// @brief a minimal map-like container that preserves insertion order
|
/// @brief a minimal map-like container that preserves insertion order
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||||
struct ordered_map;
|
struct ordered_map; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief specialization that maintains the insertion order of object keys
|
/// @brief specialization that maintains the insertion order of object keys
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||||
@@ -7144,7 +7152,7 @@ struct adl_serializer
|
|||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
// IWYU pragma: keep
|
||||||
// #include <nlohmann/byte_container_with_subtype.hpp>
|
// #include <nlohmann/byte_container_with_subtype.hpp>
|
||||||
// __ _____ _____ _____
|
// __ _____ _____ _____
|
||||||
// __| | __| | | | JSON for Modern C++
|
// __| | __| | | | JSON for Modern C++
|
||||||
@@ -7251,10 +7259,12 @@ class byte_container_with_subtype : public BinaryType
|
|||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/conversions/from_json.hpp>
|
// #include <nlohmann/detail/conversions/from_json.hpp>
|
||||||
|
// IWYU pragma: keep
|
||||||
// #include <nlohmann/detail/conversions/to_json.hpp>
|
// #include <nlohmann/detail/conversions/to_json.hpp>
|
||||||
|
// IWYU pragma: keep
|
||||||
// #include <nlohmann/detail/exceptions.hpp>
|
// #include <nlohmann/detail/exceptions.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/hash.hpp>
|
// #include <nlohmann/detail/hash.hpp>
|
||||||
@@ -17855,6 +17865,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/input/input_adapters.hpp>
|
// #include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/input/json_sax.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/input/lexer.hpp>
|
// #include <nlohmann/detail/input/lexer.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/input/parser.hpp>
|
// #include <nlohmann/detail/input/parser.hpp>
|
||||||
@@ -20836,6 +20848,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
// #include <nlohmann/detail/macro_scope.hpp>
|
// #include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/meta/detected.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/string_concat.hpp>
|
// #include <nlohmann/detail/string_concat.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/string_escape.hpp>
|
// #include <nlohmann/detail/string_escape.hpp>
|
||||||
@@ -26375,12 +26389,14 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
#include <functional> // equal_to, less
|
#include <functional> // equal_to, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iterator> // input_iterator_tag, iterator_traits
|
#include <iterator> // input_iterator_tag, iterator_traits
|
||||||
#include <memory> // allocator
|
#include <new> // for operator new (placement new)
|
||||||
#include <stdexcept> // for out_of_range
|
#include <stdexcept> // for out_of_range
|
||||||
#include <tuple> // forward_as_tuple
|
#include <tuple> // forward_as_tuple
|
||||||
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
||||||
#include <utility> // forward, move, pair, piecewise_construct
|
#include <utility> // forward, move, pair, piecewise_construct
|
||||||
#include <vector> // vector
|
#include <vector> // vector, allocator
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/macro_scope.hpp>
|
// #include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
@@ -26815,6 +26831,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
// IWYU pragma: keep
|
||||||
|
// #include <nlohmann/thirdparty/hedley/hedley.hpp>
|
||||||
|
|
||||||
|
|
||||||
#if defined(JSON_HAS_CPP_17)
|
#if defined(JSON_HAS_CPP_17)
|
||||||
@@ -31144,25 +31162,26 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
||||||
void update(const_reference j, bool merge_objects = false)
|
void update(const_reference j, bool merge_objects = false)
|
||||||
{
|
{
|
||||||
update(j.begin(), j.end(), merge_objects);
|
prepare_update();
|
||||||
|
|
||||||
|
// passed value must be an object (checked here so a type_error names
|
||||||
|
// j, not the copy made below)
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
|
{
|
||||||
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", j.type_name()), &j));
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy first: j may be *this or one of its descendants, and is
|
||||||
|
// iterated (and moved from) below to update *this
|
||||||
|
basic_json source = j;
|
||||||
|
update_from(source, merge_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief updates a JSON object from another object, overwriting existing keys
|
/// @brief updates a JSON object from another object, overwriting existing keys
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
/// @sa https://json.nlohmann.me/api/basic_json/update/
|
||||||
void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
|
void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
|
||||||
{
|
{
|
||||||
// implicitly convert a null value to an empty object
|
prepare_update();
|
||||||
if (is_null())
|
|
||||||
{
|
|
||||||
m_data.m_type = value_t::object;
|
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
assert_invariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
|
||||||
{
|
|
||||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if range iterators belong to the same JSON object
|
// check if range iterators belong to the same JSON object
|
||||||
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
|
||||||
@@ -31176,7 +31195,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
update_members(first, last, merge_objects, 0);
|
// copy first: the range may belong to *this or one of its
|
||||||
|
// descendants, and is iterated (and moved from) below to update
|
||||||
|
// *this
|
||||||
|
basic_json source(first, last);
|
||||||
|
update_from(source, merge_objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -31184,15 +31207,42 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// merge_patch_iteratively is merging into, and the members still to merge
|
/// merge_patch_iteratively is merging into, and the members still to merge
|
||||||
struct merge_frame
|
struct merge_frame
|
||||||
{
|
{
|
||||||
merge_frame(basic_json* target_, const_iterator position_, const_iterator last_) noexcept
|
merge_frame(basic_json* target_, iterator position_, iterator last_) noexcept
|
||||||
: target(target_), position(std::move(position_)), last(std::move(last_))
|
: target(target_), position(std::move(position_)), last(std::move(last_))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
basic_json* target;
|
basic_json* target;
|
||||||
const_iterator position;
|
iterator position;
|
||||||
const_iterator last;
|
iterator last;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief converts a null value to an empty object and checks that this
|
||||||
|
/// value is an object; called first by both @ref update overloads
|
||||||
|
void prepare_update()
|
||||||
|
{
|
||||||
|
// implicitly convert a null value to an empty object; create the
|
||||||
|
// object before setting the type, so a throwing allocation leaves
|
||||||
|
// this value null
|
||||||
|
if (is_null())
|
||||||
|
{
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
|
m_data.m_type = value_t::object;
|
||||||
|
assert_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(!is_object()))
|
||||||
|
{
|
||||||
|
JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief starts the @ref update_members loop over an already-copied @a
|
||||||
|
/// source; called by both @ref update overloads
|
||||||
|
void update_from(basic_json& source, const bool merge_objects)
|
||||||
|
{
|
||||||
|
update_members(source.begin(), source.end(), merge_objects, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief the members loop of @ref update, for this object and range
|
@brief the members loop of @ref update, for this object and range
|
||||||
|
|
||||||
@@ -31205,7 +31255,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
@param[in] depth nesting level of this object, counted from the object
|
@param[in] depth nesting level of this object, counted from the object
|
||||||
@ref update was called on
|
@ref update was called on
|
||||||
*/
|
*/
|
||||||
void update_members(const const_iterator& first, const const_iterator& last, const bool merge_objects, const std::size_t depth)
|
void update_members(const iterator& first, const iterator& last, const bool merge_objects, const std::size_t depth)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
||||||
{
|
{
|
||||||
@@ -31223,13 +31273,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// are overwritten as usual" behavior (see #5402).
|
// are overwritten as usual" behavior (see #5402).
|
||||||
if (it2 != m_data.m_value.object->end() && it2->second.is_object())
|
if (it2 != m_data.m_value.object->end() && it2->second.is_object())
|
||||||
{
|
{
|
||||||
it2->second.update_members(it.value().cbegin(), it.value().cend(), true, depth + 1);
|
it2->second.update_members(it.value().begin(), it.value().end(), true, depth + 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set_parent() also repairs the other members, which ordered_json
|
// set_parent() also repairs the other members, which ordered_json
|
||||||
// relocates when adding a key makes its vector grow
|
// relocates when adding a key makes its vector grow
|
||||||
set_parent(m_data.m_value.object->operator[](it.key()) = it.value());
|
set_parent(m_data.m_value.object->operator[](it.key()) = std::move(it.value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31243,7 +31293,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
version. Only reached for values nested deeper than @ref
|
version. Only reached for values nested deeper than @ref
|
||||||
detail::recursion_depth_limit.
|
detail::recursion_depth_limit.
|
||||||
*/
|
*/
|
||||||
void update_members_iteratively(const_iterator first, const_iterator last)
|
void update_members_iteratively(iterator first, iterator last)
|
||||||
{
|
{
|
||||||
std::vector<merge_frame> stack;
|
std::vector<merge_frame> stack;
|
||||||
|
|
||||||
@@ -31270,18 +31320,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
const auto it2 = target->m_data.m_value.object->find(first.key());
|
const auto it2 = target->m_data.m_value.object->find(first.key());
|
||||||
if (it2 != target->m_data.m_value.object->end() && it2->second.is_object())
|
if (it2 != target->m_data.m_value.object->end() && it2->second.is_object())
|
||||||
{
|
{
|
||||||
const basic_json& source = first.value();
|
basic_json& source = first.value();
|
||||||
++first;
|
++first;
|
||||||
stack.emplace_back(target, first, last);
|
stack.emplace_back(target, first, last);
|
||||||
target = &it2->second;
|
target = &it2->second;
|
||||||
first = source.cbegin();
|
first = source.begin();
|
||||||
last = source.cend();
|
last = source.end();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set_parent() also repairs the other members, which ordered_json
|
// set_parent() also repairs the other members, which ordered_json
|
||||||
// relocates when adding a key makes its vector grow
|
// relocates when adding a key makes its vector grow
|
||||||
target->set_parent(target->m_data.m_value.object->operator[](first.key()) = first.value());
|
target->set_parent(target->m_data.m_value.object->operator[](first.key()) = std::move(first.value()));
|
||||||
++first;
|
++first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33290,7 +33340,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
/// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
|
||||||
void merge_patch(const basic_json& apply_patch)
|
void merge_patch(const basic_json& apply_patch)
|
||||||
{
|
{
|
||||||
apply_merge_patch(apply_patch, 0);
|
// copy first: apply_patch may be *this or one of its descendants,
|
||||||
|
// and is iterated (and moved from) below to patch *this
|
||||||
|
basic_json patch = apply_patch;
|
||||||
|
apply_merge_patch(patch, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -33303,7 +33356,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
detail::recursion_depth_limit levels have been entered, @ref
|
detail::recursion_depth_limit levels have been entered, @ref
|
||||||
merge_patch_iteratively applies what is left without the call stack.
|
merge_patch_iteratively applies what is left without the call stack.
|
||||||
*/
|
*/
|
||||||
void apply_merge_patch(const basic_json& apply_patch, const std::size_t depth)
|
void apply_merge_patch(basic_json& apply_patch, const std::size_t depth)
|
||||||
{
|
{
|
||||||
if (apply_patch.is_object())
|
if (apply_patch.is_object())
|
||||||
{
|
{
|
||||||
@@ -33331,7 +33384,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*this = apply_patch;
|
*this = std::move(apply_patch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33344,12 +33397,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
recursive version. Only reached for patches nested deeper than @ref
|
recursive version. Only reached for patches nested deeper than @ref
|
||||||
detail::recursion_depth_limit.
|
detail::recursion_depth_limit.
|
||||||
*/
|
*/
|
||||||
void merge_patch_iteratively(const basic_json& apply_patch)
|
void merge_patch_iteratively(basic_json& apply_patch)
|
||||||
{
|
{
|
||||||
std::vector<merge_frame> stack;
|
std::vector<merge_frame> stack;
|
||||||
|
|
||||||
// patch `target` with `patch`, or start patching it member by member
|
// patch `target` with `patch`, or start patching it member by member
|
||||||
const auto apply = [&stack](basic_json & target, const basic_json & patch)
|
const auto apply = [&stack](basic_json & target, basic_json & patch)
|
||||||
{
|
{
|
||||||
if (patch.is_object())
|
if (patch.is_object())
|
||||||
{
|
{
|
||||||
@@ -33357,11 +33410,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
{
|
{
|
||||||
target = basic_json::object();
|
target = basic_json::object();
|
||||||
}
|
}
|
||||||
stack.emplace_back(&target, patch.cbegin(), patch.cend());
|
stack.emplace_back(&target, patch.begin(), patch.end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target = patch;
|
target = std::move(patch);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33377,7 +33430,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const const_iterator member = frame.position;
|
const iterator member = frame.position;
|
||||||
++stack.back().position;
|
++stack.back().position;
|
||||||
if (member.value().is_null())
|
if (member.value().is_null())
|
||||||
{
|
{
|
||||||
@@ -33544,6 +33597,9 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
|
// keep: undoes the macros defined via detail/macro_scope.hpp at the top of this file; removing it
|
||||||
|
// (nothing in this file *uses* a symbol from it) would leak JSON_* macros into every translation
|
||||||
|
// unit that includes this header.
|
||||||
// #include <nlohmann/detail/macro_unscope.hpp>
|
// #include <nlohmann/detail/macro_unscope.hpp>
|
||||||
// __ _____ _____ _____
|
// __ _____ _____ _____
|
||||||
// __| | __| | | | JSON for Modern C++
|
// __| | __| | | | JSON for Modern C++
|
||||||
@@ -33758,7 +33814,7 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
|
#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
|
||||||
#undef JSON_HEDLEY_FALL_THROUGH
|
#undef JSON_HEDLEY_FALL_THROUGH
|
||||||
|
|
||||||
|
// IWYU pragma: keep
|
||||||
|
|
||||||
// End of GCC diagnostic pragmas for C++ modules support
|
// End of GCC diagnostic pragmas for C++ modules support
|
||||||
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L
|
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus >= 202002L
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <string> // allocator, string
|
||||||
#include <string> // string
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
// #include <nlohmann/detail/abi_macros.hpp>
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -177,7 +176,7 @@ This serializer ignores the template arguments and uses ADL
|
|||||||
for serialization.
|
for serialization.
|
||||||
*/
|
*/
|
||||||
template<typename T = void, typename SFINAE = void>
|
template<typename T = void, typename SFINAE = void>
|
||||||
struct adl_serializer;
|
struct adl_serializer; // IWYU pragma: keep
|
||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
@@ -193,12 +192,12 @@ template<template<typename U, typename V, typename... Args> class ObjectType =
|
|||||||
adl_serializer,
|
adl_serializer,
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||||
template<typename RefStringType>
|
template<typename RefStringType>
|
||||||
class json_pointer;
|
class json_pointer; // IWYU pragma: keep
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief default specialization
|
@brief default specialization
|
||||||
@@ -209,7 +208,7 @@ using json = basic_json<>;
|
|||||||
/// @brief a minimal map-like container that preserves insertion order
|
/// @brief a minimal map-like container that preserves insertion order
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||||
struct ordered_map;
|
struct ordered_map; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief specialization that maintains the insertion order of object keys
|
/// @brief specialization that maintains the insertion order of object keys
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||||
|
|||||||
@@ -236,6 +236,31 @@ TEST_CASE("Regression tests for extended diagnostics")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Regression test for issue #5641 - parent pointers after update()/merge_patch() with an aliasing argument")
|
||||||
|
{
|
||||||
|
// update()'s and merge_patch()'s argument may be *this or one of its
|
||||||
|
// descendants; the values moved out of the (temporary) copy must end
|
||||||
|
// up with their parent pointing at their new location in *this
|
||||||
|
{
|
||||||
|
json j = {{"a", {{"a", 1}, {"b", 2}}}};
|
||||||
|
j.update(j["a"]);
|
||||||
|
CHECK(j == json({{"a", 1}, {"b", 2}}));
|
||||||
|
|
||||||
|
// Must call operator[] on const element, otherwise m_parent gets updated.
|
||||||
|
auto const& constJ = j;
|
||||||
|
CHECK_THROWS_WITH_AS(constJ["a"].at(0), "[json.exception.type_error.304] (/a) cannot use at() with number", json::type_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
json j = {{"a", {{"a", nullptr}, {"b", 2}}}};
|
||||||
|
j.merge_patch(j["a"]);
|
||||||
|
CHECK(j == json({{"b", 2}}));
|
||||||
|
|
||||||
|
auto const& constJ = j;
|
||||||
|
CHECK_THROWS_WITH_AS(constJ["b"].at(0), "[json.exception.type_error.304] (/b) cannot use at() with number", json::type_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Regression test for issue #3032 - Yet another assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
|
SECTION("Regression test for issue #3032 - Yet another assertion failure when inserting into arrays with JSON_DIAGNOSTICS set")
|
||||||
{
|
{
|
||||||
// reference operator[](size_type idx)
|
// reference operator[](size_type idx)
|
||||||
|
|||||||
@@ -374,3 +374,52 @@ TEST_CASE("JSON Merge Patch and update on ordered_json")
|
|||||||
CHECK(target == ordered_json::parse(R"({"a": 1, "e": {"y": 5}, "g": 6})"));
|
CHECK(target == ordered_json::parse(R"({"a": 1, "e": {"y": 5}, "g": 6})"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("merge_patch() with an argument that aliases *this (#5641)")
|
||||||
|
{
|
||||||
|
SECTION("j.merge_patch(j): erasing a member destroys the node the loop's iterator points to")
|
||||||
|
{
|
||||||
|
// reproduces issue #5641, case 1
|
||||||
|
json j = {{"a", nullptr}, {"b", 1}};
|
||||||
|
j.merge_patch(j);
|
||||||
|
CHECK(j == json({{"b", 1}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("j.merge_patch(j[\"a\"]): removing \"a\" destroys the patch while it is iterated")
|
||||||
|
{
|
||||||
|
// reproduces issue #5641, case 2
|
||||||
|
json j = {{"a", {{"a", nullptr}, {"b", 2}}}};
|
||||||
|
j.merge_patch(j["a"]);
|
||||||
|
CHECK(j == json({{"b", 2}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("a patch nested past the iterative descent bound aliases *this")
|
||||||
|
{
|
||||||
|
// every depth on either side of where the iterative version takes
|
||||||
|
// over (detail::recursion_depth_limit(), 128); patching *this with
|
||||||
|
// itself is idempotent, aliased or not
|
||||||
|
for (const std::size_t depth :
|
||||||
|
{
|
||||||
|
std::size_t{0}, std::size_t{127}, std::size_t{128}, std::size_t{300}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(depth);
|
||||||
|
json j = json::parse(nested_objects(depth, 0));
|
||||||
|
const json expected = j;
|
||||||
|
j.merge_patch(j);
|
||||||
|
CHECK(j == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ordered_json")
|
||||||
|
{
|
||||||
|
using nlohmann::ordered_json;
|
||||||
|
|
||||||
|
SECTION("merge_patch with a member of *this")
|
||||||
|
{
|
||||||
|
ordered_json j = {{"a", {{"a", nullptr}, {"b", 2}}}};
|
||||||
|
j.merge_patch(j["a"]);
|
||||||
|
CHECK(j == ordered_json({{"b", 2}}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1116,3 +1116,72 @@ TEST_CASE("update() on deeply nested values")
|
|||||||
CHECK(p->at("y") == 2);
|
CHECK(p->at("y") == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("update() with an argument that aliases *this (#5641)")
|
||||||
|
{
|
||||||
|
SECTION("the target is checked before the argument, as before the copy")
|
||||||
|
{
|
||||||
|
json j = 1;
|
||||||
|
CHECK_THROWS_WITH_AS(j.update(json::array()), "[json.exception.type_error.312] cannot use update() with number", json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.update(j.cbegin(), j.cend()), "[json.exception.type_error.312] cannot use update() with number", json::type_error&);
|
||||||
|
|
||||||
|
json k;
|
||||||
|
CHECK_THROWS_WITH_AS(k.update(json::array()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
|
||||||
|
CHECK(k == json::object());
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const reference")
|
||||||
|
{
|
||||||
|
SECTION("j.update(j[\"a\"]): assigning into the argument's parent destroys it mid-iteration")
|
||||||
|
{
|
||||||
|
// reproduces issue #5641, case 3
|
||||||
|
json j = {{"a", {{"a", 1}, {"b", 2}}}};
|
||||||
|
j.update(j["a"]);
|
||||||
|
CHECK(j == json({{"a", 1}, {"b", 2}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("merge_objects with an argument that is a member of *this")
|
||||||
|
{
|
||||||
|
json j = {{"defaults", {{"opts", {{"a", 1}}}}}, {"opts", {{"b", 2}}}};
|
||||||
|
j.update(j["defaults"], true);
|
||||||
|
CHECK(j == json({{"defaults", {{"opts", {{"a", 1}}}}}, {"opts", {{"a", 1}, {"b", 2}}}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("ordered_json: inserting a new key relocates the vector behind the argument")
|
||||||
|
{
|
||||||
|
// reproduces issue #5641, case 4
|
||||||
|
using nlohmann::ordered_json;
|
||||||
|
ordered_json j = {{"a", {{"x", 1}, {"y", 2}, {"z", 3}}}};
|
||||||
|
j.update(j["a"]);
|
||||||
|
CHECK(j == ordered_json({{"a", {{"x", 1}, {"y", 2}, {"z", 3}}}, {"x", 1}, {"y", 2}, {"z", 3}}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("iterator range")
|
||||||
|
{
|
||||||
|
SECTION("range that is a member of *this")
|
||||||
|
{
|
||||||
|
json j = {{"a", {{"a", 1}, {"b", 2}}}};
|
||||||
|
j.update(j["a"].begin(), j["a"].end());
|
||||||
|
CHECK(j == json({{"a", 1}, {"b", 2}}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("nested past the iterative descent bound aliases *this")
|
||||||
|
{
|
||||||
|
// every depth on either side of where the iterative version takes
|
||||||
|
// over (detail::recursion_depth_limit(), 128); merging *this into
|
||||||
|
// itself is idempotent, aliased or not
|
||||||
|
for (const std::size_t depth :
|
||||||
|
{
|
||||||
|
std::size_t{0}, std::size_t{127}, std::size_t{128}, std::size_t{300}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(depth);
|
||||||
|
json j = json::parse(nested_objects(depth, 0));
|
||||||
|
const json expected = j;
|
||||||
|
j.update(j, true);
|
||||||
|
CHECK(j == expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,4 +7,22 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
||||||
|
|
||||||
|
// libc++ annotates std::mutex for Clang's thread safety analysis, so -Weverything
|
||||||
|
// reports -Wthread-safety-negative for the locks in doctest's reporters, which are
|
||||||
|
// only compiled in this file. __has_warning keeps older Clang versions from
|
||||||
|
// reporting an unknown warning group.
|
||||||
|
#if defined(__clang__) && defined(__has_warning)
|
||||||
|
#if __has_warning("-Wthread-safety-negative")
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wthread-safety-negative"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "doctest_compatibility.h"
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#if defined(__clang__) && defined(__has_warning)
|
||||||
|
#if __has_warning("-Wthread-safety-negative")
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1 +1,4 @@
|
|||||||
|
# astyle is deliberately pinned: newer versions reformat the code, and this version
|
||||||
|
# defines the formatting that `make amalgamate` produces and check_amalgamation.yml enforces.
|
||||||
|
# Dependabot is told to ignore it in .github/dependabot.yml.
|
||||||
astyle==3.4.13
|
astyle==3.4.13
|
||||||
|
|||||||
Reference in New Issue
Block a user