mirror of
https://github.com/nlohmann/json.git
synced 2026-11-11 22:51:34 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b686490f6 | ||
|
|
95424664ab | ||
|
|
e894077e17 |
No files matched your search
@@ -60,3 +60,10 @@ updates:
|
||||
interval: daily
|
||||
cooldown:
|
||||
default-days: 7
|
||||
ignore:
|
||||
# semgrep pins these packages to exact or compatible-release versions (see its METADATA);
|
||||
# bumping them on their own makes the Semgrep job fail with ResolutionImpossible, so
|
||||
# they only move together with a semgrep release
|
||||
- dependency-name: mcp
|
||||
- dependency-name: boltons
|
||||
- dependency-name: "opentelemetry-*"
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/init@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
||||
with:
|
||||
languages: c-cpp
|
||||
# Analyze the sources without compiling them. Autobuild compiled the
|
||||
@@ -47,4 +47,4 @@ jobs:
|
||||
build-mode: none
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/analyze@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
||||
@@ -48,6 +48,6 @@ jobs:
|
||||
output: 'flawfinder_results.sarif'
|
||||
|
||||
- name: Upload analysis results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
||||
with:
|
||||
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
|
||||
@@ -80,6 +80,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -52,12 +52,8 @@ jobs:
|
||||
# the old action fell back to, running community rules with no token.
|
||||
# SEMGREP_APP_TOKEN is still passed through so registry auth works if a
|
||||
# token is ever added.
|
||||
# The version is pinned, but not by hash: Semgrep pins its own dependencies
|
||||
# to exact or compatible-release versions, so a hash-pinned lock file broke
|
||||
# on almost every Dependabot bump of a transitive dependency. Dependabot
|
||||
# only bumps the semgrep line; pip resolves the rest.
|
||||
- name: Install Semgrep
|
||||
run: python3 -m pip install --user -r cmake/requirements/requirements-semgrep.txt
|
||||
run: python3 -m pip install --user --require-hashes -r cmake/requirements/requirements-semgrep.txt
|
||||
|
||||
# `semgrep scan --sarif` always exits 0 even with findings; continue-on-error
|
||||
# is a safety net so the SARIF upload still runs if the scan itself errors.
|
||||
@@ -69,7 +65,7 @@ jobs:
|
||||
|
||||
# Upload SARIF file generated in previous step
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
||||
uses: github/codeql-action/upload-sarif@1fc58d04a4d4374f921bdac573c3811c240f9c26 # v4.39.2
|
||||
with:
|
||||
sarif_file: semgrep.sarif
|
||||
if: always()
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
container: ubuntu:24.04
|
||||
strategy:
|
||||
matrix:
|
||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local, ci_test_recursion_depth_limit_0]
|
||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_delete_deprecated_functions, ci_test_no_thread_local]
|
||||
steps:
|
||||
- name: Install build-essential
|
||||
run: apt-get update ; apt-get install -y build-essential unzip wget git
|
||||
|
||||
@@ -342,27 +342,6 @@ add_custom_target(ci_test_no_thread_local
|
||||
COMMENT "Compile and test without thread-local storage"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Change the number of levels the walks over a value recurse into.
|
||||
###############################################################################
|
||||
|
||||
# JSON_RECURSION_DEPTH_LIMIT is 128 by default, which is what the whole test
|
||||
# suite otherwise runs with. 0 sends every walk to its explicit stack at once,
|
||||
# so this target runs the whole suite through the walks that the default only
|
||||
# uses for values nested more deeply than 128 levels: results must not depend on
|
||||
# the limit. The largest limit, 254, is covered by a build of
|
||||
# tests/src/unit-recursion_depth_limit.cpp (see tests/CMakeLists.txt).
|
||||
add_custom_target(ci_test_recursion_depth_limit_0
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-DCMAKE_CXX_FLAGS=-DJSON_RECURSION_DEPTH_LIMIT=0
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_recursion_depth_limit_0 && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with JSON_RECURSION_DEPTH_LIMIT=0"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Coverage.
|
||||
###############################################################################
|
||||
|
||||
@@ -1 +1,991 @@
|
||||
semgrep==1.184.0
|
||||
# Semgrep and all its dependencies, pinned by hash for the Semgrep workflow. A pip install with
|
||||
# hashes must list every dependency, so this file was generated with
|
||||
# uv pip compile requirements.in --generate-hashes --python-version 3.14 \
|
||||
# --python-platform x86_64-manylinux_2_39 --no-header --no-annotate
|
||||
# from a requirements.in containing only "semgrep==1.184.0". Dependabot keeps it current.
|
||||
annotated-types==0.8.0 \
|
||||
--hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \
|
||||
--hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0
|
||||
anyio==4.16.0 \
|
||||
--hash=sha256:59bb03251907983d1603d27c3087ddb1e93299ea2163adcdba37899a4fb12ffb \
|
||||
--hash=sha256:c66ae634e0b8228396b801741beb3294326d4b6102f7bba4041c0dfb58c29026
|
||||
attrs==26.1.0 \
|
||||
--hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \
|
||||
--hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
|
||||
boltons==21.0.0 \
|
||||
--hash=sha256:65e70a79a731a7fe6e98592ecfb5ccf2115873d01dbc576079874629e5c90f13 \
|
||||
--hash=sha256:b9bb7b58b2b420bbe11a6025fdef6d3e5edc9f76a42fb467afe7ca212ef9948b
|
||||
bracex==3.2.2 \
|
||||
--hash=sha256:284d59c4656e5a0421ff691402074bd5847049d50410535764a2c522a47095bc \
|
||||
--hash=sha256:d18976160b3ba01a57d5c53a5c8c3aa2506efa9e0a3a62467251f82b8f563fde
|
||||
certifi==2026.10.23 \
|
||||
--hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \
|
||||
--hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1
|
||||
cffi==2.1.1 \
|
||||
--hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \
|
||||
--hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \
|
||||
--hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \
|
||||
--hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \
|
||||
--hash=sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6 \
|
||||
--hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \
|
||||
--hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \
|
||||
--hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \
|
||||
--hash=sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9 \
|
||||
--hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \
|
||||
--hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \
|
||||
--hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \
|
||||
--hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \
|
||||
--hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \
|
||||
--hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \
|
||||
--hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \
|
||||
--hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \
|
||||
--hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \
|
||||
--hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \
|
||||
--hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \
|
||||
--hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \
|
||||
--hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \
|
||||
--hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \
|
||||
--hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \
|
||||
--hash=sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659 \
|
||||
--hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \
|
||||
--hash=sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004 \
|
||||
--hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \
|
||||
--hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \
|
||||
--hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \
|
||||
--hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \
|
||||
--hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \
|
||||
--hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \
|
||||
--hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \
|
||||
--hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \
|
||||
--hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \
|
||||
--hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \
|
||||
--hash=sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9 \
|
||||
--hash=sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf \
|
||||
--hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \
|
||||
--hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \
|
||||
--hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \
|
||||
--hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \
|
||||
--hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \
|
||||
--hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \
|
||||
--hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \
|
||||
--hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \
|
||||
--hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \
|
||||
--hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \
|
||||
--hash=sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9 \
|
||||
--hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \
|
||||
--hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \
|
||||
--hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \
|
||||
--hash=sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41 \
|
||||
--hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \
|
||||
--hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \
|
||||
--hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \
|
||||
--hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \
|
||||
--hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \
|
||||
--hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \
|
||||
--hash=sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98 \
|
||||
--hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \
|
||||
--hash=sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1 \
|
||||
--hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \
|
||||
--hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \
|
||||
--hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \
|
||||
--hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \
|
||||
--hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \
|
||||
--hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \
|
||||
--hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \
|
||||
--hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \
|
||||
--hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \
|
||||
--hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \
|
||||
--hash=sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be \
|
||||
--hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \
|
||||
--hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \
|
||||
--hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \
|
||||
--hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \
|
||||
--hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \
|
||||
--hash=sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b \
|
||||
--hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \
|
||||
--hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \
|
||||
--hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \
|
||||
--hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \
|
||||
--hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \
|
||||
--hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \
|
||||
--hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \
|
||||
--hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \
|
||||
--hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \
|
||||
--hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \
|
||||
--hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \
|
||||
--hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \
|
||||
--hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \
|
||||
--hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \
|
||||
--hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \
|
||||
--hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \
|
||||
--hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \
|
||||
--hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \
|
||||
--hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \
|
||||
--hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264
|
||||
charset-normalizer==3.5.2 \
|
||||
--hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \
|
||||
--hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \
|
||||
--hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \
|
||||
--hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \
|
||||
--hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \
|
||||
--hash=sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848 \
|
||||
--hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \
|
||||
--hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \
|
||||
--hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \
|
||||
--hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \
|
||||
--hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \
|
||||
--hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \
|
||||
--hash=sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275 \
|
||||
--hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \
|
||||
--hash=sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787 \
|
||||
--hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \
|
||||
--hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \
|
||||
--hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \
|
||||
--hash=sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3 \
|
||||
--hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \
|
||||
--hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \
|
||||
--hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \
|
||||
--hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \
|
||||
--hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \
|
||||
--hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \
|
||||
--hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \
|
||||
--hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \
|
||||
--hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \
|
||||
--hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \
|
||||
--hash=sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320 \
|
||||
--hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \
|
||||
--hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \
|
||||
--hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \
|
||||
--hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \
|
||||
--hash=sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc \
|
||||
--hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \
|
||||
--hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \
|
||||
--hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \
|
||||
--hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \
|
||||
--hash=sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c \
|
||||
--hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \
|
||||
--hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \
|
||||
--hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \
|
||||
--hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \
|
||||
--hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \
|
||||
--hash=sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa \
|
||||
--hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \
|
||||
--hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \
|
||||
--hash=sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2 \
|
||||
--hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \
|
||||
--hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \
|
||||
--hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \
|
||||
--hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \
|
||||
--hash=sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9 \
|
||||
--hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \
|
||||
--hash=sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c \
|
||||
--hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \
|
||||
--hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \
|
||||
--hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \
|
||||
--hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \
|
||||
--hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \
|
||||
--hash=sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be \
|
||||
--hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \
|
||||
--hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \
|
||||
--hash=sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2 \
|
||||
--hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \
|
||||
--hash=sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a \
|
||||
--hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \
|
||||
--hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \
|
||||
--hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \
|
||||
--hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \
|
||||
--hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \
|
||||
--hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \
|
||||
--hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \
|
||||
--hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \
|
||||
--hash=sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e \
|
||||
--hash=sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5 \
|
||||
--hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \
|
||||
--hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \
|
||||
--hash=sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0 \
|
||||
--hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \
|
||||
--hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \
|
||||
--hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \
|
||||
--hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \
|
||||
--hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \
|
||||
--hash=sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac \
|
||||
--hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \
|
||||
--hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \
|
||||
--hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \
|
||||
--hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \
|
||||
--hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \
|
||||
--hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \
|
||||
--hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \
|
||||
--hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \
|
||||
--hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \
|
||||
--hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \
|
||||
--hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \
|
||||
--hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \
|
||||
--hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \
|
||||
--hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \
|
||||
--hash=sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249 \
|
||||
--hash=sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4 \
|
||||
--hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \
|
||||
--hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \
|
||||
--hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \
|
||||
--hash=sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03 \
|
||||
--hash=sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e \
|
||||
--hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \
|
||||
--hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \
|
||||
--hash=sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849 \
|
||||
--hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \
|
||||
--hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \
|
||||
--hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \
|
||||
--hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \
|
||||
--hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \
|
||||
--hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \
|
||||
--hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \
|
||||
--hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \
|
||||
--hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \
|
||||
--hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \
|
||||
--hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \
|
||||
--hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \
|
||||
--hash=sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45 \
|
||||
--hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \
|
||||
--hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \
|
||||
--hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \
|
||||
--hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \
|
||||
--hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \
|
||||
--hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \
|
||||
--hash=sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c \
|
||||
--hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \
|
||||
--hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \
|
||||
--hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \
|
||||
--hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \
|
||||
--hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \
|
||||
--hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \
|
||||
--hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \
|
||||
--hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \
|
||||
--hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \
|
||||
--hash=sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a \
|
||||
--hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \
|
||||
--hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \
|
||||
--hash=sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f \
|
||||
--hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \
|
||||
--hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \
|
||||
--hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \
|
||||
--hash=sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5 \
|
||||
--hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \
|
||||
--hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \
|
||||
--hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \
|
||||
--hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \
|
||||
--hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \
|
||||
--hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \
|
||||
--hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \
|
||||
--hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \
|
||||
--hash=sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50 \
|
||||
--hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \
|
||||
--hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \
|
||||
--hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \
|
||||
--hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \
|
||||
--hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \
|
||||
--hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \
|
||||
--hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \
|
||||
--hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \
|
||||
--hash=sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4 \
|
||||
--hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \
|
||||
--hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \
|
||||
--hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \
|
||||
--hash=sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341 \
|
||||
--hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \
|
||||
--hash=sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d \
|
||||
--hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f
|
||||
click==8.4.2 \
|
||||
--hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \
|
||||
--hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76
|
||||
click-option-group==0.5.9 \
|
||||
--hash=sha256:ad2599248bd373e2e19bec5407967c3eec1d0d4fc4a5e77b08a0481e75991080 \
|
||||
--hash=sha256:f94ed2bc4cf69052e0f29592bd1e771a1789bd7bfc482dd0bc482134aff95823
|
||||
colorama==0.4.6 \
|
||||
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
|
||||
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
|
||||
cryptography==50.0.2 \
|
||||
--hash=sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602 \
|
||||
--hash=sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2 \
|
||||
--hash=sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047 \
|
||||
--hash=sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c \
|
||||
--hash=sha256:1ba34f04897fcdaa73f74145c25f3ec146fbd56593853e88adc2e811303c5f42 \
|
||||
--hash=sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18 \
|
||||
--hash=sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51 \
|
||||
--hash=sha256:3dc4fd8058cea1644971207d530e1a03a184a805ffc8ebdddf0599d78a331b81 \
|
||||
--hash=sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856 \
|
||||
--hash=sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2 \
|
||||
--hash=sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de \
|
||||
--hash=sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7 \
|
||||
--hash=sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd \
|
||||
--hash=sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2 \
|
||||
--hash=sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be \
|
||||
--hash=sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45 \
|
||||
--hash=sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0 \
|
||||
--hash=sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e \
|
||||
--hash=sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c \
|
||||
--hash=sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5 \
|
||||
--hash=sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452 \
|
||||
--hash=sha256:7c6d0330c472d96f6a6afe24d80dfdf15176c33096f0a4397ae4c60f3dd3be48 \
|
||||
--hash=sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05 \
|
||||
--hash=sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1 \
|
||||
--hash=sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93 \
|
||||
--hash=sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04 \
|
||||
--hash=sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e \
|
||||
--hash=sha256:92e665960f25fcdc73725b9cec7a3824f279ba97a98653afe9ffac2e43668f67 \
|
||||
--hash=sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7 \
|
||||
--hash=sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107 \
|
||||
--hash=sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079 \
|
||||
--hash=sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134 \
|
||||
--hash=sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227 \
|
||||
--hash=sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1 \
|
||||
--hash=sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539 \
|
||||
--hash=sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e \
|
||||
--hash=sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d \
|
||||
--hash=sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c \
|
||||
--hash=sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd \
|
||||
--hash=sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020 \
|
||||
--hash=sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd \
|
||||
--hash=sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94 \
|
||||
--hash=sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a \
|
||||
--hash=sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408 \
|
||||
--hash=sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37 \
|
||||
--hash=sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e \
|
||||
--hash=sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454 \
|
||||
--hash=sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c \
|
||||
--hash=sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc \
|
||||
--hash=sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37 \
|
||||
--hash=sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767 \
|
||||
--hash=sha256:eef4c2f3423810b3070ab391f85436d2f8bbfcb286ac15cbc73190b3563b1f1a \
|
||||
--hash=sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5 \
|
||||
--hash=sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc \
|
||||
--hash=sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67 \
|
||||
--hash=sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8 \
|
||||
--hash=sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480 \
|
||||
--hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \
|
||||
--hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b
|
||||
exceptiongroup==1.2.2 \
|
||||
--hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \
|
||||
--hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc
|
||||
face==26.0.1 \
|
||||
--hash=sha256:8183d94bc248baaea855a9f8445f97a22a9988908e60abddccc6e251da77c4c6 \
|
||||
--hash=sha256:ab0a83c37c9789dce658a67a9a80eafaa113c9ec37c5a9d950ff5480542a062d
|
||||
glom==25.12.0 \
|
||||
--hash=sha256:1ae7da88be3693df40ad27bdf57a765a55c075c86c971bcddd67927403eb0069 \
|
||||
--hash=sha256:b9f21e77f71a6576a43864e85066b8cc3f0f778d0d50961563f8981377a6dcb1
|
||||
googleapis-common-protos==1.76.0 \
|
||||
--hash=sha256:59e13344a9f3651aa201a03e2bee815a3bf43a4baf1f9ff8a9b62a840ce25fac \
|
||||
--hash=sha256:71db0e44a1d4c2dd024ebad44ca67129cc1e2892e4861df466764749d5ef8642
|
||||
h11==0.16.0 \
|
||||
--hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
|
||||
--hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
|
||||
httpcore==1.0.9 \
|
||||
--hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \
|
||||
--hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8
|
||||
httpx==0.28.1 \
|
||||
--hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \
|
||||
--hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad
|
||||
httpx-sse==0.4.3 \
|
||||
--hash=sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc \
|
||||
--hash=sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d
|
||||
idna==3.20 \
|
||||
--hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \
|
||||
--hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c
|
||||
importlib-metadata==10.1.0 \
|
||||
--hash=sha256:82b04047fa09792c1a8cfeddfe08bec79e4b13c29c8469b0d3949860f61017e8 \
|
||||
--hash=sha256:cf45ce66a929c64e994185a809c04840d0501db17e663810d993d0f4829265c7
|
||||
jsonschema==4.25.1 \
|
||||
--hash=sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63 \
|
||||
--hash=sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85
|
||||
jsonschema-specifications==2025.9.1 \
|
||||
--hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
|
||||
--hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
|
||||
markdown-it-py==4.2.0 \
|
||||
--hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \
|
||||
--hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a
|
||||
mcp==1.29.0 \
|
||||
--hash=sha256:52d01f334de1868cc3bb2d6604931126a67631f99a6c5d3b82ba47290315ec36 \
|
||||
--hash=sha256:f5a075bb611f23d6f4d080c6a1699fa62772eebc562ba9e66b306ddde1c755f7
|
||||
mdurl==0.1.2 \
|
||||
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
|
||||
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
|
||||
opentelemetry-api==1.37.0 \
|
||||
--hash=sha256:540735b120355bd5112738ea53621f8d5edb35ebcd6fe21ada3ab1c61d1cd9a7 \
|
||||
--hash=sha256:accf2024d3e89faec14302213bc39550ec0f4095d1cf5ca688e1bfb1c8612f47
|
||||
opentelemetry-exporter-otlp-proto-common==1.37.0 \
|
||||
--hash=sha256:53038428449c559b0c564b8d718df3314da387109c4d36bd1b94c9a641b0292e \
|
||||
--hash=sha256:c87a1bdd9f41fdc408d9cc9367bb53f8d2602829659f2b90be9f9d79d0bfe62c
|
||||
opentelemetry-exporter-otlp-proto-http==1.37.0 \
|
||||
--hash=sha256:54c42b39945a6cc9d9a2a33decb876eabb9547e0dcb49df090122773447f1aef \
|
||||
--hash=sha256:e52e8600f1720d6de298419a802108a8f5afa63c96809ff83becb03f874e44ac
|
||||
opentelemetry-instrumentation==0.58b0 \
|
||||
--hash=sha256:50f97ac03100676c9f7fc28197f8240c7290ca1baa12da8bfbb9a1de4f34cc45 \
|
||||
--hash=sha256:df640f3ac715a3e05af145c18f527f4422c6ab6c467e40bd24d2ad75a00cb705
|
||||
opentelemetry-instrumentation-requests==0.58b0 \
|
||||
--hash=sha256:672a0be0bb5b52bea0c11820b35e27edcf4cd22d34abe4afc59a92a80519f8a8 \
|
||||
--hash=sha256:ae9495e6ff64e27bdb839fce91dbb4be56e325139828e8005f875baf41951a2e
|
||||
opentelemetry-instrumentation-threading==0.58b0 \
|
||||
--hash=sha256:eacc072881006aceb5b9b6831bcdce718c67ef6f31ac0b32bd6a23a94d979b4a \
|
||||
--hash=sha256:f68c61f77841f9ff6270176f4d496c10addbceacd782af434d705f83e4504862
|
||||
opentelemetry-proto==1.37.0 \
|
||||
--hash=sha256:30f5c494faf66f77faeaefa35ed4443c5edb3b0aa46dad073ed7210e1a789538 \
|
||||
--hash=sha256:8ed8c066ae8828bbf0c39229979bdf583a126981142378a9cbe9d6fd5701c6e2
|
||||
opentelemetry-sdk==1.37.0 \
|
||||
--hash=sha256:8f3c3c22063e52475c5dbced7209495c2c16723d016d39287dfc215d1771257c \
|
||||
--hash=sha256:cc8e089c10953ded765b5ab5669b198bbe0af1b3f89f1007d19acd32dc46dda5
|
||||
opentelemetry-semantic-conventions==0.58b0 \
|
||||
--hash=sha256:5564905ab1458b96684db1340232729fce3b5375a06e140e8904c78e4f815b28 \
|
||||
--hash=sha256:6bd46f51264279c433755767bb44ad00f1c9e2367e1b42af563372c5a6fa0c25
|
||||
opentelemetry-util-http==0.58b0 \
|
||||
--hash=sha256:6c6b86762ed43025fbd593dc5f700ba0aa3e09711aedc36fd48a13b23d8cb1e7 \
|
||||
--hash=sha256:de0154896c3472c6599311c83e0ecee856c4da1b17808d39fdc5cce5312e4d89
|
||||
packaging==26.3 \
|
||||
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
|
||||
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
|
||||
peewee==3.19.0 \
|
||||
--hash=sha256:de220b94766e6008c466e00ce4ba5299b9a832117d9eb36d45d0062f3cfd7417 \
|
||||
--hash=sha256:f88292a6f0d7b906cb26bca9c8599b8f4d8920ebd36124400d0cbaaaf915511f
|
||||
protobuf==6.33.6 \
|
||||
--hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \
|
||||
--hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \
|
||||
--hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \
|
||||
--hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \
|
||||
--hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \
|
||||
--hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \
|
||||
--hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \
|
||||
--hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \
|
||||
--hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \
|
||||
--hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf
|
||||
pycparser==3.12 \
|
||||
--hash=sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e \
|
||||
--hash=sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6
|
||||
pydantic==2.14.3 \
|
||||
--hash=sha256:1054f237f4d4733e5a30e1e2333bd33a2004ab9ab1510bd053a9a31bb48e232d \
|
||||
--hash=sha256:3f7b347782ab7e4cf4c798496ae3a82787d9f21ec12676a9c564355eeef8daa8
|
||||
pydantic-core==2.50.4 \
|
||||
--hash=sha256:0001d6920e3a5d92758cda460d6dc9f918a78ad6d5d092f1c8b5395e6b775356 \
|
||||
--hash=sha256:0574866e05f6adeecc520d87e87dd06210c0a51706341f6ef8421572f5a64444 \
|
||||
--hash=sha256:09450778e3ab58d3f565899fcfbf6c82926e31af29e28e799d1d50941316e0cb \
|
||||
--hash=sha256:0af56dbf8822ba9f4efcbbfdc15478f8b6fb08f1609860cb50aa2cc8476b3c34 \
|
||||
--hash=sha256:0b059a7968b1911be5a2d9a8234827ab0bef9d1e465d4b42da525894143550e8 \
|
||||
--hash=sha256:0ec20aca2b067369913716847f7dfe5f4dddf16a46965b7a70bbad5defaaba86 \
|
||||
--hash=sha256:0f87ae9db5ba8d8de40dcb93982cf8dd544e6552a80d3345af51941cc2146b80 \
|
||||
--hash=sha256:1239daaf063e62213ca1f34d96663900bd7510c42a786e843fd328af70e46445 \
|
||||
--hash=sha256:13b6dd62b5279f5b9d72f3bf918a35443ee8bd549241d9dc52d79a2c3b6d7016 \
|
||||
--hash=sha256:15bece43a02ad543c621c8305e67dedb5f27d378c5ba741e5a2c36523f8ef37f \
|
||||
--hash=sha256:16902a147b3da4840612164a5e67947104d63e978f7a57c395877a5e26690b9c \
|
||||
--hash=sha256:1afefe44ec042fbabfb4483ea258c04cf75ff4ff328d754f09b321fdaa232aca \
|
||||
--hash=sha256:1de7be9a66fc8536770481ab64a05aae5067c725f2b29a09543af00e6a417b97 \
|
||||
--hash=sha256:1e20cbde2b6deb33a51d08cd168454dd9044ec7d4474056f4d98d63f51578783 \
|
||||
--hash=sha256:2039e323acee9abfec1fb5f661776e8965fe5928f3b7f8431900a774cba5c317 \
|
||||
--hash=sha256:219114f8dcdcbe4720d82ef016b1287ce5a0a67d7c69ca61524eb72e82aac344 \
|
||||
--hash=sha256:22e874666bdbd96d6bf629d32cd8ab376fedf1fd62585b52a42b9fa9fa6c20b6 \
|
||||
--hash=sha256:23a9ba564b2db709ff16eca990992ba95a19069972b34bff87c81d4b473cd755 \
|
||||
--hash=sha256:25e7e1080f9f7ce7cd9d114b31470ce912771bd02f38c824721d3c35d312abff \
|
||||
--hash=sha256:26cb012c4b8ca9f847bd0ac15978bd3d0f55b050bfbe6c47355edfc7e945029b \
|
||||
--hash=sha256:29358a8ca74e7d81158d14e2b10c904bd18773293ae3788716c0626fe0342347 \
|
||||
--hash=sha256:2980a701be88f9128a7470189fa3bcda5387f76c298a6f8e000fc29eb2a6f4e7 \
|
||||
--hash=sha256:2a60ec2a57ac3ef3767e526e9bf706ec75aa3d79c4ea134d9d4fcf7c62a297a7 \
|
||||
--hash=sha256:2f42584e5785385f681163a42506cab0d51295e17599a648396c52a7046c1372 \
|
||||
--hash=sha256:2f5cc5bcb94063fbbdfd285a2b302da34af07491337c10bb35de1d5220fa1583 \
|
||||
--hash=sha256:2f6767122b37c780bb756a720a4eef2bc6a050a0a1143428834b3cbc89448bd2 \
|
||||
--hash=sha256:300753f71c73302e218124baf995f00058e085cd01869bd9610bcbd0bd4500c1 \
|
||||
--hash=sha256:30d4dc35bc0eea52202a90b3820445ee0072c820241bfa710a623a078c9b267b \
|
||||
--hash=sha256:32a991aebd165f227b7c7c60bb9d66c2c7de9c24308552da264c9938fde0f8d6 \
|
||||
--hash=sha256:32d6dda86383645ec428ea64dfc277036f5cbc60a72238eab28b91a3fdb9a113 \
|
||||
--hash=sha256:33b21f69540a12c2053cd1d95766d8bd9667a3897f7c712a642de8aa37eb0865 \
|
||||
--hash=sha256:39f489ce31272073e6e146f6781690f9c1ee8c126836e6403361ef91154d89fe \
|
||||
--hash=sha256:3a48a5254d15a0ad050318bfc7a9566d4ec740118187e8f303e47a6840287eb7 \
|
||||
--hash=sha256:3b8ee2589a082739c522c1fe4be227412fcf108b903abb6672ae2f5570558882 \
|
||||
--hash=sha256:3de6c2a4df2af0ac9ab4dc1488746fe8b1a90e27955d870d9edda3187d20092b \
|
||||
--hash=sha256:3e0b395648c6cb871bceb2906907f255dc876ec425f2d5b024e129985cea8519 \
|
||||
--hash=sha256:3e547ceec1da7382f01f9e13963023e53367a71802c88778b21b9645a077cbdf \
|
||||
--hash=sha256:41b2cd8b29dbb5a4c9828a70f50d1abfc92011115c813213d3a91205c6f731b3 \
|
||||
--hash=sha256:41f4f8ae714e4fea1d635880f8a1af715ecf080eed4d13c5b04a0f3210f9c61a \
|
||||
--hash=sha256:474f7e598c7902165662a5d5160d3fce31037890a2975a9871ebf7c05862300b \
|
||||
--hash=sha256:477af785d1846e4e96bf56983b92ea7553aaeccdeb8acdaa55c7cee9eda0ae32 \
|
||||
--hash=sha256:49eb1241a969a5994db6880c18c012b6cbe2340343d8f529721571806583e500 \
|
||||
--hash=sha256:4c29b8f2d6417069bb1f257e6b9113f5d64dc2f554cc200ea90b4fe2c5cdb733 \
|
||||
--hash=sha256:4eb15be588407148ef5937dc8d9256a71f6b115e6cddadb7aa20b6ee384680dc \
|
||||
--hash=sha256:4eda7e3fdef382b7d4492745988a5baaf6953923a337f8b9dde5f76fa8afde20 \
|
||||
--hash=sha256:523466eba8ee10f7480f3c2057563145978011c583130d2cc01fb1e7af808e25 \
|
||||
--hash=sha256:57fa0a9490785139f1a4e4f43891830d55dfe4408845c0c9cb5eff4aeaf75f69 \
|
||||
--hash=sha256:5b26e5f1793b96cdc60242bf38da86ff24a27a708aa396214cac9b534bf571c7 \
|
||||
--hash=sha256:5bc1811ef2b4d4ba63e8e452f6e332b6374bd1d2cbbfdf66826c8cb1f71dd10d \
|
||||
--hash=sha256:5c074454dc6d4f6f4ba6561a56bf33a14db7651d882a5a5321ba3ae8868e082d \
|
||||
--hash=sha256:5c1013647be741647895c102831dcf79c34209662dbb683df9efb864417ed7d5 \
|
||||
--hash=sha256:601fce6cea9ddeaa85329e12e7f351def38d233075f42a3012b9c48071b02941 \
|
||||
--hash=sha256:6118e5a5550e36582e19bac1a403711a748f9f18251b054c326d3db02aaa7a18 \
|
||||
--hash=sha256:629eae995185540406e3635df5d5cf1d44f19ea240840b835d3f44541ff694d8 \
|
||||
--hash=sha256:6348ad12fa741bcc9c2f173e99fbf27cbc038826d8c31a4a7d836eca27878ba2 \
|
||||
--hash=sha256:65376dbe1ab4dbc768ca2b72b7c13993562c035f5925fd3bc7ff9c8c585c515d \
|
||||
--hash=sha256:6619d49a89a15cd04334f76fec530c155923bfc60da74ff5d815a52629e1aa6c \
|
||||
--hash=sha256:664e74848c2f5fc27db8505fe24e1ecd3ac669412913bf73d176916f86cc08e2 \
|
||||
--hash=sha256:67f7cc397e1d5556a801d1cba74de0d27d827eb242e6c036c0ca273c745414f1 \
|
||||
--hash=sha256:696613a0c0e7b2b35356e389ba4195ce20cfe7a2fc2e992c87d974d973eabec7 \
|
||||
--hash=sha256:6c5687b59b6ba0f663c4f2f15470f68507d6b45ccd3a19ee6d224f95cbee70d8 \
|
||||
--hash=sha256:6c7d7b0b596319e9ce79ef96ce57a14054a2eac629c0588a0539187a218be799 \
|
||||
--hash=sha256:70dbc9f83c41f37a4faa62dae5203853847223a891da446f48ef2efcfd5df806 \
|
||||
--hash=sha256:71395a43da5584bb70556f380387e15f845c0dcf76373c1afbfa0025737576ac \
|
||||
--hash=sha256:71ade6d2e445839350d589ff99bbddfde16f3f32db28da5c894a09f99c8b2a03 \
|
||||
--hash=sha256:71e03d2ea1a221d020cfc5b6cc8bbbedef23a06704c70fcf4d0afb42965b22d1 \
|
||||
--hash=sha256:7210398a1607ad607dc73196e575b3148b00a333cbb602ddbe1b60ba54554f43 \
|
||||
--hash=sha256:7472c39480ccc11dda69a196d1b7c7a6b48eb6594b77f05d945599d3e47f731c \
|
||||
--hash=sha256:7646353a5a7c553c04167aca628e2550b538f492765b03ccf34321a560acc43c \
|
||||
--hash=sha256:76e0065998159244ff4c097a6c05ff08019c6fbb6e597a85846e73044f0215b3 \
|
||||
--hash=sha256:789a6453e5ffd18a7ab6b8c3a0dd8403053829197ec258ecb90c604c21ffcc99 \
|
||||
--hash=sha256:789f88dea57841cdebef392b5d6e90444d767117e9ff2e0d9172df5c9de6690c \
|
||||
--hash=sha256:7ac2769a7ddd661e07e26c12220adc31b17014c48234b2a5a88993b8d4109e09 \
|
||||
--hash=sha256:817953730e4a73a09008b010c4a42396cefe799616a22df2ac21d3927b3080cf \
|
||||
--hash=sha256:83d2beac85b757bfc404c5c0612df51c4ef33bbb7be65cf4a96b4da7cbc4ff4f \
|
||||
--hash=sha256:86c7c4615634b5c57a79770f5b738354e45ae219a89949aeae84f19169a05283 \
|
||||
--hash=sha256:8923fcd49f875e8a0448d7223d1fdf1a9973ae2d1f20d4158753ceb8909facd2 \
|
||||
--hash=sha256:8cceae48ae7f94990c2f4e36291e9ec9868735e8b0f19e4489a17b0422338466 \
|
||||
--hash=sha256:92f8f63df729061bb14558ed740e7a222f6e2aa6c2e6a5bcfb4e706676562049 \
|
||||
--hash=sha256:930ad463d3fb7a340d323bcc496ec32dae469ec9974c29ff569f19806b6b03b4 \
|
||||
--hash=sha256:94733cb447c37b0ce6f71b39ca1288d5f966a084023a5617b4cc35a852586859 \
|
||||
--hash=sha256:9be1cfe715ecaa060ffd5d599ef410b94ef2697a0eed4cee562f788a2aa2175b \
|
||||
--hash=sha256:a0c5210d038418a115e7cf8706bfa611bd14add2f5787274dba45aadca3155e0 \
|
||||
--hash=sha256:a2f8716344bbbd10443391be0b1f2003b34949e3c4e6883005c2bc498ab6b64b \
|
||||
--hash=sha256:a4bb174bd65f795c39ad6642d9d5bdc43351b306b7d0a654ab0d0abb38be245f \
|
||||
--hash=sha256:a70d5effebd81ebd8e15a8aabdc7980832367b2b00c36543bac378977004cc80 \
|
||||
--hash=sha256:a9ee990bf2cfbd81574c5d4f9f6c9d480a14b5b43d2c4f2ca13f4c6f48089394 \
|
||||
--hash=sha256:ab2822bcdcefb54d1e8ca29f5e3ec3afe160fb794bb3a3a73b09d11ed2671104 \
|
||||
--hash=sha256:ad92d255a165cde5f9882ff69699eaf5495e0a1f32e97566bbbb80f11e46781f \
|
||||
--hash=sha256:aead3b74b68396bf0feab5d57e050b730ded7df55853c1e048a87e00aaf033c6 \
|
||||
--hash=sha256:aeb2e123cbf978a905e9f55155c1b8316fbbfa7cf64d04521fe174bab302d100 \
|
||||
--hash=sha256:aec3c2d741a8e3ee993de7f95f37afb51e31b169c95dbd29da4cf6688f340914 \
|
||||
--hash=sha256:b0cdb655fbd1562c2dfc9986f9103a106f7058cd0915afc6e656d4b1d73f3387 \
|
||||
--hash=sha256:b26f39a5be3cd91a2035818be3d0ffdf5282c3e1f5f53d3b80b7024021acee52 \
|
||||
--hash=sha256:b2f2d13239487cecaae98c9f4d5904ad0737643cdf8873c88ec6a78b12214f20 \
|
||||
--hash=sha256:b300a30304c4c6aeab03ed06809819d9eceacdd58441d3c7dffe41edfd006091 \
|
||||
--hash=sha256:b42f64825f5d750228f08318a9bf4d723b7ecb4c472aedcb3013c3ec2dc1f949 \
|
||||
--hash=sha256:b67d38e8bb0ade7e6e84575e4bb153fab35b122458077273aeb08fdf12be9d2c \
|
||||
--hash=sha256:b867f9fd183d76977f810c626d539265183c25b2284762893a31e8d6cacc81c0 \
|
||||
--hash=sha256:b99bed995ed7c41515c11fe2beb86f8a6cc298e5537cae2f736de2f982f74ef0 \
|
||||
--hash=sha256:bd46bcc28ed85d3cf71581b42d90b4ebd1f2062f81879519fed209f8a4d1cfc6 \
|
||||
--hash=sha256:bee28aab5a580eec673f7b68dfa8dece3dd37bd207ef8d22fafe23a8e9837296 \
|
||||
--hash=sha256:c04e9d920e2674f54651fd260a15c5d2843526c73d5242ee4311325ddc9573b3 \
|
||||
--hash=sha256:c4c5a1770ecfe8bdb6c6f09f8d81ea4de04f7efb012fac1efa4ad315dccc1fd1 \
|
||||
--hash=sha256:c733087ecf7dde06b1d071679bfd5f3ba03266ba77814c1c7253bc48c9adedd9 \
|
||||
--hash=sha256:c813ada7a651193acda85b6bc1cf12abd4b37cd25c7c6a75d7183512cc374969 \
|
||||
--hash=sha256:c81d98e27d9d9261909dcccab1ba5d6ea1c98b0bb9470e368604614fd1d36ddd \
|
||||
--hash=sha256:c81e35862aced259177a537ce1a6264c3a97bae1ced184ca9dc10ea754563688 \
|
||||
--hash=sha256:c856e439a9d54d514e81a7131229ba151cdf81df7c408e0f6c89340e5003dfe2 \
|
||||
--hash=sha256:c9e70012926e97069cdd09221861aff412aa94e4cac2e019055cdb79485b150c \
|
||||
--hash=sha256:ca83a32b2b41653d89f09a3d22b770bca96da72273bef8f7a68136bdd1e8b823 \
|
||||
--hash=sha256:cbf0777d54672990b10cb8ca9b0523499e182d7e2ea39f86b138519a902aa601 \
|
||||
--hash=sha256:d49127f137f871cde3c5650af33bbbdcee02679dae76e020902fa106f522b8ae \
|
||||
--hash=sha256:d690121e80ab16e623415351ab24713534d4e500b3cadff216409cb6826063d4 \
|
||||
--hash=sha256:d6a166978f22f10cb91413f70519861605219346decf65bc79008f9257c94afe \
|
||||
--hash=sha256:d6e3485a5e5c01fb5339c1ee3d4b9e21e2135a2a9d44caafb71acd994487ee7c \
|
||||
--hash=sha256:d7d406709ae924cf0b08b8282ca2f0e1c90526911d93bc040557cbc83b74c55f \
|
||||
--hash=sha256:d8201c9f9035520cdcc7dcad383b039ec8123969b87e01cf27c3dd883c02313b \
|
||||
--hash=sha256:da779ae50b46f3f7d1e1b5f362fdc0ad376a49fd55f6f3122dc2b6149936cdf7 \
|
||||
--hash=sha256:dcf2c7eaaa4cafe8e49b017e5bb49e76e084ab6f0cd712ee4019c812b5cf68b8 \
|
||||
--hash=sha256:dd8bed00731a21e3106e5dd6bbffb6c775a2c0bbc7c0c9face534d830057bdc9 \
|
||||
--hash=sha256:df1c174796cd63eb6b139f7daf783affe1f3ed659605850e843b24764c21bfc5 \
|
||||
--hash=sha256:dfcf6e51000b34f7026322cd9ea9bc340d745637e27e0bbc22f504b4f6b967ee \
|
||||
--hash=sha256:e498900bfbf7ddddd862f810440c09e9b81674739e8a11d619b40906dccd4a9a \
|
||||
--hash=sha256:e512c75ec5cf4475c1aa50ad975ecdf253f4963b06e152e1a11edd6de4010753 \
|
||||
--hash=sha256:e5bd109d095aaae989a0463d5ef0fcc43e9ddd5de125e656d3c119a79e466380 \
|
||||
--hash=sha256:e6b4b08d09054310a4dc389fa61ee22a7a5a292cb23ab8a985136ca8828bf924 \
|
||||
--hash=sha256:e6da138a1ecc1341c8b788a5ee822670b03788e1f5decf7af9d461de6e508b8e \
|
||||
--hash=sha256:ea2f61b0bc12f3592288503961b764579dea0658852d96a0b3d823614d808821 \
|
||||
--hash=sha256:ed9c0b6f236648dbf30d57e9f57e1f74878caafa04833a19f529b5ba5164b7a8 \
|
||||
--hash=sha256:edbca8789fd10f0de534b660a6b4c71f1fd18039679c918dad392ab044bb37e4 \
|
||||
--hash=sha256:edc17549ab592e33cfcaf285f047bb75fcd98f608aa9309af1187fd736ce9641 \
|
||||
--hash=sha256:ef8a9ddb2e2a4eae4abb72dc0710eca6c2726779b0664bd10c3ce9fcfaed8c4e \
|
||||
--hash=sha256:f08ee8248aad2d054e5bc4c73554d4505464698f6d754f16198dbc5764e9821d \
|
||||
--hash=sha256:f1d62fb172db35c6478c9323da34ff37d1f3d37d7d44337a9d94ba8c583e5730 \
|
||||
--hash=sha256:f8fd23653a252cefabea11cd041efd7b80bdf403e43a36dea53f9cb0aaa21f0f \
|
||||
--hash=sha256:faa4e96385c820ce9d7f7a623486e23d4134ae3c9ba2071e44e0ab5a5a5002c4 \
|
||||
--hash=sha256:fb2bb5b557080da398b866408117d98fe9731a12334afd0cdff221b458cdc5dc \
|
||||
--hash=sha256:fc04affef30be98c1f36f0c422a4061ef618fdc1dde79f5ad5458dd496fecffa \
|
||||
--hash=sha256:ffb616d8d55965839670301dc3bae3abacff560a7e137a89056058a8a9da4d96
|
||||
pydantic-settings==2.16.2 \
|
||||
--hash=sha256:3dc08ffabed2bbd5dc2dd55ead7b78b4e4c5cd776aecd04310db5f1224caaf46 \
|
||||
--hash=sha256:8d523e5c129b097686bde019bd6109bff53f4c8c3f63f1ddf9933ffa42e5ab4f
|
||||
pygments==2.21.0 \
|
||||
--hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \
|
||||
--hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c
|
||||
pyjwt==2.15.1 \
|
||||
--hash=sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193 \
|
||||
--hash=sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8
|
||||
python-dotenv==1.2.4 \
|
||||
--hash=sha256:42269a8a5b3fd54ffa6f3d84b18abed50064717576b4ecf03dc4a55d8aa04fdc \
|
||||
--hash=sha256:f0d53e69935a851c0dcc78f3ab7aaccd8cabef0b92382b576b824212902873c0
|
||||
python-multipart==0.0.33 \
|
||||
--hash=sha256:8f16c07b36add9da6b2ee87d3efcaf0a45a6de9c3d0a5dd94e9ccf7675a7bc45 \
|
||||
--hash=sha256:b8112424a6abd162ec08d390565dd113ad699f2fe6fef3c987b8bbcbfe9e390d
|
||||
referencing==0.37.0 \
|
||||
--hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \
|
||||
--hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8
|
||||
requests==2.34.2 \
|
||||
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
|
||||
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
|
||||
rich==15.0.0 \
|
||||
--hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
|
||||
--hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
|
||||
rpds-py==2026.9.1 \
|
||||
--hash=sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25 \
|
||||
--hash=sha256:01445c8d194aa032a08e944f16567672da1c62dbdbefd8b6d0693032e290cf68 \
|
||||
--hash=sha256:028ad274ea951dac64491b5d1e65712a4aeabfdbdb9fccf797b57bd899b0c495 \
|
||||
--hash=sha256:0483515261947e4e8b8e1375bf7463e7eb6ccfb3d86e7b554d90cd5285f20f32 \
|
||||
--hash=sha256:068c37bba854ec2fe42f7365c640af11dd9895890ccbf2df5070d0c059bd7f96 \
|
||||
--hash=sha256:074a4d198bc34d9a8ea425114fc3ded6d11ec01f6a314a8db67454a5152d8834 \
|
||||
--hash=sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0 \
|
||||
--hash=sha256:08dae4a4095150a7c4545a1fb40b98e1ab1744fbc2770d92c977b9dadaa49ab6 \
|
||||
--hash=sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e \
|
||||
--hash=sha256:0f045bb053c9057720d72c56dffe30dffdc05997b2897a827b9325f0ab6623fa \
|
||||
--hash=sha256:10e208f2425d973938afcd56e28a7c4be32e27b6a60b5d381f49fb9d8acf9759 \
|
||||
--hash=sha256:136a1c3fe4402b7008bc81cb62ee538481795b61a7e83df88dff3b3f02b726ff \
|
||||
--hash=sha256:159a7aab5c5e8b112c8830f54717ce56da1252ebdbb526f5be2df2309280b9e7 \
|
||||
--hash=sha256:172e47169583f46ce118cbec68e6795d0da0f4606b488b6434f8276bca0a058c \
|
||||
--hash=sha256:1c2d1f6da5128eabf34e963d7163a818846075a52568250d006c4c953b40f903 \
|
||||
--hash=sha256:1d55198263bb51f557550c6ed2e6d1cb6a6fed6eb5c9120b741c5926bef8a45d \
|
||||
--hash=sha256:1d77b649e6f7cdf12ca5c2a98dad0ad37f9ea9b6f960408a92f0cb12bb3d04d9 \
|
||||
--hash=sha256:1e8d4d79d828299bf44a55db22a9388ab967b49d17132c88eab0f4360b48da8e \
|
||||
--hash=sha256:22ffd29a63d71fb1b81552c21f2c2b734949b7ac751a9be70675a939a900839b \
|
||||
--hash=sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a \
|
||||
--hash=sha256:270bdcdaac5d5b6f73c5e22e7e135c7f2a50e789f71d9e241d5be8d90026e19a \
|
||||
--hash=sha256:2711d29b653b3bce48a63d18b9c6b53274669e6d6c4094dddeb4d9a0e45128b2 \
|
||||
--hash=sha256:2c16ab111bc27c646ba8aa005d0527754edc538ebb636f0b1bf8e244b48d1945 \
|
||||
--hash=sha256:306ee1850d8105b5baf977e78d45fcadd12c1a54678d614c9baf217708446e91 \
|
||||
--hash=sha256:3231c4c0e521dafa5be0c9f114ee2c2ad46650836f2d72caa86801950c3e7044 \
|
||||
--hash=sha256:3890a6aa36e6baa53d5258a2a25d3ef8b37ad165a6ab27a892d7c3e3a432cd69 \
|
||||
--hash=sha256:3a72c11530d71abfb66c8d7696a2f86c43e63fca8b948f1a784ac490f4ec688e \
|
||||
--hash=sha256:3b5a6f40f0a1486b4b36c888123afc67acdbd9f33235927acf5ff295429a0ba3 \
|
||||
--hash=sha256:3c91c210ae7645626c608400e3519b4a642f837cce09ca830db3beb2e9f274d4 \
|
||||
--hash=sha256:3cd182d7291d29b92c521a0069d9c01ba6193628a9a105531d11b40a6d731a33 \
|
||||
--hash=sha256:3e524c7874ac72884d28e16dd5b8d839fd09e0fe76b020d3fbca23212a7b8c52 \
|
||||
--hash=sha256:3e93b2cd69a9830be33e03945cd7cda940a0a8bfcfbff41d6144f0cb0d3d8bd9 \
|
||||
--hash=sha256:3edae8c5ddfdb6985d49ae9d150516e5076888879022f91a26c2de9276ce0bdb \
|
||||
--hash=sha256:3f0e9ac28fc067d4d34b88ae43c48e9489455c97fee9633d851f7eeed5a05d35 \
|
||||
--hash=sha256:42e75466f83cd43f6026c81eab74246efb2bdadafb307b85700632d06c68f299 \
|
||||
--hash=sha256:44b32a7c4f0da3d28af31c259e38ddcff096f855e205ed0671d02fcf44f1ea1c \
|
||||
--hash=sha256:457866b85daf5034296666168b84a69e0b2e89dc4f1af102b46f6448a60b9063 \
|
||||
--hash=sha256:45bc6bccf78b20fd834237d18db64965d7ee68ba7f60440a26c7ab71e7b8d51a \
|
||||
--hash=sha256:46d80bc76b51a6c24f9944368c28d38b8bcbcea1da4f2f8d3ebc31a67e8c6ec6 \
|
||||
--hash=sha256:4793ef7f78268b124b73fa933440f01d258bbae01de9fa53e9080c9ab0425a12 \
|
||||
--hash=sha256:492e5e428cbe126221611f47e068f01660352feec4ad18bc0f5ea9b2ae88fb14 \
|
||||
--hash=sha256:4b26b03d9d2658ee2fa234f8f4f19f38a09773fe5261028025032e26d4d35af0 \
|
||||
--hash=sha256:4c0d2cb595a420b34d5086db0add011e26e2c09d6a024afbac4228bf8f863a30 \
|
||||
--hash=sha256:4cfaf02209061880210819934de2f4f6aa83dc04dafe6770276acc240a56da31 \
|
||||
--hash=sha256:501909f2e4a1e2dee528ef766fe3c469060ebc17e54a8383d404ba07a81a6f02 \
|
||||
--hash=sha256:50906f5aea24b5a865cbd0a589698288631d9f3a54c3a937c83aefa95a0d14af \
|
||||
--hash=sha256:54ac2158a6f96cfbabff0b2eedaf94b90c5ec7ca8317fcadc61e1c2b2e0ff6ef \
|
||||
--hash=sha256:56c6952a9b15047466d0c2347c446a761d4527f89976156341e68f0ce5cc08b0 \
|
||||
--hash=sha256:56cd8b3f77d7b6812f533b662186a1f28316931166ddc00fb893b1b0db7e9888 \
|
||||
--hash=sha256:57492a550a1d88d29d003247e5f78dd8cf04a701fac0e4c8db8745a6d2504e0a \
|
||||
--hash=sha256:5943980471829f6de242a20b109de3111ba6b77e3af0ffc587028ac854b05e6c \
|
||||
--hash=sha256:5c6ee90dee3e85e055ddfd502d611643d9b0fd94c818220bda84ec3dacd9b27b \
|
||||
--hash=sha256:5c90e7fa02e8f5de0d10c17595c568ada48c5302e749462c0ea1a4c362111a86 \
|
||||
--hash=sha256:5ce8943f79c2210f7abcc28e86367b03b28d95027fd01c46d2472373ae70c86f \
|
||||
--hash=sha256:617f59cde379b4f648a09797b7f683d04b90a46344cddab85639da5aff0f5531 \
|
||||
--hash=sha256:6307a0da524939decb8ca4a3933b8ab62525794411d6984fca6726e732804af6 \
|
||||
--hash=sha256:684fd492fff4fead00587544e059be2bbcb6f93454f21fa2a91b66fc7508be82 \
|
||||
--hash=sha256:6b5b393eda5ea42cca1c1a6665f2a4882b4fd5d1777e41ce0545a107fb008c9d \
|
||||
--hash=sha256:6b723eb406dec5bc9ec516c73ab9c3239a3284e017f7eb89ee2b3258bd504fb7 \
|
||||
--hash=sha256:6b9bf3135b4ad5981df9a73d71a35272d650a2985ae9c2746357b24d59de2448 \
|
||||
--hash=sha256:6beb738155fe8ab8091afdfa5a3226b21c2b1593f1e50ebb90eb25b44dbc0391 \
|
||||
--hash=sha256:6c0dbbcc19735fe5f8b0a54c07659d154a9e69f47e15d0a6ab7299215daf62cb \
|
||||
--hash=sha256:6cdc537c8633d7fd92a82e2e0d2ab74320a3f63d5e59fb9cf08711e08fe151c4 \
|
||||
--hash=sha256:6eae33003518fd4cb4f83a218d5371469dd3001aa3b87128c005b07762f7fe5e \
|
||||
--hash=sha256:740d0a99cf9de0b17a3943388e9294a59becf75e7c43421f387bd3c7a9901f7c \
|
||||
--hash=sha256:75c38c50ab9aca840225d9a9a3810bf11d04bd5c1f186cabbb8aee56db3e9b15 \
|
||||
--hash=sha256:761fdae6728ceb99ab182fad2f0cc1e262f610834dc891aea1d1a2a2e634776f \
|
||||
--hash=sha256:7664419f27db41d4f1c43a78dccda7dd6e8ef2428df3ee01d0c2a07a6b071297 \
|
||||
--hash=sha256:76d3af9732d2dab69f28179b40ba2d87e2f1d5824b4a694780aa787d685e8f36 \
|
||||
--hash=sha256:78326f4cb4427a56ba4996c0762b63be45f06b85f086526420d2b3a66e40f84d \
|
||||
--hash=sha256:7868b85224291c6cb6759f9b5adb9745f486d226f62b16a614dd5a2a5ab2b35b \
|
||||
--hash=sha256:815d26356930846a40c7bc1366e7b1b0320ab8a063e66c11298a208bed0fd237 \
|
||||
--hash=sha256:8171b44a054e5c67fd748ada04187f1250bf35b95f85e52ab64bcf3331a923bb \
|
||||
--hash=sha256:821b2755db9194409254012f429c56643416fb96ef9be090be82ec8826b7f477 \
|
||||
--hash=sha256:837c6b305e26fe0f75b15c92cf3b2ba29e0ae19dc40b1c557b026cb426347d0c \
|
||||
--hash=sha256:839dde845559254f34885267c6878f60d61d5205180226d976fe488d45fa128e \
|
||||
--hash=sha256:84a6ecc0c940169190d2c23bd969debd48c94dbc855acd60188a68d71d421608 \
|
||||
--hash=sha256:8601470267d938bcb7f3ab1a336100af51a4fd5b6ed030ef52461bb3ef5e7e07 \
|
||||
--hash=sha256:88b5268892fde430d5531f95bc560b6efbbd67c929662c586afd729a96e7461c \
|
||||
--hash=sha256:8aa5dda18d39b6143eb24809d158f9252c88f402749b6f1b62a506cc7d96cc35 \
|
||||
--hash=sha256:926bdd3e3b5998ddf70cc64bc8cf57209571f9044542913afb673799fec77dd0 \
|
||||
--hash=sha256:96beca19ec79de272e8668585380ff9092c47077c1d7a1e098e00bbd921f4785 \
|
||||
--hash=sha256:9a0460d43603d1fd9ef59c30278531e15d78581721ddb538fa560aa7817ea4ad \
|
||||
--hash=sha256:a03d57b86d2a51d0a66c92177e2be154ad015f357791d306e714569999cdb4cc \
|
||||
--hash=sha256:a36b70596407634ca82d4b989a3729074a008537a0522e4c8046a67c729103e9 \
|
||||
--hash=sha256:a3a52a3ba86436ab3aef510fbe21512abc2ddd1993005dfe50514bd2284ef025 \
|
||||
--hash=sha256:a3dbc5ed9514908d5046107d7b1346bde71eea61de6e0e4919c19354f97e769f \
|
||||
--hash=sha256:a431156bb41865fc14cd5d79bb9d7bbed83110b0159e34e62ae30951f96c0009 \
|
||||
--hash=sha256:a575404ebc9cf2e91edd32eaf570ec1430eb900d4f56724ba7dd4bc1fc9c176d \
|
||||
--hash=sha256:a5cf77eb04f20b720be95265a3e00eb2a14814074255cc27069c551b2db53118 \
|
||||
--hash=sha256:a8763f20692da7df39b0afdd1ba3042b004c50a45994f76c2d9a25641f7673db \
|
||||
--hash=sha256:ab4b2fda7c2b542f7f9d886cc6a838c5079d2b76f72e6081411faba11adde2c9 \
|
||||
--hash=sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab \
|
||||
--hash=sha256:b242c27c8f836305a4a72df9cdd564386ac57b807bd252a063223331c9316b37 \
|
||||
--hash=sha256:b4f062343e7ad3fa94f2c66e5ae667dee47ee74dd41a9057c4fbe163236a123d \
|
||||
--hash=sha256:b5b8b0753718d258fd454283fbd57e14545d3b40583fa672e27cb4f987626bcc \
|
||||
--hash=sha256:be3e47e2d91aa3942ff9bf4077a505226005abfc39b6f7554a91c1b9393986b9 \
|
||||
--hash=sha256:befc2d6a953e563f8a7bfd87a42c22ebf8a3e980dcb7b6a4d17b70b0e914e8a3 \
|
||||
--hash=sha256:bf35d0568abda97233239ce32896d3ad53fccc537832c104e30c94aa5fb93569 \
|
||||
--hash=sha256:c933c6678c6f116ff8af47a4c6db0868b8ace74af0343016c0ef00f00272ea69 \
|
||||
--hash=sha256:c9d1aca01f49170fdcf5c92761b1fafe97f554b721ca4570c5949fff778f0d4b \
|
||||
--hash=sha256:cdeaa99ce822dca76cfb1b993e9120c5ea212f2eb66d48950ad63c349668a018 \
|
||||
--hash=sha256:ce4d4f52e2a4324396caddbd45a97d8d7be5f42edd25d2355282a9c34f9b2f7f \
|
||||
--hash=sha256:d1028417bb44037eb3069c1009bd7b7277212876cda22fbe565b0bca9fab6d2c \
|
||||
--hash=sha256:d151e148117294133bf8af7eeace085e7e87432db15ab6adf640330298a47f6f \
|
||||
--hash=sha256:d7841166b7fa64c9c56404617ae4341448847482d45933b13135d26c130519e5 \
|
||||
--hash=sha256:d7fca4eb6df565e2a928f1c7dad92d27db8f9df0f449e76423ed5d7e713ed445 \
|
||||
--hash=sha256:d95a354e02393eada6d7351184671aced9d4cce109dabf927cb7aa99624352a1 \
|
||||
--hash=sha256:d9edf30457d74eebfd76b045535e36f1cd89062566a128a0db2145ca042d787e \
|
||||
--hash=sha256:dbc2673f9223d420c91145599b3ba45a8a50c207d1976908e5fb5ddb0c9b9429 \
|
||||
--hash=sha256:e01b3c878c8641913e688edd1b3f08658c6783d29cf6b826bd3c0d1ae7a1ffaa \
|
||||
--hash=sha256:e21c1429e205828ea886a2293a4a2c8e01f4c25d9893ca330e97a6cf73f52e7b \
|
||||
--hash=sha256:e43d4a1f673e8a1cbd8533e809e02b4bf9d4f2280269bb640436556312121250 \
|
||||
--hash=sha256:e6d198bad4e49dd6732fbd636e2fc5c082f45c8cad0b4acb756b00c82c76072e \
|
||||
--hash=sha256:e6ea1cda8d8c688278430e4268a42f5e5da3bdd74578dfadc0820c3f1766ce83 \
|
||||
--hash=sha256:ea394a937f17a54c51239348bdbe2e3518124c8d4a8951ba04a311d3095bd18f \
|
||||
--hash=sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd \
|
||||
--hash=sha256:eb61be926bb81567c1f48bdc8aa22b9855048dc2efd53871f9f7e6e9a5632346 \
|
||||
--hash=sha256:eba5d173f7d5708b22a93815017a4611873ed54db9f268077c0dd1ed99cfc858 \
|
||||
--hash=sha256:ec450527cbf485e13c8d3602a54f428ab0432fdade0ede75efd74b735421c871 \
|
||||
--hash=sha256:eef6a03b0b6d08d0835ccfa8ec8d1bc70525e3801387567137b50c557695e6da \
|
||||
--hash=sha256:ef0d8c843e2827d6c120ab4687e9423fb1d893db1df27b7c1506615bcb9734a0 \
|
||||
--hash=sha256:ef6b65b03247c54692ad4fd9ee97cb772781927db72e3cb05e70b3db6d1ff14f \
|
||||
--hash=sha256:f3d6ed6a98cfd19155996605474982cc470d7601746a6439078f1a5a3fa8b050 \
|
||||
--hash=sha256:fce4b85234a0cbad67bf8e6e1201ee815d172c9aebad75f25645bc4d834f8e31 \
|
||||
--hash=sha256:fda1d96e542c37b6c804547dbf489c129fe7c97183a76a5ec275909ba1a063df \
|
||||
--hash=sha256:fdcd198979b4ecffcc1beba366a7fbcf4eb41243691a82fe52ceb0b902f09c12 \
|
||||
--hash=sha256:fe5ad0664ec772b02c45859041aa17655709cced7a31005817fbbbd988c25567
|
||||
ruamel-yaml==0.19.1 \
|
||||
--hash=sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93 \
|
||||
--hash=sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993
|
||||
ruamel-yaml-clib==0.2.15 \
|
||||
--hash=sha256:014181cdec565c8745b7cbc4de3bf2cc8ced05183d986e6d1200168e5bb59490 \
|
||||
--hash=sha256:04d21dc9c57d9608225da28285900762befbb0165ae48482c15d8d4989d4af14 \
|
||||
--hash=sha256:05c70f7f86be6f7bee53794d80050a28ae7e13e4a0087c1839dcdefd68eb36b6 \
|
||||
--hash=sha256:0ba6604bbc3dfcef844631932d06a1a4dcac3fee904efccf582261948431628a \
|
||||
--hash=sha256:11e5499db1ccbc7f4b41f0565e4f799d863ea720e01d3e99fa0b7b5fcd7802c9 \
|
||||
--hash=sha256:1b45498cc81a4724a2d42273d6cfc243c0547ad7c6b87b4f774cb7bcc131c98d \
|
||||
--hash=sha256:1bb7b728fd9f405aa00b4a0b17ba3f3b810d0ccc5f77f7373162e9b5f0ff75d5 \
|
||||
--hash=sha256:1f66f600833af58bea694d5892453f2270695b92200280ee8c625ec5a477eed3 \
|
||||
--hash=sha256:27dc656e84396e6d687f97c6e65fb284d100483628f02d95464fd731743a4afe \
|
||||
--hash=sha256:2812ff359ec1f30129b62372e5f22a52936fac13d5d21e70373dbca5d64bb97c \
|
||||
--hash=sha256:2b216904750889133d9222b7b873c199d48ecbb12912aca78970f84a5aa1a4bc \
|
||||
--hash=sha256:331fb180858dd8534f0e61aa243b944f25e73a4dae9962bd44c46d1761126bbf \
|
||||
--hash=sha256:3cb75a3c14f1d6c3c2a94631e362802f70e83e20d1f2b2ef3026c05b415c4900 \
|
||||
--hash=sha256:3eb199178b08956e5be6288ee0b05b2fb0b5c1f309725ad25d9c6ea7e27f962a \
|
||||
--hash=sha256:424ead8cef3939d690c4b5c85ef5b52155a231ff8b252961b6516ed7cf05f6aa \
|
||||
--hash=sha256:45702dfbea1420ba3450bb3dd9a80b33f0badd57539c6aac09f42584303e0db6 \
|
||||
--hash=sha256:468858e5cbde0198337e6a2a78eda8c3fb148bdf4c6498eaf4bc9ba3f8e780bd \
|
||||
--hash=sha256:46895c17ead5e22bea5e576f1db7e41cb273e8d062c04a6a49013d9f60996c25 \
|
||||
--hash=sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600 \
|
||||
--hash=sha256:480894aee0b29752560a9de46c0e5f84a82602f2bc5c6cde8db9a345319acfdf \
|
||||
--hash=sha256:4b293a37dc97e2b1e8a1aec62792d1e52027087c8eea4fc7b5abd2bdafdd6642 \
|
||||
--hash=sha256:4be366220090d7c3424ac2b71c90d1044ea34fca8c0b88f250064fd06087e614 \
|
||||
--hash=sha256:4d1032919280ebc04a80e4fb1e93f7a738129857eaec9448310e638c8bccefcf \
|
||||
--hash=sha256:4d3b58ab2454b4747442ac76fab66739c72b1e2bb9bd173d7694b9f9dbc9c000 \
|
||||
--hash=sha256:4dcec721fddbb62e60c2801ba08c87010bd6b700054a09998c4d09c08147b8fb \
|
||||
--hash=sha256:512571ad41bba04eac7268fe33f7f4742210ca26a81fe0c75357fa682636c690 \
|
||||
--hash=sha256:542d77b72786a35563f97069b9379ce762944e67055bea293480f7734b2c7e5e \
|
||||
--hash=sha256:56ea19c157ed8c74b6be51b5fa1c3aff6e289a041575f0556f66e5fb848bb137 \
|
||||
--hash=sha256:5d3c9210219cbc0f22706f19b154c9a798ff65a6beeafbf77fc9c057ec806f7d \
|
||||
--hash=sha256:5fea0932358e18293407feb921d4f4457db837b67ec1837f87074667449f9401 \
|
||||
--hash=sha256:617d35dc765715fa86f8c3ccdae1e4229055832c452d4ec20856136acc75053f \
|
||||
--hash=sha256:64da03cbe93c1e91af133f5bec37fd24d0d4ba2418eaf970d7166b0a26a148a2 \
|
||||
--hash=sha256:65f48245279f9bb301d1276f9679b82e4c080a1ae25e679f682ac62446fac471 \
|
||||
--hash=sha256:6f1d38cbe622039d111b69e9ca945e7e3efebb30ba998867908773183357f3ed \
|
||||
--hash=sha256:713cd68af9dfbe0bb588e144a61aad8dcc00ef92a82d2e87183ca662d242f524 \
|
||||
--hash=sha256:71845d377c7a47afc6592aacfea738cc8a7e876d586dfba814501d8c53c1ba60 \
|
||||
--hash=sha256:753faf20b3a5906faf1fc50e4ddb8c074cb9b251e00b14c18b28492f933ac8ef \
|
||||
--hash=sha256:7e74ea87307303ba91073b63e67f2c667e93f05a8c63079ee5b7a5c8d0d7b043 \
|
||||
--hash=sha256:88eea8baf72f0ccf232c22124d122a7f26e8a24110a0273d9bcddcb0f7e1fa03 \
|
||||
--hash=sha256:923816815974425fbb1f1bf57e85eca6e14d8adc313c66db21c094927ad01815 \
|
||||
--hash=sha256:9b6f7d74d094d1f3a4e157278da97752f16ee230080ae331fcc219056ca54f77 \
|
||||
--hash=sha256:a8220fd4c6f98485e97aea65e1df76d4fed1678ede1fe1d0eed2957230d287c4 \
|
||||
--hash=sha256:ab0df0648d86a7ecbd9c632e8f8d6b21bb21b5fc9d9e095c796cacf32a728d2d \
|
||||
--hash=sha256:ac9b8d5fa4bb7fd2917ab5027f60d4234345fd366fe39aa711d5dca090aa1467 \
|
||||
--hash=sha256:badd1d7283f3e5894779a6ea8944cc765138b96804496c91812b2829f70e18a7 \
|
||||
--hash=sha256:bdc06ad71173b915167702f55d0f3f027fc61abd975bd308a0968c02db4a4c3e \
|
||||
--hash=sha256:bf0846d629e160223805db9fe8cc7aec16aaa11a07310c50c8c7164efa440aec \
|
||||
--hash=sha256:bfd309b316228acecfa30670c3887dcedf9b7a44ea39e2101e75d2654522acd4 \
|
||||
--hash=sha256:c583229f336682b7212a43d2fa32c30e643d3076178fb9f7a6a14dde85a2d8bd \
|
||||
--hash=sha256:cb15a2e2a90c8475df45c0949793af1ff413acfb0a716b8b94e488ea95ce7cff \
|
||||
--hash=sha256:d290eda8f6ada19e1771b54e5706b8f9807e6bb08e873900d5ba114ced13e02c \
|
||||
--hash=sha256:da3d6adadcf55a93c214d23941aef4abfd45652110aed6580e814152f385b862 \
|
||||
--hash=sha256:dcc7f3162d3711fd5d52e2267e44636e3e566d1e5675a5f0b30e98f2c4af7974 \
|
||||
--hash=sha256:def5663361f6771b18646620fca12968aae730132e104688766cf8a3b1d65922 \
|
||||
--hash=sha256:e5e9f630c73a490b758bf14d859a39f375e6999aea5ddd2e2e9da89b9953486a \
|
||||
--hash=sha256:e9fde97ecb7bb9c41261c2ce0da10323e9227555c674989f8d9eb7572fc2098d \
|
||||
--hash=sha256:ef71831bd61fbdb7aa0399d5c4da06bea37107ab5c79ff884cc07f2450910262 \
|
||||
--hash=sha256:f4421ab780c37210a07d138e56dd4b51f8642187cdfb433eb687fe8c11de0144 \
|
||||
--hash=sha256:f6d3655e95a80325b84c4e14c080b2470fe4f33b6846f288379ce36154993fb1 \
|
||||
--hash=sha256:fd4c928ddf6bce586285daa6d90680b9c291cfd045fc40aad34e445d57b1bf51 \
|
||||
--hash=sha256:fe239bdfdae2302e93bd6e8264bd9b71290218fff7084a9db250b55caaccf43f
|
||||
semantic-version==2.10.0 \
|
||||
--hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \
|
||||
--hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177
|
||||
semgrep==1.184.0 \
|
||||
--hash=sha256:0ce3064175a44236dd9fd35603627e3f56139ac61e13ca967bae2b76b2cec9bf \
|
||||
--hash=sha256:0fc8a58e9a62de59ce644dde792dfc36764245d0139ab85632f66a8e0846a8c5 \
|
||||
--hash=sha256:3c86b2961b4663d1338fb965de038c7869571661971b78e18e9346ab57e1e20a \
|
||||
--hash=sha256:42a59e95433fd05a0908f8083e25656c90994c65549e483e0de8a1a0004a7adf \
|
||||
--hash=sha256:cf82d77eb911f921902f3e9d098fb97604c5419c0a87cf7de7ab2944b05e2ceb \
|
||||
--hash=sha256:d847abb8fb6fdde77d9e30a6bc869dbfcb68eff4142dcd77897c52635a7600d9 \
|
||||
--hash=sha256:f794d7c6d33126b6881f80d069583ef35b52bd796d882a5fa249ce1124aba3f3
|
||||
sse-starlette==3.7.0 \
|
||||
--hash=sha256:326416da2ab52e9a41b3f409d3ff897eda45aa68c9f3b7b17d0913aab8d219c3 \
|
||||
--hash=sha256:f1d3136caa12d129284fca3d2ded79bc9af943320b6472712955fea52a6d3eea
|
||||
starlette==1.10.0 \
|
||||
--hash=sha256:478c0ab3b4ced6e82719849c118fa406f0278a3499c1a898cd15cd31bdc38ce4 \
|
||||
--hash=sha256:b8399098d4c1e3522734f7235dc79b1fc967f96cf139c81e0fa30479e0685f9b
|
||||
structlog==26.1.0 \
|
||||
--hash=sha256:e081a26d6c373e6d201eca24eede26d8ffab07f88f477822e679183428d3d91e \
|
||||
--hash=sha256:f63a716cbd1b1291cf7661de7794b455acfa4c43c5bcf1630e6ad5ddc1adb3b7
|
||||
tomli==2.4.1 \
|
||||
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
|
||||
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
|
||||
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
|
||||
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
|
||||
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
|
||||
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
|
||||
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
|
||||
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
|
||||
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
|
||||
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
|
||||
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
|
||||
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
|
||||
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
|
||||
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
|
||||
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
|
||||
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
|
||||
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
|
||||
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
|
||||
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
|
||||
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
|
||||
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
|
||||
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
|
||||
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
|
||||
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
|
||||
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
|
||||
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
|
||||
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
|
||||
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
|
||||
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
|
||||
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
|
||||
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
|
||||
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
|
||||
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
|
||||
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
|
||||
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
|
||||
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
|
||||
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
|
||||
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
|
||||
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
|
||||
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
|
||||
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
|
||||
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
|
||||
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
|
||||
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
|
||||
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
|
||||
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
|
||||
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
|
||||
typing-extensions==4.16.0 \
|
||||
--hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \
|
||||
--hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5
|
||||
typing-inspection==0.4.5 \
|
||||
--hash=sha256:7f16c411e7930dc79596d42ab44672a3fe5f60eb34b781a1647e7872363120c7 \
|
||||
--hash=sha256:bc210535442b39e1bf2805e0c7a17dfd6a4ace760c84c7f7d16245d23a6b1c39
|
||||
urllib3==2.8.0 \
|
||||
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \
|
||||
--hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63
|
||||
uvicorn==0.54.0 \
|
||||
--hash=sha256:505bdb0f318731d45f1f712071fc781a8981f6847a31c902c9f5e652d4f67faf \
|
||||
--hash=sha256:a2e33cbfaa0306f8e6b0c13e0cb89d7d7a2da3e62b90c66e18c33d9807b28620
|
||||
wcmatch==8.5.2 \
|
||||
--hash=sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478 \
|
||||
--hash=sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2
|
||||
wrapt==1.17.3 \
|
||||
--hash=sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56 \
|
||||
--hash=sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828 \
|
||||
--hash=sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f \
|
||||
--hash=sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396 \
|
||||
--hash=sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77 \
|
||||
--hash=sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d \
|
||||
--hash=sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139 \
|
||||
--hash=sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7 \
|
||||
--hash=sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb \
|
||||
--hash=sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f \
|
||||
--hash=sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f \
|
||||
--hash=sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067 \
|
||||
--hash=sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f \
|
||||
--hash=sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7 \
|
||||
--hash=sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b \
|
||||
--hash=sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc \
|
||||
--hash=sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05 \
|
||||
--hash=sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd \
|
||||
--hash=sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7 \
|
||||
--hash=sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9 \
|
||||
--hash=sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81 \
|
||||
--hash=sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977 \
|
||||
--hash=sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa \
|
||||
--hash=sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b \
|
||||
--hash=sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe \
|
||||
--hash=sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58 \
|
||||
--hash=sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8 \
|
||||
--hash=sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77 \
|
||||
--hash=sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85 \
|
||||
--hash=sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c \
|
||||
--hash=sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df \
|
||||
--hash=sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454 \
|
||||
--hash=sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a \
|
||||
--hash=sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e \
|
||||
--hash=sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c \
|
||||
--hash=sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6 \
|
||||
--hash=sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5 \
|
||||
--hash=sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9 \
|
||||
--hash=sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd \
|
||||
--hash=sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277 \
|
||||
--hash=sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225 \
|
||||
--hash=sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22 \
|
||||
--hash=sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116 \
|
||||
--hash=sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16 \
|
||||
--hash=sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc \
|
||||
--hash=sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00 \
|
||||
--hash=sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2 \
|
||||
--hash=sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a \
|
||||
--hash=sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804 \
|
||||
--hash=sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04 \
|
||||
--hash=sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1 \
|
||||
--hash=sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba \
|
||||
--hash=sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390 \
|
||||
--hash=sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0 \
|
||||
--hash=sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d \
|
||||
--hash=sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22 \
|
||||
--hash=sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0 \
|
||||
--hash=sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2 \
|
||||
--hash=sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18 \
|
||||
--hash=sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6 \
|
||||
--hash=sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311 \
|
||||
--hash=sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89 \
|
||||
--hash=sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f \
|
||||
--hash=sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39 \
|
||||
--hash=sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4 \
|
||||
--hash=sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5 \
|
||||
--hash=sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa \
|
||||
--hash=sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a \
|
||||
--hash=sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050 \
|
||||
--hash=sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6 \
|
||||
--hash=sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235 \
|
||||
--hash=sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056 \
|
||||
--hash=sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2 \
|
||||
--hash=sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418 \
|
||||
--hash=sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c \
|
||||
--hash=sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a \
|
||||
--hash=sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6 \
|
||||
--hash=sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0 \
|
||||
--hash=sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775 \
|
||||
--hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \
|
||||
--hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c
|
||||
zipp==4.1.2 \
|
||||
--hash=sha256:b30cb6cd253122169c47de245ca24a86bac2a5d3802ba15bf7ba6414eb9e144d \
|
||||
--hash=sha256:cf474b90b07ea932637e17c6b9479de2b2882900b0d311bdaf4f5c000a15a97f
|
||||
@@ -67,7 +67,11 @@ basic_json(basic_json&& other) noexcept;
|
||||
- **objects**: [`object_t`](object_t.md) and all kinds of compatible associative containers such as `std::map`,
|
||||
`std::unordered_map`, `std::multimap`, and `std::unordered_multimap` with a `key_type` compatible to `string_t`
|
||||
and a `value_type` from which a `basic_json` value can be constructed.
|
||||
- **strings**: `string_t`, string literals, and all compatible string containers can be used.
|
||||
- **strings**: `string_t`, string literals, and all compatible string containers can be used. Since version 3.13.0,
|
||||
this includes `#!cpp std::u8string` (C++20): its code units are stored as a JSON string and
|
||||
[`get<std::u8string>()`](get.md) reads it back (in version 3.12.0, a `#!cpp std::u8string` was stored as an array
|
||||
of numbers; `get<std::u8string>()` still accepts such an array). `#!cpp std::u8string_view` and `#!cpp char8_t`
|
||||
arrays are not strings; they are stored as arrays of code units.
|
||||
|
||||
!!! note "Rvalue containers are moved from"
|
||||
|
||||
@@ -93,18 +97,10 @@ basic_json(basic_json&& other) noexcept;
|
||||
The constructor tries to convert the internal `m_value` of the parameter. Each member value (object, array, string,
|
||||
etc.) is serialized via the corresponding `to_json()` overload. For objects and strings, the conversion requires
|
||||
that the *target* `basic_json` type's `object_t::key_type` (or `string_t`) be directly constructible from the
|
||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the result
|
||||
depends on the *source* string type:
|
||||
|
||||
- If it is a range of characters (it has `begin()` and `end()`, as `std::string` does), the conversion falls back to
|
||||
the array-conversion path, which represents objects as arrays of `[key, value]` pairs and strings as arrays of
|
||||
character codes. This result has a different type than the source value, so the constructor's
|
||||
[`JSON_ASSERT`](../macros/json_assert.md) fails; with its default definition, `assert`, the program aborts unless
|
||||
`NDEBUG` is defined, in which case the array is returned.
|
||||
- Otherwise, the conversion does not compile, even though `#!cpp std::is_constructible` reports `#!cpp true`; for
|
||||
example, when converting a `basic_json` whose `string_t` is the `alt_string` of the unit tests to `json`.
|
||||
|
||||
This is a known limitation tracked in [issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the conversion
|
||||
does not fail to compile; instead, it silently falls back to the array-conversion path, which represents objects
|
||||
as arrays of `[key, value]` pairs and strings as arrays of character codes. This is a known limitation tracked in
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||
|
||||
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
||||
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
||||
|
||||
@@ -130,6 +130,12 @@ overload (3).
|
||||
`#!cpp json(true).get<double>()` throw. This is the behavior of all 3.x versions;
|
||||
[`basic_json_view::get<T>()`](../basic_json_view/get.md) behaves the same.
|
||||
|
||||
!!! note "`std::u8string` conversions"
|
||||
|
||||
Since version 3.13.0, `#!cpp get<std::u8string>()` (C++20) reads a JSON string; it also accepts an array of numbers,
|
||||
the form in which version 3.12.0 stored a `#!cpp std::u8string`. Any other JSON type throws
|
||||
[`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) ("type must be string or array").
|
||||
|
||||
!!! note "`std::optional` conversions"
|
||||
|
||||
Prior to version 3.13.0, `#!cpp get<std::optional<T>>()` (and other conversions to `std::optional<T>`) failed to
|
||||
|
||||
@@ -102,12 +102,9 @@ objects.
|
||||
|
||||
When converting an object from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md) (overload 4), the target `object_t`'s `key_type` must be
|
||||
directly constructible from the source object's key type (with the default `std::map`, the source `basic_json`'s
|
||||
`string_t`). If this requirement is not met and the source string type is a range of characters, the
|
||||
object is converted as an array of key-value pairs, which is incorrect: the converting constructor's
|
||||
[`JSON_ASSERT`](../macros/json_assert.md) fails; with its default definition, `assert`, the program aborts unless
|
||||
`NDEBUG` is defined, in which case the array is returned. If the source string type is not a range of characters, the
|
||||
conversion does not compile at all. See [`basic_json`](basic_json.md) and
|
||||
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
|
||||
source object's key type). If this requirement is not met, the conversion does not fail; instead,
|
||||
the object is silently converted as an array of key-value pairs, which is incorrect. See
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -27,16 +27,6 @@ reference operator+=(initializer_list_t init);
|
||||
`init` is converted into an object element and added using `operator+=(const typename object_t::value_type&)`.
|
||||
Otherwise, `init` is converted to a JSON value and added using `operator+=(basic_json&&)`.
|
||||
|
||||
!!! note "Single braced JSON value"
|
||||
|
||||
For a call such as `#!cpp arr += {obj}`, where the initializer list contains a single JSON value `obj`,
|
||||
compilers may disagree unless
|
||||
[`JSON_BRACE_INIT_COPY_SEMANTICS`](../macros/json_brace_init_copy_semantics.md) is defined to `1`: GCC, for
|
||||
example, selects this overload and appends a single-element array `[obj]`, whereas Clang selects the
|
||||
`basic_json` overload and appends a copy of `obj`. With the macro, GCC and Clang both append a copy of `obj`.
|
||||
To get a portable result without the macro, write `#!cpp arr += obj` to append a copy, or
|
||||
`#!cpp arr += json::array({obj})` to append a single-element array.
|
||||
|
||||
## Iterator invalidation
|
||||
|
||||
For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including
|
||||
|
||||
@@ -27,16 +27,6 @@ void push_back(initializer_list_t init);
|
||||
`init` is converted into an object element and added using `push_back(const typename object_t::value_type&)`.
|
||||
Otherwise, `init` is converted to a JSON value and added using `push_back(basic_json&&)`.
|
||||
|
||||
!!! note "Single braced JSON value"
|
||||
|
||||
For a call such as `#!cpp arr.push_back({obj})`, where the initializer list contains a single JSON value `obj`,
|
||||
compilers may disagree unless
|
||||
[`JSON_BRACE_INIT_COPY_SEMANTICS`](../macros/json_brace_init_copy_semantics.md) is defined to `1`: GCC, for
|
||||
example, selects this overload and appends a single-element array `[obj]`, whereas Clang selects the
|
||||
`basic_json` overload and appends a copy of `obj`. With the macro, GCC and Clang both append a copy of `obj`.
|
||||
To get a portable result without the macro, write `#!cpp arr.push_back(obj)` to append a copy, or
|
||||
`#!cpp arr.push_back(json::array({obj}))` to append a single-element array.
|
||||
|
||||
## Iterator invalidation
|
||||
|
||||
For all cases where an element is added to an **array**, a reallocation can happen, in which case all iterators (including
|
||||
|
||||
@@ -60,11 +60,9 @@ String values are stored as pointers in a `basic_json` type. That is, for any ac
|
||||
When converting a string value from one `basic_json` specialization to another via the
|
||||
[converting constructor](basic_json.md) (overload 4), the target `string_t` must be directly
|
||||
constructible from the source `basic_json`'s `string_t` type. If this requirement is not met, the
|
||||
conversion depends on the source string type. If it is a range of characters, the string is converted as an array of
|
||||
character codes, which is incorrect: the converting constructor's [`JSON_ASSERT`](../macros/json_assert.md) fails; with
|
||||
its default definition, `assert`, the program aborts unless `NDEBUG` is defined, in which case the array is returned.
|
||||
If the source string type is not a range of characters, the conversion does not compile at all. See
|
||||
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||
conversion does not fail; instead, the string is silently converted as an array of character codes,
|
||||
which is incorrect. See [issue #3425](https://github.com/nlohmann/json/issues/3425) for details
|
||||
and an example.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -111,9 +111,8 @@ points apply to every edit:
|
||||
the end, and, with [`number_format::source`](../basic_json_view/number_format.md), keeps the spelling of every
|
||||
number that was not itself edited — see [Editing a document](../../features/json_view/editing.md) for
|
||||
why this matters.
|
||||
- [`read()`](read.md) discards all edits (so its `input` must not be a string obtained from this document),
|
||||
[`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once there are edits, and
|
||||
[`memory_usage()`](memory_usage.md) includes the memory edits use.
|
||||
- [`read()`](read.md) discards all edits, [`shrink_to_fit()`](shrink_to_fit.md) does not move the node index once
|
||||
there are edits, and [`memory_usage()`](memory_usage.md) includes the memory edits use.
|
||||
[`source_offset()`](../basic_json_view/source_offset.md) of a value introduced by an edit is
|
||||
`#!cpp static_cast<std::size_t>(-1)`, the same value it reports for a decoded string.
|
||||
|
||||
|
||||
@@ -113,12 +113,11 @@ How thoroughly `load()` validates `image` before trusting it.
|
||||
`full` (the default)
|
||||
: Checks everything the parser itself guarantees: structure and bounds; that every string is valid UTF-8 (and, for a
|
||||
string still in the source text, that it contains no quote, backslash, or control character); and that every number
|
||||
token is well-formed and matches the value stored for it, and has the type the parser gives it (a float node only
|
||||
for a token with a fraction or an exponent, or an integer that does not fit 64 bits). Strings and float tokens may
|
||||
share a range only if the ranges are identical (as nodes that share a value do), and never overlap otherwise.
|
||||
Reading and serializing a checked image is safe and always produces valid JSON, exactly as for a parsed document.
|
||||
This is the right choice for an image from anything you do not fully control — a file, a cache shared with other
|
||||
processes, a peer on the network.
|
||||
token is well-formed and matches the value stored for it. Strings and float tokens may share a range only if the
|
||||
ranges are identical (as nodes that share a value do), and never overlap otherwise. Reading and serializing a
|
||||
checked image is safe and always produces valid JSON, exactly as for a parsed document. This is the right choice for
|
||||
an image from anything you do not fully control — a file, a cache shared with other processes, a peer on the
|
||||
network.
|
||||
|
||||
`bounds`
|
||||
: Checks structure and bounds only: that every offset and count in the node index stays inside the image. So
|
||||
|
||||
@@ -46,34 +46,6 @@ Linear in the length of the input.
|
||||
Every view taken from `#!cpp *this` before the call — including the previous [`root()`](root.md) — is invalidated,
|
||||
whether or not the new parse succeeds; take fresh views from [`root()`](root.md) afterward.
|
||||
|
||||
!!! warning "`input` must not point into the document itself"
|
||||
|
||||
`read()` releases the document's previous text, its decoded strings, and (for an editable document) its edits
|
||||
*before* it parses `input`. An `input` that is, or points into, any of them violates a precondition: it may seem to
|
||||
work, parse empty or garbled text, be reported by a sanitizer, or read freed memory (undefined behavior).
|
||||
|
||||
This applies to every `string_view` obtained from the document whose characters live in memory that `read()`
|
||||
releases:
|
||||
|
||||
- [`source()`](source.md) of a document that owns its text;
|
||||
- [`get_string()`](../basic_json_view/get_string.md) (also as `get<string_view_t>()` or a `string_view` member of a
|
||||
decoded struct) of a string with escapes, of a string of a document that owns its text, and of an edited string;
|
||||
- [`number_token()`](../basic_json_view/number_token.md) of a number of a document that owns its text, and of a
|
||||
number written by an edit;
|
||||
- the key of an object member (`key()`) if it has escapes, was written by an edit, or the document owns its text.
|
||||
|
||||
It does not apply to a text that the caller owns and the document borrows, nor to the strings, keys, and tokens that
|
||||
are read from such a text unchanged, nor to the decoded strings of a borrowed [image](load.md), which live in the
|
||||
caller's image: `read()` never touches them. To parse JSON that a document holds in a string of its own (for
|
||||
example, JSON embedded in a string value), copy the string first, for example with
|
||||
`#!cpp std::string inner(doc.root()["payload"].get_string()); doc.read(inner);`.
|
||||
|
||||
A debug build (one without `NDEBUG`) checks this with `assert()`: an `input` in the document's text, decoded
|
||||
strings, or image, or in the most recent buffer of strings written by edits, ends the program. (Strings written
|
||||
by earlier edits are not covered.) A release build does not check, to keep the cost of reusing a document at a
|
||||
minimum. The check uses `assert()` directly, not [`JSON_ASSERT`](../macros/json_assert.md), which `json.hpp`
|
||||
undefines at its end.
|
||||
|
||||
`input` is borrowed or owned by the same rules as [`parse()`](parse.md#notes); a document can borrow on one call and
|
||||
own on the next, since ownership is decided freshly each time. An input that is copied (see the table in
|
||||
[`parse()`](parse.md#notes)) is written into the document's previous owned copy, reusing its memory; a moved-in
|
||||
|
||||
@@ -24,9 +24,6 @@ Constant.
|
||||
For a borrowed document, `source()` points directly into the caller's buffer, so it is only valid while that buffer
|
||||
is; see [`owns_source`](owns_source.md).
|
||||
|
||||
The text of a document that owns it must not be passed to [`read()`](read.md) of the same document: `read()` releases
|
||||
an owned text before it parses its input. Copy it first. (A borrowed text belongs to the caller and is not affected.)
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -48,11 +48,8 @@ Strong exception safety: if an exception is thrown, there are no changes to the
|
||||
|
||||
May throw `#!cpp std::bad_alloc` if allocating the output string fails. Unlike
|
||||
[`BasicJsonType::dump`](../basic_json/dump.md), there is no `error_handler` parameter and no
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316): the parser validated the text the view
|
||||
holds as UTF-8, so there is nothing to replace or ignore. Only a document loaded with
|
||||
[`image_check::bounds` or `image_check::none`](../basic_json_document/load.md#image_check) can still throw it: these do
|
||||
not check the strings, so `dump()` writes such a string as it is, which can be invalid UTF-8 or invalid JSON, and
|
||||
`dump()` with `ensure_ascii` set to `#!cpp true` throws `type_error.316` for invalid UTF-8.
|
||||
[`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316): the view only ever holds text the parser
|
||||
already validated as UTF-8, so there is nothing to replace or ignore.
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -46,10 +46,6 @@ The returned [`string_view_t`](index.md#member-types) is valid exactly as long a
|
||||
source text, which for a borrowed document must remain valid **and unmodified** for as long as the document exists,
|
||||
since floating-point values and unescaped strings are read from the source lazily.
|
||||
|
||||
A string with escapes, a string of a document that owns its text, and an edited string must not be passed to
|
||||
[`read()`](../basic_json_document/read.md) of the document it came from: `read()` releases them before it parses its
|
||||
input. Copy the string first. (A string read unchanged from a borrowed text is not affected.)
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
@@ -38,14 +38,9 @@ by the grammar; trailing zeros in the fraction; the case and sign of the exponen
|
||||
useful precisely where that form must survive — a price or an identifier that must be reproduced exactly, or a
|
||||
number too large for any of `BasicJsonType`'s number types to hold without loss.
|
||||
|
||||
The returned [`string_view_t`](index.md#member-types) points into the document's
|
||||
[`source()`](../basic_json_document/source.md) text or, for a number written by an
|
||||
[edit](../basic_json_document/index.md#edits), into storage owned by the document (the token of an edited `NaN` is
|
||||
`nan`). It is valid exactly as long as that text or storage is, see the [validity rules](index.md) of
|
||||
`basic_json_view`. Numbers are never decoded into the document's separate string buffer.
|
||||
|
||||
For the same reason, the token must not be passed to [`read()`](../basic_json_document/read.md) of the document it came
|
||||
from if that document owns its text or the number was written by an edit: `read()` releases both before it parses.
|
||||
The returned [`string_view_t`](index.md#member-types) always points into the document's
|
||||
[`source()`](../basic_json_document/source.md) text — numbers are never decoded into the document's separate string
|
||||
buffer — and is valid exactly as long as that text is, see the [validity rules](index.md) of `basic_json_view`.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -57,9 +57,7 @@ compared. Two arrays of different [`size()`](size.md) are rejected without visit
|
||||
Only a single number, boolean, or `#!cpp null` value is ever materialized into a `BasicJsonType`, to reuse its
|
||||
`operator==` — for numbers, so that values written differently in the source text but equal in value (e.g. an
|
||||
integer and a floating-point literal) still compare equal, following the same rules `BasicJsonType` does for special
|
||||
values such as `#!cpp NaN`: a `#!cpp NaN` that an [edit](../basic_json_document/set.md) wrote is not equal to itself, so
|
||||
a view of it is not equal to itself either, nor is a view of an array or object that contains one, as for
|
||||
`BasicJsonType`. Constructing one of these scalars never allocates. Strings are compared directly, without
|
||||
values such as `#!cpp NaN`. Constructing one of these scalars never allocates. Strings are compared directly, without
|
||||
allocating, either from the source text on both sides or, for overload 2, against `BasicJsonType`'s own string.
|
||||
Arrays and objects are never materialized at all; only their elements or members are visited, one pair at a time.
|
||||
|
||||
|
||||
@@ -40,8 +40,6 @@ header. See also the [macro overview page](../../features/macros.md).
|
||||
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||
- [**JSON_NO_SIMD**](json_no_simd.md) - use only portable code instead of vector instructions (SSE2, SSSE3, NEON)
|
||||
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||
- [**JSON_RECURSION_DEPTH_LIMIT**](json_recursion_depth_limit.md) - set how many nesting levels the operations on a value
|
||||
recurse into on the call stack (default 128)
|
||||
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
||||
- [**JSON_USE_GLOBAL_UDLS**](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||
- [**JSON_USE_SIMDUTF**](json_use_simdutf.md) - use the simdutf library to accelerate UTF-8 validation
|
||||
|
||||
@@ -27,13 +27,9 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
json j{obj};
|
||||
```
|
||||
|
||||
creates a single-element **array** `[{"key":"value"}]` instead of a copy of `obj`. For this constructor, the
|
||||
behavior was compiler-dependent for older compilers (GCC wrapped, Clang did not), but starting from Clang 20, both
|
||||
compilers behave the same way.
|
||||
|
||||
The calls `#!cpp arr.push_back({obj})` and `#!cpp arr += {obj}` are still compiler-dependent without the macro,
|
||||
even with Clang 20 and later: GCC converts `{obj}` to a single-element array and appends that array, whereas Clang
|
||||
appends a copy of `obj`. With the macro defined to `1`, both compilers append a copy of `obj`.
|
||||
creates a single-element **array** `[{"key":"value"}]` instead of a copy of `obj`. This behavior is
|
||||
compiler-dependent for older compilers (GCC wrapped, Clang did not), but starting from Clang 20, both compilers
|
||||
behave the same way.
|
||||
|
||||
Enabling this macro opts into copy/move semantics for this case
|
||||
(see [#5074](https://github.com/nlohmann/json/issues/5074)).
|
||||
|
||||
@@ -45,7 +45,6 @@ Copying and comparing fall back to working without the call stack there, as they
|
||||
|
||||
## See also
|
||||
|
||||
- [`JSON_RECURSION_DEPTH_LIMIT`](json_recursion_depth_limit.md) - set how many nesting levels the operations recurse into
|
||||
- [FAQ: Thread safety](../../home/faq.md#thread-safety) - thread-safety guarantees of the library
|
||||
- [Supported Macros](../../features/macros.md) - guide to all supported macros
|
||||
|
||||
|
||||
@@ -1,307 +0,0 @@
|
||||
# JSON_RECURSION_DEPTH_LIMIT
|
||||
|
||||
```cpp
|
||||
#define JSON_RECURSION_DEPTH_LIMIT /* value */
|
||||
```
|
||||
|
||||
This macro sets how many nesting levels the operations that walk a value recurse into on the call stack. Beyond that,
|
||||
they continue with an explicit stack on the heap. The value is an integer constant from `0` to `254`; the default is
|
||||
`128`.
|
||||
|
||||
The operations are copying a value, comparing two values, serializing with [`dump`](../basic_json/dump.md) or
|
||||
[`operator<<`](../operator_ltlt.md), hashing with `std::hash`, [`merge_patch`](../basic_json/merge_patch.md),
|
||||
[`update`](../basic_json/update.md) with `merge_objects`, [`diff`](../basic_json/diff.md),
|
||||
[`merge_diff`](../basic_json/merge_diff.md), converting a value to another specialization of `basic_json`, destroying a
|
||||
value, and the binary writers [`to_cbor`](../basic_json/to_cbor.md),
|
||||
[`to_msgpack`](../basic_json/to_msgpack.md), [`to_ubjson`](../basic_json/to_ubjson.md),
|
||||
[`to_bjdata`](../basic_json/to_bjdata.md), and [`to_bon8`](../basic_json/to_bon8.md). They share this one limit; none
|
||||
has
|
||||
a limit of its own. Recursing is the fastest way to walk a value, but a value nested deeply enough would exhaust the
|
||||
call
|
||||
stack, so the library recurses only as far as the limit and finishes the levels below with an explicit stack. This is
|
||||
what makes all of them safe for untrusted input
|
||||
(see [Nesting depth](../../features/parsing/untrusted_input.md#nesting-depth)). Parsing, the binary readers,
|
||||
[`flatten`](../basic_json/flatten.md), [`unflatten`](../basic_json/unflatten.md), and
|
||||
[`to_bson`](../basic_json/to_bson.md) always use an explicit stack and do not depend on the macro. The lockstep
|
||||
comparison of two [`json_view`](../basic_json_view/index.md) documents has a fixed bound of its own, 48 levels,
|
||||
and does not depend on it either.
|
||||
|
||||
The call stack that these operations need grows with the limit: roughly *a few kilobytes plus a cost per level times the
|
||||
limit*, where the cost per level is up to about 2.3 KiB in an unoptimized and up to about 0.5 KiB in an optimized build
|
||||
(see [Stack needed](#stack-needed)). The default of `128` levels is tuned for threads with ordinary stacks of a few
|
||||
hundred kilobytes or more. Set a lower limit if your threads have small stacks (RTOS tasks, fibers, threads of the musl
|
||||
C
|
||||
library, which has a default stack of 128 KiB), or a higher limit to trade stack for speed on deeply nested values.
|
||||
|
||||
The macro changes only how much stack is used and how fast the operations are. It never changes a result: every
|
||||
operation returns the same value for every setting of the limit, for values nested less deeply than the limit as well as
|
||||
for values nested more deeply.
|
||||
|
||||
## Default definition
|
||||
|
||||
The default value is `128`.
|
||||
|
||||
```cpp
|
||||
#define JSON_RECURSION_DEPTH_LIMIT 128
|
||||
```
|
||||
|
||||
When the macro is not defined, the library defines it to its default value.
|
||||
|
||||
## Notes
|
||||
|
||||
!!! note "Allowed values"
|
||||
|
||||
The value must be an integer constant expression from `0` to `254`; any other value (a negative number, a number
|
||||
above `254`, a floating-point number such as `254.0`, or `true` or `false`) is rejected at compile time with an
|
||||
error message that names the macro. A character of any character type (`'a'`, `L'a'`, `u8'a'`, ...) is rejected,
|
||||
too, although it is an integer.
|
||||
|
||||
- `0` is allowed, and means that every operation uses its explicit stack from the first level on and no operation
|
||||
recurses over the nesting of a value at all. That needs a constant amount of call stack (at most 16 KiB in the
|
||||
measurements below, for a value nested 20,000 levels deep) and is the setting for tiny stacks, at the price of
|
||||
speed (see [Speed](#speed)).
|
||||
- `254` is the largest allowed value. Copying a value and comparing two values (with `<=>`, or with the operators on
|
||||
objects and arrays of a custom type) cannot pass the depth down as an argument, because the signatures of the
|
||||
copy constructor and the operators are fixed. They count the levels they have descended into in a variable of type
|
||||
`#!cpp std::uint8_t` that exists once per thread (see [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md)). Only
|
||||
the levels that are descended into are counted, so the count never exceeds the limit, not even when user code (a
|
||||
copy constructor of a custom base class, say) copies a value while a copy is going on. A byte holds `255` at
|
||||
most, and the limit stays below that, so that the count cannot wrap around. (More levels would hardly be
|
||||
useful: `254` levels need up to 576 KiB of stack in an unoptimized build already, twice as much as the
|
||||
default.)
|
||||
|
||||
### Stack needed
|
||||
|
||||
The tables show the smallest stack that an operation needs, in KiB, at several limits, on a value that is nested
|
||||
more deeply than the limit (limit + 10 levels). Each cell shows the result for Clang (Apple clang 21) and for
|
||||
GCC 16, separated by a slash; both measured on macOS with arm64, compiling in C++20 mode. The operations run in a
|
||||
thread whose stack has the size given, and are not given any stack that they do not need: the value is built, and
|
||||
the result destroyed, outside of that thread. Stacks can only be set in steps of 16 KiB (the page size), so `16`
|
||||
means "16 KiB or less". A row stands for all operations listed; the table shows the largest value among them.
|
||||
|
||||
Unoptimized (`-O0`):
|
||||
|
||||
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| `dump()` and `dump(indent)`, `operator<<` | 48 / 32 | 80 / 64 | 144 / 128 | 288 / 256 | 576 / 512 |
|
||||
| copy construction and assignment | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
|
||||
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 48 |
|
||||
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 | 144 / 128 |
|
||||
| `std::hash` | 16 / 16 | 16 / 16 | 32 / 32 | 80 / 64 | 160 / 128 |
|
||||
| `merge_patch`, `update(j, true)`, `patch` | 32 / 16 | 48 / 32 | 112 / 80 | 224 / 144 | 432 / 304 |
|
||||
| `diff` | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 | 144 / 96 |
|
||||
| `merge_diff` | 16 / 16 | 48 / 32 | 80 / 48 | 176 / 112 | 352 / 224 |
|
||||
| `to_cbor`, `to_msgpack` | 16 / 16 | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 160 |
|
||||
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 | 176 / 112 |
|
||||
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 16 | 64 / 48 |
|
||||
| conversion to another `basic_json` type | 32 / 16 | 64 / 32 | 112 / 80 | 224 / 144 | 448 / 304 |
|
||||
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
|
||||
|
||||
Optimized (`-O2`):
|
||||
|
||||
| Operation | limit 16 | limit 32 | limit 64 | limit 128 | limit 254 |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| `dump()` and `dump(indent)`, `operator<<` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 |
|
||||
| copy construction and assignment | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 |
|
||||
| `==` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
| `<=>` (C++20) | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 16 |
|
||||
| `std::hash` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 48 | 80 / 80 |
|
||||
| `merge_patch`, `update(j, true)`, `patch` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 48 |
|
||||
| `diff` | 16 / 16 | 16 / 16 | 16 / 32 | 48 / 48 | 96 / 112 |
|
||||
| `merge_diff` | 16 / 16 | 16 / 16 | 16 / 16 | 48 / 32 | 96 / 64 |
|
||||
| `to_cbor`, `to_msgpack` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
| `to_ubjson`, `to_bjdata` | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 32 | 64 / 64 |
|
||||
| `to_bon8` | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 32 | 32 / 64 |
|
||||
| conversion to another `basic_json` type | 16 / 16 | 16 / 16 | 16 / 16 | 32 / 48 | 64 / 96 |
|
||||
| destruction | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 | 16 / 16 |
|
||||
|
||||
With a limit of `0`, every operation in the tables ran in a 16 KiB stack at `-O0` (Clang and GCC), on a value nested
|
||||
20,000 levels deep. The operations that do not depend on the macro (`flatten`, `unflatten`, `to_bson`) needed
|
||||
16 KiB or less at every limit.
|
||||
|
||||
The rule of thumb is
|
||||
|
||||
> stack needed ≈ a few KiB + cost per level × limit
|
||||
|
||||
with a cost per level of up to 2.3 KiB (`dump` at `-O0` with Clang; 2.1 KiB with GCC), 1.7 KiB for copying and merging
|
||||
(1.3 KiB with GCC), and 0.1 to 0.5 KiB for most other operations at `-O0`; and 0.5 KiB or less at `-O2`. The numbers
|
||||
come from the difference between the limits `128` and `254` in the tables, so they are rough: other compilers,
|
||||
other targets (the frames of x86-64 code are about as large), other standard libraries, `JSON_DIAGNOSTICS`, and
|
||||
sanitizers change them. Measure with your own tool chain (see the example below) rather than relying on the tables.
|
||||
The stack that your own code and the operating system need comes on top of these numbers.
|
||||
|
||||
Which limit to choose, for the stack that you can spare for the library (the largest limit of those measured
|
||||
for which the slowest operation needs at most that much):
|
||||
|
||||
| Stack for the library | optimized (`-O2`) | unoptimized (`-O0`) |
|
||||
|---|---:|---:|
|
||||
| 32 KiB | 64 | 0 |
|
||||
| 64 KiB | 128 | 16 |
|
||||
| 128 KiB (the default stack of threads on musl) | 254 | 32 |
|
||||
| 256 KiB | 254 | 64 |
|
||||
| 512 KiB | 254 | 128 |
|
||||
| 1 MiB or more | 254 | 254 |
|
||||
|
||||
### Speed
|
||||
|
||||
Operations are faster the more of a value they handle with plain recursion. The levels below the limit are handled with
|
||||
an explicit stack, which has to be kept on the heap and costs more per level. The macro therefore trades speed against
|
||||
stack.
|
||||
|
||||
The table shows the time of copying a value (including destroying the copy), of `==` on two equal values, of `dump`, and
|
||||
of `std::hash` for several limits, relative to the default of `128` (`1.00` means the same time; more is slower). It was
|
||||
measured with Clang 21 at `-O2` in C++17 mode on macOS with arm64, as the best of seven runs of each setting (two
|
||||
rounds, best of both). The documents are ordinary JSON files that are nested 7 (`canada.json`), 8
|
||||
(`citm_catalog.json`), 10 (`twitter.json`), and 2 levels deep (`jeopardy.json`); the other values are one array or object
|
||||
with one member per level, nested 1,000 and 100,000 levels deep. The absolute time at the limit `128` is given in the
|
||||
third column. Differences of up to about 0.1 are noise: a different limit changes the layout of the compiled code, and
|
||||
timings of the same binary vary by about as much. The slow columns (limits 0 and 1) vary more: repeating `std::hash` on
|
||||
`canada.json` gave 1.27 to 1.30 for limit 0 and 1.4 to 1.9 for limit 1, so read the cells of those two columns as
|
||||
accurate to about 0.3.
|
||||
|
||||
| Value | Operation | limit 128 (absolute) | limit 0 | limit 1 | limit 16 | limit 254 |
|
||||
|---|---|---:|---:|---:|---:|---:|
|
||||
| `canada.json` (2.1 MB) | copy | 3.5 ms | 1.80 | 1.80 | 0.99 | 1.00 |
|
||||
| `canada.json` (2.1 MB) | `==` | 350.5 µs | 2.36 | 2.38 | 1.00 | 0.99 |
|
||||
| `canada.json` (2.1 MB) | `dump` | 2.4 ms | 1.11 | 1.11 | 1.00 | 1.00 |
|
||||
| `canada.json` (2.1 MB) | `std::hash` | 920.2 µs | 1.33 | 1.59 | 1.00 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | copy | 1.8 ms | 1.38 | 1.36 | 1.00 | 0.99 |
|
||||
| `citm_catalog.json` (1.7 MB) | `==` | 275.5 µs | 1.31 | 1.31 | 0.99 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | `dump` | 314.6 µs | 1.24 | 1.23 | 1.00 | 1.00 |
|
||||
| `citm_catalog.json` (1.7 MB) | `std::hash` | 309.1 µs | 1.77 | 1.42 | 1.06 | 1.05 |
|
||||
| `twitter.json` (0.6 MB) | copy | 865.7 µs | 1.45 | 1.47 | 1.01 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `==` | 135.8 µs | 1.26 | 1.23 | 1.00 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `dump` | 224.6 µs | 1.12 | 1.12 | 1.01 | 1.00 |
|
||||
| `twitter.json` (0.6 MB) | `std::hash` | 132.9 µs | 1.28 | 1.27 | 1.03 | 1.04 |
|
||||
| `jeopardy.json` (53 MB) | copy | 111.1 ms | 1.22 | 1.25 | 1.00 | 1.00 |
|
||||
| `jeopardy.json` (53 MB) | `==` | 23.5 ms | 1.29 | 1.53 | 1.07 | 1.00 |
|
||||
| `jeopardy.json` (53 MB) | `dump` | 33.2 ms | 1.14 | 1.34 | 1.03 | 1.01 |
|
||||
| `jeopardy.json` (53 MB) | `std::hash` | 19.9 ms | 1.17 | 1.52 | 1.05 | 1.00 |
|
||||
| arrays, 1,000 levels | copy | 69.9 µs | 0.95 | 0.98 | 0.92 | 0.99 |
|
||||
| arrays, 1,000 levels | `==` | 10.4 µs | 1.02 | 1.01 | 0.96 | 1.00 |
|
||||
| arrays, 1,000 levels | `dump` | 9.6 µs | 0.97 | 0.96 | 0.97 | 1.06 |
|
||||
| arrays, 1,000 levels | `std::hash` | 16.9 µs | 1.00 | 1.01 | 1.01 | 0.98 |
|
||||
| objects, 1,000 levels | copy | 77.1 µs | 0.98 | 0.97 | 0.97 | 1.03 |
|
||||
| objects, 1,000 levels | `==` | 12.0 µs | 0.96 | 0.95 | 0.95 | 1.07 |
|
||||
| objects, 1,000 levels | `dump` | 12.6 µs | 0.97 | 0.95 | 0.98 | 1.01 |
|
||||
| objects, 1,000 levels | `std::hash` | 17.3 µs | 0.99 | 1.01 | 0.98 | 1.00 |
|
||||
| arrays, 100,000 levels | copy | 6.4 ms | 1.00 | 1.00 | 1.00 | 1.00 |
|
||||
| arrays, 100,000 levels | `==` | 1.1 ms | 1.01 | 1.03 | 1.00 | 1.06 |
|
||||
| arrays, 100,000 levels | `dump` | 917.9 µs | 1.01 | 1.01 | 1.02 | 1.01 |
|
||||
| arrays, 100,000 levels | `std::hash` | 1.7 ms | 1.04 | 1.05 | 0.99 | 0.99 |
|
||||
| objects, 100,000 levels | copy | 7.5 ms | 0.99 | 1.02 | 1.01 | 0.99 |
|
||||
| objects, 100,000 levels | `==` | 1.3 ms | 1.02 | 1.09 | 1.08 | 0.96 |
|
||||
| objects, 100,000 levels | `dump` | 1.2 ms | 1.06 | 0.99 | 1.01 | 0.99 |
|
||||
| objects, 100,000 levels | `std::hash` | 1.8 ms | 1.00 | 1.00 | 1.00 | 1.00 |
|
||||
|
||||
The results are as follows.
|
||||
|
||||
- A limit of `16` or more does not change the speed of ordinary documents (differences are within noise), because they
|
||||
are not nested more deeply than that anyway. A document nested more deeply than the limit is walked partly with the
|
||||
explicit stack.
|
||||
- A limit of `0` or `1` makes the operations on ordinary documents 1.1 to 2.4 times as slow, because even their first
|
||||
levels are handled with the explicit stack. The slowdown is largest for `==` on a document of many small containers
|
||||
(`canada.json`: 2.4 times) and for copying (up to 1.8 times).
|
||||
- For values that are nested far more deeply than any limit (1,000 and 100,000 levels deep), the limit makes no
|
||||
measurable difference: almost all of the levels are handled with the explicit stack for every setting.
|
||||
Raising the limit gains nothing for them, and lowering it costs nothing.
|
||||
|
||||
!!! note "Other macros"
|
||||
|
||||
- With [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md) defined (or for Clang targeting MinGW, where the library
|
||||
defines it by itself), copying and comparing never descend, so for them the limit does not matter. The other
|
||||
operations still recurse as many levels as the limit says. The range of the limit is the same.
|
||||
- The macro is not part of the [ABI tag](../../features/namespace.md), as `JSON_NO_THREAD_LOCAL` is not, and it is
|
||||
not undefined at the end of `json.hpp`.
|
||||
|
||||
!!! warning "Use the same value in every translation unit"
|
||||
|
||||
All translation units of a program that include the library must define the same value. Otherwise, the program
|
||||
violates the One Definition Rule: the function `nlohmann::detail::recursion_depth_limit()` and all the functions
|
||||
that use it are defined differently in different translation units. Which limit a call uses then depends on which
|
||||
functions the compiler inlined (an inlined copy uses the value of its own translation unit) and which out-of-line
|
||||
copy of each remaining function the linker kept, which is not specified. A function compiled with one value can
|
||||
call a function compiled with another, so a single operation can mix both limits.
|
||||
|
||||
Mixing values cannot corrupt the byte per thread that counts the levels of copying and comparing: each limit
|
||||
is at most `254`, and all of them stop counting at their own limit, so the count never exceeds `254`, whichever
|
||||
translation unit's definition runs. The counter exists once per thread and `basic_json` specialization, and is
|
||||
shared by all translation units. Nor can mixing values change any result, as no result depends on the limit. What
|
||||
changes is how much stack is used and how fast the operations are. Nevertheless, avoid it: the program has undefined
|
||||
behavior as far as the C++ standard is concerned.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: lower the limit"
|
||||
|
||||
The example nests an array 5,000 levels deep. With the limit set to 16, the library recurses over the first 16
|
||||
levels
|
||||
and over the rest uses an explicit stack. The results are those of the default limit.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/json_recursion_depth_limit.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
--8<-- "examples/json_recursion_depth_limit.output"
|
||||
```
|
||||
|
||||
??? example "Example: find out how much stack an operation needs"
|
||||
|
||||
The program runs `dump()` on a value nested `depth` levels deep in a thread with a stack of `kib` KiB. Compile it
|
||||
with the options and the limit that you use, e.g. `-DJSON_RECURSION_DEPTH_LIMIT=64`, run it with `depth` set to the
|
||||
limit plus 10 and decreasing values of `kib` (the stack size must be a multiple of the page size, often 4 or 16
|
||||
KiB),
|
||||
and note the smallest stack with which it still finishes. That is how the tables above were measured.
|
||||
|
||||
```cpp
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <pthread.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
static nlohmann::json value;
|
||||
|
||||
static void* run(void*)
|
||||
{
|
||||
std::cout << "dump() ok, " << value.dump().size() << " bytes\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const int depth = std::atoi(argv[1]);
|
||||
const std::size_t kib = static_cast<std::size_t>(std::atoi(argv[2]));
|
||||
|
||||
// built on the main thread, without recursion
|
||||
value = 1;
|
||||
for (int i = 0; i < depth; ++i)
|
||||
{
|
||||
nlohmann::json outer = nlohmann::json::array();
|
||||
outer.push_back(std::move(value));
|
||||
value = std::move(outer);
|
||||
}
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, kib * 1024);
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, &attr, run, nullptr);
|
||||
pthread_join(thread, nullptr);
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Nesting depth](../../features/parsing/untrusted_input.md#nesting-depth) - how the library handles deeply nested
|
||||
values
|
||||
- [`JSON_NO_THREAD_LOCAL`](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||
- [Supported Macros](../../features/macros.md) - guide to all supported macros
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -93,7 +93,7 @@ The default value is `0` (disabled, the behavior of version 3.12.0 and earlier i
|
||||
## See also
|
||||
|
||||
- [Binary formats](../../features/binary_formats/index.md) - overview of the supported binary formats
|
||||
- [`from_cbor`](../basic_json/from_cbor.md) - not affected by the macro; pass `error_handler` to validate CBOR strings
|
||||
- [`from_cbor`](../basic_json/from_cbor.md) - also affected when parsing CBOR strings
|
||||
- [`to_cbor`](../basic_json/to_cbor.md) - create a CBOR serialization of a JSON value
|
||||
- [`to_ubjson`](../basic_json/to_ubjson.md) - create a UBJSON serialization of a JSON value
|
||||
- [`to_bjdata`](../basic_json/to_bjdata.md) - create a BJData serialization of a JSON value
|
||||
|
||||
@@ -53,15 +53,12 @@ flowchart LR
|
||||
only as bytes are actually read, arrays reserve at most a fixed number of elements up front, and sizes that no
|
||||
container can hold are rejected.
|
||||
- **Memory is owned by values.** Each `basic_json` value owns its content, and there is no manual memory management in
|
||||
user code. The destructor recurses only over a bounded number of nesting levels and then continues without the call
|
||||
stack, so destroying a deeply nested value does not exhaust the stack.
|
||||
user code. The destructor does not recurse, so destroying a deeply nested value does not exhaust the stack.
|
||||
- **Bounded recursion.** The JSON parser and the binary readers keep their state in explicit stacks instead of
|
||||
recursing per nesting level. Operations that walk a value, such as [`dump`](../api/basic_json/dump.md), copying,
|
||||
comparison, hashing, [`merge_patch`](../api/basic_json/merge_patch.md), [`diff`](../api/basic_json/diff.md),
|
||||
[`flatten`](../api/basic_json/flatten.md), and the binary writers, recurse only up to a fixed depth and continue with
|
||||
an explicit stack below it. The depth is 128 levels by default and can be changed with
|
||||
[`JSON_RECURSION_DEPTH_LIMIT`](../api/macros/json_recursion_depth_limit.md), for example to run on a small stack.
|
||||
Applications that process untrusted input can limit its nesting depth with a
|
||||
an explicit stack below it. Applications that process untrusted input can limit its nesting depth with a
|
||||
[parser callback](../features/parsing/parser_callbacks.md).
|
||||
- **Invariants are checked.** The class invariant (for instance, that the pointer for the stored type is never null) is
|
||||
checked with runtime assertions throughout the test suite.
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
// walk over at most 16 nesting levels on the call stack, and over the rest with an explicit stack
|
||||
#define JSON_RECURSION_DEPTH_LIMIT 16
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
// an array nested 5,000 levels deep, built without recursion
|
||||
json j = 1;
|
||||
for (int i = 0; i < 5000; ++i)
|
||||
{
|
||||
json outer = json::array();
|
||||
outer.push_back(std::move(j));
|
||||
j = std::move(outer);
|
||||
}
|
||||
|
||||
// the results are those of any other limit
|
||||
const json copy = j;
|
||||
std::cout << std::boolalpha;
|
||||
std::cout << "limit: " << JSON_RECURSION_DEPTH_LIMIT << '\n';
|
||||
std::cout << "copy equals original: " << (copy == j) << '\n';
|
||||
std::cout << "length of dump(): " << j.dump().size() << '\n';
|
||||
std::cout << "same hash: " << (std::hash<json> {}(copy) == std::hash<json> {}(j)) << '\n';
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
limit: 16
|
||||
copy equals original: true
|
||||
length of dump(): 10001
|
||||
same hash: true
|
||||
@@ -50,13 +50,6 @@ The same holds for what a view hands out without copying: a string from
|
||||
[`number_token()`](../../api/basic_json_view/number_token.md), and [`string_view` members](reading.md#string_view-members)
|
||||
of decoded structs are valid only as long as the document and, if it borrows, its source text.
|
||||
|
||||
This includes [`read()`](../../api/basic_json_document/read.md): it releases the document's text, decoded strings, and
|
||||
edits before it parses its input, so the input must not be a `string_view` obtained from the document itself: its
|
||||
[`source()`](../../api/basic_json_document/source.md), a string from `get_string()`, a token from `number_token()`, or a
|
||||
key from an iterator (those of a borrowed text that the caller owns, read unchanged, are not affected). To re-parse a
|
||||
string that the document holds, for example JSON embedded in a string value, copy the string into a `#!cpp std::string`
|
||||
first and pass the copy; see [`read()`](../../api/basic_json_document/read.md#notes) for the exact list.
|
||||
|
||||
??? example "Example: borrowed and owned documents, and when views become invalid"
|
||||
|
||||
```cpp
|
||||
|
||||
@@ -198,16 +198,6 @@ this is planned to become the default in version 4.0.0.
|
||||
|
||||
See [full documentation of `JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md).
|
||||
|
||||
## `JSON_RECURSION_DEPTH_LIMIT`
|
||||
|
||||
Sets the number of nesting levels that the operations walking a value (copying, comparing, serializing, hashing,
|
||||
merging, diffing, converting, destroying, and the binary writers) recurse into on the call stack before they continue
|
||||
with an explicit stack on the heap. The default is `128`; allowed are the integers from `0` to `254`. Lower it for
|
||||
threads with small stacks, raise it to trade stack for speed. Results are the same for every setting; the value must be
|
||||
the same in all translation units of a program.
|
||||
|
||||
See [full documentation of `JSON_RECURSION_DEPTH_LIMIT`](../api/macros/json_recursion_depth_limit.md).
|
||||
|
||||
## `JSON_SKIP_LIBRARY_VERSION_CHECK`
|
||||
|
||||
When defined, the library will not create a compiler warning when a different version of the library was already
|
||||
|
||||
@@ -36,21 +36,15 @@ Only the following symbols are exported from `nlohmann.json`:
|
||||
- `nlohmann::basic_json`
|
||||
- `nlohmann::basic_json_document`
|
||||
- `nlohmann::basic_json_view`
|
||||
- `nlohmann::is_json_view`
|
||||
- `nlohmann::json`
|
||||
- `nlohmann::json_document`
|
||||
- `nlohmann::json_editable_document`
|
||||
- `nlohmann::json_editable_view`
|
||||
- `nlohmann::json_pointer`
|
||||
- `nlohmann::json_view`
|
||||
- `nlohmann::ordered_json`
|
||||
- `nlohmann::ordered_json_document`
|
||||
- `nlohmann::ordered_json_editable_document`
|
||||
- `nlohmann::ordered_json_editable_view`
|
||||
- `nlohmann::ordered_json_view`
|
||||
- `nlohmann::ordered_map`
|
||||
- `nlohmann::to_string`
|
||||
- `nlohmann::view_mode`
|
||||
- `nlohmann::literals::json_literals::operator""_json`
|
||||
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
||||
|
||||
@@ -62,7 +56,6 @@ Additionally, the following `nlohmann::detail` symbols are exported, solely to w
|
||||
and should not be used directly:
|
||||
|
||||
- `nlohmann::detail::json_sax_dom_callback_parser`
|
||||
- `nlohmann::detail::json_sax_dom_parser`
|
||||
- `nlohmann::detail::unknown_size`
|
||||
|
||||
## Known issues
|
||||
|
||||
@@ -54,32 +54,10 @@ Once a value has been parsed, operations that walk it recursively — serializin
|
||||
[`dump`](../../api/basic_json/dump.md), hashing it, copying it, comparing two values with `#!cpp ==`, `#!cpp <`, or (in
|
||||
C++20) `#!cpp <=>`, merging with [`update`](../../api/basic_json/update.md), applying a
|
||||
[`merge_patch`](../../api/basic_json/merge_patch.md), creating a patch with [`diff`](../../api/basic_json/diff.md) or
|
||||
[`merge_diff`](../../api/basic_json/merge_diff.md), converting it to another `basic_json` type, destroying it, and the
|
||||
binary writers (`to_cbor`, `to_msgpack`, ...) — descend at most
|
||||
[`JSON_RECURSION_DEPTH_LIMIT`](../../api/macros/json_recursion_depth_limit.md) levels on the call stack, 128 by default,
|
||||
and continue below that with an explicit stack on the heap. So the call stack does not grow with the nesting depth of the
|
||||
value, however deeply it is nested. ([`flatten`](../../api/basic_json/flatten.md),
|
||||
[`unflatten`](../../api/basic_json/unflatten.md), and [`to_bson`](../../api/basic_json/to_bson.md) never use the call
|
||||
stack for the nesting.)
|
||||
|
||||
The call stack still needs room for the levels that are recursed into, and the default limit assumes a stack of ordinary
|
||||
size. The stack that an operation needs is roughly proportional to the limit; with the default of 128 levels, the most
|
||||
demanding operation (`dump` in an unoptimized build) needed up to 288 KiB, and an optimized build needed 48 KiB or less,
|
||||
in measurements on macOS with arm64. The most demanding operation needed this much stack at the limits `0`, `32`,
|
||||
`128`, and `254`:
|
||||
|
||||
| Stack needed, in KiB | limit 0 | limit 32 | limit 128 (default) | limit 254 |
|
||||
|---|---:|---:|---:|---:|
|
||||
| unoptimized build (`-O0`) | 16 or less | 80 | 288 | 576 |
|
||||
| optimized build (`-O2`) | 16 or less | 16 or less | 48 | 112 |
|
||||
|
||||
A thread with a smaller stack (a task of a real-time operating system, a fiber, or a thread of the musl C library, whose
|
||||
default stack is 128 KiB) can still overflow its stack on deeply nested input, which is why the limit can be lowered:
|
||||
define `JSON_RECURSION_DEPTH_LIMIT` to a smaller value, down to `0`, before including the library. Such a limit changes
|
||||
only the stack that is needed and the speed (values nested more deeply than the limit are walked more slowly), never a
|
||||
result. See the [documentation of the macro](../../api/macros/json_recursion_depth_limit.md) for the complete tables,
|
||||
the speed, and the rules for choosing a value. Destroying a value (its destructor) recurses over the same number of
|
||||
levels and then continues without the call stack, and needs 32 KiB or less at every limit.
|
||||
[`merge_diff`](../../api/basic_json/merge_diff.md), [`flatten`](../../api/basic_json/flatten.md), and the binary
|
||||
writers (`to_cbor`, `to_msgpack`, ...) — descend at most 128 levels on the call stack and continue
|
||||
below that with an explicit stack instead, so none of them can exhaust the stack either, however deeply the value is
|
||||
nested. Destroying a value (its destructor) never recurses at all, regardless of nesting depth, for the same reason.
|
||||
|
||||
## Input size
|
||||
|
||||
@@ -101,19 +79,15 @@ For the binary formats, an announced size is never trusted outright:
|
||||
|
||||
## Strings
|
||||
|
||||
Invalid UTF-8 is rejected while parsing JSON text, not just while serializing:
|
||||
Invalid UTF-8 is rejected while parsing, not just while serializing:
|
||||
|
||||
- In JSON text, an ill-formed UTF-8 byte in a string is a
|
||||
[`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) ("invalid string: ill-formed UTF-8 byte").
|
||||
- In UTF-16 or UTF-32 input, an ill-formed sequence is a
|
||||
[`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) as well: a lone surrogate, a high surrogate
|
||||
that is not followed by its low surrogate, and a code point above `U+10FFFF` are all rejected.
|
||||
|
||||
In a binary format, a string that is not valid UTF-8 is accepted unchanged by default (none of the formats except BON8
|
||||
requires a decoder to reject it). Pass [`error_handler_t::strict`](../../api/basic_json/error_handler_t.md) to the
|
||||
`from_*` function to get a [`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) instead. BON8
|
||||
always validates ([`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) for an ill-formed
|
||||
sequence).
|
||||
- In a binary format, a string that is not valid UTF-8 is a
|
||||
[`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113).
|
||||
|
||||
A `#!cpp '\0'` (NUL) byte *inside* a quoted JSON string is always rejected (it must be escaped as `\u0000`). A NUL byte
|
||||
*outside* of a string is different: by default it is silently treated as the end of the input, so trailing bytes after
|
||||
@@ -124,8 +98,8 @@ that happens to embed a NUL is a way to make part of it disappear without a pars
|
||||
unexpected byte instead.
|
||||
|
||||
Parsing is not the only place invalid UTF-8 matters: a string that reached a `#!cpp json` value some other way (for
|
||||
example, constructed by application code, or read from a binary format with the default `error_handler_t::keep`)
|
||||
still has to round-trip back to JSON text. By default,
|
||||
example, constructed by application code, or, before JSON_STRICT_NUL_HANDLING existed, read from a binary format that
|
||||
does not validate strings) still has to round-trip back to JSON text. By default,
|
||||
[`dump()`](../../api/basic_json/dump.md) throws [`type_error.316`](../../home/exceptions.md#jsonexceptiontype_error316)
|
||||
if the string is not valid UTF-8; passing
|
||||
[`error_handler_t::replace`](../../api/basic_json/error_handler_t.md) or `error_handler_t::ignore` avoids the exception
|
||||
@@ -178,8 +152,6 @@ indices (or the pointer as a whole) before using them, or use [`at`](../../api/b
|
||||
format lengths.
|
||||
- Decide up front how you want a string with invalid UTF-8 — from any source, not only parsing — to be serialized
|
||||
(`strict`, `replace`, or `ignore`), rather than discovering it from an uncaught `type_error.316`.
|
||||
- For untrusted input in a binary format, pass `error_handler_t::strict` to the `from_*` function if the strings must be
|
||||
valid UTF-8; by default they are not checked (BON8 always checks).
|
||||
- If a stray NUL byte silently truncating trailing input is a problem for your input format, define
|
||||
`JSON_STRICT_NUL_HANDLING`.
|
||||
- Decide whether duplicate object keys should be an error for your application, and add a callback if so.
|
||||
|
||||
@@ -28,16 +28,15 @@ Requirements are split into two groups:
|
||||
[`BinaryType`](#binarytype)'s `value_type`, and [`NumberUnsignedType`](#numberintegertype-and-numberunsignedtype)
|
||||
being at least as wide as [`NumberIntegerType`](#numberintegertype-and-numberunsignedtype). The rest are not
|
||||
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
||||
the library. Four violations are not (always) caught at compile time:
|
||||
the library. Four violations are not caught at compile time at all:
|
||||
|
||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers
|
||||
stored as a `#!cpp long double` that is not IEEE 754 binary64 (e.g., the 80-bit x87 format), because the lexer
|
||||
hands the buffer to `#!cpp std::strtold`.
|
||||
- A stateful [`AllocatorType`](#allocatortype) compiles and silently ignores its state: allocation, deallocation,
|
||||
and [`get_allocator()`](../../api/basic_json/get_allocator.md) each use a different default-constructed instance.
|
||||
- The two [cross-specialization conversions](#cross-specialization-conversions) below, when the source string type
|
||||
is a range of characters. They compile and fail the `#!cpp JSON_ASSERT`: with its default definition, the program
|
||||
aborts unless `#!cpp NDEBUG` is defined, in which case the wrong result is returned silently.
|
||||
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
||||
in a normal build, and only fail silently under `#!cpp NDEBUG`.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -426,7 +425,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
||||
| Type | Reason |
|
||||
|----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
|
||||
| `#!cpp std::wstring`, `#!cpp std::u16string`, `#!cpp std::u32string` | the character type is not one byte wide |
|
||||
| `#!cpp std::u8string` | one byte wide, but `#!cpp char8_t` is not `#!cpp char`-compatible |
|
||||
| `#!cpp std::u8string` | one byte wide, but `#!cpp char8_t` is not `#!cpp char`-compatible (as a *value*, it converts to and from a JSON string) |
|
||||
| `absl::Cord` | no `value_type`, and the storage is not contiguous |
|
||||
| `QString` | no `append(const char*, size_type)`; its `QChar` is also two bytes wide, though that is never diagnosed |
|
||||
|
||||
@@ -766,18 +765,14 @@ See [`json_base_class_t`](../../api/basic_json/json_base_class_t.md) for an exam
|
||||
## Cross-specialization conversions
|
||||
|
||||
Converting a value from one `basic_json` specialization into another (see the
|
||||
[converting constructor](../../api/basic_json/basic_json.md)) imposes two additional requirements:
|
||||
[converting constructor](../../api/basic_json/basic_json.md)) imposes two additional requirements that are not
|
||||
diagnosed at compile time. With assertions enabled they abort on the `#!cpp JSON_ASSERT` at the end of the converting
|
||||
constructor; under `#!cpp NDEBUG` they fail **silently** at runtime:
|
||||
|
||||
- The target `string_t` must be directly constructible from the source `string_t`.
|
||||
- The target `object_t::key_type` must be directly constructible from the source object's key type.
|
||||
|
||||
If a requirement is not met, the result depends on the source string type. If it is a range of characters (it has
|
||||
`begin()` and `end()`, as `std::string` does), the conversion compiles and then fails the `#!cpp JSON_ASSERT` at the
|
||||
end of the converting constructor: with its default definition, `assert`, the program aborts unless `#!cpp NDEBUG` is
|
||||
defined, in which case it **silently** returns an array (of character codes for a string, of key/value pairs for an
|
||||
object). Otherwise, the conversion does not compile, even though
|
||||
`#!cpp std::is_constructible` reports `#!cpp true`; for example, when converting a `basic_json` whose `string_t` is the
|
||||
`alt_string` of the unit tests to `json`.
|
||||
- The target `string_t` must be directly constructible from the source `string_t`. Otherwise the string is converted to
|
||||
an array of character codes.
|
||||
- The target `object_t::key_type` must be directly constructible from the source object's key type. Otherwise the
|
||||
object is converted to an array of key/value pairs.
|
||||
|
||||
See [issue #3425](https://github.com/nlohmann/json/issues/3425), [`string_t`](../../api/basic_json/string_t.md), and
|
||||
[`object_t`](../../api/basic_json/object_t.md).
|
||||
|
||||
@@ -8,6 +8,16 @@ These changes are part of the `develop` branch, but not of a release yet.
|
||||
exception is thrown during the conversion, the source may be partially moved-from, so the strong exception guarantee
|
||||
no longer holds for the source of an rvalue conversion (the JSON value itself is unaffected). Lvalues and `const`
|
||||
objects are still copied. See [`basic_json`](../../api/basic_json/basic_json.md).
|
||||
- In C++20 (library support for `char8_t`, `__cpp_lib_char8_t`), a `#!cpp std::u8string` is a JSON **string**:
|
||||
`json j = std::u8string(u8"abc");` stores `"abc"`, and `#!cpp j.get<std::u8string>()` reads it back. Version 3.12.0
|
||||
stored a `#!cpp std::u8string` as an array of code units (`[97,98,99]`); on the 3.13.0 development branch it was
|
||||
already stored as a string if `std::filesystem` is available, but could not be read back. Now the result no longer
|
||||
depends on whether `std::filesystem::path` is supported, and `#!cpp get<std::u8string>()` accepts both a JSON string
|
||||
and the array of numbers written by 3.12.0. **Consequence:** JSON documents produced from a `#!cpp std::u8string` by
|
||||
3.12.0 (arrays) are still read, but code that checks `is_array()` on such a value, or that reads it as
|
||||
`#!cpp std::vector<char8_t>` / `#!cpp std::vector<std::uint8_t>`, now sees a string; to keep the array form, convert
|
||||
explicitly, e.g., `#!cpp json(std::vector<char8_t>(s.begin(), s.end()))`. `#!cpp std::u8string_view` and
|
||||
`#!cpp char8_t` arrays are unchanged (arrays of code units). See [`basic_json`](../../api/basic_json/basic_json.md).
|
||||
|
||||
## API changes
|
||||
|
||||
|
||||
@@ -454,7 +454,6 @@ nav:
|
||||
- 'JSON_NO_SIMD': api/macros/json_no_simd.md
|
||||
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
||||
- 'JSON_PRECISE_STREAM_POSITION': api/macros/json_precise_stream_position.md
|
||||
- 'JSON_RECURSION_DEPTH_LIMIT': api/macros/json_recursion_depth_limit.md
|
||||
- 'JSON_SKIP_LIBRARY_VERSION_CHECK': api/macros/json_skip_library_version_check.md
|
||||
- 'JSON_SKIP_UNSUPPORTED_COMPILER_CHECK': api/macros/json_skip_unsupported_compiler_check.md
|
||||
- 'JSON_STRICT_BINARY_UTF8': api/macros/json_strict_binary_utf8.md
|
||||
|
||||
@@ -785,6 +785,37 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
|
||||
from_json_pair_array_to_map(j, m);
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
// a std::u8string is read from a JSON string; the array of code units written by
|
||||
// versions before 3.13.0 is still accepted
|
||||
template<typename BasicJsonType, typename Tr, typename Allocator,
|
||||
enable_if_t<std::is_same<typename json_type_of_t<BasicJsonType>::string_t::value_type, char>::value, int> = 0>
|
||||
inline void from_json(const BasicJsonType& j, std::basic_string<char8_t, Tr, Allocator>& s)
|
||||
{
|
||||
if (j.is_string())
|
||||
{
|
||||
const auto& str = string_value(j);
|
||||
const char* const data = str.data();
|
||||
const std::size_t size = str.size();
|
||||
std::basic_string<char8_t, Tr, Allocator> ret(s.get_allocator());
|
||||
ret.resize(size);
|
||||
for (std::size_t i = 0; i < size; ++i)
|
||||
{
|
||||
ret[i] = static_cast<char8_t>(static_cast<unsigned char>(data[i]));
|
||||
}
|
||||
s = std::move(ret);
|
||||
}
|
||||
else if (j.is_array())
|
||||
{
|
||||
from_json_array_impl(j, s, priority_tag<3> {});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_type_must_be("string or array", j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
|
||||
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
|
||||
|
||||
@@ -625,16 +625,20 @@ inline void to_json(BasicJsonType& j, const T& t)
|
||||
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
|
||||
}
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
// a std::u8string is a JSON string (it was an array of code units before 3.13.0);
|
||||
// defined outside the std::filesystem guard so that the result does not depend
|
||||
// on whether std::filesystem::path is supported
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
template<typename BasicJsonType, typename Tr, typename Allocator>
|
||||
inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
|
||||
{
|
||||
using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
|
||||
j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
// char may alias any object; the code units are copied unchanged
|
||||
j = string_t(reinterpret_cast<const char*>(s.data()), s.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_to_json (issue #4996)
|
||||
template<typename BasicJsonType>
|
||||
struct has_to_json<BasicJsonType, std_fs::path, void> : std::true_type {};
|
||||
|
||||
@@ -1312,23 +1312,15 @@ struct can_compare_ne_either_order : std::integral_constant < bool,
|
||||
can_compare_ne_impl<IteratorType, SentinelType>::value ||
|
||||
can_compare_ne_reversed<IteratorType, SentinelType>::value > {};
|
||||
|
||||
// Two kinds of SentinelType are excluded explicitly:
|
||||
//
|
||||
// - std::nullptr_t: a literal `nullptr` passed as a trailing default argument
|
||||
// (e.g. parse(s, nullptr, ...)) must never be mistaken for a sentinel, and
|
||||
// some compilers (e.g. GCC 4.8) unreliably SFINAE the `operator!=` detection
|
||||
// above for std::nullptr_t against container/string types, which would
|
||||
// otherwise make such calls ambiguous with the compatible-input overload.
|
||||
// - function pointers and functions: a parser callback passed as plain function
|
||||
// (e.g. parse(s, cb)) is never a sentinel. The callback's parameter types
|
||||
// make basic_json an associated class, so ADL finds the friend
|
||||
// operator!=(const_reference, ScalarType) of basic_json, which makes
|
||||
// `s != cb` well-formed (both convert to basic_json) and would select the
|
||||
// iterator/sentinel overload.
|
||||
// std::nullptr_t is excluded explicitly: a literal `nullptr` passed as a
|
||||
// trailing default argument (e.g. parse(s, nullptr, ...)) must never be
|
||||
// mistaken for a sentinel, and some compilers (e.g. GCC 4.8) unreliably
|
||||
// SFINAE the `operator!=` detection above for std::nullptr_t against
|
||||
// container/string types, which would otherwise make such calls ambiguous
|
||||
// with the compatible-input overload.
|
||||
template<typename IteratorType, typename SentinelType>
|
||||
struct can_compare_ne : std::integral_constant < bool,
|
||||
!std::is_same<SentinelType, std::nullptr_t>::value &&
|
||||
!std::is_function<typename std::remove_pointer<SentinelType>::type>::value &&
|
||||
can_compare_ne_either_order<IteratorType, SentinelType>::value > {};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -1091,32 +1091,6 @@ class json_pointer
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief the number of the deepest step of the previous path that is a prefix of the new one
|
||||
|
||||
Comparing every one of many steps with the beginning of the path would take
|
||||
quadratic time. Instead, the length of the common beginning of the two paths
|
||||
is computed once: a step whose prefix is not longer is a prefix of the new
|
||||
path, too. For few steps, which is the usual case, @ref resolve_plain
|
||||
compares them, which is cheaper.
|
||||
*/
|
||||
template<typename Steps>
|
||||
JSON_HEDLEY_NEVER_INLINE static std::size_t deepest_shared_step(const string_t& path, const std::size_t length, const string_t& previous, const Steps& steps) noexcept
|
||||
{
|
||||
const std::size_t same = common_prefix_length(path.data(), previous.data(), (std::min)(length, previous.size()));
|
||||
std::size_t depth = steps.size();
|
||||
for (; depth > 1; --depth)
|
||||
{
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= same && (prefix == length || path[prefix] == '/'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief resolve a plain JSON pointer without building its reference tokens
|
||||
|
||||
@@ -1145,20 +1119,13 @@ class json_pointer
|
||||
if (cache.path != nullptr && !steps.empty() && steps[0].second == root)
|
||||
{
|
||||
const string_t& previous = *cache.path;
|
||||
if (JSON_HEDLEY_UNLIKELY(steps.size() > 16))
|
||||
for (depth = steps.size(); depth > 1; --depth)
|
||||
{
|
||||
depth = deepest_shared_step(path, length, previous, steps);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (depth = steps.size(); depth > 1; --depth)
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= length && (prefix == length || path[prefix] == '/') && std::memcmp(path.data(), previous.data(), prefix) == 0)
|
||||
{
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= length && (prefix == length || path[prefix] == '/') && std::memcmp(path.data(), previous.data(), prefix) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
steps.resize(depth);
|
||||
|
||||
@@ -224,12 +224,6 @@
|
||||
#define JSON_NO_THREAD_LOCAL 1
|
||||
#endif
|
||||
|
||||
// JSON_RECURSION_DEPTH_LIMIT (the number of nesting levels the walks over a
|
||||
// value recurse into before they continue with an explicit stack; 128 by
|
||||
// default, 0 to 254 allowed) is defined and checked where it is used, in
|
||||
// detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part
|
||||
// of the ABI tag nor undefined at the end of json.hpp.
|
||||
|
||||
// allow disabling exceptions
|
||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
||||
#define JSON_THROW(exception) throw exception
|
||||
|
||||
@@ -9,22 +9,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <type_traits> // false_type, is_integral, remove_cv, true_type
|
||||
|
||||
#include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
// JSON_RECURSION_DEPTH_LIMIT: the number of nesting levels the operations that
|
||||
// walk a value recurse into on the call stack before they continue with an
|
||||
// explicit stack (see detail::recursion_depth_limit() below).
|
||||
//
|
||||
// May be defined by the user before the first include of the library; it has
|
||||
// to be the same in every translation unit of a program (it is not part of the
|
||||
// ABI tag, see https://json.nlohmann.me/api/macros/json_recursion_depth_limit/).
|
||||
// Allowed: an integer constant expression from 0 to 254. The default is 128.
|
||||
#ifndef JSON_RECURSION_DEPTH_LIMIT
|
||||
#define JSON_RECURSION_DEPTH_LIMIT 128
|
||||
#endif
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
@@ -33,71 +20,21 @@ namespace detail
|
||||
@brief the number of nesting levels an operation recurses into
|
||||
|
||||
Operations that walk a value (copying, comparing, serializing, hashing, merging,
|
||||
diffing, converting, destroying, and writing the binary formats CBOR,
|
||||
MessagePack, UBJSON, BJData, and BON8) recurse once per nesting level, which is
|
||||
fastest, but a value nested deeply enough would exhaust the call stack. So they
|
||||
recurse only this many levels deep and finish whatever lies below with an
|
||||
explicit stack that lives on the heap. All of them share this limit and none has
|
||||
a constant of its own. It is the value of the macro JSON_RECURSION_DEPTH_LIMIT,
|
||||
128 by default. (Parsing, the binary readers, flatten(), unflatten(), and
|
||||
to_bson() always use an explicit stack and do not read it, and the lockstep
|
||||
comparison of json_view documents has a fixed bound of its own, 48 levels.)
|
||||
...) recurse once
|
||||
per nesting level, which is fastest, but a value nested deeply enough would
|
||||
exhaust the call stack. So they recurse only this many levels deep and finish
|
||||
whatever lies below with an explicit stack. All of them share this limit.
|
||||
|
||||
Most of the operations pass the depth down as an argument. The copy constructor
|
||||
and the comparison operators cannot, as their signatures are fixed, so they
|
||||
count it in basic_json::nesting_depth() instead, a byte per thread. Only the
|
||||
levels that are descended into are counted, so the count never exceeds the limit.
|
||||
The limit must fit in the byte with some headroom, so that the count cannot wrap
|
||||
around: it must be below 255, and 254 is the largest value allowed. (More levels
|
||||
would hardly be useful: 254 levels need up to 576 KiB of stack in an unoptimized
|
||||
build already, twice the stack of the default.)
|
||||
Most of them pass the depth down as an argument. The copy constructor and the
|
||||
comparison operators cannot, as their signatures are fixed, so they count it
|
||||
in basic_json::nesting_depth() instead, a byte per thread; the limit must
|
||||
therefore stay below 255.
|
||||
|
||||
The smallest value is 0: every operation then uses its explicit stack from the
|
||||
first level on and no operation recurses over the nesting of a value at all.
|
||||
That is slower, but needs a constant amount of call stack. It works because
|
||||
every use of the limit compares a depth with it (`depth >= limit`, or `<` for
|
||||
the opposite), which holds for 0 as for any other value; nothing computes
|
||||
`limit - 1` or `limit + 1`, so nothing wraps around. Each operation's explicit
|
||||
stack handles any nesting level, including the first, so none of them relies on
|
||||
having recursed first.
|
||||
|
||||
The call stack that an operation needs is roughly a few KiB plus a cost per level
|
||||
times the limit. At the default of 128 levels, an unoptimized build needs up to
|
||||
about 290 KiB (`dump()` with Clang at -O0: about 2.3 KiB per level) and an
|
||||
optimized build up to about 48 KiB; with 254 levels it is up to 576 KiB and
|
||||
112 KiB, and with 0 it is 16 KiB or less. Lower the limit for threads with small
|
||||
stacks (RTOS tasks, fibers, musl threads), raise it to trade stack for speed on
|
||||
deeply nested values. All of this, with the measurements, is in the
|
||||
documentation of the macro.
|
||||
|
||||
@sa https://json.nlohmann.me/api/macros/json_recursion_depth_limit/
|
||||
@sa https://github.com/nlohmann/json/issues/5387
|
||||
*/
|
||||
/// the type of the value of JSON_RECURSION_DEPTH_LIMIT is bool or a character type
|
||||
template<typename T> struct recursion_depth_limit_is_char_or_bool : std::false_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<bool> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<signed char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<unsigned char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<wchar_t> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char16_t> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char32_t> : std::true_type {};
|
||||
#if defined(__cpp_char8_t)
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char8_t> : std::true_type {};
|
||||
#endif
|
||||
|
||||
constexpr std::size_t recursion_depth_limit() noexcept
|
||||
{
|
||||
// an integer: not a floating-point number, whose range check would pass for 1.5 or 254.0
|
||||
// (bool and the character types are integer types, too, but true, false or 'a' are
|
||||
// no way to say a limit; JSON_UBJSON_VALUELESS_ELEMENTS_PER_BYTE refuses them as well)
|
||||
static_assert(std::is_integral<decltype(JSON_RECURSION_DEPTH_LIMIT)>::value
|
||||
&& !recursion_depth_limit_is_char_or_bool<typename std::remove_cv<decltype(JSON_RECURSION_DEPTH_LIMIT)>::type>::value,
|
||||
"JSON_RECURSION_DEPTH_LIMIT must be an integer constant (not bool or a character type)");
|
||||
static_assert(JSON_RECURSION_DEPTH_LIMIT >= 0 && JSON_RECURSION_DEPTH_LIMIT <= 254,
|
||||
"JSON_RECURSION_DEPTH_LIMIT must be between 0 and 254: the nesting depth is counted in a byte per thread "
|
||||
"and may exceed the limit by one (see https://json.nlohmann.me/api/macros/json_recursion_depth_limit/)");
|
||||
return static_cast<std::size_t>(JSON_RECURSION_DEPTH_LIMIT);
|
||||
return 128;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -79,14 +79,6 @@ NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_equal(const char* x, const char* y, std::
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether a float node holds the text nan, which an edit writes for a NaN (and records without a digit layout, so
|
||||
/// that a parsed float is told apart by one comparison of what the walk has loaded anyway): equal tokens are an
|
||||
/// equal value, except for this one
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE bool float_token_is_nan(const node& n, const char* s) noexcept
|
||||
{
|
||||
return NLOHMANN_VIEW_UNLIKELY(n.extra == 0xFFFFu) && n.len == 3 && s[0] == 'n';
|
||||
}
|
||||
|
||||
/// whether the n1 bytes at x are before the n2 bytes at y (memcmp() order, then the shorter first);
|
||||
/// the first difference is found eight bytes at a time
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_less(const char* x, std::size_t n1, const char* y, std::size_t n2) noexcept
|
||||
@@ -696,7 +688,7 @@ class lockstep
|
||||
case value_t::string:
|
||||
return a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
case value_t::number_float: // (the token, and the digit layout that the value is read with: they only differ in a damaged image)
|
||||
return same_float(a, b, std::integral_constant<bool, EA> {});
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
return integer_bits(*a) == integer_bits(*b);
|
||||
@@ -791,17 +783,6 @@ class lockstep
|
||||
return true;
|
||||
}
|
||||
|
||||
/// (a read-only document holds no NaN)
|
||||
bool same_float(const node* a, const node* b, std::false_type /*editable*/) const noexcept
|
||||
{
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
}
|
||||
|
||||
bool same_float(const node* a, const node* b, std::true_type /*editable*/) const noexcept
|
||||
{
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len) && !float_token_is_nan(*a, m_a.str(*a));
|
||||
}
|
||||
|
||||
bool elements(const node* a, const node* b, unsigned budget, lockstep_path::entry& stop) noexcept
|
||||
{
|
||||
const node* pa = nav_a::first(m_a, a);
|
||||
@@ -858,9 +839,9 @@ bool certainly_equal(const view_side<BasicJsonType, ViewA>& a, const view_side<B
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (na == nb && (!view_side<BasicJsonType, ViewA>::nav::editable() || a.document().edits == nullptr))
|
||||
if (na == nb)
|
||||
{
|
||||
return true; // (the same node of the same document: documents have distinct nodes; a document with edits is walked, as an edit can have written a NaN, which is not equal to itself)
|
||||
return true; // (the same node of the same document: documents have distinct nodes)
|
||||
}
|
||||
path.resume = nullptr;
|
||||
if (path.next < path.length && path.nodes[path.next].a == na && path.nodes[path.next].b == nb)
|
||||
@@ -905,7 +886,7 @@ void resume_array(const lockstep_path& /*path*/, const A& /*a*/, const B& /*b*/,
|
||||
template<typename BasicJsonType, typename ViewA, typename ViewB>
|
||||
bool floats_equal(const view_side<BasicJsonType, ViewA>& a, const view_side<BasicJsonType, ViewB>& b)
|
||||
{
|
||||
return (a.value_node()->extra == b.value_node()->extra && a.float_token() == b.float_token() && !(view_side<BasicJsonType, ViewA>::nav::editable() && float_token_is_nan(*a.value_node(), a.float_token().data()))) || std::equal_to<typename BasicJsonType::number_float_t>()(a.floating(), b.floating());
|
||||
return (a.value_node()->extra == b.value_node()->extra && a.float_token() == b.float_token()) || std::equal_to<typename BasicJsonType::number_float_t>()(a.floating(), b.floating());
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t, uint32_t
|
||||
#include <cstring> // memcmp, memcpy
|
||||
#include <functional> // less
|
||||
#include <limits> // numeric_limits
|
||||
#include <map> // map
|
||||
#include <memory> // unique_ptr
|
||||
@@ -150,23 +149,6 @@ struct document_data
|
||||
node_capacity = inline_capacity;
|
||||
}
|
||||
|
||||
/// whether the n bytes at p overlap memory that the next parse releases or
|
||||
/// reuses: the owned text, the decoded strings, an owned image, and the
|
||||
/// current buffer of strings written by edits (earlier edit buffers are not
|
||||
/// covered, as their sizes are not kept); for the debug check in read()
|
||||
bool holds(const char* p, std::size_t n) const noexcept
|
||||
{
|
||||
const auto overlaps = [p, n](const char* b, std::size_t m) noexcept
|
||||
{
|
||||
// (std::less: a total order also for pointers into different objects)
|
||||
return n != 0 && m != 0 && std::less<const char*>()(p, b + m) && std::less<const char*>()(b, p + n);
|
||||
};
|
||||
return overlaps(owned.data(), owned.capacity())
|
||||
|| overlaps(arena.data(), arena.capacity())
|
||||
|| overlaps(reinterpret_cast<const char*>(owned_image.data()), owned_image.capacity()) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
|| (edits && !edits->texts.empty() && overlaps(edits->texts.back().get(), edits->text_cap));
|
||||
}
|
||||
|
||||
/// the largest node count whose size in bytes fits a std::size_t
|
||||
static constexpr std::size_t max_nodes() noexcept
|
||||
{
|
||||
|
||||
@@ -416,28 +416,6 @@ inline bool float_token_finite(const unsigned char* s, std::size_t len, const nu
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether an integer token (well-formed, no fraction or exponent) fits 64
|
||||
/// bits: the parser stores a number_integer or number_unsigned node for it,
|
||||
/// and a number_float node only for a token that does not fit
|
||||
inline bool integer_token_fits(const number_token& t)
|
||||
{
|
||||
if (t.int_digits > 20)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t.int_digits == 20)
|
||||
{
|
||||
// (20 digits are compared with 2^64 - 1; a negative one is below -2^63)
|
||||
// (only a leading 1 needs the comparison: the first digit of 20 is not 0)
|
||||
return !t.negative && *t.int_start == '1' && std::memcmp(t.int_start, "18446744073709551615", 20) <= 0;
|
||||
}
|
||||
if (t.negative && t.int_digits == 19)
|
||||
{
|
||||
return *t.int_start != '9' || std::memcmp(t.int_start, "9223372036854775808", 19) <= 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether an integer node matches its token the way the parser records it
|
||||
/// (after the bounds check; the token has at most 256 characters)
|
||||
inline bool check_integer(const node& n, const unsigned char* text)
|
||||
@@ -557,8 +535,7 @@ inline bool check_float_ranges(std::vector<float_range>& ranges, const unsigned
|
||||
if (!plain_float_token(s, r.len, r.extra))
|
||||
{
|
||||
number_token t{};
|
||||
// (an integer token is a float node only if it does not fit 64 bits)
|
||||
if (!scan_number_token(s, r.len, t) || (!t.is_float && integer_token_fits(t)) || !float_token_finite(s, r.len, t))
|
||||
if (!scan_number_token(s, r.len, t) || !float_token_finite(s, r.len, t))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -71,11 +71,6 @@
|
||||
#define NLOHMANN_VIEW_THROW JSON_THROW_USER
|
||||
#endif
|
||||
|
||||
// debug checks of preconditions (assert(), off with NDEBUG): JSON_ASSERT is
|
||||
// one of the macros that json.hpp undefines at its end
|
||||
#include <cassert> // assert
|
||||
#define NLOHMANN_VIEW_ASSERT(x) assert(x)
|
||||
|
||||
// the parser stores a node's first word at once where the layout of `node` is
|
||||
// known to be little-endian (MSVC targets are); elsewhere field by field
|
||||
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_MSC_VER)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#undef NLOHMANN_VIEW_NOCLONE
|
||||
#undef NLOHMANN_VIEW_NODISCARD
|
||||
#undef NLOHMANN_VIEW_THROW
|
||||
#undef NLOHMANN_VIEW_ASSERT
|
||||
#undef NLOHMANN_VIEW_LITTLE_ENDIAN
|
||||
#undef NLOHMANN_VIEW_REPEAT16
|
||||
#undef NLOHMANN_VIEW_REPEAT_SECOND_8
|
||||
|
||||
@@ -1256,10 +1256,8 @@ public:
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// nesting_depth() is a byte that never exceeds the limit (JSON_RECURSION_DEPTH_LIMIT),
|
||||
// which is at most 254: the largest value stays one below the byte's maximum, so
|
||||
// that the count cannot wrap around to 0 and let a descent go on without a bound.
|
||||
// recursion_depth_limit() checks this range with a static_assert.
|
||||
// nesting_depth() is a byte and may exceed the limit by one level
|
||||
static_assert(detail::recursion_depth_limit() < 255, "the nesting depth count must fit in a byte");
|
||||
|
||||
/*!
|
||||
@brief how many levels the operation going on in this thread has descended into
|
||||
@@ -1270,15 +1268,8 @@ public:
|
||||
user code nests them anyway, sharing the count only ends a descent sooner
|
||||
than it had to, which costs a little speed and is never wrong.
|
||||
|
||||
A byte is enough: only the levels that are descended into are counted
|
||||
(@ref nesting_depth_guard), so the count never exceeds the limit, and the
|
||||
limit is at most 254.
|
||||
|
||||
The count is per thread and not per value or per library configuration: all
|
||||
translation units of a program share it, even if they were compiled with
|
||||
different values of JSON_RECURSION_DEPTH_LIMIT (which is not supported, see
|
||||
the documentation of the macro); each of them then compares the shared count
|
||||
with its own limit.
|
||||
A byte is enough: the count never exceeds the limit by more than the single
|
||||
level that notices the limit has been reached.
|
||||
*/
|
||||
static std::uint8_t& nesting_depth() noexcept
|
||||
{
|
||||
@@ -1336,25 +1327,14 @@ public:
|
||||
#endif
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// Only a level that is entered is counted, so that the count never
|
||||
// exceeds the limit. A level that is not entered is finished without
|
||||
// descending, and whatever runs while it is (a copy made by a custom
|
||||
// base class, say) sees the same count as the level itself did and
|
||||
// is not entered either.
|
||||
if (m_okay)
|
||||
{
|
||||
++nesting_depth();
|
||||
}
|
||||
++nesting_depth();
|
||||
#endif
|
||||
}
|
||||
|
||||
~nesting_depth_guard()
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
if (m_okay)
|
||||
{
|
||||
--nesting_depth();
|
||||
}
|
||||
--nesting_depth();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5266,10 +5246,7 @@ public:
|
||||
*/
|
||||
void update_members(const iterator& first, const iterator& last, const bool merge_objects, const std::size_t depth)
|
||||
{
|
||||
// without merge_objects the loop below never descends, so there is no
|
||||
// call stack to save (and the explicit stack always merges); the
|
||||
// distinction matters for a limit of 0, which reaches this at depth 0
|
||||
if (JSON_HEDLEY_UNLIKELY(merge_objects && depth >= detail::recursion_depth_limit()))
|
||||
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
||||
{
|
||||
update_members_iteratively(first, last);
|
||||
return;
|
||||
|
||||
@@ -1531,10 +1531,6 @@ class basic_json_document
|
||||
/// sentinel: src[size] is readable and 0 (std::string, C strings)
|
||||
void build(const char* src, std::size_t size, on_error allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
{
|
||||
// precondition of read(): a borrowed input is not held by this document,
|
||||
// which releases what it holds below (checked in debug builds only, as
|
||||
// it would cost every read() of a small message a few percent)
|
||||
NLOHMANN_VIEW_ASSERT(owned || !m_data || !m_data->holds(src, size));
|
||||
ensure_data(src, size);
|
||||
document_data& d = *m_data;
|
||||
if (!owned)
|
||||
@@ -1624,10 +1620,6 @@ class basic_json_document
|
||||
template<typename T>
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
{
|
||||
// (the precondition of read() as for a borrowed input, although only an
|
||||
// input in the owned text breaks a copy: the same call borrows, for
|
||||
// example a std::string_view in C++17, and must not depend on that)
|
||||
NLOHMANN_VIEW_ASSERT(!m_data || !m_data->holds(reinterpret_cast<const char*>(s.data()), static_cast<std::size_t>(s.size()))); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
build_copy(s, ae, c, tc);
|
||||
}
|
||||
|
||||
@@ -1646,24 +1638,9 @@ class basic_json_document
|
||||
template<typename T>
|
||||
void read_kind(T&& input, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
{
|
||||
NLOHMANN_VIEW_ASSERT(!held(input)); // (see the copy_range overload)
|
||||
build_copy(std::forward<T>(input), ae, c, tc);
|
||||
}
|
||||
|
||||
/// whether an input read through the input adapter is held by this document:
|
||||
/// string_view_t before C++17 (a string handed out by a view), for the
|
||||
/// debug check of read(); other inputs of this kind do not point into it
|
||||
bool held(const detail::view::string_ref& s) const noexcept
|
||||
{
|
||||
return m_data && m_data->holds(s.data(), s.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool held(const T& /*input*/) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range(IteratorType first, IteratorType last, on_error ae, bool c, bool tc)
|
||||
{
|
||||
|
||||
Generated
+65
-163
@@ -2597,12 +2597,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP
|
||||
#define JSON_NO_THREAD_LOCAL 1
|
||||
#endif
|
||||
|
||||
// JSON_RECURSION_DEPTH_LIMIT (the number of nesting levels the walks over a
|
||||
// value recurse into before they continue with an explicit stack; 128 by
|
||||
// default, 0 to 254 allowed) is defined and checked where it is used, in
|
||||
// detail/recursion_depth_limit.hpp. Like JSON_NO_THREAD_LOCAL it is neither part
|
||||
// of the ABI tag nor undefined at the end of json.hpp.
|
||||
|
||||
// allow disabling exceptions
|
||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
||||
#define JSON_THROW(exception) throw exception
|
||||
@@ -6934,6 +6928,37 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
|
||||
from_json_pair_array_to_map(j, m);
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
// a std::u8string is read from a JSON string; the array of code units written by
|
||||
// versions before 3.13.0 is still accepted
|
||||
template<typename BasicJsonType, typename Tr, typename Allocator,
|
||||
enable_if_t<std::is_same<typename json_type_of_t<BasicJsonType>::string_t::value_type, char>::value, int> = 0>
|
||||
inline void from_json(const BasicJsonType& j, std::basic_string<char8_t, Tr, Allocator>& s)
|
||||
{
|
||||
if (j.is_string())
|
||||
{
|
||||
const auto& str = string_value(j);
|
||||
const char* const data = str.data();
|
||||
const std::size_t size = str.size();
|
||||
std::basic_string<char8_t, Tr, Allocator> ret(s.get_allocator());
|
||||
ret.resize(size);
|
||||
for (std::size_t i = 0; i < size; ++i)
|
||||
{
|
||||
ret[i] = static_cast<char8_t>(static_cast<unsigned char>(data[i]));
|
||||
}
|
||||
s = std::move(ret);
|
||||
}
|
||||
else if (j.is_array())
|
||||
{
|
||||
from_json_array_impl(j, s, priority_tag<3> {});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_type_must_be("string or array", j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
|
||||
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_from_json (issue #4996)
|
||||
@@ -8335,16 +8360,20 @@ inline void to_json(BasicJsonType& j, const T& t)
|
||||
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
|
||||
}
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
// a std::u8string is a JSON string (it was an array of code units before 3.13.0);
|
||||
// defined outside the std::filesystem guard so that the result does not depend
|
||||
// on whether std::filesystem::path is supported
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
template<typename BasicJsonType, typename Tr, typename Allocator>
|
||||
inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
|
||||
{
|
||||
using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
|
||||
j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
// char may alias any object; the code units are copied unchanged
|
||||
j = string_t(reinterpret_cast<const char*>(s.data()), s.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
// Workaround for MSVC 19.51 (and possibly later): in large cpp files, the compiler may fail to resolve with generic has_to_json (issue #4996)
|
||||
template<typename BasicJsonType>
|
||||
struct has_to_json<BasicJsonType, std_fs::path, void> : std::true_type {};
|
||||
@@ -8606,23 +8635,10 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <type_traits> // false_type, is_integral, remove_cv, true_type
|
||||
|
||||
// #include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
|
||||
// JSON_RECURSION_DEPTH_LIMIT: the number of nesting levels the operations that
|
||||
// walk a value recurse into on the call stack before they continue with an
|
||||
// explicit stack (see detail::recursion_depth_limit() below).
|
||||
//
|
||||
// May be defined by the user before the first include of the library; it has
|
||||
// to be the same in every translation unit of a program (it is not part of the
|
||||
// ABI tag, see https://json.nlohmann.me/api/macros/json_recursion_depth_limit/).
|
||||
// Allowed: an integer constant expression from 0 to 254. The default is 128.
|
||||
#ifndef JSON_RECURSION_DEPTH_LIMIT
|
||||
#define JSON_RECURSION_DEPTH_LIMIT 128
|
||||
#endif
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
namespace detail
|
||||
{
|
||||
@@ -8631,71 +8647,21 @@ namespace detail
|
||||
@brief the number of nesting levels an operation recurses into
|
||||
|
||||
Operations that walk a value (copying, comparing, serializing, hashing, merging,
|
||||
diffing, converting, destroying, and writing the binary formats CBOR,
|
||||
MessagePack, UBJSON, BJData, and BON8) recurse once per nesting level, which is
|
||||
fastest, but a value nested deeply enough would exhaust the call stack. So they
|
||||
recurse only this many levels deep and finish whatever lies below with an
|
||||
explicit stack that lives on the heap. All of them share this limit and none has
|
||||
a constant of its own. It is the value of the macro JSON_RECURSION_DEPTH_LIMIT,
|
||||
128 by default. (Parsing, the binary readers, flatten(), unflatten(), and
|
||||
to_bson() always use an explicit stack and do not read it, and the lockstep
|
||||
comparison of json_view documents has a fixed bound of its own, 48 levels.)
|
||||
...) recurse once
|
||||
per nesting level, which is fastest, but a value nested deeply enough would
|
||||
exhaust the call stack. So they recurse only this many levels deep and finish
|
||||
whatever lies below with an explicit stack. All of them share this limit.
|
||||
|
||||
Most of the operations pass the depth down as an argument. The copy constructor
|
||||
and the comparison operators cannot, as their signatures are fixed, so they
|
||||
count it in basic_json::nesting_depth() instead, a byte per thread. Only the
|
||||
levels that are descended into are counted, so the count never exceeds the limit.
|
||||
The limit must fit in the byte with some headroom, so that the count cannot wrap
|
||||
around: it must be below 255, and 254 is the largest value allowed. (More levels
|
||||
would hardly be useful: 254 levels need up to 576 KiB of stack in an unoptimized
|
||||
build already, twice the stack of the default.)
|
||||
Most of them pass the depth down as an argument. The copy constructor and the
|
||||
comparison operators cannot, as their signatures are fixed, so they count it
|
||||
in basic_json::nesting_depth() instead, a byte per thread; the limit must
|
||||
therefore stay below 255.
|
||||
|
||||
The smallest value is 0: every operation then uses its explicit stack from the
|
||||
first level on and no operation recurses over the nesting of a value at all.
|
||||
That is slower, but needs a constant amount of call stack. It works because
|
||||
every use of the limit compares a depth with it (`depth >= limit`, or `<` for
|
||||
the opposite), which holds for 0 as for any other value; nothing computes
|
||||
`limit - 1` or `limit + 1`, so nothing wraps around. Each operation's explicit
|
||||
stack handles any nesting level, including the first, so none of them relies on
|
||||
having recursed first.
|
||||
|
||||
The call stack that an operation needs is roughly a few KiB plus a cost per level
|
||||
times the limit. At the default of 128 levels, an unoptimized build needs up to
|
||||
about 290 KiB (`dump()` with Clang at -O0: about 2.3 KiB per level) and an
|
||||
optimized build up to about 48 KiB; with 254 levels it is up to 576 KiB and
|
||||
112 KiB, and with 0 it is 16 KiB or less. Lower the limit for threads with small
|
||||
stacks (RTOS tasks, fibers, musl threads), raise it to trade stack for speed on
|
||||
deeply nested values. All of this, with the measurements, is in the
|
||||
documentation of the macro.
|
||||
|
||||
@sa https://json.nlohmann.me/api/macros/json_recursion_depth_limit/
|
||||
@sa https://github.com/nlohmann/json/issues/5387
|
||||
*/
|
||||
/// the type of the value of JSON_RECURSION_DEPTH_LIMIT is bool or a character type
|
||||
template<typename T> struct recursion_depth_limit_is_char_or_bool : std::false_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<bool> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<signed char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<unsigned char> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<wchar_t> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char16_t> : std::true_type {};
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char32_t> : std::true_type {};
|
||||
#if defined(__cpp_char8_t)
|
||||
template<> struct recursion_depth_limit_is_char_or_bool<char8_t> : std::true_type {};
|
||||
#endif
|
||||
|
||||
constexpr std::size_t recursion_depth_limit() noexcept
|
||||
{
|
||||
// an integer: not a floating-point number, whose range check would pass for 1.5 or 254.0
|
||||
// (bool and the character types are integer types, too, but true, false or 'a' are
|
||||
// no way to say a limit; JSON_UBJSON_VALUELESS_ELEMENTS_PER_BYTE refuses them as well)
|
||||
static_assert(std::is_integral<decltype(JSON_RECURSION_DEPTH_LIMIT)>::value
|
||||
&& !recursion_depth_limit_is_char_or_bool<typename std::remove_cv<decltype(JSON_RECURSION_DEPTH_LIMIT)>::type>::value,
|
||||
"JSON_RECURSION_DEPTH_LIMIT must be an integer constant (not bool or a character type)");
|
||||
static_assert(JSON_RECURSION_DEPTH_LIMIT >= 0 && JSON_RECURSION_DEPTH_LIMIT <= 254,
|
||||
"JSON_RECURSION_DEPTH_LIMIT must be between 0 and 254: the nesting depth is counted in a byte per thread "
|
||||
"and may exceed the limit by one (see https://json.nlohmann.me/api/macros/json_recursion_depth_limit/)");
|
||||
return static_cast<std::size_t>(JSON_RECURSION_DEPTH_LIMIT);
|
||||
return 128;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
@@ -10490,23 +10456,15 @@ struct can_compare_ne_either_order : std::integral_constant < bool,
|
||||
can_compare_ne_impl<IteratorType, SentinelType>::value ||
|
||||
can_compare_ne_reversed<IteratorType, SentinelType>::value > {};
|
||||
|
||||
// Two kinds of SentinelType are excluded explicitly:
|
||||
//
|
||||
// - std::nullptr_t: a literal `nullptr` passed as a trailing default argument
|
||||
// (e.g. parse(s, nullptr, ...)) must never be mistaken for a sentinel, and
|
||||
// some compilers (e.g. GCC 4.8) unreliably SFINAE the `operator!=` detection
|
||||
// above for std::nullptr_t against container/string types, which would
|
||||
// otherwise make such calls ambiguous with the compatible-input overload.
|
||||
// - function pointers and functions: a parser callback passed as plain function
|
||||
// (e.g. parse(s, cb)) is never a sentinel. The callback's parameter types
|
||||
// make basic_json an associated class, so ADL finds the friend
|
||||
// operator!=(const_reference, ScalarType) of basic_json, which makes
|
||||
// `s != cb` well-formed (both convert to basic_json) and would select the
|
||||
// iterator/sentinel overload.
|
||||
// std::nullptr_t is excluded explicitly: a literal `nullptr` passed as a
|
||||
// trailing default argument (e.g. parse(s, nullptr, ...)) must never be
|
||||
// mistaken for a sentinel, and some compilers (e.g. GCC 4.8) unreliably
|
||||
// SFINAE the `operator!=` detection above for std::nullptr_t against
|
||||
// container/string types, which would otherwise make such calls ambiguous
|
||||
// with the compatible-input overload.
|
||||
template<typename IteratorType, typename SentinelType>
|
||||
struct can_compare_ne : std::integral_constant < bool,
|
||||
!std::is_same<SentinelType, std::nullptr_t>::value &&
|
||||
!std::is_function<typename std::remove_pointer<SentinelType>::type>::value &&
|
||||
can_compare_ne_either_order<IteratorType, SentinelType>::value > {};
|
||||
|
||||
template<typename T>
|
||||
@@ -27343,32 +27301,6 @@ class json_pointer
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief the number of the deepest step of the previous path that is a prefix of the new one
|
||||
|
||||
Comparing every one of many steps with the beginning of the path would take
|
||||
quadratic time. Instead, the length of the common beginning of the two paths
|
||||
is computed once: a step whose prefix is not longer is a prefix of the new
|
||||
path, too. For few steps, which is the usual case, @ref resolve_plain
|
||||
compares them, which is cheaper.
|
||||
*/
|
||||
template<typename Steps>
|
||||
JSON_HEDLEY_NEVER_INLINE static std::size_t deepest_shared_step(const string_t& path, const std::size_t length, const string_t& previous, const Steps& steps) noexcept
|
||||
{
|
||||
const std::size_t same = common_prefix_length(path.data(), previous.data(), (std::min)(length, previous.size()));
|
||||
std::size_t depth = steps.size();
|
||||
for (; depth > 1; --depth)
|
||||
{
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= same && (prefix == length || path[prefix] == '/'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief resolve a plain JSON pointer without building its reference tokens
|
||||
|
||||
@@ -27397,20 +27329,13 @@ class json_pointer
|
||||
if (cache.path != nullptr && !steps.empty() && steps[0].second == root)
|
||||
{
|
||||
const string_t& previous = *cache.path;
|
||||
if (JSON_HEDLEY_UNLIKELY(steps.size() > 16))
|
||||
for (depth = steps.size(); depth > 1; --depth)
|
||||
{
|
||||
depth = deepest_shared_step(path, length, previous, steps);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (depth = steps.size(); depth > 1; --depth)
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= length && (prefix == length || path[prefix] == '/') && std::memcmp(path.data(), previous.data(), prefix) == 0)
|
||||
{
|
||||
// a step ends at a token boundary of the previous path
|
||||
const std::size_t prefix = steps[depth - 1].first;
|
||||
if (prefix <= length && (prefix == length || path[prefix] == '/') && std::memcmp(path.data(), previous.data(), prefix) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
steps.resize(depth);
|
||||
@@ -40516,10 +40441,8 @@ public:
|
||||
}
|
||||
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// nesting_depth() is a byte that never exceeds the limit (JSON_RECURSION_DEPTH_LIMIT),
|
||||
// which is at most 254: the largest value stays one below the byte's maximum, so
|
||||
// that the count cannot wrap around to 0 and let a descent go on without a bound.
|
||||
// recursion_depth_limit() checks this range with a static_assert.
|
||||
// nesting_depth() is a byte and may exceed the limit by one level
|
||||
static_assert(detail::recursion_depth_limit() < 255, "the nesting depth count must fit in a byte");
|
||||
|
||||
/*!
|
||||
@brief how many levels the operation going on in this thread has descended into
|
||||
@@ -40530,15 +40453,8 @@ public:
|
||||
user code nests them anyway, sharing the count only ends a descent sooner
|
||||
than it had to, which costs a little speed and is never wrong.
|
||||
|
||||
A byte is enough: only the levels that are descended into are counted
|
||||
(@ref nesting_depth_guard), so the count never exceeds the limit, and the
|
||||
limit is at most 254.
|
||||
|
||||
The count is per thread and not per value or per library configuration: all
|
||||
translation units of a program share it, even if they were compiled with
|
||||
different values of JSON_RECURSION_DEPTH_LIMIT (which is not supported, see
|
||||
the documentation of the macro); each of them then compares the shared count
|
||||
with its own limit.
|
||||
A byte is enough: the count never exceeds the limit by more than the single
|
||||
level that notices the limit has been reached.
|
||||
*/
|
||||
static std::uint8_t& nesting_depth() noexcept
|
||||
{
|
||||
@@ -40596,25 +40512,14 @@ public:
|
||||
#endif
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
// Only a level that is entered is counted, so that the count never
|
||||
// exceeds the limit. A level that is not entered is finished without
|
||||
// descending, and whatever runs while it is (a copy made by a custom
|
||||
// base class, say) sees the same count as the level itself did and
|
||||
// is not entered either.
|
||||
if (m_okay)
|
||||
{
|
||||
++nesting_depth();
|
||||
}
|
||||
++nesting_depth();
|
||||
#endif
|
||||
}
|
||||
|
||||
~nesting_depth_guard()
|
||||
{
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
if (m_okay)
|
||||
{
|
||||
--nesting_depth();
|
||||
}
|
||||
--nesting_depth();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -44526,10 +44431,7 @@ public:
|
||||
*/
|
||||
void update_members(const iterator& first, const iterator& last, const bool merge_objects, const std::size_t depth)
|
||||
{
|
||||
// without merge_objects the loop below never descends, so there is no
|
||||
// call stack to save (and the explicit stack always merges); the
|
||||
// distinction matters for a limit of 0, which reaches this at depth 0
|
||||
if (JSON_HEDLEY_UNLIKELY(merge_objects && depth >= detail::recursion_depth_limit()))
|
||||
if (JSON_HEDLEY_UNLIKELY(depth >= detail::recursion_depth_limit()))
|
||||
{
|
||||
update_members_iteratively(first, last);
|
||||
return;
|
||||
|
||||
Generated
+5
-94
@@ -106,7 +106,6 @@
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t, uint32_t
|
||||
#include <cstring> // memcmp, memcpy
|
||||
#include <functional> // less
|
||||
#include <limits> // numeric_limits
|
||||
#include <map> // map
|
||||
#include <memory> // unique_ptr
|
||||
@@ -189,11 +188,6 @@
|
||||
#define NLOHMANN_VIEW_THROW JSON_THROW_USER
|
||||
#endif
|
||||
|
||||
// debug checks of preconditions (assert(), off with NDEBUG): JSON_ASSERT is
|
||||
// one of the macros that json.hpp undefines at its end
|
||||
#include <cassert> // assert
|
||||
#define NLOHMANN_VIEW_ASSERT(x) assert(x)
|
||||
|
||||
// the parser stores a node's first word at once where the layout of `node` is
|
||||
// known to be little-endian (MSVC targets are); elsewhere field by field
|
||||
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(_MSC_VER)
|
||||
@@ -494,23 +488,6 @@ struct document_data
|
||||
node_capacity = inline_capacity;
|
||||
}
|
||||
|
||||
/// whether the n bytes at p overlap memory that the next parse releases or
|
||||
/// reuses: the owned text, the decoded strings, an owned image, and the
|
||||
/// current buffer of strings written by edits (earlier edit buffers are not
|
||||
/// covered, as their sizes are not kept); for the debug check in read()
|
||||
bool holds(const char* p, std::size_t n) const noexcept
|
||||
{
|
||||
const auto overlaps = [p, n](const char* b, std::size_t m) noexcept
|
||||
{
|
||||
// (std::less: a total order also for pointers into different objects)
|
||||
return n != 0 && m != 0 && std::less<const char*>()(p, b + m) && std::less<const char*>()(b, p + n);
|
||||
};
|
||||
return overlaps(owned.data(), owned.capacity())
|
||||
|| overlaps(arena.data(), arena.capacity())
|
||||
|| overlaps(reinterpret_cast<const char*>(owned_image.data()), owned_image.capacity()) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
|| (edits && !edits->texts.empty() && overlaps(edits->texts.back().get(), edits->text_cap));
|
||||
}
|
||||
|
||||
/// the largest node count whose size in bytes fits a std::size_t
|
||||
static constexpr std::size_t max_nodes() noexcept
|
||||
{
|
||||
@@ -3262,14 +3239,6 @@ NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_equal(const char* x, const char* y, std::
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether a float node holds the text nan, which an edit writes for a NaN (and records without a digit layout, so
|
||||
/// that a parsed float is told apart by one comparison of what the walk has loaded anyway): equal tokens are an
|
||||
/// equal value, except for this one
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE bool float_token_is_nan(const node& n, const char* s) noexcept
|
||||
{
|
||||
return NLOHMANN_VIEW_UNLIKELY(n.extra == 0xFFFFu) && n.len == 3 && s[0] == 'n';
|
||||
}
|
||||
|
||||
/// whether the n1 bytes at x are before the n2 bytes at y (memcmp() order, then the shorter first);
|
||||
/// the first difference is found eight bytes at a time
|
||||
NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_less(const char* x, std::size_t n1, const char* y, std::size_t n2) noexcept
|
||||
@@ -3879,7 +3848,7 @@ class lockstep
|
||||
case value_t::string:
|
||||
return a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
case value_t::number_float: // (the token, and the digit layout that the value is read with: they only differ in a damaged image)
|
||||
return same_float(a, b, std::integral_constant<bool, EA> {});
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
return integer_bits(*a) == integer_bits(*b);
|
||||
@@ -3974,17 +3943,6 @@ class lockstep
|
||||
return true;
|
||||
}
|
||||
|
||||
/// (a read-only document holds no NaN)
|
||||
bool same_float(const node* a, const node* b, std::false_type /*editable*/) const noexcept
|
||||
{
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len);
|
||||
}
|
||||
|
||||
bool same_float(const node* a, const node* b, std::true_type /*editable*/) const noexcept
|
||||
{
|
||||
return a->extra == b->extra && a->len == b->len && bytes_equal(m_a.str(*a), m_b.str(*b), a->len) && !float_token_is_nan(*a, m_a.str(*a));
|
||||
}
|
||||
|
||||
bool elements(const node* a, const node* b, unsigned budget, lockstep_path::entry& stop) noexcept
|
||||
{
|
||||
const node* pa = nav_a::first(m_a, a);
|
||||
@@ -4041,9 +3999,9 @@ bool certainly_equal(const view_side<BasicJsonType, ViewA>& a, const view_side<B
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (na == nb && (!view_side<BasicJsonType, ViewA>::nav::editable() || a.document().edits == nullptr))
|
||||
if (na == nb)
|
||||
{
|
||||
return true; // (the same node of the same document: documents have distinct nodes; a document with edits is walked, as an edit can have written a NaN, which is not equal to itself)
|
||||
return true; // (the same node of the same document: documents have distinct nodes)
|
||||
}
|
||||
path.resume = nullptr;
|
||||
if (path.next < path.length && path.nodes[path.next].a == na && path.nodes[path.next].b == nb)
|
||||
@@ -4088,7 +4046,7 @@ void resume_array(const lockstep_path& /*path*/, const A& /*a*/, const B& /*b*/,
|
||||
template<typename BasicJsonType, typename ViewA, typename ViewB>
|
||||
bool floats_equal(const view_side<BasicJsonType, ViewA>& a, const view_side<BasicJsonType, ViewB>& b)
|
||||
{
|
||||
return (a.value_node()->extra == b.value_node()->extra && a.float_token() == b.float_token() && !(view_side<BasicJsonType, ViewA>::nav::editable() && float_token_is_nan(*a.value_node(), a.float_token().data()))) || std::equal_to<typename BasicJsonType::number_float_t>()(a.floating(), b.floating());
|
||||
return (a.value_node()->extra == b.value_node()->extra && a.float_token() == b.float_token()) || std::equal_to<typename BasicJsonType::number_float_t>()(a.floating(), b.floating());
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
@@ -7458,28 +7416,6 @@ inline bool float_token_finite(const unsigned char* s, std::size_t len, const nu
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether an integer token (well-formed, no fraction or exponent) fits 64
|
||||
/// bits: the parser stores a number_integer or number_unsigned node for it,
|
||||
/// and a number_float node only for a token that does not fit
|
||||
inline bool integer_token_fits(const number_token& t)
|
||||
{
|
||||
if (t.int_digits > 20)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (t.int_digits == 20)
|
||||
{
|
||||
// (20 digits are compared with 2^64 - 1; a negative one is below -2^63)
|
||||
// (only a leading 1 needs the comparison: the first digit of 20 is not 0)
|
||||
return !t.negative && *t.int_start == '1' && std::memcmp(t.int_start, "18446744073709551615", 20) <= 0;
|
||||
}
|
||||
if (t.negative && t.int_digits == 19)
|
||||
{
|
||||
return *t.int_start != '9' || std::memcmp(t.int_start, "9223372036854775808", 19) <= 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// whether an integer node matches its token the way the parser records it
|
||||
/// (after the bounds check; the token has at most 256 characters)
|
||||
inline bool check_integer(const node& n, const unsigned char* text)
|
||||
@@ -7599,8 +7535,7 @@ inline bool check_float_ranges(std::vector<float_range>& ranges, const unsigned
|
||||
if (!plain_float_token(s, r.len, r.extra))
|
||||
{
|
||||
number_token t{};
|
||||
// (an integer token is a float node only if it does not fit 64 bits)
|
||||
if (!scan_number_token(s, r.len, t) || (!t.is_float && integer_token_fits(t)) || !float_token_finite(s, r.len, t))
|
||||
if (!scan_number_token(s, r.len, t) || !float_token_finite(s, r.len, t))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -11695,10 +11630,6 @@ class basic_json_document
|
||||
/// sentinel: src[size] is readable and 0 (std::string, C strings)
|
||||
void build(const char* src, std::size_t size, on_error allow_exceptions, bool comments, bool trailing_commas, bool owned, bool sentinel)
|
||||
{
|
||||
// precondition of read(): a borrowed input is not held by this document,
|
||||
// which releases what it holds below (checked in debug builds only, as
|
||||
// it would cost every read() of a small message a few percent)
|
||||
NLOHMANN_VIEW_ASSERT(owned || !m_data || !m_data->holds(src, size));
|
||||
ensure_data(src, size);
|
||||
document_data& d = *m_data;
|
||||
if (!owned)
|
||||
@@ -11788,10 +11719,6 @@ class basic_json_document
|
||||
template<typename T>
|
||||
void read_kind(const T& s, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::copy_range> /*unused*/)
|
||||
{
|
||||
// (the precondition of read() as for a borrowed input, although only an
|
||||
// input in the owned text breaks a copy: the same call borrows, for
|
||||
// example a std::string_view in C++17, and must not depend on that)
|
||||
NLOHMANN_VIEW_ASSERT(!m_data || !m_data->holds(reinterpret_cast<const char*>(s.data()), static_cast<std::size_t>(s.size()))); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
build_copy(s, ae, c, tc);
|
||||
}
|
||||
|
||||
@@ -11810,24 +11737,9 @@ class basic_json_document
|
||||
template<typename T>
|
||||
void read_kind(T&& input, on_error ae, bool c, bool tc, std::integral_constant<input_kind, input_kind::adapter> /*unused*/)
|
||||
{
|
||||
NLOHMANN_VIEW_ASSERT(!held(input)); // (see the copy_range overload)
|
||||
build_copy(std::forward<T>(input), ae, c, tc);
|
||||
}
|
||||
|
||||
/// whether an input read through the input adapter is held by this document:
|
||||
/// string_view_t before C++17 (a string handed out by a view), for the
|
||||
/// debug check of read(); other inputs of this kind do not point into it
|
||||
bool held(const detail::view::string_ref& s) const noexcept
|
||||
{
|
||||
return m_data && m_data->holds(s.data(), s.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool held(const T& /*input*/) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename IteratorType>
|
||||
void read_range(IteratorType first, IteratorType last, on_error ae, bool c, bool tc)
|
||||
{
|
||||
@@ -11983,7 +11895,6 @@ class tuple_element<N, ::nlohmann::detail::view::view_item<View>> // NOLINT(cert
|
||||
#undef NLOHMANN_VIEW_NOCLONE
|
||||
#undef NLOHMANN_VIEW_NODISCARD
|
||||
#undef NLOHMANN_VIEW_THROW
|
||||
#undef NLOHMANN_VIEW_ASSERT
|
||||
#undef NLOHMANN_VIEW_LITTLE_ENDIAN
|
||||
#undef NLOHMANN_VIEW_REPEAT16
|
||||
#undef NLOHMANN_VIEW_REPEAT_SECOND_8
|
||||
|
||||
@@ -36,21 +36,15 @@ using NLOHMANN_JSON_NAMESPACE::adl_serializer;
|
||||
using NLOHMANN_JSON_NAMESPACE::basic_json;
|
||||
using NLOHMANN_JSON_NAMESPACE::basic_json_document;
|
||||
using NLOHMANN_JSON_NAMESPACE::basic_json_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::is_json_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::json;
|
||||
using NLOHMANN_JSON_NAMESPACE::json_document;
|
||||
using NLOHMANN_JSON_NAMESPACE::json_editable_document;
|
||||
using NLOHMANN_JSON_NAMESPACE::json_editable_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::json_pointer;
|
||||
using NLOHMANN_JSON_NAMESPACE::json_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_json;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_json_document;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_json_editable_document;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_json_editable_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_json_view;
|
||||
using NLOHMANN_JSON_NAMESPACE::ordered_map;
|
||||
using NLOHMANN_JSON_NAMESPACE::to_string;
|
||||
using NLOHMANN_JSON_NAMESPACE::view_mode;
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
|
||||
+10
-14
@@ -355,20 +355,6 @@ json_test_add_test_for(src/unit-comparison.cpp
|
||||
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
|
||||
)
|
||||
|
||||
# test the walks over deeply nested values with the extreme settings of
|
||||
# JSON_RECURSION_DEPTH_LIMIT: 0 (every walk uses its explicit stack from the
|
||||
# first level on), 1, and 254 (the largest limit that fits the byte that counts
|
||||
# the nesting of a copy)
|
||||
foreach(recursion_depth_limit 0 1 254)
|
||||
json_test_set_test_options(test-recursion_depth_limit_${recursion_depth_limit}
|
||||
COMPILE_DEFINITIONS JSON_RECURSION_DEPTH_LIMIT=${recursion_depth_limit}
|
||||
)
|
||||
json_test_add_test_for(src/unit-recursion_depth_limit.cpp
|
||||
NAME test-recursion_depth_limit_${recursion_depth_limit}
|
||||
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# test the parser again with JSON_DIAGNOSTIC_POSITIONS enabled
|
||||
json_test_set_test_options(test-class_parser_diagnostic_positions
|
||||
COMPILE_DEFINITIONS JSON_DIAGNOSTIC_POSITIONS=1
|
||||
@@ -378,6 +364,16 @@ json_test_add_test_for(src/unit-class_parser.cpp
|
||||
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
|
||||
)
|
||||
|
||||
# test the conversions again without std::filesystem::path support: a
|
||||
# std::u8string must be a JSON string in this configuration, too
|
||||
json_test_set_test_options(test-conversions2_no_filesystem
|
||||
COMPILE_DEFINITIONS JSON_HAS_FILESYSTEM=0 JSON_HAS_EXPERIMENTAL_FILESYSTEM=0
|
||||
)
|
||||
json_test_add_test_for(src/unit-conversions2.cpp
|
||||
NAME test-conversions2_no_filesystem
|
||||
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
|
||||
)
|
||||
|
||||
# test diagnostic positions again without regular diagnostics (JSON pointer paths)
|
||||
json_test_set_test_options(test-diagnostic-positions_only
|
||||
COMPILE_DEFINITIONS JSON_DIAGNOSTICS=0
|
||||
|
||||
@@ -56,26 +56,9 @@ int main()
|
||||
const nlohmann::json_document doc = nlohmann::json_document::parse(R"({"a": 1, "list": [1, 2, 3]})");
|
||||
const std::size_t doc_size = doc.root().size();
|
||||
|
||||
// editable documents and views, view_mode, is_json_view and the ordered variants
|
||||
nlohmann::json_editable_document edoc = nlohmann::json_editable_document::parse(R"({"a": 1, "list": [1, 2, 3]})");
|
||||
edoc.set(edoc.root(), "b", 2);
|
||||
edoc.push_back(edoc.root()["list"], 4);
|
||||
const nlohmann::json_editable_view eroot = edoc.root();
|
||||
const std::size_t edit_size = eroot.size();
|
||||
const std::size_t list_size = eroot["list"].size();
|
||||
nlohmann::ordered_json_editable_document oedoc = nlohmann::ordered_json_editable_document::parse(R"({"z": 1, "y": 2})");
|
||||
oedoc.erase(oedoc.root(), "z");
|
||||
const nlohmann::ordered_json_editable_view oeroot = oedoc.root();
|
||||
nlohmann::basic_json_document<nlohmann::json, nlohmann::view_mode::editable> mdoc = nlohmann::basic_json_document<nlohmann::json, nlohmann::view_mode::editable>::parse("[]");
|
||||
mdoc.push_back(mdoc.root(), 1);
|
||||
static_assert(nlohmann::is_json_view<nlohmann::json_view>::value, "json_view is a view");
|
||||
static_assert(nlohmann::is_json_view<nlohmann::json_editable_view>::value, "json_editable_view is a view");
|
||||
static_assert(!nlohmann::is_json_view<nlohmann::json>::value, "json is not a view");
|
||||
|
||||
// use every result so the references cannot be optimized away
|
||||
return (a == 1 && last == 3 && b == 2 && lit.size() == 3
|
||||
&& m.size() == 1 && !dumped.empty() && !os.str().empty()
|
||||
&& doc_size == 2
|
||||
&& edit_size == 3 && list_size == 4 && oeroot.size() == 1 && mdoc.root().size() == 1)
|
||||
&& doc_size == 2)
|
||||
? 0 : 1;
|
||||
}
|
||||
@@ -236,8 +236,7 @@ TEST_CASE("controlled bad_alloc")
|
||||
|
||||
next_construct_fails = false;
|
||||
|
||||
// deeper than the levels the copy constructor descends into
|
||||
// (recursion_depth_limit(): 128 by default, 254 at most)
|
||||
// deeper than the 128 levels the copy constructor descends into
|
||||
const std::size_t depth = 300;
|
||||
|
||||
my_json j = 1;
|
||||
@@ -301,9 +300,8 @@ struct nth_alloc_fails_allocator : std::allocator<T>
|
||||
};
|
||||
};
|
||||
|
||||
// builds a value nested more than recursion_depth_limit() (128 by default)
|
||||
// levels deep - the bound the copy constructor descends into before it
|
||||
// continues without the call stack - and
|
||||
// builds a value nested more than 128 levels deep - the bound the copy
|
||||
// constructor descends into before it continues without the call stack - and
|
||||
// checks that a copy survives any single allocation of it failing: every
|
||||
// attempt either throws std::bad_alloc, without crashing or leaving the
|
||||
// source altered, or completes the copy
|
||||
@@ -314,9 +312,9 @@ void check_deep_copy_survives_failing_allocation(bool nest_objects)
|
||||
|
||||
fail_at_alloc_call = -1;
|
||||
|
||||
// [[[ ... [1] ... ]]], or the same nesting with objects, two levels deeper than the limit
|
||||
// [[[ ... [1] ... ]]], or the same nesting with objects, 130 levels deep
|
||||
BasicJsonType src = 1;
|
||||
for (std::size_t i = 0; i < nlohmann::detail::recursion_depth_limit() + 2; ++i)
|
||||
for (std::size_t i = 0; i < 130; ++i)
|
||||
{
|
||||
if (nest_objects)
|
||||
{
|
||||
@@ -442,9 +440,8 @@ TEST_CASE("deep copy uses the provided allocator")
|
||||
{
|
||||
using counting_json = nlohmann::json::with_allocator_t<scratch_counting_allocator>;
|
||||
|
||||
// deeper than the levels the copy constructor descends into (128 by
|
||||
// default, 254 at most), so the innermost objects are copied by the
|
||||
// iterative deep copy
|
||||
// deeper than the 128 levels the copy constructor descends into, so the
|
||||
// innermost objects are copied by the iterative deep copy
|
||||
counting_json j = 1;
|
||||
for (std::size_t i = 0; i < 300; ++i)
|
||||
{
|
||||
@@ -502,12 +499,11 @@ TEST_CASE("converting a deeply nested value from another specialization fails cl
|
||||
#if !(defined(_MSC_VER) && _MSC_VER < 1910 && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL > 0)
|
||||
using countdown_json = nlohmann::json::with_allocator_t<countdown_allocator>;
|
||||
|
||||
// deeper than the levels the converting constructor descends into
|
||||
// (recursion_depth_limit(), 128 by default), so that failures land on both
|
||||
// sides of the bound - or, built with JSON_NO_THREAD_LOCAL, all in the
|
||||
// iterative conversion
|
||||
// deeper than the 128 levels the converting constructor descends into, so
|
||||
// that failures land on both sides of the bound - or, built with
|
||||
// JSON_NO_THREAD_LOCAL, all in the iterative conversion
|
||||
json j = {1, "two", {{"three", 3}}};
|
||||
for (std::size_t i = 0; i < nlohmann::detail::recursion_depth_limit() + 22; ++i)
|
||||
for (std::size_t i = 0; i < 150; ++i)
|
||||
{
|
||||
j = json{{"a", json::array({j, "sibling"})}};
|
||||
}
|
||||
|
||||
@@ -531,12 +531,25 @@ TEST_CASE("alternative string type with json_view")
|
||||
CHECK(d.root().materialize() == expected);
|
||||
CHECK(alt_json::parse(d.root().dump()) == expected);
|
||||
|
||||
// save() and load() do not exist on big-endian targets
|
||||
#if !(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
const alt_editable_document loaded = alt_editable_document::load(d.save());
|
||||
CHECK(loaded.root().materialize() == expected);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// a std::u8string is a JSON string, whatever the string type of the JSON value
|
||||
// JSON_HAS_CPP_20 JSON_HAS_CPP_23 (do not remove; see note at top of file)
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
TEST_CASE("alternative string type and std::u8string")
|
||||
{
|
||||
const std::u8string s = u8"abc";
|
||||
const alt_json j = s;
|
||||
CHECK(j.is_string());
|
||||
CHECK(j.get<alt_string>() == alt_string("abc"));
|
||||
CHECK(j.get<std::u8string>() == s);
|
||||
|
||||
// the array of code units written by versions before 3.13.0
|
||||
CHECK(alt_json::array({0x61, 0x62, 0x63}).get<std::u8string>() == s);
|
||||
}
|
||||
#endif
|
||||
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_POP
|
||||
@@ -94,37 +94,6 @@ TEST_CASE("JSON_BRACE_INIT_COPY_SEMANTICS")
|
||||
CHECK(j3 == pair_shaped);
|
||||
}
|
||||
|
||||
SECTION("push_back and operator+= with a single braced JSON value")
|
||||
{
|
||||
// with the macro, the result does not depend on the compiler;
|
||||
// without it, GCC wraps a JSON value and Clang does not (a literal
|
||||
// such as {1} is wrapped by both)
|
||||
json const obj = {{"key", "value"}};
|
||||
json const arr = {1, 2};
|
||||
|
||||
json a1 = json::array();
|
||||
a1.push_back({obj});
|
||||
CHECK(a1 == json::array({obj}));
|
||||
|
||||
json a2 = json::array();
|
||||
a2 += {obj};
|
||||
CHECK(a2 == json::array({obj}));
|
||||
|
||||
json b1 = json::array();
|
||||
b1.push_back({arr});
|
||||
CHECK(b1 == json::array({arr}));
|
||||
|
||||
json b2 = json::array();
|
||||
b2 += {arr};
|
||||
CHECK(b2 == json::array({arr}));
|
||||
|
||||
// a literal is copied as well
|
||||
json c = json::array();
|
||||
c.push_back({1});
|
||||
c += {2};
|
||||
CHECK(c == json::array({1, 2}));
|
||||
}
|
||||
|
||||
SECTION("what the macro does not change")
|
||||
{
|
||||
// lists with more than one element are unaffected
|
||||
|
||||
@@ -3232,40 +3232,3 @@ TEST_CASE("object keys are delivered decoded and validated")
|
||||
CHECK(keys_of_format(std::string("\x87\xC3\x28\x91"), json::input_format_t::bon8).empty());
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// a plain function (not a lambda or std::function) used as parser callback
|
||||
bool keep_everything_callback(int /*depth*/, json::parse_event_t /*event*/, json& /*parsed*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("a plain function is accepted as parser callback for containers")
|
||||
{
|
||||
// ADL finds basic_json's friend operator!= for "container != function
|
||||
// pointer", which must not make the iterator/sentinel overloads viable
|
||||
|
||||
const json expected = {1, 2};
|
||||
const std::string text = "[1,2]";
|
||||
const std::vector<std::uint8_t> bytes(text.begin(), text.end());
|
||||
const std::vector<char> chars(text.begin(), text.end());
|
||||
|
||||
CHECK(json::parse(text, keep_everything_callback) == expected);
|
||||
CHECK(json::parse(text, &keep_everything_callback) == expected);
|
||||
CHECK(json::parse(std::string("[1,2]"), keep_everything_callback) == expected);
|
||||
CHECK(json::parse(bytes, keep_everything_callback) == expected);
|
||||
CHECK(json::parse(bytes, &keep_everything_callback) == expected);
|
||||
CHECK(json::parse(chars, keep_everything_callback) == expected);
|
||||
CHECK(json::parse(text.begin(), text.end(), keep_everything_callback) == expected);
|
||||
|
||||
// the sentinel overloads (shared constraint of parse, accept, sax_parse and
|
||||
// the from_* functions) are not viable for a container and a function
|
||||
// pointer, but still are for iterator pairs
|
||||
using callback_pointer = decltype(&keep_everything_callback);
|
||||
CHECK_FALSE((nlohmann::detail::can_compare_ne<std::string, callback_pointer>::value));
|
||||
CHECK_FALSE((nlohmann::detail::can_compare_ne<std::vector<std::uint8_t>, callback_pointer>::value));
|
||||
CHECK((nlohmann::detail::can_compare_ne<std::string::const_iterator, std::string::const_iterator>::value));
|
||||
CHECK((nlohmann::detail::can_compare_ne<const char*, const char*>::value));
|
||||
}
|
||||
@@ -62,15 +62,6 @@ template<> struct StringMaker<std::partial_ordering>
|
||||
|
||||
namespace
|
||||
{
|
||||
// nesting depths on either side of detail::recursion_depth_limit(): none, the
|
||||
// last one within the limit, the first one past it, and well past it (0, 127,
|
||||
// 128, and 200 by default)
|
||||
std::vector<std::size_t> depths_around_recursion_limit()
|
||||
{
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
return {0, limit > 0 ? limit - 1 : 0, limit, limit + 72};
|
||||
}
|
||||
|
||||
// helper function to check std::less<json::value_t>
|
||||
// see https://en.cppreference.com/w/cpp/utility/functional/less
|
||||
template <typename A, typename B, typename U = std::less<json::value_t>>
|
||||
@@ -977,7 +968,7 @@ TEST_CASE("copying an object preserves its comparator's state")
|
||||
object["a"] = 3;
|
||||
REQUIRE(object.dump() == R"({"B":2,"a":3,"b":1})");
|
||||
|
||||
for (const std::size_t depth : depths_around_recursion_limit())
|
||||
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
|
||||
{
|
||||
CAPTURE(depth)
|
||||
|
||||
@@ -1020,7 +1011,7 @@ TEST_CASE("equality of an object whose comparator treats different keys as equiv
|
||||
// sanity check: the object type's own comparison already disagrees
|
||||
CHECK_FALSE(a.get_ref<const ci_json::object_t&>() == b.get_ref<const ci_json::object_t&>());
|
||||
|
||||
for (const std::size_t depth : depths_around_recursion_limit())
|
||||
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
|
||||
{
|
||||
CAPTURE(depth)
|
||||
|
||||
@@ -1144,10 +1135,9 @@ TEST_CASE("operator<=> of binary values with a different subtype does not depend
|
||||
return result;
|
||||
};
|
||||
|
||||
// one level less than the recursion depth limit (127 by default) stays within it;
|
||||
// the limit itself and more (128 and 200) do not, and must still agree with the
|
||||
// levels that do
|
||||
for (const std::size_t depth : depths_around_recursion_limit())
|
||||
// 127 levels stay within nesting_depth_limit() (128); 128 and 200 do not,
|
||||
// and must still agree with the levels that do
|
||||
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
|
||||
{
|
||||
CAPTURE(depth)
|
||||
const json x = deep(a, depth);
|
||||
|
||||
@@ -27,10 +27,12 @@ using nlohmann::json;
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
|
||||
// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
||||
@@ -707,38 +709,114 @@ TEST_CASE("std::filesystem::path")
|
||||
}
|
||||
#endif
|
||||
|
||||
// the ADL to_json overload for std::u8string only exists under the same guard
|
||||
// as std::filesystem::path support (it is otherwise only reached indirectly,
|
||||
// via std::filesystem::path::u8string()) -- mirror both #if conditions from
|
||||
// include/nlohmann/detail/conversions/to_json.hpp exactly
|
||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||
// a std::u8string is a JSON string since 3.13.0 (it was an array of code units
|
||||
// before); independent of whether std::filesystem::path is supported, see the
|
||||
// test-conversions2_no_filesystem target
|
||||
// JSON_HAS_CPP_20 JSON_HAS_CPP_23 (do not remove; see note at top of file)
|
||||
#if defined(__cpp_lib_char8_t)
|
||||
TEST_CASE("std::u8string")
|
||||
{
|
||||
// use \u universal-character-names (rather than raw \x byte escapes
|
||||
// or literal non-ASCII source bytes) to compose the multi-byte UTF-8
|
||||
// encoding -- MSVC treats \x escapes used that way inside a u8
|
||||
// literal as a nonstandard extension (warning C5321), which some of
|
||||
// our CI configs promote to an error; \u is portable and produces
|
||||
// the exact same encoded bytes without depending on the source
|
||||
// file's encoding
|
||||
const std::u8string utf8 = u8"P\u011B\u0161ina";
|
||||
|
||||
SECTION("ascii")
|
||||
{
|
||||
const std::u8string s = u8"Path";
|
||||
json const j = s;
|
||||
|
||||
CHECK(j.is_string());
|
||||
CHECK(j.template get<std::string>() == "Path");
|
||||
}
|
||||
|
||||
SECTION("utf-8")
|
||||
{
|
||||
// use \u universal-character-names (rather than raw \x byte escapes
|
||||
// or literal non-ASCII source bytes) to compose the multi-byte UTF-8
|
||||
// encoding -- MSVC treats \x escapes used that way inside a u8
|
||||
// literal as a nonstandard extension (warning C5321), which some of
|
||||
// our CI configs promote to an error; \u is portable and produces
|
||||
// the exact same encoded bytes without depending on the source
|
||||
// file's encoding
|
||||
const std::u8string s = u8"P\u011B\u0161ina";
|
||||
json const j = s;
|
||||
json const j = utf8;
|
||||
|
||||
CHECK(j.is_string());
|
||||
CHECK(j.template get<std::string>() == "P\xc4\x9b\xc5\xa1ina");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("round trip")
|
||||
{
|
||||
json const j = utf8;
|
||||
CHECK(j.template get<std::u8string>() == utf8);
|
||||
|
||||
std::u8string back;
|
||||
j.get_to(back);
|
||||
CHECK(back == utf8);
|
||||
|
||||
// from a string
|
||||
json const j_string = "P\xc4\x9b\xc5\xa1ina";
|
||||
CHECK(j_string.template get<std::u8string>() == utf8);
|
||||
|
||||
// empty, and with an embedded NUL
|
||||
CHECK(json(std::u8string()).template get<std::u8string>().empty());
|
||||
const std::u8string with_nul(u8"a\0b", 3);
|
||||
CHECK(json(with_nul).template get<std::u8string>() == with_nul);
|
||||
|
||||
// the lvalue and rvalue paths, and in containers
|
||||
std::u8string lvalue = utf8;
|
||||
CHECK(json(lvalue).template get<std::u8string>() == utf8);
|
||||
CHECK(json(std::move(lvalue)).template get<std::u8string>() == utf8);
|
||||
const std::vector<std::u8string> vec = {utf8, u8"x"};
|
||||
json const j_vec = vec;
|
||||
CHECK(j_vec.is_array());
|
||||
CHECK(j_vec[0].is_string());
|
||||
CHECK(j_vec.template get<std::vector<std::u8string>>() == vec);
|
||||
const std::map<std::string, std::u8string> map = {{"k", utf8}};
|
||||
CHECK(json(map).template get<std::map<std::string, std::u8string>>() == map);
|
||||
}
|
||||
|
||||
SECTION("array of code units (written by versions before 3.13.0)")
|
||||
{
|
||||
json const j = json::array({0x50, 0xC4, 0x9B, 0xC5, 0xA1, 0x69, 0x6E, 0x61});
|
||||
CHECK(j.template get<std::u8string>() == utf8);
|
||||
CHECK(json::array().template get<std::u8string>().empty());
|
||||
CHECK(json::parse("[97, 98]").template get<std::u8string>() == u8"ab");
|
||||
|
||||
std::u8string s = u8"overwritten";
|
||||
j.get_to(s);
|
||||
CHECK(s == utf8);
|
||||
}
|
||||
|
||||
SECTION("other types")
|
||||
{
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
CHECK_THROWS_WITH_AS(json(1).template get<std::u8string>(), "[json.exception.type_error.302] type must be string or array, but is number", json::type_error);
|
||||
CHECK_THROWS_WITH_AS(json(nullptr).template get<std::u8string>(), "[json.exception.type_error.302] type must be string or array, but is null", json::type_error);
|
||||
CHECK_THROWS_AS(json::object().template get<std::u8string>(), json::type_error);
|
||||
// an element that is not a number
|
||||
CHECK_THROWS_AS(json::array({"a"}).template get<std::u8string>(), json::type_error);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("ordered_json")
|
||||
{
|
||||
nlohmann::ordered_json const j = utf8;
|
||||
CHECK(j.is_string());
|
||||
CHECK(j.template get<std::string>() == "P\xc4\x9b\xc5\xa1ina");
|
||||
CHECK(j.template get<std::u8string>() == utf8);
|
||||
CHECK(nlohmann::ordered_json::array({0x61, 0x62}).template get<std::u8string>() == u8"ab");
|
||||
}
|
||||
|
||||
SECTION("std::u8string_view and char8_t arrays are unchanged (arrays of code units)")
|
||||
{
|
||||
const std::u8string_view view = utf8;
|
||||
json const j_view = view;
|
||||
CHECK(j_view.is_array());
|
||||
CHECK(j_view.size() == 8);
|
||||
|
||||
const char8_t arr[] = u8"ab";
|
||||
json const j_arr = arr;
|
||||
CHECK(j_arr == json::array({0x61, 0x62, 0}));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
@@ -218,17 +217,16 @@ TEST_CASE("array type with std::deque nested beyond the recursion limit")
|
||||
// recursion_depth_limit() with an explicit stack of frames; with the
|
||||
// iterators of std::deque, these frames are copied and moved through
|
||||
// their own special members
|
||||
const std::size_t depth = nlohmann::detail::recursion_depth_limit() + 72; // 200 by default
|
||||
deque_json j = 1;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
for (int i = 0; i < 200; ++i)
|
||||
{
|
||||
deque_json outer = deque_json::array();
|
||||
outer.push_back(std::move(j));
|
||||
j = std::move(outer);
|
||||
}
|
||||
|
||||
// `depth` arrays of one element each (0x81) around the integer 1
|
||||
std::vector<std::uint8_t> expected(depth, 0x81);
|
||||
// 200 arrays of one element each (0x81) around the integer 1
|
||||
std::vector<std::uint8_t> expected(200, 0x81);
|
||||
expected.push_back(0x01);
|
||||
CHECK(deque_json::to_cbor(j) == expected);
|
||||
}
|
||||
@@ -475,10 +475,10 @@ TEST_CASE("Regression test for issue #5674 - copy construction must not require
|
||||
|
||||
SECTION("nested deeper than the copy constructor's descent bound")
|
||||
{
|
||||
// beyond recursion_depth_limit() (128 by default) levels, the copy constructor
|
||||
// beyond nesting_depth_limit() (128) levels, the copy constructor
|
||||
// copies without the call stack (copy_iteratively / copy_array_level),
|
||||
// which used to assign the base class of every element it created
|
||||
const std::size_t depth = nlohmann::detail::recursion_depth_limit() + 172;
|
||||
const std::size_t depth = 300;
|
||||
|
||||
const json_with_const_base j = make_nested_array(depth);
|
||||
const json_with_const_base copy = j; // NOLINT(performance-unnecessary-copy-initialization)
|
||||
|
||||
@@ -128,19 +128,16 @@ TEST_CASE("Better diagnostics with positions")
|
||||
check_copy(depth, true);
|
||||
};
|
||||
|
||||
// around detail::recursion_depth_limit() (127, 128, and 129 by default)
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
|
||||
check_arrays(1);
|
||||
check_arrays(limit > 0 ? limit - 1 : 0);
|
||||
check_arrays(limit);
|
||||
check_arrays(limit + 1);
|
||||
check_arrays(127);
|
||||
check_arrays(128);
|
||||
check_arrays(129);
|
||||
check_arrays(300);
|
||||
|
||||
check_objects(1);
|
||||
check_objects(limit > 0 ? limit - 1 : 0);
|
||||
check_objects(limit);
|
||||
check_objects(limit + 1);
|
||||
check_objects(127);
|
||||
check_objects(128);
|
||||
check_objects(129);
|
||||
check_objects(300);
|
||||
}
|
||||
|
||||
@@ -189,13 +186,10 @@ TEST_CASE("Better diagnostics with positions")
|
||||
}
|
||||
};
|
||||
|
||||
// around detail::recursion_depth_limit() (127, 128, and 129 by default)
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
|
||||
check_conversion(1);
|
||||
check_conversion(limit > 0 ? limit - 1 : 0);
|
||||
check_conversion(limit);
|
||||
check_conversion(limit + 1);
|
||||
check_conversion(127);
|
||||
check_conversion(128);
|
||||
check_conversion(129);
|
||||
check_conversion(300);
|
||||
}
|
||||
|
||||
|
||||
@@ -515,11 +515,9 @@ TEST_CASE("Regression tests for extended diagnostics")
|
||||
|
||||
// update(j, true) around its descent bound, where the nested vectors
|
||||
// grow while the objects are merged without recursing
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
// (the limit can be 0, where "one level less" is no level)
|
||||
for (const std::size_t depth :
|
||||
{
|
||||
limit > 0 ? limit - 1 : 0, limit, limit + 2
|
||||
nlohmann::detail::recursion_depth_limit() - 1, nlohmann::detail::recursion_depth_limit(), nlohmann::detail::recursion_depth_limit() + 2
|
||||
})
|
||||
{
|
||||
ordered_json j = {{"z", {{"x", 1}}}};
|
||||
|
||||
@@ -14,12 +14,9 @@ using nlohmann::json;
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -1978,15 +1975,14 @@ TEST_CASE("JSON patch: diff of deeply nested values")
|
||||
SECTION("the diff reproduces the target at every depth")
|
||||
{
|
||||
// depths on either side of the nesting depth up to which diff()
|
||||
// recurses (detail::recursion_depth_limit(), 128 by default); not every depth up
|
||||
// recurses (detail::recursion_depth_limit(), 128); not every depth up
|
||||
// to 300, as the test would then time out under Valgrind
|
||||
std::vector<std::size_t> depths;
|
||||
for (std::size_t depth = 0; depth <= 16; ++depth)
|
||||
{
|
||||
depths.push_back(depth);
|
||||
}
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
for (std::size_t depth = limit > 8 ? limit - 8 : 0; depth <= limit + 8; ++depth)
|
||||
for (std::size_t depth = 120; depth <= 136; ++depth)
|
||||
{
|
||||
depths.push_back(depth);
|
||||
}
|
||||
@@ -2528,7 +2524,7 @@ TEST_CASE("JSON patch - diff of leaf values below the bound of the recursive des
|
||||
// the values at the innermost level are diffed without recursion: equal
|
||||
// leaves yield nothing, leaves of different types and different leaves
|
||||
// are replaced
|
||||
const std::size_t depth = nlohmann::detail::recursion_depth_limit() + 72; // 200 by default
|
||||
const std::size_t depth = 200;
|
||||
|
||||
json source = {1, "text", 3, {{"x", 1}, {"y", 2}}, true, nullptr};
|
||||
json target = {1, 2, 4, {{"x", 1}, {"y", 3}}, true, nullptr};
|
||||
@@ -2555,419 +2551,3 @@ TEST_CASE("JSON patch - diff of leaf values below the bound of the recursive des
|
||||
CHECK(object_patch.size() == 2);
|
||||
CHECK(object_source.patch(object_patch) == object_target);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// all pointers to values below `value` (not to `value` itself)
|
||||
void collect_pointers(const json& value, const std::string& path, std::vector<std::string>& pointers)
|
||||
{
|
||||
if (value.is_object())
|
||||
{
|
||||
for (const auto& element : value.items())
|
||||
{
|
||||
std::string child = path;
|
||||
child += '/';
|
||||
for (const char c : element.key())
|
||||
{
|
||||
if (c == '~')
|
||||
{
|
||||
child += "~0";
|
||||
}
|
||||
else if (c == '/')
|
||||
{
|
||||
child += "~1";
|
||||
}
|
||||
else
|
||||
{
|
||||
child += c;
|
||||
}
|
||||
}
|
||||
pointers.push_back(child);
|
||||
collect_pointers(element.value(), child, pointers);
|
||||
}
|
||||
}
|
||||
else if (value.is_array())
|
||||
{
|
||||
for (std::size_t i = 0; i < value.size(); ++i)
|
||||
{
|
||||
std::string child = path;
|
||||
child += '/';
|
||||
child += std::to_string(i);
|
||||
pointers.push_back(child);
|
||||
collect_pointers(value[i], child, pointers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a random document of at most `depth` levels, with the names as keys
|
||||
json random_document(std::mt19937& gen, const std::vector<std::string>& names, const int depth)
|
||||
{
|
||||
const int kind = std::uniform_int_distribution<int>(0, 9)(gen);
|
||||
if (depth == 0 || kind < 2)
|
||||
{
|
||||
return std::uniform_int_distribution<int>(0, 3)(gen);
|
||||
}
|
||||
const int size = std::uniform_int_distribution<int>(1, 3)(gen);
|
||||
json result = kind < 6 ? json::array() : json::object();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
if (kind < 6)
|
||||
{
|
||||
result.push_back(random_document(gen, names, depth - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
result[names[std::uniform_int_distribution<std::size_t>(0, names.size() - 1)(gen)]] = random_document(gen, names, depth - 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// the strings, one after the other
|
||||
std::string concat(std::string first, const std::string& second, const std::string& third = std::string())
|
||||
{
|
||||
first += second;
|
||||
first += third;
|
||||
return first;
|
||||
}
|
||||
|
||||
// the best of five times in seconds that std::clock() measures to apply the patch
|
||||
double patch_cpu_time(json& doc, const json& patch)
|
||||
{
|
||||
double best = 1e30;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
const std::clock_t start = std::clock();
|
||||
doc.patch_inplace(patch);
|
||||
best = (std::min)(best, static_cast<double>(std::clock() - start) / static_cast<double>(CLOCKS_PER_SEC));
|
||||
}
|
||||
return best;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("JSON patch - consecutive operations with paths that share a prefix")
|
||||
{
|
||||
SECTION("tokens that start the same way")
|
||||
{
|
||||
const json doc = {{"a", {{"bc", {{"x", 1}}}, {"b", {{"x", 2}}}, {"b2", 3}}}};
|
||||
|
||||
// the second path shares "/a/b" with the first, but not the token "bc"
|
||||
const json patch = json::parse(R"([
|
||||
{"op": "test", "path": "/a/bc/x", "value": 1},
|
||||
{"op": "test", "path": "/a/b/x", "value": 2},
|
||||
{"op": "test", "path": "/a/bc/x", "value": 1},
|
||||
{"op": "test", "path": "/a/b2", "value": 3},
|
||||
{"op": "test", "path": "/a/b/x", "value": 2}
|
||||
])");
|
||||
CHECK(doc.patch(patch) == doc);
|
||||
|
||||
json inplace = doc;
|
||||
inplace.patch_inplace(patch);
|
||||
CHECK(inplace == doc);
|
||||
|
||||
// a path that is a prefix of the previous one, and the other way round
|
||||
const json prefixes = json::parse(R"([
|
||||
{"op": "test", "path": "/a/bc/x", "value": 1},
|
||||
{"op": "test", "path": "/a/bc", "value": {"x": 1}},
|
||||
{"op": "test", "path": "/a/bc/x", "value": 1},
|
||||
{"op": "test", "path": "/a", "value": {"bc": {"x": 1}, "b": {"x": 2}, "b2": 3}},
|
||||
{"op": "test", "path": "/a/b/x", "value": 2},
|
||||
{"op": "test", "path": "", "value": {"a": {"bc": {"x": 1}, "b": {"x": 2}, "b2": 3}}}
|
||||
])");
|
||||
CHECK(doc.patch(prefixes) == doc);
|
||||
}
|
||||
|
||||
SECTION("operations above a path that was resolved before")
|
||||
{
|
||||
const json doc = json::parse(R"({"a": [{"b": [1, 2, 3]}, {"b": [4, 5, 6]}], "c": {"d": {"e": 7}}})");
|
||||
|
||||
// an element inserted before the elements of an array moves them
|
||||
CHECK(doc.patch(json::parse(R"([
|
||||
{"op": "test", "path": "/a/0/b/2", "value": 3},
|
||||
{"op": "add", "path": "/a/0", "value": {"b": [9]}},
|
||||
{"op": "test", "path": "/a/1/b/2", "value": 3},
|
||||
{"op": "test", "path": "/a/0/b/0", "value": 9},
|
||||
{"op": "test", "path": "/a/2/b/0", "value": 4}
|
||||
])")) == json::parse(R"({"a": [{"b": [9]}, {"b": [1, 2, 3]}, {"b": [4, 5, 6]}], "c": {"d": {"e": 7}}})"));
|
||||
|
||||
// an element removed from the front
|
||||
CHECK(doc.patch(json::parse(R"([
|
||||
{"op": "test", "path": "/a/1/b/2", "value": 6},
|
||||
{"op": "remove", "path": "/a/0"},
|
||||
{"op": "test", "path": "/a/0/b/2", "value": 6},
|
||||
{"op": "replace", "path": "/a/0/b/2", "value": 60},
|
||||
{"op": "test", "path": "/a/0/b/2", "value": 60}
|
||||
])")) == json::parse(R"({"a": [{"b": [4, 5, 60]}], "c": {"d": {"e": 7}}})"));
|
||||
|
||||
// a value replaced above the path that was resolved before
|
||||
CHECK(doc.patch(json::parse(R"([
|
||||
{"op": "test", "path": "/c/d/e", "value": 7},
|
||||
{"op": "replace", "path": "/c/d", "value": {"e": 8, "f": {"g": 9}}},
|
||||
{"op": "test", "path": "/c/d/e", "value": 8},
|
||||
{"op": "test", "path": "/c/d/f/g", "value": 9},
|
||||
{"op": "remove", "path": "/c/d/f"},
|
||||
{"op": "add", "path": "/c/d/f", "value": [1]},
|
||||
{"op": "test", "path": "/c/d/f/0", "value": 1}
|
||||
])")) == json::parse(R"({"a": [{"b": [1, 2, 3]}, {"b": [4, 5, 6]}], "c": {"d": {"e": 8, "f": [1]}}})"));
|
||||
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
// a value removed above the path that was resolved before is gone
|
||||
const json removed = json::parse(R"([
|
||||
{"op": "test", "path": "/c/d/e", "value": 7},
|
||||
{"op": "remove", "path": "/c/d"},
|
||||
{"op": "test", "path": "/c/d/e", "value": 7}
|
||||
])");
|
||||
CHECK_THROWS_AS(doc.patch(removed), json::other_error&);
|
||||
json inplace = doc;
|
||||
CHECK_THROWS_AS(inplace.patch_inplace(removed), json::other_error&);
|
||||
|
||||
const json emptied = json::parse(R"([
|
||||
{"op": "test", "path": "/a/1/b/2", "value": 6},
|
||||
{"op": "remove", "path": "/a/1"},
|
||||
{"op": "test", "path": "/a/1/b/2", "value": 6}
|
||||
])");
|
||||
CHECK_THROWS_AS(doc.patch(emptied), json::other_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("paths with more than 16 tokens")
|
||||
{
|
||||
// 40 levels, with an array at the bottom and a second branch at level 20
|
||||
std::string prefix20;
|
||||
std::string prefix40;
|
||||
json doc = {{"leaf", {1, 2, 3}}};
|
||||
for (int i = 40; i > 0; --i)
|
||||
{
|
||||
if (i == 20)
|
||||
{
|
||||
doc["other"] = {{"x", 5}};
|
||||
}
|
||||
doc = {{"n", doc}};
|
||||
}
|
||||
for (int i = 1; i <= 40; ++i)
|
||||
{
|
||||
prefix40 += "/n";
|
||||
if (i == 20)
|
||||
{
|
||||
prefix20 = prefix40;
|
||||
}
|
||||
}
|
||||
|
||||
const auto op = [](const char* name, const std::string & path, const json & value)
|
||||
{
|
||||
return json({{"op", name}, {"path", path}, {"value", value}});
|
||||
};
|
||||
const json patch =
|
||||
{
|
||||
op("test", concat(prefix40, "/leaf/2"), 3),
|
||||
op("test", concat(prefix20, "/other/x"), 5),
|
||||
op("test", concat(prefix40, "/leaf/0"), 1),
|
||||
op("add", concat(prefix40, "/leaf/0"), 0),
|
||||
op("test", concat(prefix40, "/leaf/3"), 3),
|
||||
op("replace", concat(prefix20, "/other"), {{"x", 6}}),
|
||||
op("test", concat(prefix20, "/other/x"), 6),
|
||||
op("test", concat(prefix40, "/leaf/1"), 1),
|
||||
{{"op", "remove"}, {"path", concat(prefix20, "/other")}},
|
||||
op("test", concat(prefix40, "/leaf/1"), 1)
|
||||
};
|
||||
json expected = doc;
|
||||
for (const auto& operation : patch)
|
||||
{
|
||||
expected = expected.patch(json::array({operation}));
|
||||
}
|
||||
CHECK(doc.patch(patch) == expected);
|
||||
json inplace = doc;
|
||||
inplace.patch_inplace(patch);
|
||||
CHECK(inplace == expected);
|
||||
CHECK(expected[json::json_pointer(concat(prefix40, "/leaf"))] == json({0, 1, 2, 3}));
|
||||
CHECK(!expected[json::json_pointer(prefix20)].contains("other"));
|
||||
|
||||
#if !defined(JSON_NOEXCEPTION)
|
||||
// the value that was resolved before is gone with the member that held it
|
||||
const json gone =
|
||||
{
|
||||
op("test", concat(prefix40, "/leaf/2"), 3),
|
||||
{{"op", "remove"}, {"path", prefix20}},
|
||||
op("test", concat(prefix40, "/leaf/2"), 3)
|
||||
};
|
||||
CHECK_THROWS_AS(doc.patch(gone), json::other_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("random sequences of operations give the same result as one operation at a time")
|
||||
{
|
||||
std::mt19937 gen(20261110); // NOLINT(cert-msc32-c,cert-msc51-cpp,bugprone-random-generator-seed): reproducible
|
||||
const std::vector<std::string> names = {"a", "b", "ab", "abc", "a/b", "a~b", "1", "10", "token_longer_than_eight_bytes"};
|
||||
const auto pick = [&gen](const std::size_t n)
|
||||
{
|
||||
return std::uniform_int_distribution<std::size_t>(0, n - 1)(gen);
|
||||
};
|
||||
|
||||
for (int round = 0; round < 300; ++round)
|
||||
{
|
||||
const json start = random_document(gen, names, 7);
|
||||
json current = start;
|
||||
json patch = json::array();
|
||||
std::string previous;
|
||||
|
||||
for (int step = 0; step < 25; ++step)
|
||||
{
|
||||
std::vector<std::string> pointers;
|
||||
collect_pointers(current, "", pointers);
|
||||
if (pointers.empty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// most of the time, stay below a part of the previous path
|
||||
std::vector<std::string> candidates;
|
||||
if (!previous.empty() && pick(10) < 8)
|
||||
{
|
||||
std::string prefix = previous;
|
||||
const std::size_t cut = prefix.find('/', 1 + pick(prefix.size()));
|
||||
prefix = prefix.substr(0, cut == std::string::npos ? prefix.size() : cut);
|
||||
for (const auto& p : pointers)
|
||||
{
|
||||
if (p.compare(0, prefix.size(), prefix) == 0)
|
||||
{
|
||||
candidates.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidates.empty())
|
||||
{
|
||||
candidates = pointers;
|
||||
}
|
||||
const std::string path = candidates[pick(candidates.size())];
|
||||
const json::json_pointer pointer(path);
|
||||
|
||||
json operation;
|
||||
switch (pick(5))
|
||||
{
|
||||
case 0:
|
||||
operation = {{"op", "test"}, {"path", path}, {"value", current[pointer]}};
|
||||
break;
|
||||
case 1:
|
||||
operation = {{"op", "replace"}, {"path", path}, {"value", static_cast<int>(pick(100))}};
|
||||
break;
|
||||
case 2:
|
||||
operation = {{"op", "remove"}, {"path", path}};
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// add below an array or object, which may be the root
|
||||
const json::json_pointer parent_pointer = pick(4) == 0 ? json::json_pointer() : pointer;
|
||||
const std::string parent_path = parent_pointer.to_string();
|
||||
const json& parent = current[parent_pointer];
|
||||
std::string token = "-";
|
||||
if (parent.is_array())
|
||||
{
|
||||
token = pick(3) == 0 ? "-" : std::to_string(pick(parent.size() + 1));
|
||||
}
|
||||
else if (parent.is_object())
|
||||
{
|
||||
token = pick(2) == 0 ? "new" : "ab";
|
||||
}
|
||||
else
|
||||
{
|
||||
// a primitive parent: replace it instead
|
||||
operation = {{"op", "replace"}, {"path", parent_path}, {"value", json::array({1, 2})}};
|
||||
break;
|
||||
}
|
||||
operation = {{"op", "add"}, {"path", concat(parent_path, "/", token)}, {"value", json::object({{"k", {1, 2}}})}};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (operation["path"].get<std::string>().empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// one operation at a time: the cache is empty at the start of each
|
||||
current = current.patch(json::array({operation}));
|
||||
patch.push_back(operation);
|
||||
previous = operation["path"].get<std::string>();
|
||||
}
|
||||
|
||||
CHECK(start.patch(patch) == current);
|
||||
json inplace = start;
|
||||
inplace.patch_inplace(patch);
|
||||
CHECK(inplace == current);
|
||||
|
||||
// the same for a type that keeps the order of the members, which makes
|
||||
// objects that were built in a different order unequal: leave out the
|
||||
// tests of structured values
|
||||
json without_tests = json::array();
|
||||
for (const auto& operation : patch)
|
||||
{
|
||||
if (operation["op"] != "test" || !operation["value"].is_structured())
|
||||
{
|
||||
without_tests.push_back(operation);
|
||||
}
|
||||
}
|
||||
const nlohmann::ordered_json ordered_patch = without_tests;
|
||||
nlohmann::ordered_json ordered_inplace = start;
|
||||
ordered_inplace.patch_inplace(ordered_patch);
|
||||
CHECK(json(ordered_inplace) == current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JSON patch - time is linear for long paths that share a prefix")
|
||||
{
|
||||
// The time of the patch is compared with the time of a patch that is
|
||||
// linear for sure, because a bound in seconds would depend on the machine:
|
||||
// both test the same two values at the end of paths with 2n tokens. The
|
||||
// second path of the first patch shares n tokens with the first one and
|
||||
// continues for n tokens: the ratio is 1 to 2, and about 60 when every
|
||||
// step is compared with the start of the path. The time that std::clock()
|
||||
// measures is mostly the time of the processor, which a busy machine does
|
||||
// not inflate (on MSVC, it is the time that has passed).
|
||||
constexpr std::size_t n = 25000;
|
||||
|
||||
const auto nest = [](const std::size_t depth, const std::string & inner)
|
||||
{
|
||||
std::string text;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
text += "{\"a\":";
|
||||
}
|
||||
text += inner;
|
||||
text.append(depth, '}');
|
||||
return text;
|
||||
};
|
||||
std::string as;
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
as += "/a";
|
||||
}
|
||||
const std::string deep = nest(n, "1");
|
||||
std::string members = "{\"x\":";
|
||||
members += deep;
|
||||
members += ",\"y\":";
|
||||
members += deep;
|
||||
members += "}";
|
||||
json doc = json::parse(nest(n, members));
|
||||
|
||||
const auto test_op = [](const std::string & path)
|
||||
{
|
||||
return json({{"op", "test"}, {"path", path}, {"value", 1}});
|
||||
};
|
||||
const json shared = json::array({test_op(concat(as, "/x", as)), test_op(concat(as, "/y", as))});
|
||||
const json same = json::array({test_op(concat(as, "/x", as)), test_op(concat(as, "/x", as))});
|
||||
|
||||
// the operations do not change the document, which is too deep to copy;
|
||||
// a busy machine may spoil one comparison, hardly two
|
||||
bool linear = false;
|
||||
double t_shared = 0;
|
||||
double t_same = 0;
|
||||
for (int attempt = 0; attempt < 2 && !linear; ++attempt)
|
||||
{
|
||||
t_shared = patch_cpu_time(doc, shared);
|
||||
t_same = (std::max)(patch_cpu_time(doc, same), 1e-3);
|
||||
linear = t_shared < 10 * t_same;
|
||||
}
|
||||
CAPTURE(t_shared)
|
||||
CAPTURE(t_same)
|
||||
CHECK(linear);
|
||||
}
|
||||
@@ -906,71 +906,3 @@ TEST_CASE("json_view node array size limit")
|
||||
d->reserve(cap);
|
||||
CHECK(d->nodes == nodes);
|
||||
}
|
||||
|
||||
TEST_CASE("json_view document_data::holds() (the debug check of read())")
|
||||
{
|
||||
std::unique_ptr<document_data, document_data::deleter> d(document_data::create(0));
|
||||
const std::string other = "[1,2,3]";
|
||||
// an empty document holds nothing
|
||||
CHECK(!d->holds(other.data(), other.size()));
|
||||
|
||||
SECTION("owned text")
|
||||
{
|
||||
d->owned = "{\"a\":\"some text that does not fit a short string\"}";
|
||||
const char* const b = d->owned.data();
|
||||
CHECK(d->holds(b, 1));
|
||||
CHECK(d->holds(b + 5, 3));
|
||||
CHECK(d->holds(b + d->owned.size() - 1, 1));
|
||||
// also after clear(), which keeps the buffer that the next parse writes
|
||||
d->owned.clear();
|
||||
CHECK(d->holds(b, 4));
|
||||
CHECK(!d->holds(other.data(), other.size()));
|
||||
CHECK(!d->holds(b, 0));
|
||||
}
|
||||
|
||||
SECTION("decoded strings")
|
||||
{
|
||||
d->arena.assign(32, 'x');
|
||||
CHECK(d->holds(d->arena.data() + 31, 1));
|
||||
CHECK(d->holds(d->arena.data() + 31, 8)); // (overlapping the end)
|
||||
CHECK(!d->holds(other.data(), other.size()));
|
||||
}
|
||||
|
||||
SECTION("owned image")
|
||||
{
|
||||
d->owned_image.assign(16, 0);
|
||||
CHECK(d->holds(reinterpret_cast<const char*>(d->owned_image.data()) + 8, 2)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
}
|
||||
|
||||
SECTION("current edit buffer")
|
||||
{
|
||||
d->edits.reset(new document_data::edit_state()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
CHECK(!d->holds(other.data(), other.size()));
|
||||
d->edits->texts.emplace_back(new char[16]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
d->edits->text_cap = 16;
|
||||
CHECK(d->holds(d->edits->texts.back().get() + 3, 3));
|
||||
CHECK(!d->holds(other.data(), other.size()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("json_view read() of inputs the check must accept")
|
||||
{
|
||||
// in a debug build each read() below runs the check; none of the inputs
|
||||
// is held by the document
|
||||
const std::string text = R"({"a":"x\ny","b":[1,2]})";
|
||||
nlohmann::json_document d;
|
||||
d.read(text); // borrowed
|
||||
d.read(text); // the same borrowed text again
|
||||
CHECK(d.root()["b"][1].get<int>() == 2);
|
||||
const std::string copy(d.root()["a"].get_string()); // a decoded string, copied first
|
||||
d.read(std::string(text)); // owned
|
||||
d.read(R"(["x"])");
|
||||
d.read(text);
|
||||
CHECK(copy == "x\ny");
|
||||
nlohmann::json_editable_document e;
|
||||
e.read(text);
|
||||
e.set(e.root(), "a", "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]");
|
||||
const std::string edited(e.root()["a"].get_string()); // an edited string, copied first
|
||||
e.read(edited);
|
||||
CHECK(e.root().size() == 16);
|
||||
}
|
||||
@@ -206,44 +206,6 @@ TEST_CASE("json_view edits: views and values")
|
||||
CHECK(d.root().materialize().dump() == json::parse(R"([1.5, 100.0, 0.1, null, null, 18446744073709551615, -9223372036854775808])").dump());
|
||||
}
|
||||
|
||||
SECTION("a NaN written by an edit is not equal to itself")
|
||||
{
|
||||
// as for basic_json: NaN != NaN, so a view of it, of the array that holds it, and the same view twice agree
|
||||
json_editable_document d = json_editable_document::parse("[0, 0, 1.5]");
|
||||
d.set(d.root(), 0, std::numeric_limits<double>::quiet_NaN());
|
||||
d.set(d.root(), 1, std::numeric_limits<double>::quiet_NaN());
|
||||
json_editable_document other = json_editable_document::parse("[0, 0, 1.5]");
|
||||
other.set(other.root(), 0, std::numeric_limits<double>::quiet_NaN());
|
||||
other.set(other.root(), 1, std::numeric_limits<double>::quiet_NaN());
|
||||
const json value = d.root().materialize();
|
||||
|
||||
CHECK_FALSE(value == value);
|
||||
CHECK_FALSE(d.root()[0] == d.root()[0]);
|
||||
CHECK_FALSE(d.root()[0] == d.root()[1]);
|
||||
CHECK_FALSE(d.root() == d.root());
|
||||
CHECK_FALSE(d.root() == other.root());
|
||||
CHECK_FALSE(d.root()[0] == other.root()[0]);
|
||||
CHECK(d.root() != d.root());
|
||||
CHECK(d.root()[0] != d.root()[0]);
|
||||
CHECK_FALSE(d.root() == value);
|
||||
CHECK_FALSE(d.root()[0] == value[0]);
|
||||
// the other elements are equal as before
|
||||
CHECK(d.root()[2] == d.root()[2]);
|
||||
CHECK(d.root()[2] == other.root()[2]);
|
||||
// finite and infinite floats written by an edit stay equal to themselves
|
||||
d.set(d.root(), 0, 0.1);
|
||||
d.set(d.root(), 1, std::numeric_limits<double>::infinity());
|
||||
other.set(other.root(), 0, 0.1);
|
||||
other.set(other.root(), 1, std::numeric_limits<double>::infinity());
|
||||
CHECK(d.root() == d.root());
|
||||
CHECK(d.root() == other.root());
|
||||
CHECK(d.root()[1] == other.root()[1]);
|
||||
// a document that was never edited
|
||||
const json_editable_document untouched = json_editable_document::parse("[0.5, [1, 2]]");
|
||||
CHECK(untouched.root() == untouched.root());
|
||||
CHECK(untouched.root()[1] == untouched.root()[1]);
|
||||
}
|
||||
|
||||
SECTION("numbers of other float types")
|
||||
{
|
||||
// doubles have their own path to the output; other float types are
|
||||
|
||||
@@ -759,48 +759,6 @@ TEST_CASE("json_view images: errors")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("float tokens: an integer token is a float node only if it does not fit 64 bits")
|
||||
{
|
||||
for (const char* const token :
|
||||
{
|
||||
"18446744073709551616", "-9223372036854775809", "100000000000000000000", "-18446744073709551616", "123456789012345678901234567890"
|
||||
})
|
||||
{
|
||||
CAPTURE(token)
|
||||
const std::string text = std::string("[") + token + "]";
|
||||
const json_document d = json_document::parse(text);
|
||||
CHECK(d.root()[0].is_number_float());
|
||||
const std::vector<std::uint8_t> image = d.save();
|
||||
const std::size_t at = text_at(image) + 1; // the first byte of the token
|
||||
CHECK(loaded_dump(image) == json::parse(text).dump());
|
||||
for (std::size_t pos = token[0] == '-' ? 1 : 0; token[pos] != '\0'; ++pos) // (not the sign: that changes the digits)
|
||||
{
|
||||
for (char digit = '0'; digit <= '9'; ++digit)
|
||||
{
|
||||
std::vector<std::uint8_t> changed = image;
|
||||
changed[at + pos] = static_cast<std::uint8_t>(digit);
|
||||
std::string t = token;
|
||||
t[pos] = digit;
|
||||
CAPTURE(pos)
|
||||
CAPTURE(digit)
|
||||
CAPTURE(t)
|
||||
// the parser stores an integer for the changed token if it is one (and fits)
|
||||
const bool float_node = json::accept(t) && json::parse(t).is_number_float();
|
||||
const std::string result = load_result(changed, image_check::full);
|
||||
if (float_node)
|
||||
{
|
||||
CHECK(result.empty());
|
||||
CHECK(loaded_dump(changed) == json::parse("[" + t + "]").dump());
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(result == check_failed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8 of a decoded string: the compact dump writes it, the others throw")
|
||||
{
|
||||
const json_document d = json_document::parse(R"({"k\n":"\u00e9x"})");
|
||||
|
||||
@@ -50,18 +50,13 @@ json nested_object(const std::size_t depth, json leaf)
|
||||
|
||||
TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
{
|
||||
// The limit (128 by default) of the levels that the writers recurse into.
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
|
||||
// 72 levels more than the limit (200 by default) is past the point where
|
||||
// the writers stop recursing, and still shallow enough that from_* (which
|
||||
// does not recurse) and operator== (which does, up to the limit) are quick.
|
||||
const json deep_array = nested_array(limit + 72, json(0));
|
||||
const json deep_object = nested_object(limit + 72, json("x"));
|
||||
const json empty_array = nested_array(limit + 72, json::array());
|
||||
const json empty_object = nested_object(limit + 72, json::object());
|
||||
// 2 * (limit / 2 + 16) levels: 160 by default, and more than the limit for every limit
|
||||
const json mixed = nested_object((limit / 2) + 16, nested_array((limit / 2) + 16, json(true)));
|
||||
// 200 is past the point where the writers stop recursing, and still
|
||||
// shallow enough that from_* and operator== (which still recurse) are fine.
|
||||
const json deep_array = nested_array(200, json(0));
|
||||
const json deep_object = nested_object(200, json("x"));
|
||||
const json empty_array = nested_array(200, json::array());
|
||||
const json empty_object = nested_object(200, json::object());
|
||||
const json mixed = nested_object(80, nested_array(80, json(true)));
|
||||
|
||||
SECTION("roundtrip past the recursion bound")
|
||||
{
|
||||
@@ -100,7 +95,7 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
|
||||
SECTION("the two ways of writing a value meet at the bound")
|
||||
{
|
||||
for (std::size_t depth = limit > 8 ? limit - 8 : 0; depth <= limit + 12; ++depth)
|
||||
for (std::size_t depth = 120; depth <= 140; ++depth)
|
||||
{
|
||||
CAPTURE(depth)
|
||||
|
||||
@@ -123,8 +118,8 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
const json ndarray = json({{"_ArrayType_", "uint8"}, {"_ArraySize_", {2, 3}}, {"_ArrayData_", {1, 2, 3, 4, 5, 6}}});
|
||||
const json invalid = json({{"_ArrayType_", "nope"}, {"_ArraySize_", {1}}, {"_ArrayData_", {1}}});
|
||||
|
||||
const json deep_ndarray = nested_array(limit + 12, ndarray);
|
||||
const json deep_invalid = nested_array(limit + 12, invalid);
|
||||
const json deep_ndarray = nested_array(140, ndarray);
|
||||
const json deep_invalid = nested_array(140, invalid);
|
||||
|
||||
CHECK(json::from_bjdata(json::to_bjdata(deep_ndarray)) == deep_ndarray);
|
||||
CHECK(json::from_bjdata(json::to_bjdata(deep_invalid)) == deep_invalid);
|
||||
@@ -136,10 +131,10 @@ TEST_CASE("issue #5392 - binary writers on deeply nested values")
|
||||
// nested one-element arrays around the recursion bound: the exact
|
||||
// bytes a writer produces do not depend on whether it stayed on the
|
||||
// call stack or moved to the heap one partway through
|
||||
// (the limit can be 0, where "one level less" is no level)
|
||||
for (const std::size_t depth :
|
||||
{
|
||||
limit > 0 ? limit - 1 : 0, limit, limit + 1, limit + 2
|
||||
nlohmann::detail::recursion_depth_limit() - 1, nlohmann::detail::recursion_depth_limit(),
|
||||
nlohmann::detail::recursion_depth_limit() + 1, nlohmann::detail::recursion_depth_limit() + 2
|
||||
})
|
||||
{
|
||||
CAPTURE(depth)
|
||||
|
||||
@@ -115,7 +115,7 @@ TEST_CASE("issue #5650 - stack overflow converting between specializations")
|
||||
// members that the two object types enumerate in different orders.
|
||||
const auto bury = [](nlohmann::ordered_json value)
|
||||
{
|
||||
for (std::size_t i = 0; i < nlohmann::detail::recursion_depth_limit() + 72; ++i)
|
||||
for (std::size_t i = 0; i < 200; ++i)
|
||||
{
|
||||
value = nlohmann::ordered_json::array({std::move(value)});
|
||||
}
|
||||
@@ -124,7 +124,7 @@ TEST_CASE("issue #5650 - stack overflow converting between specializations")
|
||||
const auto dig = [](const json & value)
|
||||
{
|
||||
const json* current = &value;
|
||||
for (std::size_t i = 0; i < nlohmann::detail::recursion_depth_limit() + 72; ++i)
|
||||
for (std::size_t i = 0; i < 200; ++i)
|
||||
{
|
||||
current = ¤t->at(0);
|
||||
}
|
||||
|
||||
@@ -930,15 +930,14 @@ TEST_CASE("JSON Merge Patch diff of deeply nested values")
|
||||
SECTION("the patch is the same past the descent bound")
|
||||
{
|
||||
// depths on either side of the nesting depth up to which merge_diff()
|
||||
// recurses (detail::recursion_depth_limit(), 128 by default); not every depth up
|
||||
// recurses (detail::recursion_depth_limit(), 128); not every depth up
|
||||
// to 300, to keep the test fast under Valgrind
|
||||
std::vector<std::size_t> depths;
|
||||
for (std::size_t depth = 0; depth <= 16; ++depth)
|
||||
{
|
||||
depths.push_back(depth);
|
||||
}
|
||||
const std::size_t limit = nlohmann::detail::recursion_depth_limit();
|
||||
for (std::size_t depth = limit > 8 ? limit - 8 : 0; depth <= limit + 8; ++depth)
|
||||
for (std::size_t depth = 120; depth <= 136; ++depth)
|
||||
{
|
||||
depths.push_back(depth);
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ TEST_CASE("JSON Merge Patch on deeply nested values")
|
||||
SECTION("patching past the descent bound gives the same result")
|
||||
{
|
||||
// every depth on either side of where the iterative version takes
|
||||
// over (detail::recursion_depth_limit(), 128 by default)
|
||||
// over (detail::recursion_depth_limit(), 128)
|
||||
for (std::size_t depth = 0; depth <= 300; ++depth)
|
||||
{
|
||||
CAPTURE(depth)
|
||||
@@ -396,7 +396,7 @@ TEST_CASE("merge_patch() with an argument that aliases *this (#5641)")
|
||||
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 by default); patching *this with
|
||||
// over (detail::recursion_depth_limit(), 128); patching *this with
|
||||
// itself is idempotent, aliased or not
|
||||
for (const std::size_t depth :
|
||||
{
|
||||
|
||||
@@ -1124,7 +1124,7 @@ TEST_CASE("update() on deeply nested values")
|
||||
SECTION("merging past the descent bound gives the same result")
|
||||
{
|
||||
// every depth on either side of where the iterative version takes
|
||||
// over (detail::recursion_depth_limit(), 128 by default)
|
||||
// over (detail::recursion_depth_limit(), 128)
|
||||
for (std::size_t depth = 0; depth <= 300; ++depth)
|
||||
{
|
||||
CAPTURE(depth)
|
||||
@@ -1215,7 +1215,7 @@ TEST_CASE("update() with an argument that aliases *this (#5641)")
|
||||
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 by default); merging *this into
|
||||
// over (detail::recursion_depth_limit(), 128); merging *this into
|
||||
// itself is idempotent, aliased or not
|
||||
for (const std::size_t depth :
|
||||
{
|
||||
|
||||
@@ -1,614 +0,0 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// JSON_RECURSION_DEPTH_LIMIT changes only how much call stack the walks over a
|
||||
// value use, never what they return. This file checks both: the macro is
|
||||
// honoured (the number of levels the containers handle themselves is the limit)
|
||||
// and every walk returns what it returns with the default limit. The expected
|
||||
// results are built here, without the library, so that the same file passes for
|
||||
// every limit; tests/CMakeLists.txt builds it with limits 0, 1, and 254 besides
|
||||
// the default. Values are nested up to 300 levels (and past every limit, so that
|
||||
// the explicit stack of every walk is exercised, even for the limit of 254) and
|
||||
// are built and taken apart without recursion. Keep the depths moderate: walks
|
||||
// like diff and dump with indentation are quadratic in the depth.
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr std::size_t limit()
|
||||
{
|
||||
return nlohmann::detail::recursion_depth_limit();
|
||||
}
|
||||
|
||||
// a value nested as @a kinds says, outermost level first: 'a' is an array of
|
||||
// one element, 'o' an object with the single key "a"; @a leaf is innermost
|
||||
json build(const std::string& kinds, json leaf)
|
||||
{
|
||||
json j = std::move(leaf);
|
||||
for (std::size_t i = kinds.size(); i-- > 0;)
|
||||
{
|
||||
if (kinds[i] == 'a')
|
||||
{
|
||||
json a = json::array();
|
||||
a.push_back(std::move(j));
|
||||
j = std::move(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
json o = json::object();
|
||||
o["a"] = std::move(j);
|
||||
j = std::move(o);
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
std::string repeat(const std::string& s, std::size_t n)
|
||||
{
|
||||
std::string result;
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
result += s;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// the nesting of the given shape and depth: arrays, objects, or both alternating
|
||||
std::string make_kinds(char shape, std::size_t depth)
|
||||
{
|
||||
std::string kinds;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
if (shape == 'm')
|
||||
{
|
||||
kinds += i % 2 == 0 ? 'a' : 'o';
|
||||
}
|
||||
else
|
||||
{
|
||||
kinds += shape;
|
||||
}
|
||||
}
|
||||
return kinds;
|
||||
}
|
||||
|
||||
std::string expected_compact(const std::string& kinds, const std::string& leaf)
|
||||
{
|
||||
std::string s;
|
||||
for (const char kind : kinds)
|
||||
{
|
||||
s += kind == 'a' ? "[" : "{\"a\":";
|
||||
}
|
||||
s += leaf;
|
||||
for (std::size_t i = kinds.size(); i-- > 0;)
|
||||
{
|
||||
s += kinds[i] == 'a' ? "]" : "}";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// dump(1)
|
||||
std::string expected_indented(const std::string& kinds, const std::string& leaf)
|
||||
{
|
||||
std::string s;
|
||||
for (std::size_t i = 0; i < kinds.size(); ++i)
|
||||
{
|
||||
s += kinds[i] == 'a' ? "[\n" : "{\n";
|
||||
s += std::string(i + 1, ' ');
|
||||
if (kinds[i] == 'o')
|
||||
{
|
||||
s += "\"a\": ";
|
||||
}
|
||||
}
|
||||
s += leaf;
|
||||
for (std::size_t i = kinds.size(); i-- > 0;)
|
||||
{
|
||||
s += "\n" + std::string(i, ' ') + (kinds[i] == 'a' ? "]" : "}");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// the JSON pointer to the innermost value
|
||||
std::string pointer(const std::string& kinds)
|
||||
{
|
||||
std::string s;
|
||||
for (const char kind : kinds)
|
||||
{
|
||||
s += kind == 'a' ? "/0" : "/a";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// the binary formats: the bytes that open and close a level, and the leaf 1
|
||||
std::vector<std::uint8_t> expected_cbor(const std::string& kinds)
|
||||
{
|
||||
std::vector<std::uint8_t> bytes;
|
||||
for (const char kind : kinds)
|
||||
{
|
||||
if (kind == 'a')
|
||||
{
|
||||
bytes.push_back(0x81);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes.push_back(0xA1);
|
||||
bytes.push_back(0x61);
|
||||
bytes.push_back('a');
|
||||
}
|
||||
}
|
||||
bytes.push_back(0x01);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> expected_msgpack(const std::string& kinds)
|
||||
{
|
||||
std::vector<std::uint8_t> bytes;
|
||||
for (const char kind : kinds)
|
||||
{
|
||||
if (kind == 'a')
|
||||
{
|
||||
bytes.push_back(0x91);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes.push_back(0x81);
|
||||
bytes.push_back(0xA1);
|
||||
bytes.push_back('a');
|
||||
}
|
||||
}
|
||||
bytes.push_back(0x01);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> expected_ubjson(const std::string& kinds)
|
||||
{
|
||||
std::vector<std::uint8_t> bytes;
|
||||
for (const char kind : kinds)
|
||||
{
|
||||
if (kind == 'a')
|
||||
{
|
||||
bytes.push_back('[');
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes.push_back('{');
|
||||
bytes.push_back('i');
|
||||
bytes.push_back(1);
|
||||
bytes.push_back('a');
|
||||
}
|
||||
}
|
||||
bytes.push_back('i');
|
||||
bytes.push_back(1);
|
||||
for (std::size_t i = kinds.size(); i-- > 0;)
|
||||
{
|
||||
bytes.push_back(kinds[i] == 'a' ? ']' : '}');
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// the depths worth trying for the limit: either side of it, twice it (if that
|
||||
// is not too deep to be quick), and a value nested well past all limits
|
||||
std::vector<std::size_t> depths()
|
||||
{
|
||||
std::vector<std::size_t> result;
|
||||
result.push_back(1);
|
||||
result.push_back(2);
|
||||
result.push_back(limit() > 0 ? limit() - 1 : 3);
|
||||
result.push_back(limit());
|
||||
result.push_back(limit() + 1);
|
||||
if ((2 * limit()) + 5 <= 300)
|
||||
{
|
||||
result.push_back((2 * limit()) + 5);
|
||||
}
|
||||
result.push_back(300);
|
||||
std::sort(result.begin(), result.end());
|
||||
result.erase(std::unique(result.begin(), result.end()), result.end());
|
||||
result.erase(std::remove(result.begin(), result.end(), static_cast<std::size_t>(0)), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
// the call for every shape and depth
|
||||
void for_each_value(const std::function<void(const std::string&)>& check)
|
||||
{
|
||||
const std::string shapes = "aom";
|
||||
for (const char shape : shapes)
|
||||
{
|
||||
for (const std::size_t depth : depths())
|
||||
{
|
||||
CAPTURE(shape)
|
||||
CAPTURE(depth)
|
||||
check(make_kinds(shape, depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An array type that counts how many of its copies are being made at once. A
|
||||
// copy of a value copies one level at a time through the array type until the
|
||||
// limit has been reached, so the peak is the number of levels that were copied
|
||||
// with the call stack.
|
||||
std::size_t copies_going_on = 0;
|
||||
std::size_t copies_peak = 0;
|
||||
std::size_t equal_going_on = 0;
|
||||
std::size_t equal_peak = 0;
|
||||
|
||||
template<class T, class Allocator = std::allocator<T>>
|
||||
class counting_vector : public std::vector<T, Allocator>
|
||||
{
|
||||
public:
|
||||
counting_vector() = default;
|
||||
|
||||
template<class InputIt>
|
||||
counting_vector(InputIt first, InputIt last) : std::vector<T, Allocator>(first, last) {}
|
||||
|
||||
counting_vector(const counting_vector& other) : std::vector<T, Allocator>()
|
||||
{
|
||||
++copies_going_on;
|
||||
copies_peak = (std::max)(copies_peak, copies_going_on);
|
||||
this->std::vector<T, Allocator>::operator=(static_cast<const std::vector<T, Allocator>&>(other));
|
||||
--copies_going_on;
|
||||
}
|
||||
|
||||
counting_vector(counting_vector&&) = default;
|
||||
counting_vector& operator=(const counting_vector&) = default;
|
||||
counting_vector& operator=(counting_vector&&) = default;
|
||||
~counting_vector() = default;
|
||||
|
||||
friend bool operator==(const counting_vector& lhs, const counting_vector& rhs)
|
||||
{
|
||||
++equal_going_on;
|
||||
equal_peak = (std::max)(equal_peak, equal_going_on);
|
||||
const bool result = static_cast<const std::vector<T, Allocator>&>(lhs) == static_cast<const std::vector<T, Allocator>&>(rhs);
|
||||
--equal_going_on;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
using counting_json = json::with_array_t<counting_vector>;
|
||||
|
||||
// A base class whose copy constructor copies a whole value of the same
|
||||
// specialization when it copies a marked element, as user code may do from a
|
||||
// hook. That copy runs while the copy that it is part of is going on.
|
||||
struct copy_hook // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||
{
|
||||
int mark = 0;
|
||||
|
||||
copy_hook() = default;
|
||||
copy_hook(const copy_hook& other);
|
||||
copy_hook(copy_hook&&) = default;
|
||||
copy_hook& operator=(const copy_hook&) = default;
|
||||
copy_hook& operator=(copy_hook&&) = default;
|
||||
};
|
||||
|
||||
using hook_json = nlohmann::basic_json<std::map, counting_vector, std::string, bool, std::int64_t, std::uint64_t, double,
|
||||
std::allocator, nlohmann::adl_serializer, std::vector<std::uint8_t>, copy_hook>;
|
||||
|
||||
const hook_json* hook_copy_source = nullptr;
|
||||
int hook_copies_going_on = 0;
|
||||
|
||||
copy_hook::copy_hook(const copy_hook& other) : mark(other.mark)
|
||||
{
|
||||
// the value that is copied is marked, too: its copy copies it again, once
|
||||
if (other.mark == 1 && hook_copy_source != nullptr && hook_copies_going_on < 2)
|
||||
{
|
||||
++hook_copies_going_on;
|
||||
const hook_json nested = *hook_copy_source; // NOLINT(performance-unnecessary-copy-initialization)
|
||||
static_cast<void>(nested);
|
||||
--hook_copies_going_on;
|
||||
}
|
||||
}
|
||||
|
||||
// an array nested @a depth levels around the integer 1, which is marked if @a marked
|
||||
hook_json hook_nested(std::size_t depth, bool marked)
|
||||
{
|
||||
hook_json j = 1;
|
||||
if (marked)
|
||||
{
|
||||
static_cast<copy_hook&>(j).mark = 1;
|
||||
}
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
{
|
||||
hook_json a = hook_json::array();
|
||||
a.push_back(std::move(j));
|
||||
j = std::move(a);
|
||||
}
|
||||
return j;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// the macro is the limit, and is in the range the library supports
|
||||
static_assert(nlohmann::detail::recursion_depth_limit() == static_cast<std::size_t>(JSON_RECURSION_DEPTH_LIMIT),
|
||||
"the library does not use JSON_RECURSION_DEPTH_LIMIT");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit() <= 254, "the nesting depth must fit in a byte");
|
||||
|
||||
// the macro must not be a character or bool: every character type is refused
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<bool>::value, "bool is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<char>::value, "char is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<signed char>::value, "signed char is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<unsigned char>::value, "unsigned char is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<wchar_t>::value, "wchar_t is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<char16_t>::value, "char16_t is refused");
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<char32_t>::value, "char32_t is refused");
|
||||
#if defined(__cpp_char8_t)
|
||||
static_assert(nlohmann::detail::recursion_depth_limit_is_char_or_bool<char8_t>::value, "char8_t is refused");
|
||||
#endif
|
||||
static_assert(!nlohmann::detail::recursion_depth_limit_is_char_or_bool<int>::value, "int is accepted");
|
||||
static_assert(!nlohmann::detail::recursion_depth_limit_is_char_or_bool<unsigned long long>::value, "unsigned long long is accepted");
|
||||
|
||||
TEST_CASE("JSON_RECURSION_DEPTH_LIMIT is honoured")
|
||||
{
|
||||
SECTION("copying and comparing stop descending at the limit")
|
||||
{
|
||||
// copy and compare a value nested deeper than the limit, with the array type that counts
|
||||
counting_json inner = 1;
|
||||
for (std::size_t i = 0; i < (2 * limit()) + 5; ++i)
|
||||
{
|
||||
counting_json a = counting_json::array();
|
||||
a.push_back(std::move(inner));
|
||||
inner = std::move(a);
|
||||
}
|
||||
|
||||
copies_going_on = copies_peak = 0;
|
||||
const counting_json copy = inner;
|
||||
CHECK(copies_going_on == 0);
|
||||
|
||||
equal_going_on = equal_peak = 0;
|
||||
CHECK((inner == copy));
|
||||
CHECK(equal_going_on == 0);
|
||||
|
||||
#ifdef JSON_NO_THREAD_LOCAL
|
||||
// without the counters of the levels, no level is descended into
|
||||
CHECK(copies_peak == 0);
|
||||
CHECK(equal_peak == 0);
|
||||
#else
|
||||
// copying descends into as many levels as the limit says, and nothing further
|
||||
CHECK(copies_peak == limit());
|
||||
CHECK(equal_peak == limit());
|
||||
#endif
|
||||
|
||||
// a value that is not nested deeper than the limit is not cut short
|
||||
const std::size_t shallow = limit() > 0 ? limit() : 1;
|
||||
counting_json small = 1;
|
||||
for (std::size_t i = 0; i < shallow; ++i)
|
||||
{
|
||||
counting_json a = counting_json::array();
|
||||
a.push_back(std::move(small));
|
||||
small = std::move(a);
|
||||
}
|
||||
copies_going_on = copies_peak = 0;
|
||||
const counting_json small_copy = small;
|
||||
CHECK(copies_going_on == 0);
|
||||
#ifndef JSON_NO_THREAD_LOCAL
|
||||
CHECK(copies_peak == limit());
|
||||
#endif
|
||||
CHECK(small_copy.dump() == expected_compact(make_kinds('a', shallow), "1"));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("a copy made while a copy is going on is bounded, too")
|
||||
{
|
||||
// The innermost element of the value is marked, and copying it (which happens
|
||||
// after limit() levels have been entered, when the copy continues without the
|
||||
// call stack) copies the value again, and that copy once more. Those copies
|
||||
// must not be given limit() levels of their own: the count of the levels entered
|
||||
// never exceeds the limit, not even by one, which for the largest limit would
|
||||
// wrap the byte that holds it around to 0.
|
||||
const hook_json marked = hook_nested((2 * limit()) + 5, true);
|
||||
hook_copy_source = &marked;
|
||||
|
||||
copies_going_on = copies_peak = 0;
|
||||
const hook_json copy = marked; // NOLINT(performance-unnecessary-copy-initialization)
|
||||
hook_copy_source = nullptr;
|
||||
CHECK(copies_going_on == 0);
|
||||
CHECK(static_cast<const copy_hook&>(copy).mark == 0); // (the top level is not marked)
|
||||
|
||||
#ifdef JSON_NO_THREAD_LOCAL
|
||||
CHECK(copies_peak == 0);
|
||||
#else
|
||||
CHECK(copies_peak == limit());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("walks over values nested around the recursion depth limit")
|
||||
{
|
||||
SECTION("copying and comparing")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const json b = a; // NOLINT(performance-unnecessary-copy-initialization)
|
||||
CHECK((a == b));
|
||||
CHECK_FALSE((a != b));
|
||||
CHECK_FALSE((a < b));
|
||||
CHECK((a <= b));
|
||||
CHECK((a >= b));
|
||||
CHECK_FALSE((a > b));
|
||||
|
||||
json assigned;
|
||||
assigned = a;
|
||||
CHECK((assigned == a));
|
||||
|
||||
// differing only in the innermost value
|
||||
const json c = build(kinds, 2);
|
||||
CHECK((a != c));
|
||||
CHECK((a < c));
|
||||
CHECK((c > a));
|
||||
CHECK_FALSE((c < a));
|
||||
CHECK_FALSE((a == c));
|
||||
|
||||
// a same-shape array or object that is one level shallower
|
||||
const json shallower = build(kinds.substr(1), 1);
|
||||
CHECK((shallower != a));
|
||||
const json outer = build(kinds.substr(0, 1), 1);
|
||||
CHECK((outer != a) == (kinds.size() > 1));
|
||||
|
||||
const json moved = std::move(assigned);
|
||||
CHECK((moved == a));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("serializing")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const std::string compact = expected_compact(kinds, "1");
|
||||
const std::string indented = expected_indented(kinds, "1");
|
||||
|
||||
CHECK(a.dump() == compact);
|
||||
CHECK(a.dump(1) == indented);
|
||||
|
||||
std::ostringstream compact_stream;
|
||||
compact_stream << a;
|
||||
CHECK(compact_stream.str() == compact);
|
||||
std::ostringstream indented_stream;
|
||||
indented_stream << std::setw(1) << a;
|
||||
CHECK(indented_stream.str() == indented);
|
||||
|
||||
CHECK((json::parse(compact) == a));
|
||||
CHECK((json::parse(indented) == a));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("hashing")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const std::hash<json> hash;
|
||||
CHECK(hash(a) == hash(json(a)));
|
||||
CHECK(hash(a) == hash(json::parse(expected_compact(kinds, "1"))));
|
||||
CHECK(hash(a) != hash(build(kinds, 2)));
|
||||
CHECK(hash(a) != hash(build(kinds.substr(1), 1)));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("diff and patch")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const json b = build(kinds, 2);
|
||||
|
||||
const json difference = json::diff(a, b);
|
||||
CHECK(difference.dump() == "[{\"op\":\"replace\",\"path\":\"" + pointer(kinds) + "\",\"value\":2}]");
|
||||
CHECK((a.patch(difference) == b));
|
||||
CHECK((json::diff(a, a) == json::array()));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("flatten and unflatten")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const json flat = a.flatten();
|
||||
CHECK(flat.dump() == "{\"" + pointer(kinds) + "\":1}");
|
||||
CHECK((flat.unflatten() == a));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("merge_patch and update")
|
||||
{
|
||||
for (const std::size_t depth : depths())
|
||||
{
|
||||
CAPTURE(depth)
|
||||
const std::string kinds = make_kinds('o', depth);
|
||||
const std::string all_but_leaf = repeat("{\"a\":", depth - 1);
|
||||
|
||||
// the patch removes the innermost member, or replaces it
|
||||
json target = build(kinds, 1);
|
||||
target.merge_patch(build(kinds, json(nullptr)));
|
||||
CHECK(target.dump() == all_but_leaf + "{}" + repeat("}", depth - 1));
|
||||
|
||||
target = build(kinds, 1);
|
||||
target.merge_patch(build(kinds, 2));
|
||||
CHECK(target.dump() == expected_compact(kinds, "2"));
|
||||
|
||||
// merging the objects of two values nested alike, and replacing the first level
|
||||
const json base = build(kinds.substr(1), json::parse("{\"x\":1}"));
|
||||
const json other = build(kinds.substr(1), json::parse("{\"y\":2}"));
|
||||
json merged = json{{"a", base}};
|
||||
merged.update(json{{"a", other}}, true);
|
||||
CHECK(merged.dump() == expected_compact(kinds, "{\"x\":1,\"y\":2}"));
|
||||
|
||||
json replaced = json{{"a", base}};
|
||||
replaced.update(json{{"a", other}});
|
||||
CHECK(replaced.dump() == expected_compact(kinds, "{\"y\":2}"));
|
||||
|
||||
// update from a range
|
||||
json from_range = json{{"a", base}};
|
||||
const json source = json{{"a", other}};
|
||||
from_range.update(source.begin(), source.end(), true);
|
||||
CHECK((from_range == merged));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("binary formats")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
|
||||
const std::vector<std::uint8_t> cbor = json::to_cbor(a);
|
||||
CHECK(cbor == expected_cbor(kinds));
|
||||
CHECK((json::from_cbor(cbor) == a));
|
||||
|
||||
const std::vector<std::uint8_t> msgpack = json::to_msgpack(a);
|
||||
CHECK(msgpack == expected_msgpack(kinds));
|
||||
CHECK((json::from_msgpack(msgpack) == a));
|
||||
|
||||
const std::vector<std::uint8_t> ubjson = json::to_ubjson(a);
|
||||
CHECK(ubjson == expected_ubjson(kinds));
|
||||
CHECK((json::from_ubjson(ubjson) == a));
|
||||
|
||||
CHECK((json::from_bjdata(json::to_bjdata(a)) == a));
|
||||
CHECK((json::from_bon8(json::to_bon8(a)) == a));
|
||||
|
||||
// BSON documents are objects
|
||||
const json document = json{{"a", a}};
|
||||
CHECK((json::from_bson(json::to_bson(document)) == document));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("conversion to another specialization")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
const json a = build(kinds, 1);
|
||||
const nlohmann::ordered_json ordered = a;
|
||||
CHECK(ordered.dump() == expected_compact(kinds, "1"));
|
||||
const json back = ordered;
|
||||
CHECK((back == a));
|
||||
});
|
||||
}
|
||||
|
||||
SECTION("destroying")
|
||||
{
|
||||
for_each_value([](const std::string & kinds)
|
||||
{
|
||||
json a = build(kinds, 1);
|
||||
a = nullptr;
|
||||
CHECK(a.is_null());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1554,10 +1554,8 @@ TEST_CASE("regression tests 1")
|
||||
SECTION("a missing member of an object")
|
||||
{
|
||||
my_json j = make();
|
||||
#if defined(JSON_NO_THREAD_LOCAL) || JSON_RECURSION_DEPTH_LIMIT < 2
|
||||
// (set by the user, or by the library for clang with MinGW; or fewer than two
|
||||
// levels are copied by the object type itself, as for a recursion depth limit
|
||||
// of 0 or 1: the objects below the outermost one are the second level)
|
||||
#ifdef JSON_NO_THREAD_LOCAL
|
||||
// (set by the user, or by the library for clang with MinGW)
|
||||
// the objects below the outermost one are not copied by their
|
||||
// object_t here, but member by member, which keeps their
|
||||
// timestamps correct: "c" is not mistaken for "b" and is inserted
|
||||
|
||||
Reference in new issue
Block a user