mirror of
https://github.com/nlohmann/json.git
synced 2026-10-01 12:10:32 +00:00
Compare commits
51
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a757ca675 | ||
|
|
9d44e3f359 | ||
|
|
e400780533 | ||
|
|
9d88ead578 | ||
|
|
e5a89d671f | ||
|
|
b54ed188e6 | ||
|
|
cff0a61369 | ||
|
|
3926fcaac3 | ||
|
|
18dd5663b0 | ||
|
|
a32f61eb98 | ||
|
|
1d675cdb46 | ||
|
|
c261578431 | ||
|
|
35802e78d6 | ||
|
|
791cd88dfc | ||
|
|
7d7055ec50 | ||
|
|
3b6ae43c53 | ||
|
|
f1014c938a | ||
|
|
e91fdad877 | ||
|
|
9c71689715 | ||
|
|
44ec53c77b | ||
|
|
6a073dbae4 | ||
|
|
fdcc569eee | ||
|
|
6fc0d501f3 | ||
|
|
67435c9c7e | ||
|
|
2ea6d8c127 | ||
|
|
66877675b1 | ||
|
|
7fd6895788 | ||
|
|
6ae17630a4 | ||
|
|
5bd766aa50 | ||
|
|
4bb1b14b06 | ||
|
|
bfe0f32d71 | ||
|
|
44a88d85be | ||
|
|
5b11a0282c | ||
|
|
bfea6f36d3 | ||
|
|
e444a66276 | ||
|
|
1151826508 | ||
|
|
6218aa212b | ||
|
|
42f89e3130 | ||
|
|
6d7845d207 | ||
|
|
678fd3017b | ||
|
|
fc4c9c3446 | ||
|
|
68beba727c | ||
|
|
0050d0f7a4 | ||
|
|
6a8a7735ed | ||
|
|
65af260117 | ||
|
|
d268eaa693 | ||
|
|
5b9ffae8bb | ||
|
|
04f6ddd227 | ||
|
|
633de8e44b | ||
|
|
fc03b9912e | ||
|
|
9e1a09eec0 |
-17
@@ -1,17 +0,0 @@
|
|||||||
arm_container:
|
|
||||||
image: gcc:latest
|
|
||||||
|
|
||||||
check_task:
|
|
||||||
check_script:
|
|
||||||
# the gcc image ships an outdated CMake, so fetch a recent prebuilt binary
|
|
||||||
# instead of compiling CMake from source
|
|
||||||
- wget -q https://github.com/Kitware/CMake/releases/download/v4.3.4/cmake-4.3.4-linux-aarch64.tar.gz
|
|
||||||
- tar xfz cmake-4.3.4-linux-aarch64.tar.gz
|
|
||||||
- export PATH="$(pwd)/cmake-4.3.4-linux-aarch64/bin:$PATH"
|
|
||||||
- cmake --version
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake .. -DJSON_FastTests=ON
|
|
||||||
- make -j4
|
|
||||||
- cd tests
|
|
||||||
- ctest -j4
|
|
||||||
+10
-5
@@ -1,9 +1,15 @@
|
|||||||
# TODO: The first three checks are only removed to get the CI going. They have to be addressed at some point.
|
# bugprone-use-after-move (hicpp-invalid-access-moved is its alias) still flags
|
||||||
# TODO: portability-avoid-pragma-once: should be fixed eventually
|
# the basic_json move constructor, which forwards the whole object to its base
|
||||||
|
# class (#5724), and two forwards in the error-message construction of
|
||||||
|
# at(KeyType&&) (json.hpp, both overloads: find(std::forward<KeyType>(key))
|
||||||
|
# followed by string_t(std::forward<KeyType>(key)) in the throw), which #5689
|
||||||
|
# rewrites. Re-enable both checks once those changes have landed.
|
||||||
|
# portability-avoid-pragma-once: kept disabled on purpose. #pragma once is accepted
|
||||||
|
# by every supported compiler, and tools/amalgamate/amalgamate.py strips it from
|
||||||
|
# single_include, so there is nothing left to fix here.
|
||||||
|
|
||||||
Checks: '*,
|
Checks: '*,
|
||||||
|
|
||||||
-portability-template-virtual-member-function,
|
|
||||||
-bugprone-use-after-move,
|
-bugprone-use-after-move,
|
||||||
-hicpp-invalid-access-moved,
|
-hicpp-invalid-access-moved,
|
||||||
|
|
||||||
@@ -37,7 +43,6 @@ Checks: '*,
|
|||||||
-google-readability-function-size,
|
-google-readability-function-size,
|
||||||
-google-runtime-float,
|
-google-runtime-float,
|
||||||
-google-runtime-int,
|
-google-runtime-int,
|
||||||
-google-runtime-references,
|
|
||||||
-hicpp-avoid-goto,
|
-hicpp-avoid-goto,
|
||||||
-hicpp-explicit-conversions,
|
-hicpp-explicit-conversions,
|
||||||
-hicpp-function-size,
|
-hicpp-function-size,
|
||||||
@@ -71,6 +76,7 @@ Checks: '*,
|
|||||||
-readability-magic-numbers,
|
-readability-magic-numbers,
|
||||||
-readability-redundant-access-specifiers,
|
-readability-redundant-access-specifiers,
|
||||||
-readability-redundant-parentheses,
|
-readability-redundant-parentheses,
|
||||||
|
-readability-redundant-typename,
|
||||||
-readability-simplify-boolean-expr,
|
-readability-simplify-boolean-expr,
|
||||||
-readability-uppercase-literal-suffix,
|
-readability-uppercase-literal-suffix,
|
||||||
-readability-use-concise-preprocessor-directives'
|
-readability-use-concise-preprocessor-directives'
|
||||||
@@ -81,5 +87,4 @@ CheckOptions:
|
|||||||
|
|
||||||
WarningsAsErrors: '*'
|
WarningsAsErrors: '*'
|
||||||
|
|
||||||
#HeaderFilterRegex: '.*nlohmann.*'
|
|
||||||
HeaderFilterRegex: '.*hpp$'
|
HeaderFilterRegex: '.*hpp$'
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ updates:
|
|||||||
interval: daily
|
interval: daily
|
||||||
cooldown:
|
cooldown:
|
||||||
default-days: 7
|
default-days: 7
|
||||||
|
ignore:
|
||||||
|
# astyle is deliberately pinned (see tools/astyle/requirements.txt): newer versions
|
||||||
|
# reformat the code, and the pinned version defines the formatting CI enforces
|
||||||
|
- dependency-name: astyle
|
||||||
|
|
||||||
- package-ecosystem: pip
|
- package-ecosystem: pip
|
||||||
directory: /tools/generate_natvis
|
directory: /tools/generate_natvis
|
||||||
|
|||||||
@@ -30,14 +30,6 @@ environment:
|
|||||||
CMAKE_OPTIONS: ""
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
configuration: Release
|
|
||||||
platform: x86
|
|
||||||
name: with_win_header
|
|
||||||
CXX_FLAGS: "/W4 /WX"
|
|
||||||
CMAKE_OPTIONS: ""
|
|
||||||
GENERATOR: Visual Studio 14 2015
|
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
configuration: Release
|
configuration: Release
|
||||||
platform: x86
|
platform: x86
|
||||||
@@ -74,9 +66,6 @@ install:
|
|||||||
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
|
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
# for with_win_header build, inject the inclusion of Windows.h to the single-header library
|
|
||||||
- ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
|
|
||||||
- ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
|
|
||||||
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
|
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
|||||||
@@ -2,16 +2,23 @@ name: "Check amalgamation"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
# also check develop itself: a PR can be merged before its own run of this
|
||||||
|
# workflow completes (e.g. while it is still queued), leaving single_include
|
||||||
|
# stale on develop without any failing check
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
save:
|
save:
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
@@ -35,6 +42,7 @@ jobs:
|
|||||||
MAIN_DIR: ${{ github.workspace }}/main
|
MAIN_DIR: ${{ github.workspace }}/main
|
||||||
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
|
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
|
||||||
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
|
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
|
||||||
|
NATVIS_TOOL_DIR: ${{ github.workspace }}/tools/tools/generate_natvis
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
@@ -42,11 +50,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
- name: Checkout pull request
|
- name: Checkout pull request or pushed commit
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
path: main
|
path: main
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Checkout tools
|
- name: Checkout tools
|
||||||
@@ -61,12 +69,55 @@ jobs:
|
|||||||
python3 -mvenv venv
|
python3 -mvenv venv
|
||||||
venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
|
venv/bin/pip3 install -r $MAIN_DIR/tools/astyle/requirements.txt
|
||||||
|
|
||||||
|
- name: Install generate_natvis dependencies
|
||||||
|
run: pip3 install -r $NATVIS_TOOL_DIR/requirements.txt
|
||||||
|
|
||||||
|
- name: Regenerate the tools/macro_builder tables in macro_scope.hpp
|
||||||
|
run: |
|
||||||
|
cd $MAIN_DIR
|
||||||
|
|
||||||
|
# Built from this PR's own tools/macro_builder/main.cpp, not a
|
||||||
|
# develop checkout: unlike amalgamate.py and generate_natvis.py,
|
||||||
|
# this tool has no other source of truth to check against (its
|
||||||
|
# own README documents that it must reproduce macro_scope.hpp
|
||||||
|
# byte for byte), so there is nothing to gain from checking out a
|
||||||
|
# separate copy, and doing so would make this step fail on a PR
|
||||||
|
# that adds support for a new dispatch table until that PR itself
|
||||||
|
# merges to develop, the same way generate_natvis.py's --version
|
||||||
|
# requirement briefly did.
|
||||||
|
TMPDIR=$(mktemp -d ./macro_builder_check.XXXXXX)
|
||||||
|
c++ -std=c++11 tools/macro_builder/main.cpp -o "$TMPDIR/macro_builder"
|
||||||
|
"$TMPDIR/macro_builder" > "$TMPDIR/paste.hpp"
|
||||||
|
"$TMPDIR/macro_builder" type_body > "$TMPDIR/type_body.hpp"
|
||||||
|
|
||||||
|
# Splice the (still unindented) generated blocks back into
|
||||||
|
# macro_scope.hpp; the astyle pass below indents their
|
||||||
|
# continuation lines the same way it does for the rest of
|
||||||
|
# include/, so a correctly regenerated file comes out unchanged.
|
||||||
|
awk -v newfile="$TMPDIR/paste.hpp" '
|
||||||
|
BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
|
||||||
|
/^#define NLOHMANN_JSON_EXPAND\( x \) x$/ { printf "%s", new; skip=1 }
|
||||||
|
skip && /^#define NLOHMANN_JSON_DOUBLE_PASTE63\(/ { skip=0; next }
|
||||||
|
skip { next }
|
||||||
|
{ print }
|
||||||
|
' include/nlohmann/detail/macro_scope.hpp > "$TMPDIR/macro_scope_1.hpp"
|
||||||
|
awk -v newfile="$TMPDIR/type_body.hpp" '
|
||||||
|
BEGIN { while ((getline line < newfile) > 0) { new = new line "\n" } }
|
||||||
|
/^#define NLOHMANN_JSON_TYPE_BODY\(Prefix, \.\.\.\)/ { printf "%s", new; skip=1 }
|
||||||
|
skip && /^[[:space:]]*NLOHMANN_JSON_TYPE_BODY_SENTINEL\)\)$/ { skip=0; next }
|
||||||
|
skip { next }
|
||||||
|
{ print }
|
||||||
|
' "$TMPDIR/macro_scope_1.hpp" > "$TMPDIR/macro_scope_2.hpp"
|
||||||
|
mv "$TMPDIR/macro_scope_2.hpp" include/nlohmann/detail/macro_scope.hpp
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
|
||||||
- name: Regenerate amalgamation, formatting, and BUILD.bazel
|
- name: Regenerate amalgamation, formatting, and BUILD.bazel
|
||||||
run: |
|
run: |
|
||||||
cd $MAIN_DIR
|
cd $MAIN_DIR
|
||||||
|
|
||||||
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
|
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
|
||||||
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
|
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
|
||||||
|
cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
|
||||||
|
|
||||||
# the header list of the Bazel "json" target must match the files in include/
|
# the header list of the Bazel "json" target must match the files in include/
|
||||||
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
||||||
@@ -87,6 +138,19 @@ jobs:
|
|||||||
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
|
${{ github.workspace }}/venv/bin/astyle --project=tools/astyle/.astylerc --suffix=none --quiet \
|
||||||
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
|
$(find $SOURCE_DIRS -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
|
||||||
|
|
||||||
|
- name: Regenerate nlohmann_json.natvis
|
||||||
|
run: |
|
||||||
|
cd $MAIN_DIR
|
||||||
|
# Pass --version explicitly so this step also works with the tool
|
||||||
|
# copy from develop before this repository's own generate_natvis.py
|
||||||
|
# learns to derive the version itself: the older script requires
|
||||||
|
# --version, and the newer one accepts it as an explicit override.
|
||||||
|
ABI_MACROS=include/nlohmann/detail/abi_macros.hpp
|
||||||
|
VERSION_MAJOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MAJOR' $ABI_MACROS | grep -o '[0-9]\+')
|
||||||
|
VERSION_MINOR=$(grep -m1 'define NLOHMANN_JSON_VERSION_MINOR' $ABI_MACROS | grep -o '[0-9]\+')
|
||||||
|
VERSION_PATCH=$(grep -m1 'define NLOHMANN_JSON_VERSION_PATCH' $ABI_MACROS | grep -o '[0-9]\+')
|
||||||
|
python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
|
||||||
|
|
||||||
- name: Build patch and check for differences
|
- name: Build patch and check for differences
|
||||||
id: diff
|
id: diff
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
comment:
|
comment:
|
||||||
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
|
# push runs on develop have no PR to comment on (and no "pr" artifact)
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@@ -7,6 +7,16 @@ on:
|
|||||||
- develop
|
- develop
|
||||||
paths:
|
paths:
|
||||||
- docs/mkdocs/**
|
- docs/mkdocs/**
|
||||||
|
# the site also embeds these files via pymdownx.snippets
|
||||||
|
# (mkdocs.yml sets restrict_base_path: false for this)
|
||||||
|
- .clang-tidy
|
||||||
|
- .github/CODE_OF_CONDUCT.md
|
||||||
|
- .github/CONTRIBUTING.md
|
||||||
|
- .github/SECURITY.md
|
||||||
|
- cmake/clang_flags.cmake
|
||||||
|
- cmake/gcc_flags.cmake
|
||||||
|
- tests/fmt_formatter/project/main.cpp
|
||||||
|
- tools/astyle/.astylerc
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
# we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications
|
# we don't want to have concurrent jobs, and we don't want to cancel running jobs to avoid broken publications
|
||||||
@@ -23,7 +33,7 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
if: github.repository == 'nlohmann/json'
|
if: github.repository == 'nlohmann/json'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Harden Runner
|
- name: Harden Runner
|
||||||
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
|
||||||
@@ -31,6 +41,8 @@ jobs:
|
|||||||
egress-policy: audit
|
egress-policy: audit
|
||||||
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install virtual environment
|
- name: Install virtual environment
|
||||||
run: make install_venv -C docs/mkdocs
|
run: make install_venv -C docs/mkdocs
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ jobs:
|
|||||||
run: cmake -S . -B build -DJSON_CI=On
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ci_infer
|
run: cmake --build build --target ci_infer
|
||||||
|
- name: Archive Infer report
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
|
with:
|
||||||
|
name: infer-report
|
||||||
|
path: ${{ github.workspace }}/build/build_infer/infer-out/report.txt
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
ci_static_analysis_ubuntu:
|
ci_static_analysis_ubuntu:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -78,7 +85,7 @@ jobs:
|
|||||||
|
|
||||||
ci_static_analysis_clang:
|
ci_static_analysis_clang:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: silkeh/clang:dev
|
container: silkeh/clang:22
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [ci_test_clang, ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze, ci_single_binaries]
|
target: [ci_test_clang, ci_clang_tidy, ci_test_clang_sanitizer, ci_clang_analyze, ci_single_binaries]
|
||||||
@@ -97,13 +104,13 @@ jobs:
|
|||||||
|
|
||||||
ci_cmake_options:
|
ci_cmake_options:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: ubuntu:focal
|
container: ubuntu:24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
|
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_no_thread_local]
|
||||||
steps:
|
steps:
|
||||||
- name: Install build-essential
|
- name: Install build-essential
|
||||||
run: apt-get update ; apt-get install -y build-essential unzip wget git libssl-dev
|
run: apt-get update ; apt-get install -y build-essential unzip wget git
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
@@ -346,6 +353,8 @@ jobs:
|
|||||||
container: intel/oneapi-hpckit:latest
|
container: intel/oneapi-hpckit:latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: Get latest CMake and ninja
|
- name: Get latest CMake and ninja
|
||||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
- name: Run CMake
|
- name: Run CMake
|
||||||
@@ -358,6 +367,8 @@ jobs:
|
|||||||
container: nvcr.io/nvidia/nvhpc:25.5-devel-cuda12.9-ubuntu22.04
|
container: nvcr.io/nvidia/nvhpc:25.5-devel-cuda12.9-ubuntu22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: Get latest CMake and ninja
|
- name: Get latest CMake and ninja
|
||||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
- name: Run CMake
|
- name: Run CMake
|
||||||
@@ -403,3 +414,21 @@ jobs:
|
|||||||
run: cmake -S . -B build -DJSON_CI=On
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ${{ matrix.target }}
|
run: cmake --build build --target ${{ matrix.target }}
|
||||||
|
|
||||||
|
# Native Linux ARM64 runner with the latest GCC. The ubuntu-24.04-arm label is
|
||||||
|
# only available for public repositories.
|
||||||
|
ci_test_arm64:
|
||||||
|
runs-on: ubuntu-24.04-arm
|
||||||
|
container: gcc:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Get latest CMake and ninja
|
||||||
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
|
- name: Check that the job runs natively on arm64
|
||||||
|
run: uname -m && test "$(uname -m)" = aarch64
|
||||||
|
- name: Run CMake
|
||||||
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --target ci_test_compiler_default
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: Get latest CMake and ninja
|
- name: Get latest CMake and ninja
|
||||||
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
uses: lukka/get-cmake@fffaaafeea488556c2c12dad60690008bc1caacb # v4.4.2
|
||||||
- name: Set extra CXX_FLAGS for latest std_version
|
- name: Set extra CXX_FLAGS for latest std_version
|
||||||
@@ -123,6 +125,8 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: Run CMake (Release)
|
- name: Run CMake (Release)
|
||||||
run: cmake -S . -B build -G "Visual Studio 18 2026" -A ARM64 -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 18 2026" -A ARM64 -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
||||||
if: matrix.build_type == 'Release'
|
if: matrix.build_type == 'Release'
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"_comment": "Used by the ci_infer CMake target (#5715 item 4b). fail-on-issue makes CI fail on Infer findings; disable-issue-type is a type-level baseline for the ~174 pre-existing findings (all PULSE_UNNECESSARY_COPY*/PULSE_RESOURCE_LEAK/PULSE_CONST_REFABLE, mostly in test code) triaged in run https://github.com/nlohmann/json/actions/runs/35829411620 on commit 1054b2097, so CI fails only on a NEW issue type. Remove an entry here once its findings have been fixed or explicitly accepted.",
|
||||||
|
"fail-on-issue": true,
|
||||||
|
"disable-issue-type": [
|
||||||
|
"PULSE_UNNECESSARY_COPY_ASSIGNMENT",
|
||||||
|
"PULSE_UNNECESSARY_COPY",
|
||||||
|
"PULSE_UNNECESSARY_COPY_INTERMEDIATE",
|
||||||
|
"PULSE_UNNECESSARY_COPY_OPTIONAL",
|
||||||
|
"PULSE_RESOURCE_LEAK",
|
||||||
|
"PULSE_CONST_REFABLE"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -23,10 +23,6 @@ Files: tests/thirdparty/fifo_map/*
|
|||||||
Copyright: 2015-2017 Niels Lohmann
|
Copyright: 2015-2017 Niels Lohmann
|
||||||
License: MIT
|
License: MIT
|
||||||
|
|
||||||
Files: tests/thirdparty/Fuzzer/*
|
|
||||||
Copyright: 2003-2022 LLVM Project.
|
|
||||||
License: Apache-2.0
|
|
||||||
|
|
||||||
Files: tests/thirdparty/imapdl/*
|
Files: tests/thirdparty/imapdl/*
|
||||||
Copyright: 2017 Georg Sauthoff <mail@gms.tf>
|
Copyright: 2017 Georg Sauthoff <mail@gms.tf>
|
||||||
License: GPL-3.0-only
|
License: GPL-3.0-only
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ cc_library(
|
|||||||
"include/nlohmann/adl_serializer.hpp",
|
"include/nlohmann/adl_serializer.hpp",
|
||||||
"include/nlohmann/byte_container_with_subtype.hpp",
|
"include/nlohmann/byte_container_with_subtype.hpp",
|
||||||
"include/nlohmann/detail/abi_macros.hpp",
|
"include/nlohmann/detail/abi_macros.hpp",
|
||||||
|
"include/nlohmann/detail/bit_ops.hpp",
|
||||||
"include/nlohmann/detail/conversions/from_json.hpp",
|
"include/nlohmann/detail/conversions/from_json.hpp",
|
||||||
"include/nlohmann/detail/conversions/to_chars.hpp",
|
"include/nlohmann/detail/conversions/to_chars.hpp",
|
||||||
"include/nlohmann/detail/conversions/to_json.hpp",
|
"include/nlohmann/detail/conversions/to_json.hpp",
|
||||||
@@ -33,6 +34,7 @@ cc_library(
|
|||||||
"include/nlohmann/detail/input/number_parse.hpp",
|
"include/nlohmann/detail/input/number_parse.hpp",
|
||||||
"include/nlohmann/detail/input/parser.hpp",
|
"include/nlohmann/detail/input/parser.hpp",
|
||||||
"include/nlohmann/detail/input/position_t.hpp",
|
"include/nlohmann/detail/input/position_t.hpp",
|
||||||
|
"include/nlohmann/detail/input/pow5_table.hpp",
|
||||||
"include/nlohmann/detail/input/string_scan.hpp",
|
"include/nlohmann/detail/input/string_scan.hpp",
|
||||||
"include/nlohmann/detail/iterators/internal_iterator.hpp",
|
"include/nlohmann/detail/iterators/internal_iterator.hpp",
|
||||||
"include/nlohmann/detail/iterators/iter_impl.hpp",
|
"include/nlohmann/detail/iterators/iter_impl.hpp",
|
||||||
@@ -65,6 +67,7 @@ cc_library(
|
|||||||
"include/nlohmann/detail/value_t.hpp",
|
"include/nlohmann/detail/value_t.hpp",
|
||||||
"include/nlohmann/json.hpp",
|
"include/nlohmann/json.hpp",
|
||||||
"include/nlohmann/json_fwd.hpp",
|
"include/nlohmann/json_fwd.hpp",
|
||||||
|
"include/nlohmann/json_literals.hpp",
|
||||||
"include/nlohmann/ordered_map.hpp",
|
"include/nlohmann/ordered_map.hpp",
|
||||||
"include/nlohmann/thirdparty/hedley/hedley.hpp",
|
"include/nlohmann/thirdparty/hedley/hedley.hpp",
|
||||||
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
|
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ option(JSON_Diagnostic_Positions "Enable diagnostic positions." OFF)
|
|||||||
option(JSON_GlobalUDLs "Place user-defined string literals in the global namespace." ON)
|
option(JSON_GlobalUDLs "Place user-defined string literals in the global namespace." ON)
|
||||||
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
|
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
|
||||||
option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF)
|
option(JSON_DisableEnumSerialization "Disable default integer enum serialization." OFF)
|
||||||
|
option(JSON_DisableTupleReferenceConversion "Disable conversion from a one-element tuple of a JSON reference." OFF)
|
||||||
option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF)
|
option(JSON_LegacyDiscardedValueComparison "Enable legacy discarded value comparison." OFF)
|
||||||
option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
|
option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
|
||||||
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON)
|
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." ON)
|
||||||
@@ -101,6 +102,10 @@ if (JSON_DisableEnumSerialization)
|
|||||||
message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=1)")
|
message(STATUS "Enum integer serialization is disabled (JSON_DISABLE_ENUM_SERIALIZATION=1)")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (JSON_DisableTupleReferenceConversion)
|
||||||
|
message(STATUS "Tuple reference conversion is disabled (JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1)")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (JSON_LegacyDiscardedValueComparison)
|
if (JSON_LegacyDiscardedValueComparison)
|
||||||
message(STATUS "Legacy discarded value comparison enabled (JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1)")
|
message(STATUS "Legacy discarded value comparison enabled (JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1)")
|
||||||
endif()
|
endif()
|
||||||
@@ -143,6 +148,7 @@ target_compile_definitions(
|
|||||||
$<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:JSON_USE_GLOBAL_UDLS=0>
|
$<$<NOT:$<BOOL:${JSON_GlobalUDLs}>>:JSON_USE_GLOBAL_UDLS=0>
|
||||||
$<$<NOT:$<BOOL:${JSON_ImplicitConversions}>>:JSON_USE_IMPLICIT_CONVERSIONS=0>
|
$<$<NOT:$<BOOL:${JSON_ImplicitConversions}>>:JSON_USE_IMPLICIT_CONVERSIONS=0>
|
||||||
$<$<BOOL:${JSON_DisableEnumSerialization}>:JSON_DISABLE_ENUM_SERIALIZATION=1>
|
$<$<BOOL:${JSON_DisableEnumSerialization}>:JSON_DISABLE_ENUM_SERIALIZATION=1>
|
||||||
|
$<$<BOOL:${JSON_DisableTupleReferenceConversion}>:JSON_DISABLE_TUPLE_REFERENCE_CONVERSION=1>
|
||||||
$<$<BOOL:${JSON_Diagnostics}>:JSON_DIAGNOSTICS=1>
|
$<$<BOOL:${JSON_Diagnostics}>:JSON_DIAGNOSTICS=1>
|
||||||
$<$<BOOL:${JSON_Diagnostic_Positions}>:JSON_DIAGNOSTIC_POSITIONS=1>
|
$<$<BOOL:${JSON_Diagnostic_Positions}>:JSON_DIAGNOSTIC_POSITIONS=1>
|
||||||
$<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
|
$<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
|
||||||
|
|||||||
@@ -33,17 +33,6 @@ Further documentation:
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> The folder `.github/workflows` is predetermined by GitHub.
|
> The folder `.github/workflows` is predetermined by GitHub.
|
||||||
|
|
||||||
### `.cirrus.yml`
|
|
||||||
|
|
||||||
Configuration file for the pipeline at [Cirrus CI](https://cirrus-ci.com/github/nlohmann/json).
|
|
||||||
|
|
||||||
Further documentation:
|
|
||||||
|
|
||||||
- [Writing tasks](https://cirrus-ci.org/guide/writing-tasks/)
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> The filename `.cirrus.yml` and position (root of the repository) are predetermined by Cirrus CI.
|
|
||||||
|
|
||||||
### `.github/external_ci/appveyor.yml`
|
### `.github/external_ci/appveyor.yml`
|
||||||
|
|
||||||
Configuration for the pipelines at [AppVeyor](https://ci.appveyor.com/project/nlohmann/json).
|
Configuration for the pipelines at [AppVeyor](https://ci.appveyor.com/project/nlohmann/json).
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel
|
.PHONY: pretty clean ChangeLog.md release update_hedley update_hedley_undef BUILD.bazel natvis macro_builder_check
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# configuration
|
# configuration
|
||||||
@@ -21,6 +21,11 @@ TESTS_SRCS=$(shell find tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name
|
|||||||
# the single headers (amalgamated from the source files)
|
# the single headers (amalgamated from the source files)
|
||||||
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
|
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
|
||||||
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
||||||
|
# json_literals.hpp only includes <nlohmann/json.hpp>, so it is copied verbatim
|
||||||
|
AMALGAMATED_LITERALS_FILE=single_include/nlohmann/json_literals.hpp
|
||||||
|
|
||||||
|
# the header with the argument-counting macros generated by tools/macro_builder
|
||||||
|
MACRO_SCOPE_HPP=include/nlohmann/detail/macro_scope.hpp
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -29,18 +34,14 @@ AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
|||||||
|
|
||||||
# main target
|
# main target
|
||||||
all:
|
all:
|
||||||
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd}.hpp from the include/nlohmann sources"
|
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals}.hpp from the include/nlohmann sources"
|
||||||
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
||||||
@echo "ChangeLog.md - generate ChangeLog file"
|
@echo "ChangeLog.md - generate ChangeLog file"
|
||||||
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
|
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
|
||||||
@echo "clean - remove built files"
|
@echo "clean - remove built files"
|
||||||
@echo "doctest - compile example files and check their output"
|
@echo "fuzzing - see tests/fuzzing.md for how to build and run the fuzzers"
|
||||||
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
|
@echo "macro_builder_check - check that macro_scope.hpp matches tools/macro_builder's output"
|
||||||
@echo "fuzz_testing_bon8 - prepare fuzz testing of the BON8 parser"
|
@echo "natvis - regenerate nlohmann_json.natvis from the current ABI tags and version"
|
||||||
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
|
|
||||||
@echo "fuzz_testing_cbor - prepare fuzz testing of the CBOR parser"
|
|
||||||
@echo "fuzz_testing_msgpack - prepare fuzz testing of the MessagePack parser"
|
|
||||||
@echo "fuzz_testing_ubjson - prepare fuzz testing of the UBJSON parser"
|
|
||||||
@echo "pretty - beautify code with Artistic Style"
|
@echo "pretty - beautify code with Artistic Style"
|
||||||
@echo "run_benchmarks - build and run benchmarks"
|
@echo "run_benchmarks - build and run benchmarks"
|
||||||
@echo "update_hedley - download Hedley and regenerate hedley.hpp / hedley_undef.hpp"
|
@echo "update_hedley - download Hedley and regenerate hedley.hpp / hedley_undef.hpp"
|
||||||
@@ -59,74 +60,6 @@ run_benchmarks:
|
|||||||
cd cmake-build-benchmarks ; ./json_benchmarks
|
cd cmake-build-benchmarks ; ./json_benchmarks
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# fuzzing
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
# the overall fuzz testing target
|
|
||||||
fuzz_testing:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_afl_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_afl_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data/json_tests -size -5k -name *json | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzz_testing_bon8:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_bon8_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_bon8_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data -size -5k -name *.bon8 | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzz_testing_bson:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_bson_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_bson_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data -size -5k -name *.bson | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzz_testing_cbor:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_cbor_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_cbor_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data -size -5k -name *.cbor | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzz_testing_msgpack:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_msgpack_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_msgpack_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data -size -5k -name *.msgpack | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzz_testing_ubjson:
|
|
||||||
rm -fr fuzz-testing
|
|
||||||
mkdir -p fuzz-testing fuzz-testing/testcases fuzz-testing/out
|
|
||||||
$(MAKE) parse_ubjson_fuzzer -C tests CXX=afl-clang++
|
|
||||||
mv tests/parse_ubjson_fuzzer fuzz-testing/fuzzer
|
|
||||||
find tests/data -size -5k -name *.ubjson | xargs -I{} cp "{}" fuzz-testing/testcases
|
|
||||||
@echo "Execute: afl-fuzz -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer"
|
|
||||||
|
|
||||||
fuzzing-start:
|
|
||||||
afl-fuzz -S fuzzer1 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer2 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer3 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer4 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer5 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer6 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -S fuzzer7 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer > /dev/null &
|
|
||||||
afl-fuzz -M fuzzer0 -i fuzz-testing/testcases -o fuzz-testing/out fuzz-testing/fuzzer
|
|
||||||
|
|
||||||
fuzzing-stop:
|
|
||||||
-killall fuzzer
|
|
||||||
-killall afl-fuzz
|
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Static analysis
|
# Static analysis
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -154,14 +87,10 @@ install_astyle:
|
|||||||
|
|
||||||
# call the Artistic Style pretty printer on all source files
|
# call the Artistic Style pretty printer on all source files
|
||||||
pretty: install_astyle
|
pretty: install_astyle
|
||||||
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/mkdocs/docs/examples/*.cpp
|
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp docs/mkdocs/docs/examples/*.hpp
|
||||||
|
|
||||||
# call the Clang-Format on all source files
|
|
||||||
pretty_format:
|
|
||||||
for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/mkdocs/docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
|
|
||||||
|
|
||||||
# create single header files and pretty print
|
# create single header files and pretty print
|
||||||
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
|
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE)
|
||||||
$(MAKE) pretty
|
$(MAKE) pretty
|
||||||
|
|
||||||
# call the amalgamation tool for json.hpp
|
# call the amalgamation tool for json.hpp
|
||||||
@@ -172,20 +101,50 @@ $(AMALGAMATED_FILE): $(SRCS)
|
|||||||
$(AMALGAMATED_FWD_FILE): $(SRCS)
|
$(AMALGAMATED_FWD_FILE): $(SRCS)
|
||||||
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_fwd.json -s . --verbose=yes
|
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_fwd.json -s . --verbose=yes
|
||||||
|
|
||||||
|
# copy json_literals.hpp
|
||||||
|
$(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp
|
||||||
|
cp include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE)
|
||||||
|
|
||||||
|
# regenerate nlohmann_json.natvis from the ABI tags and version in include/nlohmann/detail/abi_macros.hpp
|
||||||
|
natvis:
|
||||||
|
python3 tools/generate_natvis/generate_natvis.py .
|
||||||
|
|
||||||
|
# regenerate the two tools/macro_builder blocks of $(MACRO_SCOPE_HPP) (see its README.md) and diff against the
|
||||||
|
# checked-in header; phony, because it never writes $(MACRO_SCOPE_HPP) itself
|
||||||
|
macro_builder_check:
|
||||||
|
@set -e; \
|
||||||
|
TMPDIR=$$(mktemp -d ./macro_builder_check.XXXXXX); \
|
||||||
|
trap 'rm -rf "$$TMPDIR"' EXIT; \
|
||||||
|
$(CXX) -std=c++11 tools/macro_builder/main.cpp -o "$$TMPDIR/macro_builder"; \
|
||||||
|
"$$TMPDIR/macro_builder" > "$$TMPDIR/paste.hpp"; \
|
||||||
|
"$$TMPDIR/macro_builder" type_body > "$$TMPDIR/type_body.hpp"; \
|
||||||
|
$(ASTYLE) --project=tools/astyle/.astylerc --suffix=none --quiet "$$TMPDIR/paste.hpp" "$$TMPDIR/type_body.hpp"; \
|
||||||
|
sed -n '/^#define NLOHMANN_JSON_EXPAND( x ) x$$/,/^#define NLOHMANN_JSON_DOUBLE_PASTE63(/p' $(MACRO_SCOPE_HPP) > "$$TMPDIR/paste_actual.hpp"; \
|
||||||
|
sed -n '/^#define NLOHMANN_JSON_TYPE_BODY(Prefix, \.\.\.)/,/^ NLOHMANN_JSON_TYPE_BODY_SENTINEL))$$/p' $(MACRO_SCOPE_HPP) > "$$TMPDIR/type_body_actual.hpp"; \
|
||||||
|
diff "$$TMPDIR/paste.hpp" "$$TMPDIR/paste_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_EXPAND..NLOHMANN_JSON_DOUBLE_PASTE63) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1); \
|
||||||
|
diff "$$TMPDIR/type_body.hpp" "$$TMPDIR/type_body_actual.hpp" || (echo "===================================================================\n $(MACRO_SCOPE_HPP) (NLOHMANN_JSON_TYPE_BODY) is out of date!\n Regenerate it, see tools/macro_builder/README.md.\n===================================================================" ; exit 1)
|
||||||
|
|
||||||
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
|
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
|
||||||
# Note: this target is called by Travis
|
|
||||||
check-amalgamation:
|
check-amalgamation:
|
||||||
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
|
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
|
||||||
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
|
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
|
||||||
|
@mv $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~
|
||||||
@$(MAKE) amalgamate
|
@$(MAKE) amalgamate
|
||||||
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
|
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
|
||||||
@diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
|
@diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
|
||||||
|
@diff $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE) ; false)
|
||||||
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
|
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
|
||||||
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
|
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
|
||||||
|
@mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE)
|
||||||
@mv BUILD.bazel BUILD.bazel~
|
@mv BUILD.bazel BUILD.bazel~
|
||||||
@$(MAKE) BUILD.bazel
|
@$(MAKE) BUILD.bazel
|
||||||
@diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
|
@diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
|
||||||
@mv BUILD.bazel~ BUILD.bazel
|
@mv BUILD.bazel~ BUILD.bazel
|
||||||
|
@mv nlohmann_json.natvis nlohmann_json.natvis~
|
||||||
|
@$(MAKE) natvis
|
||||||
|
@diff nlohmann_json.natvis nlohmann_json.natvis~ || (echo "===================================================================\n nlohmann_json.natvis is out of date! Please run 'make natvis'.\n===================================================================" ; mv nlohmann_json.natvis~ nlohmann_json.natvis ; false)
|
||||||
|
@mv nlohmann_json.natvis~ nlohmann_json.natvis
|
||||||
|
@$(MAKE) macro_builder_check
|
||||||
|
|
||||||
# generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild
|
# generate the Bazel BUILD file; phony, because a removed header would not trigger a rebuild
|
||||||
BUILD.bazel:
|
BUILD.bazel:
|
||||||
@@ -222,7 +181,7 @@ json.tar.xz:
|
|||||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||||
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
||||||
include.zip: BUILD.bazel
|
include.zip: BUILD.bazel
|
||||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
||||||
|
|
||||||
# Create the files for a release and add signatures and hashes.
|
# Create the files for a release and add signatures and hashes.
|
||||||
release: include.zip json.tar.xz
|
release: include.zip json.tar.xz
|
||||||
@@ -231,11 +190,13 @@ release: include.zip json.tar.xz
|
|||||||
gpg --armor --detach-sig include.zip
|
gpg --armor --detach-sig include.zip
|
||||||
gpg --armor --detach-sig $(AMALGAMATED_FILE)
|
gpg --armor --detach-sig $(AMALGAMATED_FILE)
|
||||||
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
|
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
|
||||||
|
gpg --armor --detach-sig $(AMALGAMATED_LITERALS_FILE)
|
||||||
gpg --armor --detach-sig json.tar.xz
|
gpg --armor --detach-sig json.tar.xz
|
||||||
cp $(AMALGAMATED_FILE) release_files
|
cp $(AMALGAMATED_FILE) release_files
|
||||||
cp $(AMALGAMATED_FWD_FILE) release_files
|
cp $(AMALGAMATED_FWD_FILE) release_files
|
||||||
mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
|
cp $(AMALGAMATED_LITERALS_FILE) release_files
|
||||||
cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt
|
mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc $(AMALGAMATED_LITERALS_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
|
||||||
|
cd release_files ; shasum -a 256 $$(find . -type f -not -name '*.asc' | sed 's|^\./||' | sort) > hashes.txt
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -245,7 +206,6 @@ release: include.zip json.tar.xz
|
|||||||
# clean up
|
# clean up
|
||||||
clean:
|
clean:
|
||||||
rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM
|
rm -fr fuzz fuzz-testing *.dSYM tests/*.dSYM
|
||||||
rm -fr benchmarks/files/numbers/*.json
|
|
||||||
rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
|
rm -fr cmake-build-benchmarks fuzz-testing cmake-build-pvs-studio release_files
|
||||||
$(MAKE) clean -Cdocs
|
$(MAKE) clean -Cdocs
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
[](https://coveralls.io/github/nlohmann/json?branch=develop)
|
[](https://coveralls.io/github/nlohmann/json?branch=develop)
|
||||||
[](https://scan.coverity.com/projects/nlohmann-json)
|
[](https://scan.coverity.com/projects/nlohmann-json)
|
||||||
[](https://app.codacy.com/gh/nlohmann/json/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
[](https://app.codacy.com/gh/nlohmann/json/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
||||||
[](https://cirrus-ci.com/github/nlohmann/json)
|
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
|
||||||
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
|
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
|
||||||
[](https://json.nlohmann.me)
|
[](https://json.nlohmann.me)
|
||||||
@@ -1395,6 +1394,7 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
|||||||
- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
- The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
||||||
- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
- The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||||
- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
- The class contains parts of [Google Abseil](https://github.com/abseil/abseil-cpp) which is licensed under the [Apache 2.0 License](https://opensource.org/licenses/Apache-2.0).
|
||||||
|
- The class contains an adapted version of the Eisel-Lemire algorithm, its table of powers of five, and its digit comparison for long numbers from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
||||||
|
|
||||||
<img align="right" src="https://git.fsfe.org/reuse/reuse-ci/raw/branch/master/reuse-horizontal.png" alt="REUSE Software">
|
<img align="right" src="https://git.fsfe.org/reuse/reuse-ci/raw/branch/master/reuse-horizontal.png" alt="REUSE Software">
|
||||||
|
|
||||||
|
|||||||
+127
-85
@@ -8,24 +8,24 @@ set(N 10)
|
|||||||
include(FindPython3)
|
include(FindPython3)
|
||||||
find_package(Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
|
||||||
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
|
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-22 clang++-21 clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
|
||||||
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
|
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
||||||
|
|
||||||
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
|
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-22 clang-tidy-21 clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
|
||||||
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
|
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
|
message(STATUS "🔖 Clang-Tidy ${CLANG_TIDY_TOOL_VERSION} (${CLANG_TIDY_TOOL})")
|
||||||
|
|
||||||
message(STATUS "🔖 CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})")
|
message(STATUS "🔖 CMake ${CMAKE_VERSION} (${CMAKE_COMMAND})")
|
||||||
|
|
||||||
find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-15 g++-14 g++-13 g++-12 g++-11 g++-10)
|
find_program(GCC_TOOL NAMES g++-latest g++-HEAD g++ g++-16 g++-15 g++-14 g++-13 g++-12 g++-11 g++-10)
|
||||||
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
|
execute_process(COMMAND ${GCC_TOOL} --version OUTPUT_VARIABLE GCC_TOOL_VERSION ERROR_VARIABLE GCC_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCC_TOOL_VERSION "${GCC_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
|
message(STATUS "🔖 GCC ${GCC_TOOL_VERSION} (${GCC_TOOL})")
|
||||||
|
|
||||||
find_program(GCOV_TOOL NAMES gcov-HEAD gcov gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10)
|
find_program(GCOV_TOOL NAMES gcov-HEAD gcov gcov-16 gcov-15 gcov-14 gcov-13 gcov-12 gcov-11 gcov-10)
|
||||||
execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION)
|
execute_process(COMMAND ${GCOV_TOOL} --version OUTPUT_VARIABLE GCOV_TOOL_VERSION ERROR_VARIABLE GCOV_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" GCOV_TOOL_VERSION "${GCOV_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})")
|
message(STATUS "🔖 GCOV ${GCOV_TOOL_VERSION} (${GCOV_TOOL})")
|
||||||
@@ -40,6 +40,14 @@ execute_process(COMMAND ${IWYU_TOOL} --version OUTPUT_VARIABLE IWYU_TOOL_VERSION
|
|||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" IWYU_TOOL_VERSION "${IWYU_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
|
message(STATUS "🔖 include-what-you-use ${IWYU_TOOL_VERSION} (${IWYU_TOOL})")
|
||||||
|
|
||||||
|
# CMake's CXX_INCLUDE_WHAT_YOU_USE launcher runs IWYU during the normal compile step (useful to see
|
||||||
|
# diagnostics inline), but CMake's own __run_co_compile wrapper does not propagate the launched
|
||||||
|
# tool's exit code to the build, so IWYU's own "-Xiwyu --error" cannot fail that step (verified: a
|
||||||
|
# deliberately-unused #include in a header still lets `cmake --build` finish with exit code 0).
|
||||||
|
# iwyu_tool.py, which ships with IWYU, reads compile_commands.json and does return a non-zero exit
|
||||||
|
# code for any analyzed file with findings; ci_single_binaries uses it to actually fail on findings.
|
||||||
|
find_program(IWYU_TOOL_PY NAMES iwyu_tool iwyu_tool.py iwyu-tool)
|
||||||
|
|
||||||
find_program(INFER_TOOL NAMES infer)
|
find_program(INFER_TOOL NAMES infer)
|
||||||
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
|
execute_process(COMMAND ${INFER_TOOL} --version OUTPUT_VARIABLE INFER_TOOL_VERSION ERROR_VARIABLE INFER_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" INFER_TOOL_VERSION "${INFER_TOOL_VERSION}")
|
||||||
@@ -55,12 +63,6 @@ execute_process(COMMAND ${NINJA_TOOL} --version OUTPUT_VARIABLE NINJA_TOOL_VERSI
|
|||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" NINJA_TOOL_VERSION "${NINJA_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
|
message(STATUS "🔖 Ninja ${NINJA_TOOL_VERSION} (${NINJA_TOOL})")
|
||||||
|
|
||||||
find_program(OCLINT_TOOL NAMES oclint-json-compilation-database)
|
|
||||||
find_program(OCLINT_VERSION_TOOL NAMES oclint)
|
|
||||||
execute_process(COMMAND ${OCLINT_VERSION_TOOL} --version OUTPUT_VARIABLE OCLINT_TOOL_VERSION ERROR_VARIABLE OCLINT_TOOL_VERSION)
|
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" OCLINT_TOOL_VERSION "${OCLINT_TOOL_VERSION}")
|
|
||||||
message(STATUS "🔖 OCLint ${OCLINT_TOOL_VERSION} (${OCLINT_TOOL})")
|
|
||||||
|
|
||||||
find_program(VALGRIND_TOOL NAMES valgrind)
|
find_program(VALGRIND_TOOL NAMES valgrind)
|
||||||
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
|
execute_process(COMMAND ${VALGRIND_TOOL} --version OUTPUT_VARIABLE VALGRIND_TOOL_VERSION ERROR_VARIABLE VALGRIND_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" VALGRIND_TOOL_VERSION "${VALGRIND_TOOL_VERSION}")
|
||||||
@@ -128,16 +130,16 @@ foreach(CXX_STANDARD 11 14 17 20 23 26)
|
|||||||
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# pass -stdlib=libc++ through CXXFLAGS: an explicit -DCMAKE_CXX_FLAGS would make CMake ignore CXXFLAGS
|
||||||
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
|
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
|
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS};-stdlib=libc++" ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||||
-DJSON_TestStandards=${CXX_STANDARD}
|
-DJSON_TestStandards=${CXX_STANDARD}
|
||||||
-DCMAKE_CXX_FLAGS="-stdlib=libc++"
|
|
||||||
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
|
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD}
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_libcxx_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||||
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
|
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
|
||||||
)
|
)
|
||||||
endforeach()
|
endforeach()
|
||||||
@@ -276,6 +278,20 @@ add_custom_target(ci_test_disableenumserialization
|
|||||||
COMMENT "Compile and test with enum serialization disabled"
|
COMMENT "Compile and test with enum serialization disabled"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Disable conversion from a one-element tuple of a JSON reference.
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
add_custom_target(ci_test_disabletuplereferenceconversion
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
|
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DisableTupleReferenceConversion=ON
|
||||||
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion
|
||||||
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_disabletuplereferenceconversion && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||||
|
COMMENT "Compile and test with tuple reference conversion disabled"
|
||||||
|
)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Skip the multiple-inclusion library version check.
|
# Skip the multiple-inclusion library version check.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -362,20 +378,29 @@ add_custom_target(ci_test_clang_sanitizer
|
|||||||
# Check if header is amalgamated and sources are properly indented.
|
# Check if header is amalgamated and sources are properly indented.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
# Same file set as .github/workflows/check_amalgamation.yml, so a direct push to develop/master/release/*
|
||||||
|
# (which only this CMake target checks, not the pull_request-only workflow) is held to the same standard.
|
||||||
file(GLOB_RECURSE INDENT_FILES
|
file(GLOB_RECURSE INDENT_FILES
|
||||||
${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.hpp
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/docs/mkdocs/docs/examples/*.cu
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/*.cu
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/tests/*.cu
|
||||||
)
|
)
|
||||||
|
list(FILTER INDENT_FILES EXCLUDE REGEX "/tests/thirdparty/|/tests/abi/include/nlohmann/")
|
||||||
|
|
||||||
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
||||||
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
||||||
add_custom_target(ci_test_amalgamation
|
add_custom_target(ci_test_amalgamation
|
||||||
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~
|
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~
|
||||||
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
||||||
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
||||||
|
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
|
||||||
|
COMMAND cp ${PROJECT_SOURCE_DIR}/BUILD.bazel ${PROJECT_SOURCE_DIR}/BUILD.bazel~
|
||||||
|
|
||||||
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
||||||
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
||||||
@@ -383,16 +408,20 @@ add_custom_target(ci_test_amalgamation
|
|||||||
|
|
||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
|
||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
||||||
|
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/scripts/gen_bazel_build_file.cmake
|
||||||
|
|
||||||
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
||||||
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
||||||
|
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
|
||||||
|
COMMAND diff ${PROJECT_SOURCE_DIR}/BUILD.bazel~ ${PROJECT_SOURCE_DIR}/BUILD.bazel
|
||||||
|
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
||||||
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
||||||
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
COMMENT "Check amalgamation and indentation"
|
COMMENT "Check amalgamation, formatting, and BUILD.bazel"
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -427,14 +456,14 @@ add_custom_target(ci_test_valgrind
|
|||||||
# Check code with Clang Static Analyzer.
|
# Check code with Clang Static Analyzer.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
set(CLANG_ANALYZER_CHECKS "fuchsia.HandleChecker,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.mpi.MPI-Checker,optin.osx.OSObjectCStyleCast,optin.osx.cocoa.localizability.EmptyLocalizationContextChecker,optin.osx.cocoa.localizability.NonLocalizedStringChecker,optin.performance.GCDAntipattern,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,webkit.NoUncountedMemberChecker,webkit.RefCntblBaseVirtualDtor,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,osx.API,osx.MIG,osx.NumberObjectConversion,osx.OSObjectRetainCount,osx.ObjCProperty,osx.SecKeychainAPI,osx.cocoa.AtSync,osx.cocoa.AutoreleaseWrite,osx.cocoa.ClassRelease,osx.cocoa.Dealloc,osx.cocoa.IncompatibleMethodTypes,osx.cocoa.Loops,osx.cocoa.MissingSuperCall,osx.cocoa.NSAutoreleasePool,osx.cocoa.NSError,osx.cocoa.NilArg,osx.cocoa.NonNilReturnValue,osx.cocoa.ObjCGenerics,osx.cocoa.RetainCount,osx.cocoa.RunLoopAutoreleaseLeak,osx.cocoa.SelfInit,osx.cocoa.SuperDealloc,osx.cocoa.UnusedIvars,osx.cocoa.VariadicMethodTypes,osx.coreFoundation.CFError,osx.coreFoundation.CFNumber,osx.coreFoundation.CFRetainRelease,osx.coreFoundation.containers.OutOfBounds,osx.coreFoundation.containers.PointerSizedValues,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
|
set(CLANG_ANALYZER_CHECKS "nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,optin.cplusplus.UninitializedObject,optin.cplusplus.VirtualCall,optin.performance.Padding,optin.portability.UnixAPI,security.FloatLoopCounter,security.insecureAPI.DeprecatedOrUnsafeBufferHandling,security.insecureAPI.bcmp,security.insecureAPI.bcopy,security.insecureAPI.bzero,security.insecureAPI.rand,security.insecureAPI.strcpy,valist.CopyToSelf,valist.Uninitialized,valist.Unterminated,core.CallAndMessage,core.DivideZero,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.VLASize,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.PlacementNew,cplusplus.PureVirtualCall,deadcode.DeadStores,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,security.insecureAPI.UncheckedReturn,security.insecureAPI.decodeValueOfObjCType,security.insecureAPI.getpw,security.insecureAPI.gets,security.insecureAPI.mkstemp,security.insecureAPI.mktemp,security.insecureAPI.vfork,unix.API,unix.Malloc,unix.MallocSizeof,unix.MismatchedDeallocator,unix.Vfork,unix.cstring.BadSizeArg,unix.cstring.NullArg")
|
||||||
|
|
||||||
add_custom_target(ci_clang_analyze
|
add_custom_target(ci_clang_analyze
|
||||||
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
||||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||||
-DJSON_BuildTests=ON
|
-DJSON_BuildTests=ON
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_analyze
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} -analyze-headers -o ${PROJECT_BINARY_DIR}/report ninja
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_analyze && ${SCAN_BUILD_TOOL} -enable-checker ${CLANG_ANALYZER_CHECKS} --use-c++=${CLANG_TOOL} --use-analyzer=${CLANG_TOOL} -analyze-headers --status-bugs -o ${PROJECT_BINARY_DIR}/report ninja
|
||||||
COMMENT "Check code with Clang Analyzer"
|
COMMENT "Check code with Clang Analyzer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -450,7 +479,7 @@ add_custom_target(ci_cppcheck
|
|||||||
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
|
COMMAND venv_cppcheck/bin/cppcheck --enable=warning --check-level=exhaustive --inline-suppr --inconclusive --force
|
||||||
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
|
--std=c++11 ${PROJECT_SOURCE_DIR}/include/nlohmann/json.hpp -I ${CMAKE_SOURCE_DIR}/include
|
||||||
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
|
--error-exitcode=1 --relative-paths=${PROJECT_SOURCE_DIR} -j ${N} --include=default_defines.hpp
|
||||||
--cppcheck-build-dir=cppcheck --check-level=exhaustive
|
--cppcheck-build-dir=cppcheck
|
||||||
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
|
-UJSON_CATCH_USER -UJSON_TRY_USER -UJSON_ASSERT -UJSON_INTERNAL_CATCH -UJSON_THROW
|
||||||
-DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON
|
-DJSON_HAS_CPP_11 -UJSON_HAS_CPP_14 -UJSON_HAS_CPP_17 -UJSON_HAS_CPP_20 -UJSON_HAS_THREE_WAY_COMPARISON
|
||||||
COMMENT "Check code with Cppcheck"
|
COMMENT "Check code with Cppcheck"
|
||||||
@@ -468,34 +497,6 @@ add_custom_target(ci_cpplint
|
|||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Check code with OCLint.
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
file(COPY ${PROJECT_SOURCE_DIR}/single_include/nlohmann/json.hpp DESTINATION ${PROJECT_BINARY_DIR}/src_single)
|
|
||||||
file(RENAME ${PROJECT_BINARY_DIR}/src_single/json.hpp ${PROJECT_BINARY_DIR}/src_single/all.cpp)
|
|
||||||
file(APPEND "${PROJECT_BINARY_DIR}/src_single/all.cpp" "\n\nint main()\n{}\n")
|
|
||||||
|
|
||||||
add_executable(single_all ${PROJECT_BINARY_DIR}/src_single/all.cpp)
|
|
||||||
target_compile_features(single_all PRIVATE cxx_std_11)
|
|
||||||
|
|
||||||
add_custom_target(ci_oclint
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
||||||
-DJSON_BuildTests=OFF -DJSON_CI=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_oclint
|
|
||||||
COMMAND ${OCLINT_TOOL} -i ${PROJECT_BINARY_DIR}/build_oclint/src_single/all.cpp -p ${PROJECT_BINARY_DIR}/build_oclint --
|
|
||||||
-report-type html -enable-global-analysis --max-priority-1=0 --max-priority-2=1000 --max-priority-3=2000
|
|
||||||
--disable-rule=MultipleUnaryOperator
|
|
||||||
--disable-rule=DoubleNegative
|
|
||||||
--disable-rule=ShortVariableName
|
|
||||||
--disable-rule=GotoStatement
|
|
||||||
--disable-rule=LongLine
|
|
||||||
-o ${PROJECT_BINARY_DIR}/build_oclint/oclint_report.html
|
|
||||||
COMMENT "Check code with OCLint"
|
|
||||||
)
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Check code with Clang-Tidy.
|
# Check code with Clang-Tidy.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@@ -510,29 +511,16 @@ add_custom_target(ci_clang_tidy
|
|||||||
COMMENT "Check code with Clang-Tidy"
|
COMMENT "Check code with Clang-Tidy"
|
||||||
)
|
)
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Check code with PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>.
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
add_custom_target(ci_pvs_studio
|
|
||||||
COMMAND CXX=${CLANG_TOOL} ${CMAKE_COMMAND}
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
||||||
-DJSON_BuildTests=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_pvs_studio
|
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PVS_STUDIO_ANALYZER_TOOL} analyze -j 10
|
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_pvs_studio && ${PLOG_CONVERTER_TOOL} -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
|
||||||
COMMENT "Check code with PVS Studio"
|
|
||||||
)
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Check code with Infer <https://fbinfer.com> static analyzer.
|
# Check code with Infer <https://fbinfer.com> static analyzer.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
# .inferconfig (repository root) pins --fail-on-issue and the currently-triaged issue types that
|
||||||
|
# are disabled until they are addressed separately; see #5715 item 4b.
|
||||||
add_custom_target(ci_infer
|
add_custom_target(ci_infer
|
||||||
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
|
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/build_infer
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} compile -- ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${PROJECT_SOURCE_DIR} -DJSON_BuildTests=ON
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run -- make
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_infer && ${INFER_TOOL} run --project-root ${PROJECT_SOURCE_DIR} -- make
|
||||||
COMMENT "Check code with Infer"
|
COMMENT "Check code with Infer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -588,7 +576,13 @@ add_custom_target(ci_reproducible_tests
|
|||||||
# be compiled individually.
|
# be compiled individually.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
set(iwyu_path_and_options ${IWYU_TOOL} -Xiwyu --max_line_length=300)
|
set(iwyu_options -Xiwyu --error -Xiwyu --max_line_length=300)
|
||||||
|
set(iwyu_path_and_options ${IWYU_TOOL} ${iwyu_options})
|
||||||
|
|
||||||
|
# CMake needs to know the exact flags used to compile each src_single/*.cpp below to hand them to
|
||||||
|
# iwyu_tool.py; JSON_CI already implies a from-scratch configure, so enabling this project-wide has
|
||||||
|
# no downside here.
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
foreach(SRC_FILE ${SRC_FILES})
|
foreach(SRC_FILE ${SRC_FILES})
|
||||||
# get relative path of the header file
|
# get relative path of the header file
|
||||||
@@ -603,14 +597,34 @@ foreach(SRC_FILE ${SRC_FILES})
|
|||||||
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(single_${RELATIVE_SRC_FILE} PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
||||||
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
|
target_compile_features(single_${RELATIVE_SRC_FILE} PRIVATE cxx_std_11)
|
||||||
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
|
set_property(TARGET single_${RELATIVE_SRC_FILE} PROPERTY CXX_INCLUDE_WHAT_YOU_USE "${iwyu_path_and_options}")
|
||||||
# remember binary for ci_single_binaries target
|
# remember binary for ci_single_binaries
|
||||||
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
|
list(APPEND single_binaries single_${RELATIVE_SRC_FILE})
|
||||||
|
# json.hpp pulls together the whole library behind heavily templated, SFINAE-based code, and
|
||||||
|
# IWYU's suggestion for its one truly ambiguous symbol (a container-comparison "swap,
|
||||||
|
# operator!=") is not deterministic between runs (observed <set>, <unordered_map>, and <map>
|
||||||
|
# for the exact same source across otherwise-identical local and containerized builds). Keep
|
||||||
|
# reporting its diagnostics (informational, via CXX_INCLUDE_WHAT_YOU_USE above) but exclude it
|
||||||
|
# from the hard gate below so a fresh IWYU/compiler combination does not fail this target on a
|
||||||
|
# nondeterministic suggestion for a header that already re-exports everything on purpose.
|
||||||
|
if(NOT RELATIVE_SRC_FILE STREQUAL "json")
|
||||||
|
list(APPEND single_binaries_tus src_single/${RELATIVE_SRC_FILE}.cpp)
|
||||||
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
if(IWYU_TOOL_PY)
|
||||||
|
add_custom_target(ci_single_binaries
|
||||||
|
DEPENDS ${single_binaries}
|
||||||
|
COMMAND ${IWYU_TOOL_PY} -p ${PROJECT_BINARY_DIR} ${single_binaries_tus} -- ${iwyu_options}
|
||||||
|
COMMENT "Check if headers are self-contained"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# iwyu_tool.py (ships with IWYU, e.g. as /usr/bin/iwyu_tool on Debian/Ubuntu) was not found;
|
||||||
|
# fall back to building the self-containment check without enforcing the IWYU findings.
|
||||||
add_custom_target(ci_single_binaries
|
add_custom_target(ci_single_binaries
|
||||||
DEPENDS ${single_binaries}
|
DEPENDS ${single_binaries}
|
||||||
COMMENT "Check if headers are self-contained"
|
COMMENT "Check if headers are self-contained"
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Benchmarks
|
# Benchmarks
|
||||||
@@ -632,10 +646,29 @@ add_custom_target(ci_benchmarks
|
|||||||
# we test the project with different CMake versions:
|
# we test the project with different CMake versions:
|
||||||
# - CMake 3.5 (the earliest supported)
|
# - CMake 3.5 (the earliest supported)
|
||||||
# - CMake 3.31.6 (the latest 3.x release)
|
# - CMake 3.31.6 (the latest 3.x release)
|
||||||
# - CMake 4.0.0 (the latest release)
|
# - CMake 4.0.0 (the first 4.x release)
|
||||||
|
# - the CMake version running this build (usually the latest release)
|
||||||
|
|
||||||
function(ci_get_cmake version var)
|
function(ci_get_cmake version var)
|
||||||
set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}/bin/cmake)
|
set(${var} ${PROJECT_BINARY_DIR}/cmake-${version}/bin/cmake)
|
||||||
|
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$")
|
||||||
|
# Kitware publishes a prebuilt Linux x86_64 archive for every release; unpacking it is far
|
||||||
|
# cheaper than compiling all of CMake (including its own test helpers) from source.
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${${var}}
|
||||||
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-linux-x86_64.tar.gz
|
||||||
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-SHA-256.txt
|
||||||
|
# verify the archive against Kitware's published SHA-256 sums before unpacking it
|
||||||
|
COMMAND sh -c "grep ' cmake-${version}-linux-x86_64[.]tar[.]gz$' cmake-${version}-SHA-256.txt | sha256sum -c -"
|
||||||
|
COMMAND tar xfz cmake-${version}-linux-x86_64.tar.gz
|
||||||
|
COMMAND rm cmake-${version}-linux-x86_64.tar.gz cmake-${version}-SHA-256.txt
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -rf cmake-${version}
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rename cmake-${version}-linux-x86_64 cmake-${version}
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
COMMENT "Download prebuilt CMake ${version}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# no prebuilt archive for this platform (e.g. macOS or Linux aarch64): build from source
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${${var}}
|
OUTPUT ${${var}}
|
||||||
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}.tar.gz
|
COMMAND wget -nc https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}.tar.gz
|
||||||
@@ -645,8 +678,9 @@ function(ci_get_cmake version var)
|
|||||||
COMMAND cmake -S cmake-${version} -B cmake-${version} -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
COMMAND cmake -S cmake-${version} -B cmake-${version} -DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||||
COMMAND cmake --build cmake-${version} --parallel 10
|
COMMAND cmake --build cmake-${version} --parallel 10
|
||||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
COMMENT "Download CMake ${version}"
|
COMMENT "Download and build CMake ${version} from source"
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
set(${var} ${${var}} PARENT_SCOPE)
|
set(${var} ${${var}} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
@@ -656,30 +690,24 @@ ci_get_cmake(4.0.0 CMAKE_4_0_0_BINARY)
|
|||||||
|
|
||||||
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
|
# the tests require CMake 3.13 or later, so they are excluded for CMake 3.5.0
|
||||||
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
set(JSON_CMAKE_FLAGS_3_5_0 JSON_Diagnostics JSON_Diagnostic_Positions JSON_GlobalUDLs JSON_ImplicitConversions JSON_DisableEnumSerialization
|
||||||
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind)
|
JSON_LegacyDiscardedValueComparison JSON_Install JSON_MultipleHeaders JSON_SystemInclude JSON_Valgrind
|
||||||
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_31_6})
|
JSON_StrictNulHandling)
|
||||||
|
set(JSON_CMAKE_FLAGS_3_31_6 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
||||||
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
set(JSON_CMAKE_FLAGS_4_0_0 JSON_BuildTests ${JSON_CMAKE_FLAGS_3_5_0})
|
||||||
|
|
||||||
function(ci_add_cmake_flags_targets flag min_version)
|
function(ci_add_cmake_flags_targets flag min_version)
|
||||||
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
|
string(TOLOWER "ci_cmake_flag_${flag}" flag_target)
|
||||||
string(REPLACE . _ min_version_var ${min_version})
|
string(REPLACE . _ min_version_var ${min_version})
|
||||||
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
|
set(cmake_binary ${CMAKE_${min_version_var}_BINARY})
|
||||||
add_custom_target(${flag_target}_${min_version}_2
|
|
||||||
COMMENT "Check CMake flag ${flag} (CMake ${CMAKE_VERSION})"
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-Werror=dev
|
|
||||||
-D${flag}=ON
|
|
||||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
|
|
||||||
)
|
|
||||||
add_custom_target(${flag_target}_${min_version_var}
|
add_custom_target(${flag_target}_${min_version_var}
|
||||||
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${min_version})"
|
COMMENT "Check CMake flag ${flag} (CMake ${min_version})"
|
||||||
COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
COMMAND mkdir -pv ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
||||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
COMMAND cd ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var}
|
||||||
&& ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
|
&& ${cmake_binary} -Werror=dev ${PROJECT_SOURCE_DIR} -D${flag}=ON
|
||||||
DEPENDS ${cmake_binary}
|
DEPENDS ${cmake_binary}
|
||||||
)
|
)
|
||||||
list(APPEND JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGET} ${flag_target}_${min_version_var})
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target}_${min_version_var})
|
||||||
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target} ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target}_${min_version_var})
|
||||||
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
|
set(JSON_CMAKE_FLAG_TARGETS ${JSON_CMAKE_FLAG_TARGETS} PARENT_SCOPE)
|
||||||
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
|
set(JSON_CMAKE_FLAG_BUILD_DIRS ${JSON_CMAKE_FLAG_BUILD_DIRS} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
@@ -696,6 +724,20 @@ foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
|||||||
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 4.0.0)
|
ci_add_cmake_flags_targets(${JSON_CMAKE_FLAG} 4.0.0)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
# check the same flags with the CMake version running this build
|
||||||
|
foreach(JSON_CMAKE_FLAG ${JSON_CMAKE_FLAGS_4_0_0})
|
||||||
|
string(TOLOWER "ci_cmake_flag_${JSON_CMAKE_FLAG}" flag_target)
|
||||||
|
add_custom_target(${flag_target}
|
||||||
|
COMMENT "Check CMake flag ${JSON_CMAKE_FLAG} (CMake ${CMAKE_VERSION})"
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-Werror=dev
|
||||||
|
-D${JSON_CMAKE_FLAG}=ON
|
||||||
|
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_${flag_target}
|
||||||
|
)
|
||||||
|
list(APPEND JSON_CMAKE_FLAG_TARGETS ${flag_target})
|
||||||
|
list(APPEND JSON_CMAKE_FLAG_BUILD_DIRS ${PROJECT_BINARY_DIR}/build_${flag_target})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(ci_cmake_flags
|
add_custom_target(ci_cmake_flags
|
||||||
DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
|
DEPENDS ${JSON_CMAKE_FLAG_TARGETS}
|
||||||
COMMENT "Check CMake flags"
|
COMMENT "Check CMake flags"
|
||||||
@@ -854,6 +896,6 @@ add_custom_target(ci_test_build_documentation
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
add_custom_target(ci_clean
|
add_custom_target(ci_clean
|
||||||
COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* cmake-3.5.0-Darwin64 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
|
COMMAND rm -fr ${PROJECT_BINARY_DIR}/build_* ${PROJECT_BINARY_DIR}/cmake-3.5.0 ${PROJECT_BINARY_DIR}/cmake-3.31.6 ${PROJECT_BINARY_DIR}/cmake-4.0.0 ${JSON_CMAKE_FLAG_BUILD_DIRS} ${single_binaries}
|
||||||
COMMENT "Clean generated directories"
|
COMMENT "Clean generated directories"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
# -Wno-c++98-compat The library targets C++11.
|
# -Wno-c++98-compat The library targets C++11.
|
||||||
# -Wno-c++98-compat-pedantic The library targets C++11.
|
# -Wno-c++98-compat-pedantic The library targets C++11.
|
||||||
# -Wno-deprecated-declarations The library contains annotations for deprecated functions.
|
# -Wno-deprecated-declarations The library contains annotations for deprecated functions.
|
||||||
# -Wno-extra-semi-stmt The library uses assert which triggers this warning.
|
|
||||||
# -Wno-padded We do not care about padding warnings.
|
# -Wno-padded We do not care about padding warnings.
|
||||||
# -Wno-covered-switch-default All switches list all cases and a default case.
|
# -Wno-covered-switch-default All switches list all cases and a default case.
|
||||||
# -Wno-c2y-extensions Clang 22.1 diagnoses __COUNTER__ as a C2y extension, also in
|
# -Wno-c2y-extensions Clang 22.1 diagnoses __COUNTER__ as a C2y extension, also in
|
||||||
@@ -20,7 +19,6 @@ set(CLANG_CXXFLAGS
|
|||||||
-Wno-c++98-compat
|
-Wno-c++98-compat
|
||||||
-Wno-c++98-compat-pedantic
|
-Wno-c++98-compat-pedantic
|
||||||
-Wno-deprecated-declarations
|
-Wno-deprecated-declarations
|
||||||
-Wno-extra-semi-stmt
|
|
||||||
-Wno-padded
|
-Wno-padded
|
||||||
-Wno-covered-switch-default
|
-Wno-covered-switch-default
|
||||||
-Wno-c2y-extensions
|
-Wno-c2y-extensions
|
||||||
|
|||||||
+24
-13
@@ -1,4 +1,4 @@
|
|||||||
# Warning flags determined for GCC 15.1.0 with https://github.com/nlohmann/gcc_flags:
|
# Warning flags determined for GCC 16.2.0 with https://github.com/nlohmann/gcc_flags:
|
||||||
# Ignored GCC warnings:
|
# Ignored GCC warnings:
|
||||||
# -Wno-abi-tag We do not care about ABI tags.
|
# -Wno-abi-tag We do not care about ABI tags.
|
||||||
# -Wno-aggregate-return The library uses aggregate returns.
|
# -Wno-aggregate-return The library uses aggregate returns.
|
||||||
@@ -16,6 +16,8 @@ set(GCC_CXXFLAGS
|
|||||||
--extra-warnings
|
--extra-warnings
|
||||||
-W
|
-W
|
||||||
-WNSObject-attribute
|
-WNSObject-attribute
|
||||||
|
-Wabbreviated-auto-in-template-arg
|
||||||
|
-Wabi
|
||||||
-Wno-abi-tag
|
-Wno-abi-tag
|
||||||
-Waddress
|
-Waddress
|
||||||
-Waddress-of-packed-member
|
-Waddress-of-packed-member
|
||||||
@@ -64,6 +66,7 @@ set(GCC_CXXFLAGS
|
|||||||
-Wanalyzer-tainted-divisor
|
-Wanalyzer-tainted-divisor
|
||||||
-Wanalyzer-tainted-offset
|
-Wanalyzer-tainted-offset
|
||||||
-Wanalyzer-tainted-size
|
-Wanalyzer-tainted-size
|
||||||
|
-Wanalyzer-throw-of-unexpected-type
|
||||||
-Wanalyzer-too-complex
|
-Wanalyzer-too-complex
|
||||||
-Wanalyzer-undefined-behavior-ptrdiff
|
-Wanalyzer-undefined-behavior-ptrdiff
|
||||||
-Wanalyzer-undefined-behavior-strtok
|
-Wanalyzer-undefined-behavior-strtok
|
||||||
@@ -80,10 +83,13 @@ set(GCC_CXXFLAGS
|
|||||||
-Warith-conversion
|
-Warith-conversion
|
||||||
-Warray-bounds=2
|
-Warray-bounds=2
|
||||||
-Warray-compare
|
-Warray-compare
|
||||||
|
-Warray-parameter
|
||||||
-Warray-parameter=2
|
-Warray-parameter=2
|
||||||
-Wattribute-alias=2
|
-Wattribute-alias=2
|
||||||
-Wattribute-warning
|
-Wattribute-warning
|
||||||
-Wattributes
|
-Wattributes
|
||||||
|
-Wauto-profile
|
||||||
|
-Wbidi-chars=any
|
||||||
-Wbool-compare
|
-Wbool-compare
|
||||||
-Wbool-operation
|
-Wbool-operation
|
||||||
-Wbuiltin-declaration-mismatch
|
-Wbuiltin-declaration-mismatch
|
||||||
@@ -99,6 +105,7 @@ set(GCC_CXXFLAGS
|
|||||||
-Wc++20-compat
|
-Wc++20-compat
|
||||||
-Wc++20-extensions
|
-Wc++20-extensions
|
||||||
-Wc++23-extensions
|
-Wc++23-extensions
|
||||||
|
-Wc++26-compat
|
||||||
-Wc++26-extensions
|
-Wc++26-extensions
|
||||||
-Wc++2a-compat
|
-Wc++2a-compat
|
||||||
-Wcalloc-transposed-args
|
-Wcalloc-transposed-args
|
||||||
@@ -142,6 +149,7 @@ set(GCC_CXXFLAGS
|
|||||||
-Wdeprecated-enum-enum-conversion
|
-Wdeprecated-enum-enum-conversion
|
||||||
-Wdeprecated-enum-float-conversion
|
-Wdeprecated-enum-float-conversion
|
||||||
-Wdeprecated-literal-operator
|
-Wdeprecated-literal-operator
|
||||||
|
-Wdeprecated-openmp
|
||||||
-Wdeprecated-variadic-comma-omission
|
-Wdeprecated-variadic-comma-omission
|
||||||
-Wdisabled-optimization
|
-Wdisabled-optimization
|
||||||
-Wdiv-by-zero
|
-Wdiv-by-zero
|
||||||
@@ -156,21 +164,18 @@ set(GCC_CXXFLAGS
|
|||||||
-Wenum-conversion
|
-Wenum-conversion
|
||||||
-Wexceptions
|
-Wexceptions
|
||||||
-Wexpansion-to-defined
|
-Wexpansion-to-defined
|
||||||
|
-Wexperimental-fmv-target
|
||||||
|
-Wexpose-global-module-tu-local
|
||||||
|
-Wexternal-tu-local
|
||||||
-Wextra
|
-Wextra
|
||||||
-Wextra-semi
|
-Wextra-semi
|
||||||
-Wflex-array-member-not-at-end
|
-Wflex-array-member-not-at-end
|
||||||
-Wfloat-conversion
|
-Wfloat-conversion
|
||||||
-Wfloat-equal
|
-Wfloat-equal
|
||||||
-Wformat -Wformat-contains-nul
|
-Wformat-diag
|
||||||
-Wformat -Wformat-diag
|
-Wformat-overflow=2
|
||||||
-Wformat -Wformat-extra-args
|
-Wformat-signedness
|
||||||
-Wformat -Wformat-nonliteral
|
-Wformat-truncation=2
|
||||||
-Wformat -Wformat-overflow=2
|
|
||||||
-Wformat -Wformat-security
|
|
||||||
-Wformat -Wformat-signedness
|
|
||||||
-Wformat -Wformat-truncation=2
|
|
||||||
-Wformat -Wformat-y2k
|
|
||||||
-Wformat -Wformat-zero-length
|
|
||||||
-Wformat=2
|
-Wformat=2
|
||||||
-Wframe-address
|
-Wframe-address
|
||||||
-Wfree-nonheap-object
|
-Wfree-nonheap-object
|
||||||
@@ -197,6 +202,8 @@ set(GCC_CXXFLAGS
|
|||||||
-Winvalid-offsetof
|
-Winvalid-offsetof
|
||||||
-Winvalid-pch
|
-Winvalid-pch
|
||||||
-Winvalid-utf8
|
-Winvalid-utf8
|
||||||
|
-Wkeyword-macro
|
||||||
|
-Wleading-whitespace=spaces
|
||||||
-Wliteral-suffix
|
-Wliteral-suffix
|
||||||
-Wlogical-not-parentheses
|
-Wlogical-not-parentheses
|
||||||
-Wlogical-op
|
-Wlogical-op
|
||||||
@@ -227,6 +234,7 @@ set(GCC_CXXFLAGS
|
|||||||
-Wnarrowing
|
-Wnarrowing
|
||||||
-Wnoexcept
|
-Wnoexcept
|
||||||
-Wnoexcept-type
|
-Wnoexcept-type
|
||||||
|
-Wnon-c-typedef-for-linkage
|
||||||
-Wnon-template-friend
|
-Wnon-template-friend
|
||||||
-Wnon-virtual-dtor
|
-Wnon-virtual-dtor
|
||||||
-Wnonnull
|
-Wnonnull
|
||||||
@@ -269,6 +277,8 @@ set(GCC_CXXFLAGS
|
|||||||
-Wscalar-storage-order
|
-Wscalar-storage-order
|
||||||
-Wself-move
|
-Wself-move
|
||||||
-Wsequence-point
|
-Wsequence-point
|
||||||
|
-Wsfinae-incomplete
|
||||||
|
-Wsfinae-incomplete=2
|
||||||
-Wshadow=compatible-local
|
-Wshadow=compatible-local
|
||||||
-Wshadow=global
|
-Wshadow=global
|
||||||
-Wshadow=local
|
-Wshadow=local
|
||||||
@@ -289,6 +299,7 @@ set(GCC_CXXFLAGS
|
|||||||
-Wstrict-aliasing=3
|
-Wstrict-aliasing=3
|
||||||
-Wstrict-null-sentinel
|
-Wstrict-null-sentinel
|
||||||
-Wstrict-overflow
|
-Wstrict-overflow
|
||||||
|
-Wstrict-overflow=5
|
||||||
-Wstring-compare
|
-Wstring-compare
|
||||||
-Wstringop-overflow
|
-Wstringop-overflow
|
||||||
-Wstringop-overflow=4
|
-Wstringop-overflow=4
|
||||||
@@ -333,8 +344,8 @@ set(GCC_CXXFLAGS
|
|||||||
-Wunreachable-code
|
-Wunreachable-code
|
||||||
-Wunsafe-loop-optimizations
|
-Wunsafe-loop-optimizations
|
||||||
-Wunused
|
-Wunused
|
||||||
-Wunused-but-set-parameter
|
-Wunused-but-set-parameter=3
|
||||||
-Wunused-but-set-variable
|
-Wunused-but-set-variable=3
|
||||||
-Wunused-const-variable=2
|
-Wunused-const-variable=2
|
||||||
-Wunused-function
|
-Wunused-function
|
||||||
-Wunused-label
|
-Wunused-label
|
||||||
|
|||||||
+16
-5
@@ -11,20 +11,31 @@ EXAMPLES = $(wildcard mkdocs/docs/examples/*.cpp)
|
|||||||
|
|
||||||
cxx_standard = $(lastword c++11 $(filter c++%, $(subst ., ,$1)))
|
cxx_standard = $(lastword c++11 $(filter c++%, $(subst ., ,$1)))
|
||||||
|
|
||||||
|
# common compile flags for the stand-alone example files
|
||||||
|
EXAMPLE_CPPFLAGS = -I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0
|
||||||
|
EXAMPLE_WARNFLAGS = -Werror=deprecated-declarations
|
||||||
|
|
||||||
|
# examples that document deprecated API and are allowed to use it
|
||||||
|
DEPRECATED_EXAMPLES = $(addprefix mkdocs/docs/examples/, \
|
||||||
|
json_pointer__operator__equal_stringtype \
|
||||||
|
json_pointer__operator__notequal_stringtype \
|
||||||
|
json_pointer__operator_string_t)
|
||||||
|
$(DEPRECATED_EXAMPLES:=.output) $(DEPRECATED_EXAMPLES:=.test): EXAMPLE_WARNFLAGS = -Wno-deprecated-declarations
|
||||||
|
|
||||||
# create output from a stand-alone example file
|
# create output from a stand-alone example file
|
||||||
%.output: %.cpp
|
%.output: %.cpp
|
||||||
@echo "standard $(call cxx_standard $(<:.cpp=))"
|
@echo "standard $(call cxx_standard,$(<:.cpp=))"
|
||||||
$(MAKE) $(<:.cpp=) \
|
$(MAKE) $(<:.cpp=) \
|
||||||
CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \
|
CPPFLAGS="$(EXAMPLE_CPPFLAGS)" \
|
||||||
CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations"
|
CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) $(EXAMPLE_WARNFLAGS)"
|
||||||
./$(<:.cpp=) > $@
|
./$(<:.cpp=) > $@
|
||||||
rm $(<:.cpp=)
|
rm $(<:.cpp=)
|
||||||
|
|
||||||
# compare created output with current output of the example files
|
# compare created output with current output of the example files
|
||||||
%.test: %.cpp
|
%.test: %.cpp
|
||||||
$(MAKE) $(<:.cpp=) \
|
$(MAKE) $(<:.cpp=) \
|
||||||
CPPFLAGS="-I $(SRCDIR) -DJSON_USE_GLOBAL_UDLS=0" \
|
CPPFLAGS="$(EXAMPLE_CPPFLAGS)" \
|
||||||
CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) -Wno-deprecated-declarations"
|
CXXFLAGS="-std=$(call cxx_standard,$(<:.cpp=)) $(EXAMPLE_WARNFLAGS)"
|
||||||
./$(<:.cpp=) > $@
|
./$(<:.cpp=) > $@
|
||||||
diff $@ $(<:.cpp=.output)
|
diff $@ $(<:.cpp=.output)
|
||||||
rm $(<:.cpp=) $@
|
rm $(<:.cpp=) $@
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<key>dashIndexFilePath</key>
|
<key>dashIndexFilePath</key>
|
||||||
<string>index.html</string>
|
<string>index.html</string>
|
||||||
<key>DashDocSetFallbackURL</key>
|
<key>DashDocSetFallbackURL</key>
|
||||||
<string>https://nlohmann.github.io/json/</string>
|
<string>https://json.nlohmann.me/</string>
|
||||||
<key>isJavaScriptEnabled</key>
|
<key>isJavaScriptEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
+12
-22
@@ -52,35 +52,25 @@ install_docset_zeal: JSON_for_Modern_C++.docset
|
|||||||
mkdir -p $$docset_root; \
|
mkdir -p $$docset_root; \
|
||||||
cp -r JSON_for_Modern_C++.docset $$docset_root/
|
cp -r JSON_for_Modern_C++.docset $$docset_root/
|
||||||
|
|
||||||
|
# both targets below compare the docset search index with the mkdocs page
|
||||||
|
# set. They share the same normalization (docs/foo/index.md and
|
||||||
|
# docs/foo.md both become foo/index.html, the URL mkdocs itself would
|
||||||
|
# give the page; the top-level index.md is excluded, as it is not part
|
||||||
|
# of the hand-curated docSet.sql) and use comm(1) on two sorted lists
|
||||||
|
# instead of running a sqlite3 query, or an O(n*m) nested shell loop,
|
||||||
|
# once per page.
|
||||||
|
DOCSET_INDEX_PATHS=$(shell sqlite3 docSet.dsidx "SELECT DISTINCT path FROM searchIndex" | sort)
|
||||||
|
DOCSET_PAGE_PATHS=$(shell echo '$(MKDOCS_PAGES)' | tr ' ' '\n' | grep -v '^index\.md$$' | $(SED) -E 's@/index\.md$$@/index.html@; s@\.md$$@/index.html@' | sort)
|
||||||
|
|
||||||
# list mkdocs pages missing from the docset index
|
# list mkdocs pages missing from the docset index
|
||||||
.PHONY: list_missing_pages
|
.PHONY: list_missing_pages
|
||||||
list_missing_pages: docSet.dsidx
|
list_missing_pages: docSet.dsidx
|
||||||
@for page in $(MKDOCS_PAGES); do \
|
@comm -23 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
|
||||||
case "$$page" in \
|
|
||||||
*/index.md) path=$${page/\/index.md/} ;; \
|
|
||||||
*) path=$${page/.md/} ;; \
|
|
||||||
esac; \
|
|
||||||
if [ "x$$page" != "xindex.md" -a "x$$(sqlite3 docSet.dsidx "SELECT COUNT(*) FROM searchIndex WHERE path='$$path/index.html'")" = "x0" ]; then \
|
|
||||||
echo $$page; \
|
|
||||||
fi \
|
|
||||||
done
|
|
||||||
|
|
||||||
# list paths in the docset index without a corresponding mkdocs page
|
# list paths in the docset index without a corresponding mkdocs page
|
||||||
.PHONY: list_removed_paths
|
.PHONY: list_removed_paths
|
||||||
list_removed_paths: docSet.dsidx
|
list_removed_paths: docSet.dsidx
|
||||||
@for path in $$(sqlite3 docSet.dsidx "SELECT path FROM searchIndex"); do \
|
@comm -13 <(echo '$(DOCSET_PAGE_PATHS)' | tr ' ' '\n') <(echo '$(DOCSET_INDEX_PATHS)' | tr ' ' '\n')
|
||||||
page=$${path/\/index.html/.md}; \
|
|
||||||
page_index=$${path/index.html/index.md}; \
|
|
||||||
page_found=0; \
|
|
||||||
for p in $(MKDOCS_PAGES); do \
|
|
||||||
if [ "x$$p" = "x$$page" -o "x$$p" = "x$$page_index" ]; then \
|
|
||||||
page_found=1; \
|
|
||||||
fi \
|
|
||||||
done; \
|
|
||||||
if [ "x$$page_found" = "x0" ]; then \
|
|
||||||
echo $$path; \
|
|
||||||
fi \
|
|
||||||
done
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ documentation browsers like [Dash](https://kapeli.com/dash), [Velocity](https://
|
|||||||
The docset can be created with
|
The docset can be created with
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make nlohmann_json.docset
|
make JSON_for_Modern_C++.docset
|
||||||
```
|
```
|
||||||
|
|
||||||
The generated folder `nlohmann_json.docset` can then be opened in the documentation browser.
|
The generated folder `JSON_for_Modern_C++.docset` can then be opened in the documentation browser. `make all` builds a
|
||||||
|
`JSON_for_Modern_C++.tgz` archive instead, and `make install_docset_zeal` installs the docset for Zeal directly.
|
||||||
|
|
||||||
A recent version is also part of the [Dash user contributions](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B).
|
A recent version is also part of the [Dash user contributions](https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/JSON_for_Modern_C%2B%2B).
|
||||||
|
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'a
|
|||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTICS', 'Macro', 'api/macros/json_diagnostics/index.html');
|
||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTIC_POSITIONS', 'Macro', 'api/macros/json_diagnostic_positions/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DIAGNOSTIC_POSITIONS', 'Macro', 'api/macros/json_diagnostic_positions/index.html');
|
||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html');
|
||||||
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DISABLE_TUPLE_REFERENCE_CONVERSION', 'Macro', 'api/macros/json_disable_tuple_reference_conversion/index.html');
|
||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_11', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_14', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
||||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_HAS_CPP_17', 'Macro', 'api/macros/json_has_cpp_11/index.html');
|
||||||
|
|||||||
@@ -139,8 +139,8 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
|
|
||||||
- In case of a `#!json null` type, [invalid_iterator.206](../../home/exceptions.md#jsonexceptioninvalid_iterator206)
|
- In case of a `#!json null` type, [invalid_iterator.206](../../home/exceptions.md#jsonexceptioninvalid_iterator206)
|
||||||
is thrown.
|
is thrown.
|
||||||
- In case of other primitive types (number, boolean, or string), `first` must be `begin()` and `last` must be
|
- In case of other primitive types (number, boolean, string, or binary), `first` must be `begin()` and `last`
|
||||||
`end()`. In this case, the value is copied. Otherwise,
|
must be `end()`. In this case, the value is copied. Otherwise,
|
||||||
[`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) is thrown.
|
[`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) is thrown.
|
||||||
- In case of structured types (array, object), the constructor behaves as similar versions for `std::vector` or
|
- In case of structured types (array, object), the constructor behaves as similar versions for `std::vector` or
|
||||||
`std::map`; that is, a JSON array or object is constructed from the values in the range.
|
`std::map`; that is, a JSON array or object is constructed from the values in the range.
|
||||||
@@ -159,6 +159,8 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
- `CompatibleType` is not `basic_json` (to avoid hijacking copy/move constructors),
|
- `CompatibleType` is not `basic_json` (to avoid hijacking copy/move constructors),
|
||||||
- `CompatibleType` is not a different `basic_json` type (i.e. with different template arguments)
|
- `CompatibleType` is not a different `basic_json` type (i.e. with different template arguments)
|
||||||
- `CompatibleType` is not a `basic_json` nested type (e.g., `json_pointer`, `iterator`, etc.)
|
- `CompatibleType` is not a `basic_json` nested type (e.g., `json_pointer`, `iterator`, etc.)
|
||||||
|
- if [`JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../macros/json_disable_tuple_reference_conversion.md) is defined
|
||||||
|
to `1`: `CompatibleType` is not a one-element `std::tuple` holding a reference to `basic_json`
|
||||||
- `json_serializer<U>` (with `U = uncvref_t<CompatibleType>`) has a `to_json(basic_json_t&, CompatibleType&&)`
|
- `json_serializer<U>` (with `U = uncvref_t<CompatibleType>`) has a `to_json(basic_json_t&, CompatibleType&&)`
|
||||||
method
|
method
|
||||||
|
|
||||||
@@ -242,8 +244,8 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range
|
and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range
|
||||||
`[first, last)` is undefined.
|
`[first, last)` is undefined.
|
||||||
- Throws [`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) if iterators `first`
|
- Throws [`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) if iterators `first`
|
||||||
and `last` belong to a primitive type (number, boolean, or string), but `first` does not point to the first
|
and `last` belong to a primitive type (number, boolean, string, or binary), but `first` does not point to the
|
||||||
element anymore. In this case, the range `[first, last)` is undefined. See the example code below.
|
first element anymore. In this case, the range `[first, last)` is undefined. See the example code below.
|
||||||
- Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first`
|
- Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first`
|
||||||
and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined.
|
and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined.
|
||||||
8. (none)
|
8. (none)
|
||||||
@@ -423,6 +425,8 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
4. Since version 3.2.0.
|
4. Since version 3.2.0.
|
||||||
5. Since version 1.0.0.
|
5. Since version 1.0.0.
|
||||||
6. Since version 1.0.0.
|
6. Since version 1.0.0.
|
||||||
7. Since version 1.0.0.
|
7. Since version 1.0.0. Fixed in version 3.13.0 to also check the iterator range for binary values; before, a range
|
||||||
|
that did not cover the whole value (such as `(end(), end())`) was accepted and the whole binary value was copied,
|
||||||
|
unlike the other primitive types.
|
||||||
8. Since version 1.0.0.
|
8. Since version 1.0.0.
|
||||||
9. Since version 1.0.0.
|
9. Since version 1.0.0.
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ Clears the content of a JSON value and resets it to the default value as if [`ba
|
|||||||
have been called with the current value type from [`type()`](type.md):
|
have been called with the current value type from [`type()`](type.md):
|
||||||
|
|
||||||
| Value type | initial value |
|
| Value type | initial value |
|
||||||
|------------|----------------------|
|
|------------|-----------------------------------------|
|
||||||
| null | `null` |
|
| null | `null` |
|
||||||
| boolean | `false` |
|
| boolean | `false` |
|
||||||
| string | `""` |
|
| string | `""` |
|
||||||
| number | `0` |
|
| number | `0` |
|
||||||
| binary | An empty byte vector |
|
| binary | An empty byte vector with no subtype |
|
||||||
| object | `{}` |
|
| object | `{}` |
|
||||||
| array | `[]` |
|
| array | `[]` |
|
||||||
|
|
||||||
@@ -56,3 +56,4 @@ All iterators, pointers, and references related to this container are invalidate
|
|||||||
|
|
||||||
- Added in version 1.0.0.
|
- Added in version 1.0.0.
|
||||||
- Added support for binary types in version 3.8.0.
|
- Added support for binary types in version 3.8.0.
|
||||||
|
- Fixed in version 3.13.0 to also clear the subtype of a binary value; before, the subtype was left unchanged.
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ Logarithmic in the size of the JSON object.
|
|||||||
|
|
||||||
- This method always returns `#!cpp false` when executed on a JSON type that is not an object.
|
- This method always returns `#!cpp false` when executed on a JSON type that is not an object.
|
||||||
- This method can be executed on any JSON value type.
|
- This method can be executed on any JSON value type.
|
||||||
|
- Calling this function with an integer argument (for example, `#!cpp contains(0)`) does not compile: such an argument
|
||||||
|
would otherwise implicitly convert to a null `#!cpp const char*` and, from there, cause undefined behavior when
|
||||||
|
constructing a `#!cpp std::string` for the object key. To check for an array element instead, use [`at`](at.md),
|
||||||
|
[`operator[]`](operator%5B%5D.md), or compare against [`size`](size.md).
|
||||||
|
|
||||||
!!! info "Postconditions"
|
!!! info "Postconditions"
|
||||||
|
|
||||||
@@ -117,3 +121,5 @@ Logarithmic in the size of the JSON object.
|
|||||||
1. Added in version 3.11.0.
|
1. Added in version 3.11.0.
|
||||||
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0.
|
2. Added in version 3.6.0. Extended template `KeyType` to support comparable types in version 3.11.0.
|
||||||
3. Added in version 3.7.0.
|
3. Added in version 3.7.0.
|
||||||
|
4. Deleted overloads for integral key types added in version 3.13.0 to reject such calls at compile time instead of
|
||||||
|
causing undefined behavior at runtime.
|
||||||
|
|||||||
@@ -40,7 +40,11 @@ Logarithmic in the size of the JSON object.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
This method always returns `0` when executed on a JSON type that is not an object.
|
- This method always returns `0` when executed on a JSON type that is not an object.
|
||||||
|
- Calling this function with an integer argument (for example, `#!cpp count(0)`) does not compile: such an argument
|
||||||
|
would otherwise implicitly convert to a null `#!cpp const char*` and, from there, cause undefined behavior when
|
||||||
|
constructing a `#!cpp std::string` for the object key. To check for an array element instead, use [`at`](at.md),
|
||||||
|
[`operator[]`](operator%5B%5D.md), or compare against [`size`](size.md).
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -81,3 +85,5 @@ This method always returns `0` when executed on a JSON type that is not an objec
|
|||||||
|
|
||||||
1. Added in version 3.11.0.
|
1. Added in version 3.11.0.
|
||||||
2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0.
|
2. Added in version 1.0.0. Changed parameter `key` type to `KeyType&&` in version 3.11.0.
|
||||||
|
3. Deleted overload for integral key types added in version 3.13.0 to reject such calls at compile time instead of
|
||||||
|
causing undefined behavior at runtime.
|
||||||
|
|||||||
@@ -44,7 +44,11 @@ Logarithmic in the size of the JSON object.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
This method always returns `end()` when executed on a JSON type that is not an object.
|
- This method always returns `end()` when executed on a JSON type that is not an object.
|
||||||
|
- Calling this function with an integer argument (for example, `#!cpp find(0)`) does not compile: such an argument
|
||||||
|
would otherwise implicitly convert to a null `#!cpp const char*` and, from there, cause undefined behavior when
|
||||||
|
constructing a `#!cpp std::string` for the object key. To access an array element instead, use [`at`](at.md),
|
||||||
|
[`operator[]`](operator%5B%5D.md), or compare against [`size`](size.md).
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -85,3 +89,5 @@ This method always returns `end()` when executed on a JSON type that is not an o
|
|||||||
|
|
||||||
1. Added in version 3.11.0.
|
1. Added in version 3.11.0.
|
||||||
2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0.
|
2. Added in version 1.0.0. Changed to support comparable types in version 3.11.0.
|
||||||
|
3. Deleted overloads for integral key types added in version 3.13.0 to reject such calls at compile time instead of
|
||||||
|
causing undefined behavior at runtime.
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
the end of the file was not reached when `strict` was set to true
|
the end of the file was not reached when `strict` was set to true
|
||||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from CBOR were
|
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from CBOR were
|
||||||
used in the given input or if the input is not valid CBOR
|
used in the given input or if the input is not valid CBOR
|
||||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||||
but not found
|
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
the end of the file was not reached when `strict` was set to true
|
the end of the file was not reached when `strict` was set to true
|
||||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from
|
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from
|
||||||
MessagePack were used in the given input or if the input is not valid MessagePack
|
MessagePack were used in the given input or if the input is not valid MessagePack
|
||||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||||
but not found
|
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
|
|||||||
@@ -195,5 +195,7 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
|||||||
1. Added in version 1.0.0.
|
1. Added in version 1.0.0.
|
||||||
2. Added in version 1.0.0.
|
2. Added in version 1.0.0.
|
||||||
3. Added in version 1.0.0.
|
3. Added in version 1.0.0.
|
||||||
4. Added in version 1.0.0.
|
4. Added in version 1.0.0. Fixed in version 3.13.0 to copy the values before inserting; before, an `ilist` that
|
||||||
|
referred to elements of the array being inserted into could insert wrong values, because the range insert could
|
||||||
|
move from or shift an element before it was copied.
|
||||||
5. Added in version 3.0.0.
|
5. Added in version 3.0.0.
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ Thereby, `Target` is the current object; that is, the patch is applied to the cu
|
|||||||
|
|
||||||
Linear in the lengths of `apply_patch`.
|
Linear in the lengths of `apply_patch`.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
`apply_patch` may be `#!cpp *this` itself or refer to a value contained in `#!cpp *this` (for example, a subobject
|
||||||
|
returned by `#!cpp (*this)[key]`); it is read as it was when `merge_patch()` was called, before any modification of
|
||||||
|
`#!cpp *this`.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
@@ -61,3 +67,5 @@ Linear in the lengths of `apply_patch`.
|
|||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.0.0.
|
- Added in version 3.0.0.
|
||||||
|
- Fixed use of freed or relocated memory when `apply_patch` is `#!cpp *this` or refers to a value contained in
|
||||||
|
`#!cpp *this`, in version 3.13.0.
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ type to use.
|
|||||||
## Template parameters
|
## Template parameters
|
||||||
|
|
||||||
`NumberFloatType`
|
`NumberFloatType`
|
||||||
: the type to store floating-point numbers. Parsing and serialization are implemented in terms of
|
: the type to store floating-point numbers. The parser converts `#!cpp float`, `#!cpp double`, and a
|
||||||
`#!cpp std::strtof`/`#!cpp std::strtod`/`#!cpp std::strtold` and `#!cpp std::snprintf`, so the type must be
|
`#!cpp long double` that is IEEE 754 binary64 itself and other `#!cpp long double` formats with
|
||||||
`#!cpp float`, `#!cpp double`, or `#!cpp long double`. The
|
`#!cpp std::from_chars` or `#!cpp std::strtold`, and serialization falls back to `#!cpp std::snprintf`, so the
|
||||||
|
type must be `#!cpp float`, `#!cpp double`, or `#!cpp long double`. The
|
||||||
[binary formats](../../features/binary_formats/index.md) additionally require `#!cpp float` or `#!cpp double`,
|
[binary formats](../../features/binary_formats/index.md) additionally require `#!cpp float` or `#!cpp double`,
|
||||||
because they have no encoding for `#!cpp long double`. See
|
because they have no encoding for `#!cpp long double`. See
|
||||||
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
|
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ range will yield over/underflow when used in a constructor. During deserializati
|
|||||||
will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md).
|
will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md).
|
||||||
|
|
||||||
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
||||||
> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are
|
> Note that when such software is used, numbers that are integers and are in the range [-2<sup>53</sup>+1, 2<sup>53</sup>-1] are
|
||||||
> interoperable in the sense that implementations will agree exactly on their numeric values.
|
> interoperable in the sense that implementations will agree exactly on their numeric values.
|
||||||
|
|
||||||
As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is
|
As this range is a subrange of the exactly supported range [INT64_MIN, INT64_MAX], this class's integer type is
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ when used in a constructor. During deserialization, too large or small integer n
|
|||||||
as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md).
|
as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md).
|
||||||
|
|
||||||
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
||||||
> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are
|
> Note that when such software is used, numbers that are integers and are in the range [-2<sup>53</sup>+1, 2<sup>53</sup>-1] are
|
||||||
> interoperable in the sense that implementations will agree exactly on their numeric values.
|
> interoperable in the sense that implementations will agree exactly on their numeric values.
|
||||||
|
|
||||||
As this range is a subrange (when considered in conjunction with the `number_integer_t` type) of the exactly supported
|
As this range is a subrange (when considered in conjunction with the `number_integer_t` type) of the exactly supported
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
|||||||
1. The function can throw the following exceptions:
|
1. The function can throw the following exceptions:
|
||||||
- Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an array
|
- Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an array
|
||||||
or null; in that case, using the `[]` operator with an index makes no sense.
|
or null; in that case, using the `[]` operator with an index makes no sense.
|
||||||
|
- Throws `#!cpp std::length_error` if `idx` equals the maximum value of `size_type`; the array is left unchanged.
|
||||||
|
(This is the one index for which growing the array to hold it cannot be expressed as a `size_type` size, the same
|
||||||
|
way an oversized [`resize`](https://en.cppreference.com/w/cpp/container/vector/resize) throws.)
|
||||||
2. The function can throw the following exceptions:
|
2. The function can throw the following exceptions:
|
||||||
- Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an object
|
- Throws [`type_error.305`](../../home/exceptions.md#jsonexceptiontype_error305) if the JSON value is not an object
|
||||||
or null; in that case, using the `[]` operator with a key makes no sense.
|
or null; in that case, using the `[]` operator with a key makes no sense.
|
||||||
@@ -257,7 +260,8 @@ Strong exception safety: if an exception occurs, the original value stays intact
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 1.0.0.
|
1. Added in version 1.0.0. Fixed in version 3.13.0 to throw `#!cpp std::length_error` instead of emptying the array and
|
||||||
|
accessing it out of bounds when `idx` equals the maximum value of `size_type`.
|
||||||
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
|
2. Added in version 1.0.0. Added overloads for `T* key` in version 1.1.0. Removed overloads for `T* key` (replaced by 3)
|
||||||
in version 3.11.0.
|
in version 3.11.0.
|
||||||
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
|
3. Added in version 3.11.0. Fixed in version 3.13.0 to consistently accept `std::string_view`-convertible keys, as
|
||||||
|
|||||||
@@ -88,7 +88,12 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
## Exceptions
|
## Exceptions
|
||||||
|
|
||||||
- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or
|
- Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or
|
||||||
empty input like a null `FILE*` or `char*` pointer.
|
empty input like a null `FILE*` or `char*` pointer, or an `std::istream` without a stream buffer
|
||||||
|
(`#!cpp i.rdbuf() == nullptr`, for instance `#!cpp std::istream(nullptr)`).
|
||||||
|
- If reading from an `std::istream` reaches the end of the input and `eofbit` is part of the stream's
|
||||||
|
[`exceptions()`](https://en.cppreference.com/w/cpp/io/basic_ios/exceptions) mask, the `std::ios_base::failure`
|
||||||
|
thrown by the stream itself propagates instead of a `parse_error`, the same as it would for the standard library's
|
||||||
|
own extraction operators.
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
@@ -254,6 +259,8 @@ outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-by
|
|||||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||||
- `JSON_STRICT_NUL_HANDLING` added in version 3.13.0 to optionally reject a NUL byte in the input instead of treating
|
- `JSON_STRICT_NUL_HANDLING` added in version 3.13.0 to optionally reject a NUL byte in the input instead of treating
|
||||||
it as end of input; planned to become the default in version 4.0.0.
|
it as end of input; planned to become the default in version 4.0.0.
|
||||||
|
- Extended empty-input detection to also cover an `std::istream` without a stream buffer, and fixed a crash
|
||||||
|
(`std::terminate`) when parsing from an `std::istream` with `eofbit` in its exception mask, in version 3.13.0.
|
||||||
|
|
||||||
!!! warning "Deprecation"
|
!!! warning "Deprecation"
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ classDiagram
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
For an input with $n$ bytes, 1 is the index of the first character and $n+1$ is the index of the terminating null byte
|
For an input with <i>n</i> bytes, 1 is the index of the first character and <i>n</i>+1 is the index of the terminating null byte
|
||||||
or the end of file. This also holds true when reading a byte vector for binary formats.
|
or the end of file. This also holds true when reading a byte vector for binary formats.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|||||||
@@ -100,3 +100,6 @@ the latter case, it is skipped completely, or replaced by `null` if it is the to
|
|||||||
- Added in version 1.0.0.
|
- Added in version 1.0.0.
|
||||||
- Fixed in version 3.13.0 to also remove discarded values from a parent object; before, discarding an array or a value
|
- Fixed in version 3.13.0 to also remove discarded values from a parent object; before, discarding an array or a value
|
||||||
stored under an object key left a discarded member behind, which made the parse result serialize to invalid JSON.
|
stored under an object key left a discarded member behind, which made the parse result serialize to invalid JSON.
|
||||||
|
- Fixed in version 3.13.0 so that discarding an array or object at its start event also hides its content from the
|
||||||
|
callback, as documented above; before, the callback was still called for the content, and the key of every member of
|
||||||
|
a discarded object was kept in memory until the parse ended.
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ void swap(reference other) noexcept (
|
|||||||
std::is_nothrow_move_constructible<value_t>::value &&
|
std::is_nothrow_move_constructible<value_t>::value &&
|
||||||
std::is_nothrow_move_assignable<value_t>::value &&
|
std::is_nothrow_move_assignable<value_t>::value &&
|
||||||
std::is_nothrow_move_constructible<json_value>::value &&
|
std::is_nothrow_move_constructible<json_value>::value &&
|
||||||
std::is_nothrow_move_assignable<json_value>::value
|
std::is_nothrow_move_assignable<json_value>::value &&
|
||||||
|
std::is_nothrow_move_constructible<json_base_class_t>::value &&
|
||||||
|
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||||
);
|
);
|
||||||
|
|
||||||
// (2)
|
// (2)
|
||||||
@@ -14,7 +16,9 @@ friend void swap(reference left, reference right) noexcept (
|
|||||||
std::is_nothrow_move_constructible<value_t>::value &&
|
std::is_nothrow_move_constructible<value_t>::value &&
|
||||||
std::is_nothrow_move_assignable<value_t>::value &&
|
std::is_nothrow_move_assignable<value_t>::value &&
|
||||||
std::is_nothrow_move_constructible<json_value>::value &&
|
std::is_nothrow_move_constructible<json_value>::value &&
|
||||||
std::is_nothrow_move_assignable<json_value>::value
|
std::is_nothrow_move_assignable<json_value>::value &&
|
||||||
|
std::is_nothrow_move_constructible<json_base_class_t>::value &&
|
||||||
|
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||||
);
|
);
|
||||||
|
|
||||||
// (3)
|
// (3)
|
||||||
@@ -37,11 +41,15 @@ void swap(typename binary_t::container_type& other);
|
|||||||
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. If macro
|
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. If macro
|
||||||
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
||||||
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
||||||
|
The [`json_base_class_t`](json_base_class_t.md) subobject is exchanged along with the value as well, the same way it
|
||||||
|
is copied or moved by the copy/move constructors and assignment operators.
|
||||||
2. Exchanges the contents of the JSON value from `left` with those of `right`. Does not invoke any move, copy, or swap
|
2. Exchanges the contents of the JSON value from `left` with those of `right`. Does not invoke any move, copy, or swap
|
||||||
operations on individual elements. All iterators and references remain valid. The past-the-end iterator is
|
operations on individual elements. All iterators and references remain valid. The past-the-end iterator is
|
||||||
invalidated. Implemented as a friend function callable via ADL. If macro
|
invalidated. Implemented as a friend function callable via ADL. If macro
|
||||||
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
||||||
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
||||||
|
The [`json_base_class_t`](json_base_class_t.md) subobject is exchanged along with the value as well, the same way it
|
||||||
|
is copied or moved by the copy/move constructors and assignment operators.
|
||||||
3. Exchanges the contents of a JSON array with those of `other`. Does not invoke any move, copy, or swap operations on
|
3. Exchanges the contents of a JSON array with those of `other`. Does not invoke any move, copy, or swap operations on
|
||||||
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated.
|
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated.
|
||||||
4. Exchanges the contents of a JSON object with those of `other`. Does not invoke any move, copy, or swap operations on
|
4. Exchanges the contents of a JSON object with those of `other`. Does not invoke any move, copy, or swap operations on
|
||||||
@@ -164,8 +172,8 @@ Constant.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Since version 1.0.0.
|
1. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
|
||||||
2. Since version 1.0.0.
|
2. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
|
||||||
3. Since version 1.0.0.
|
3. Since version 1.0.0.
|
||||||
4. Since version 1.0.0.
|
4. Since version 1.0.0.
|
||||||
5. Since version 1.0.0.
|
5. Since version 1.0.0.
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
|||||||
- Throws [`out_of_range.412`](../../home/exceptions.md#jsonexceptionout_of_range412) if the length of a document, array,
|
- Throws [`out_of_range.412`](../../home/exceptions.md#jsonexceptionout_of_range412) if the length of a document, array,
|
||||||
string, or binary value exceeds the range of the 32-bit BSON length field; example:
|
string, or binary value exceeds the range of the 32-bit BSON length field; example:
|
||||||
`"BSON length 2147483661 exceeds maximum of 2147483647"`
|
`"BSON length 2147483661 exceeds maximum of 2147483647"`
|
||||||
|
- Throws [`out_of_range.415`](../../home/exceptions.md#jsonexceptionout_of_range415) if the subtype of a binary value
|
||||||
|
exceeds 255, the maximum of the BSON binary subtype; example:
|
||||||
|
`"subtype 70000 is too large for the BSON binary subtype (max 255)"`
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
@@ -78,3 +81,4 @@ pass before anything is written.
|
|||||||
|
|
||||||
- Added in version 3.4.0.
|
- Added in version 3.4.0.
|
||||||
- Linear in the size of `j`, and no longer limited by the call stack for deeply nested values, since version 3.13.0.
|
- Linear in the size of `j`, and no longer limited by the call stack for deeply nested values, since version 3.13.0.
|
||||||
|
- `out_of_range.415` is now detected before anything is written, like the other exceptions above, since version 3.13.0.
|
||||||
|
|||||||
@@ -76,3 +76,6 @@ Linear in the size of the JSON value `j`.
|
|||||||
|
|
||||||
- Added in version 2.0.9.
|
- Added in version 2.0.9.
|
||||||
- Throws `out_of_range.412` and `out_of_range.415` since version 3.13.0.
|
- Throws `out_of_range.412` and `out_of_range.415` since version 3.13.0.
|
||||||
|
- Fixed in version 3.13.0 to serialize `number_integer_t`/`number_unsigned_t` pairs of different width correctly;
|
||||||
|
before, integers could be serialized with the wrong value if `number_integer_t` was narrower than
|
||||||
|
`number_unsigned_t`.
|
||||||
|
|||||||
@@ -59,6 +59,12 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
|||||||
1. O(N*log(size() + N)), where N is the number of elements to insert.
|
1. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||||
2. O(N*log(size() + N)), where N is the number of elements to insert.
|
2. O(N*log(size() + N)), where N is the number of elements to insert.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
The argument `j` (or, for overload (2), the range `[first, last)`) may be `#!cpp *this` itself or refer to a value
|
||||||
|
contained in `#!cpp *this` (for example, a subobject returned by `#!cpp (*this)[key]`); it is read as it was when
|
||||||
|
`update()` was called, before any modification of `#!cpp *this`.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
@@ -155,3 +161,5 @@ Basic guarantee: if an exception is thrown during the operation, the JSON value
|
|||||||
|
|
||||||
- Added in version 3.0.0.
|
- Added in version 3.0.0.
|
||||||
- Added `merge_objects` parameter in 3.10.5.
|
- Added `merge_objects` parameter in 3.10.5.
|
||||||
|
- Fixed use of freed or relocated memory when the argument is `#!cpp *this` or refers to a value contained in
|
||||||
|
`#!cpp *this`, in version 3.13.0.
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ This is equivalent to Python's `dict.get(key, default)`.
|
|||||||
- Unlike [`operator[]`](operator[].md), this function does not implicitly add an element to the position defined by
|
- Unlike [`operator[]`](operator[].md), this function does not implicitly add an element to the position defined by
|
||||||
`key`/`ptr` key. This function is furthermore also applicable to const objects.
|
`key`/`ptr` key. This function is furthermore also applicable to const objects.
|
||||||
|
|
||||||
|
!!! note "Integer keys"
|
||||||
|
|
||||||
|
Calling this function with an integer `key` argument (for example, `#!cpp value(0, 1)`) does not compile in
|
||||||
|
C++11, where `object_comparator_t` is not transparent: such an argument would otherwise implicitly convert to a
|
||||||
|
null `#!cpp const char*` and, from there, cause undefined behavior when constructing a `#!cpp std::string` for the
|
||||||
|
object key. To access an array element with a default value, use [`at`](at.md) together with a `#!cpp try`/`#!cpp
|
||||||
|
catch` block, or compare against [`size`](size.md) instead.
|
||||||
|
|
||||||
## Template parameters
|
## Template parameters
|
||||||
|
|
||||||
`KeyType`
|
`KeyType`
|
||||||
@@ -184,7 +192,9 @@ changes to any JSON value.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version 3.11.0.
|
1. Added in version 1.0.0. Changed parameter `default_value` type from `const ValueType&` to `ValueType&&` in version
|
||||||
|
3.11.0. Deleted overload for integral key types added in version 3.13.0 to reject such calls at compile time
|
||||||
|
instead of causing undefined behavior at runtime.
|
||||||
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
2. Added in version 3.11.0. Made `ValueType` the first template parameter in version 3.11.2.
|
||||||
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
3. Added in version 2.0.2. Extended to work with arrays in version 3.13.0, including fixing an issue where resolving
|
||||||
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
`ptr` through an array unexpectedly threw `out_of_range` instead of returning the resolved element (or
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ header. See also the [macro overview page](../../features/macros.md).
|
|||||||
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
||||||
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
||||||
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
||||||
|
- [**JSON_NO_AUTOMATIC_UDLS**](json_no_automatic_udls.md) - do not include the user-defined string literals (UDLs) automatically
|
||||||
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||||
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||||
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
||||||
@@ -52,6 +53,7 @@ header. See also the [macro overview page](../../features/macros.md).
|
|||||||
|
|
||||||
- [**JSON_BRACE_INIT_COPY_SEMANTICS**](json_brace_init_copy_semantics.md) - opt in to copy/move semantics for single-element brace initialization
|
- [**JSON_BRACE_INIT_COPY_SEMANTICS**](json_brace_init_copy_semantics.md) - opt in to copy/move semantics for single-element brace initialization
|
||||||
- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums
|
- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums
|
||||||
|
- [**JSON_DISABLE_TUPLE_REFERENCE_CONVERSION**](json_disable_tuple_reference_conversion.md) - switch off conversion from a one-element tuple of a JSON reference
|
||||||
- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions
|
- [**JSON_USE_IMPLICIT_CONVERSIONS**](json_use_implicit_conversions.md) - control implicit conversions
|
||||||
|
|
||||||
## Comparison behavior
|
## Comparison behavior
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION /* value */
|
||||||
|
```
|
||||||
|
|
||||||
|
When defined to `1`, a `basic_json` value can no longer be constructed from a one-element `std::tuple` whose element is
|
||||||
|
a reference to that `basic_json` type, such as `std::tuple<json&>`, `std::tuple<const json&>`, or `std::tuple<json&&>`.
|
||||||
|
These are the tuples created by `std::forward_as_tuple(j)`.
|
||||||
|
|
||||||
|
## Default definition
|
||||||
|
|
||||||
|
The default value is `0` (disabled — existing behavior is preserved).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
!!! note "Background"
|
||||||
|
|
||||||
|
By default, `basic_json` can be constructed from any `std::tuple` whose elements can be converted to JSON; the result
|
||||||
|
is an array. This includes `std::tuple<json&>`, which becomes a one-element array.
|
||||||
|
|
||||||
|
`std::tuple` only converts another tuple element by element if its element type cannot be constructed from the whole
|
||||||
|
source tuple. Because `json` *can* be constructed from `std::tuple<json&>`, `std::tuple` instead converts the whole
|
||||||
|
tuple into a single `json` value. This has two surprising effects:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
json j = true;
|
||||||
|
|
||||||
|
// rejected by some standard libraries (e.g., libc++); with others, the
|
||||||
|
// reference binds to a temporary that is destroyed right away
|
||||||
|
std::tuple<const json&> t1(std::forward_as_tuple(j));
|
||||||
|
|
||||||
|
// compiles, but std::get<0>(t2) is [true], not true
|
||||||
|
std::tuple<json> t2(std::forward_as_tuple(j));
|
||||||
|
```
|
||||||
|
|
||||||
|
Enabling this macro removes the conversion, so both tuples are converted element by element: `std::get<0>(t1)`
|
||||||
|
refers to `j`, and `std::get<0>(t2)` is a copy of `j` (see [#2226](https://github.com/nlohmann/json/issues/2226)).
|
||||||
|
|
||||||
|
!!! warning "Opt-in only"
|
||||||
|
|
||||||
|
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no effect.
|
||||||
|
|
||||||
|
!!! note "Affected conversions"
|
||||||
|
|
||||||
|
Only one-element tuples holding a reference to the **same** `basic_json` type are affected. Constructing a JSON value
|
||||||
|
from them no longer compiles:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
json j = true;
|
||||||
|
json a = std::forward_as_tuple(j); // error with the macro enabled
|
||||||
|
json b = json::array({j}); // use this instead: [true]
|
||||||
|
```
|
||||||
|
|
||||||
|
Tuples holding a JSON value (`std::make_tuple(j)`), tuples with more than one element, and tuples holding references
|
||||||
|
to other types (including other `basic_json` specializations) are converted to arrays as before.
|
||||||
|
|
||||||
|
!!! hint "CMake option"
|
||||||
|
|
||||||
|
This behavior can also be controlled with the CMake option
|
||||||
|
[`JSON_DisableTupleReferenceConversion`](../../integration/cmake.md#json_disabletuplereferenceconversion)
|
||||||
|
(`OFF` by default) which defines `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION` accordingly.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
??? example "Default behavior (macro not defined)"
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
json j = true;
|
||||||
|
|
||||||
|
std::tuple<json> t(std::forward_as_tuple(j));
|
||||||
|
// std::get<0>(t) is [true] -- the whole tuple was converted
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
??? example "Conversion disabled (macro defined to 1)"
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 1
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
json j = true;
|
||||||
|
|
||||||
|
std::tuple<json> t(std::forward_as_tuple(j));
|
||||||
|
// std::get<0>(t) is true -- a copy of j
|
||||||
|
|
||||||
|
std::tuple<const json&> r(std::forward_as_tuple(j));
|
||||||
|
// std::get<0>(r) refers to j
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [**basic_json(CompatibleType&&)**](../basic_json/basic_json.md) - the affected constructor
|
||||||
|
- [:simple-cmake: JSON_DisableTupleReferenceConversion](../../integration/cmake.md#json_disabletuplereferenceconversion) -
|
||||||
|
CMake option to control the macro
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
- Added in version 3.13.0.
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
# JSON_NO_AUTOMATIC_UDLS
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_NO_AUTOMATIC_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
When defined, `<nlohmann/json.hpp>` does not include `<nlohmann/json_literals.hpp>`, so the user-defined string
|
||||||
|
literals [`operator""_json`](../operator_literal_json.md) and
|
||||||
|
[`operator""_json_pointer`](../operator_literal_json_pointer.md) are not declared. Include
|
||||||
|
`<nlohmann/json_literals.hpp>` in the files that use them.
|
||||||
|
|
||||||
|
The literals are ordinary inline functions whose bodies call the parser, so every translation unit that includes them
|
||||||
|
instantiates the parser — even if it never parses anything itself. Defining `JSON_NO_AUTOMATIC_UDLS` for a whole project
|
||||||
|
avoids this cost in translation units that do not parse (e.g., ones that only define types and conversions or pass
|
||||||
|
`json` values around) and reduces their compile time.
|
||||||
|
|
||||||
|
## Default definition
|
||||||
|
|
||||||
|
By default, `#!cpp JSON_NO_AUTOMATIC_UDLS` is not defined, and `<nlohmann/json.hpp>` includes
|
||||||
|
`<nlohmann/json_literals.hpp>`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#undef JSON_NO_AUTOMATIC_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
!!! info "Header `<nlohmann/json_literals.hpp>`"
|
||||||
|
|
||||||
|
The header includes `<nlohmann/json.hpp>` itself and places the literals according to
|
||||||
|
[`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md). It is part of the multi-header sources (`include/nlohmann`)
|
||||||
|
and of the single-header sources (`single_include/nlohmann`), next to `json.hpp`.
|
||||||
|
|
||||||
|
!!! info "C++ modules"
|
||||||
|
|
||||||
|
The `nlohmann.json` [module](../../features/modules.md) always exports the literals, regardless of this macro.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The code below includes the library without the literals and adds them in a single translation unit.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// compiled with -DJSON_NO_AUTOMATIC_UDLS for the whole project
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
// this file uses the literals, so it includes them explicitly
|
||||||
|
#include <nlohmann/json_literals.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
auto j = R"({"foo": 42})"_json;
|
||||||
|
return j.at("/foo"_json_pointer) == 42 ? 0 : 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Without the include of `<nlohmann/json_literals.hpp>`, the code would fail to compile.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
- Added in version 3.13.0.
|
||||||
@@ -16,7 +16,8 @@ byte is still not rejected:
|
|||||||
[`from_msgpack`](../basic_json/from_msgpack.md), [`from_ubjson`](../basic_json/from_ubjson.md)) are never affected: there, `0x00` is ordinary data.
|
[`from_msgpack`](../basic_json/from_msgpack.md), [`from_ubjson`](../basic_json/from_ubjson.md)) are never affected: there, `0x00` is ordinary data.
|
||||||
- A bare `const char*` pointer has no length of its own, so its length is still determined with `strlen()`. The first
|
- A bare `const char*` pointer has no length of its own, so its length is still determined with `strlen()`. The first
|
||||||
NUL byte therefore still marks the end of the input, and nothing after it is read.
|
NUL byte therefore still marks the end of the input, and nothing after it is read.
|
||||||
- One trailing `'\0'` at the end of a `char` array (e.g., a string literal) is trimmed; see the warning below.
|
- One trailing `'\0'` at the end of a `char`, `wchar_t`, `char16_t`, `char32_t`, or (C++20) `char8_t` array (e.g., a
|
||||||
|
string literal) is trimmed; see the warning below.
|
||||||
|
|
||||||
## Default definition
|
## Default definition
|
||||||
|
|
||||||
@@ -57,13 +58,15 @@ The default value is `0` (disabled — existing behavior is preserved).
|
|||||||
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
|
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
|
||||||
effect.
|
effect.
|
||||||
|
|
||||||
Enabling it also changes how a `char` array (including a string literal, e.g. `json::parse("123")`) is read: such
|
Enabling it also changes how an array of a text-literal element type (`char`, `wchar_t`, `char16_t`, `char32_t`,
|
||||||
an array normally carries a trailing `'\0'` contributed by the compiler, not by the source text. With this macro
|
or, since C++20, `char8_t` - including a string literal, e.g. `json::parse("123")` or `json::parse(L"123")`) is
|
||||||
enabled, that one trailing byte is trimmed if present so that parsing a string literal keeps working; every other
|
read: such an array normally carries a trailing `'\0'` contributed by the compiler, not by the source text. With
|
||||||
byte in the array - including any `'\0'` that is not the very last element - is read as real data and rejected
|
this macro enabled, that one trailing element is trimmed if present so that parsing a string literal keeps
|
||||||
like any other unexpected byte. Arrays of any other element type (`unsigned char`, `std::uint8_t`, ...), as used
|
working, for any of these character types; every other element in the array - including any `'\0'` that is not
|
||||||
for CBOR or MessagePack, are never affected by this trimming; their full extent - including a genuine trailing
|
the very last element - is read as real data and rejected like any other unexpected byte. Arrays of any other
|
||||||
`0x00` - is always preserved, in both states of this macro.
|
element type (`unsigned char`, `std::uint8_t`, ...), as used for CBOR or MessagePack, are never affected by this
|
||||||
|
trimming; their full extent - including a genuine trailing `0x00` - is always preserved, in both states of this
|
||||||
|
macro.
|
||||||
|
|
||||||
!!! note "ABI compatibility"
|
!!! note "ABI compatibility"
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ The default value is `1`.
|
|||||||
#define JSON_USE_GLOBAL_UDLS 1
|
#define JSON_USE_GLOBAL_UDLS 1
|
||||||
```
|
```
|
||||||
|
|
||||||
When the macro is not defined, the library will define it to its default value.
|
When the macro is not defined, the library behaves as if it were defined to its default value.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
@@ -32,6 +32,11 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
||||||
`JSON_USE_GLOBAL_UDLS` accordingly.
|
`JSON_USE_GLOBAL_UDLS` accordingly.
|
||||||
|
|
||||||
|
!!! info "Leaving out the literals"
|
||||||
|
|
||||||
|
If [`JSON_NO_AUTOMATIC_UDLS`](json_no_automatic_udls.md) is defined, the literals are only declared where
|
||||||
|
`<nlohmann/json_literals.hpp>` is included; this macro then applies to that header.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example "Example 1: Default behavior"
|
??? example "Example 1: Default behavior"
|
||||||
@@ -92,6 +97,7 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
- [`operator""_json`](../operator_literal_json.md)
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_NO_AUTOMATIC_UDLS`](json_no_automatic_udls.md) - do not include the user-defined string literals automatically
|
||||||
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|||||||
@@ -18,9 +18,18 @@ Deserializes an input stream to a JSON value.
|
|||||||
|
|
||||||
the stream `i`
|
the stream `i`
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
Strong guarantee: if an exception is thrown, there are no changes in `j`.
|
||||||
|
|
||||||
## Exceptions
|
## Exceptions
|
||||||
|
|
||||||
- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token.
|
- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or if
|
||||||
|
`i` has no stream buffer (`#!cpp i.rdbuf() == nullptr`, for instance `#!cpp std::istream(nullptr)`).
|
||||||
|
- If reading from `i` reaches the end of the input and `eofbit` is part of `i`'s
|
||||||
|
[`exceptions()`](https://en.cppreference.com/w/cpp/io/basic_ios/exceptions) mask, the `std::ios_base::failure`
|
||||||
|
thrown by `i` itself propagates instead of a `parse_error`, the same as it would for the standard library's own
|
||||||
|
extraction operators.
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
@@ -118,3 +127,7 @@ being read.
|
|||||||
it as end of input; planned to become the default in version 4.0.0.
|
it as end of input; planned to become the default in version 4.0.0.
|
||||||
- `JSON_PRECISE_STREAM_POSITION` added in version 3.13.0 to optionally leave the character that terminates a number in
|
- `JSON_PRECISE_STREAM_POSITION` added in version 3.13.0 to optionally leave the character that terminates a number in
|
||||||
the stream; planned to become the default in version 4.0.0.
|
the stream; planned to become the default in version 4.0.0.
|
||||||
|
- Fixed a null pointer dereference for an `std::istream` without a stream buffer (now throws `parse_error.101`), and a
|
||||||
|
crash (`std::terminate`) when `i` has `eofbit` in its exception mask, in version 3.13.0.
|
||||||
|
- Changed to the strong exception safety guarantee in version 3.13.0: `j` is no longer left with a partially parsed
|
||||||
|
value if parsing throws.
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ using namespace nlohmann;
|
|||||||
```
|
```
|
||||||
|
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is declared in header
|
||||||
|
`<nlohmann/json_literals.hpp>`, which `<nlohmann/json.hpp>` includes unless
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](macros/json_no_automatic_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -59,6 +61,8 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
||||||
|
- [JSON_NO_AUTOMATIC_UDLS](macros/json_no_automatic_udls.md) - do not include the user-defined string literals
|
||||||
|
automatically
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ using namespace nlohmann::literals::json_literals;
|
|||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
```
|
```
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is declared in header
|
||||||
|
`<nlohmann/json_literals.hpp>`, which `<nlohmann/json.hpp>` includes unless
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](macros/json_no_automatic_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -58,6 +60,8 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
||||||
|
- [JSON_NO_AUTOMATIC_UDLS](macros/json_no_automatic_udls.md) - do not include the user-defined string literals
|
||||||
|
automatically
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ A minimal map-like container that preserves insertion order for use within [`nlo
|
|||||||
The type uses a `std::vector` to store object elements. Therefore, adding elements can yield a reallocation in which
|
The type uses a `std::vector` to store object elements. Therefore, adding elements can yield a reallocation in which
|
||||||
case all iterators (including the `end()` iterator) and all references to the elements are invalidated.
|
case all iterators (including the `end()` iterator) and all references to the elements are invalidated.
|
||||||
|
|
||||||
|
When the storage grows, the keys are copied and the mapped values are moved to the new storage. A plain `std::vector`
|
||||||
|
would copy the whole elements instead, because their `#!cpp const` keys make them not nothrow move constructible; for
|
||||||
|
[`ordered_json`](ordered_json.md), this would be a deep copy of every nested value. The values are only copied if
|
||||||
|
`T` is not default constructible or not nothrow move assignable.
|
||||||
|
|
||||||
## Member types
|
## Member types
|
||||||
|
|
||||||
- **key_type** - key type (`Key`)
|
- **key_type** - key type (`Key`)
|
||||||
@@ -56,6 +61,11 @@ std::equal_to<> // since C++14
|
|||||||
- **find**
|
- **find**
|
||||||
- **insert**
|
- **insert**
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
**emplace**, **operator\[\]**, and **insert(value)** have the strong exception guarantee: if an exception is thrown (for
|
||||||
|
instance, because copying a key or allocating memory fails), the contents of the container are unchanged.
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
Because the elements are stored in a `std::vector` in insertion order, there is no index to look a key up by. Every
|
Because the elements are stored in a `std::vector` in insertion order, there is no index to look a key up by. Every
|
||||||
@@ -122,3 +132,4 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
|
|||||||
|
|
||||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
||||||
- Added **key_compare** member in version 3.11.0.
|
- Added **key_compare** member in version 3.11.0.
|
||||||
|
- Changed in version 3.13.0: growing the storage moves the mapped values instead of copying them.
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
| GNU 14.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 14.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 15.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
| GNU 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||||
| GNU 16.1.0 | arm64 | Linux 6.1.100 | Cirrus CI |
|
| GNU 16.1.0 | arm64 | Ubuntu 24.04 | GitHub |
|
||||||
| icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
| icpc (ICC) 2021.10.0 20230609 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||||
| icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub |
|
| icpx (Intel oneAPI DPC++/C++) 2025.3.2 | x86_64 | Ubuntu 24.04 LTS | GitHub |
|
||||||
| nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
| nvc++ (NVIDIA HPC SDK) 25.5-0 | x86_64 | Ubuntu 22.04 LTS | GitHub |
|
||||||
@@ -132,7 +132,8 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
|||||||
[libstdc++](https://gcc.gnu.org/onlinedocs/libstdc++/) to detect subtle differences or incompatibilities.
|
[libstdc++](https://gcc.gnu.org/onlinedocs/libstdc++/) to detect subtle differences or incompatibilities.
|
||||||
- [x] The code checked with [Include What You Use (IWYU)](https://include-what-you-use.org) that all required standard
|
- [x] The code checked with [Include What You Use (IWYU)](https://include-what-you-use.org) that all required standard
|
||||||
headers are included.
|
headers are included.
|
||||||
- [x] On Windows, the library is compiled with `<Windows.h>` being included to detect and avoid common bugs.
|
- [x] On Windows, the library is compiled with `<Windows.h>` being included to detect and avoid common bugs (see
|
||||||
|
[`unit-windows_h.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-windows_h.cpp)).
|
||||||
- [x] The library is compiled with exceptions disabled to support alternative means of error handling.
|
- [x] The library is compiled with exceptions disabled to support alternative means of error handling.
|
||||||
|
|
||||||
## Stable public API
|
## Stable public API
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
<a target="_blank" href="https://wandbox.org/permlink/hUJYo1HWmfTBLMGn"><b>online</b></a>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<a target="_blank" href="https://wandbox.org/permlink/AWbpa8e1xRV3y4MM"><b>online</b></a>
|
|
||||||
@@ -61,7 +61,7 @@ The library uses the following mapping from JSON values types to BJData types ac
|
|||||||
|
|
||||||
The following values can **not** be converted to a BJData value:
|
The following values can **not** be converted to a BJData value:
|
||||||
|
|
||||||
- strings with more than 18446744073709551615 bytes, i.e., $2^{64}-1$ bytes (theoretical)
|
- strings with more than 18446744073709551615 bytes, i.e., 2<sup>64</sup>-1 bytes (theoretical)
|
||||||
|
|
||||||
!!! info "Unused BJData markers"
|
!!! info "Unused BJData markers"
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,20 @@ The library maps CBOR types to JSON value types as follows:
|
|||||||
|
|
||||||
!!! warning "Object keys"
|
!!! warning "Object keys"
|
||||||
|
|
||||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps
|
||||||
|
with keys other than text strings (major type 3) are rejected with a
|
||||||
|
[`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with `allow_exceptions` set
|
||||||
|
to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||||
|
```
|
||||||
|
|
||||||
|
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||||
|
on. This is a deliberate restriction of the library's JSON value model, not an oversight: formats built on CBOR
|
||||||
|
maps with integer keys, such as COSE ([RFC 9052](https://www.rfc-editor.org/rfc/rfc9052.html)) or CWT
|
||||||
|
([RFC 8392](https://www.rfc-editor.org/rfc/rfc8392.html)), cannot be read with this library and need a
|
||||||
|
general-purpose CBOR library instead.
|
||||||
|
|
||||||
!!! warning "UTF-8 validation of text strings"
|
!!! warning "UTF-8 validation of text strings"
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,21 @@ The library maps MessagePack types to JSON value types as follows:
|
|||||||
|
|
||||||
Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`.
|
Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`.
|
||||||
|
|
||||||
|
!!! warning "Object keys"
|
||||||
|
|
||||||
|
MessagePack allows map keys of any type, whereas JSON only allows strings as keys in object values. Like the
|
||||||
|
JSON-compatible [profile](https://github.com/msgpack/msgpack/blob/master/spec.md#profile) sketched in the
|
||||||
|
MessagePack specification, this library restricts map keys to `str` values. Maps with keys of any other type are
|
||||||
|
rejected with a [`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with
|
||||||
|
`allow_exceptions` set to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||||
|
```
|
||||||
|
|
||||||
|
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||||
|
on. Such input needs a general-purpose MessagePack library instead.
|
||||||
|
|
||||||
!!! warning "UTF-8 validation of string values"
|
!!! warning "UTF-8 validation of string values"
|
||||||
|
|
||||||
The MessagePack specification requires `str` values (`fixstr`, `str 8`, `str 16`, `str 32`) to be valid UTF-8.
|
The MessagePack specification requires `str` values (`fixstr`, `str 8`, `str 16`, `str 32`) to be valid UTF-8.
|
||||||
|
|||||||
@@ -83,6 +83,22 @@ When defined, default parse and serialize functions for enums are excluded and h
|
|||||||
|
|
||||||
See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md).
|
See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md).
|
||||||
|
|
||||||
|
## `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`
|
||||||
|
|
||||||
|
When defined to `1`, a JSON value can no longer be created from a one-element `std::tuple` holding a reference to a JSON
|
||||||
|
value, such as the result of `std::forward_as_tuple(j)`. This lets `std::tuple` convert such tuples element-wise.
|
||||||
|
|
||||||
|
See [full documentation of `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md).
|
||||||
|
|
||||||
|
## `JSON_NO_AUTOMATIC_UDLS`
|
||||||
|
|
||||||
|
When defined, `<nlohmann/json.hpp>` does not include `<nlohmann/json_literals.hpp>` with the user-defined string literals
|
||||||
|
`operator""_json` and `operator""_json_pointer`. This reduces the compile time of translation units that do not use
|
||||||
|
them, because the literals instantiate the parser in every translation unit that includes them. Include
|
||||||
|
`<nlohmann/json_literals.hpp>` where the literals are needed.
|
||||||
|
|
||||||
|
See [full documentation of `JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
||||||
|
|
||||||
## `JSON_NO_IO`
|
## `JSON_NO_IO`
|
||||||
|
|
||||||
When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
|
When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ Only the following symbols are exported from `nlohmann.json`:
|
|||||||
- `nlohmann::literals::json_literals::operator""_json`
|
- `nlohmann::literals::json_literals::operator""_json`
|
||||||
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
||||||
|
|
||||||
|
The module always exports the two user-defined string literals, even if
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) is defined when building it.
|
||||||
|
|
||||||
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
||||||
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
||||||
and should not be used directly:
|
and should not be used directly:
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ When the default type is used, the maximal unsigned integer number that can be s
|
|||||||
|
|
||||||
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
[RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
|
||||||
|
|
||||||
> Note that when such software is used, numbers that are integers and are in the range $[-2^{53}+1, 2^{53}-1]$ are interoperable in the sense that implementations will agree exactly on their numeric values.
|
> Note that when such software is used, numbers that are integers and are in the range [-2<sup>53</sup>+1, 2<sup>53</sup>-1] are interoperable in the sense that implementations will agree exactly on their numeric values.
|
||||||
|
|
||||||
As this range is a subrange of the exactly supported range [`INT64_MIN`, `INT64_MAX`], this class's integer type is interoperable.
|
As this range is a subrange of the exactly supported range [`INT64_MIN`, `INT64_MAX`], this class's integer type is interoperable.
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ On number interoperability, the following remarks are made:
|
|||||||
for numeric magnitude and precision than is widely available.
|
for numeric magnitude and precision than is widely available.
|
||||||
|
|
||||||
Note that when such software is used, numbers that are integers and
|
Note that when such software is used, numbers that are integers and
|
||||||
are in the range $[-2^{53}+1, 2^{53}-1]$ are interoperable in the
|
are in the range [-2<sup>53</sup>+1, 2<sup>53</sup>-1] are interoperable in the
|
||||||
sense that implementations will agree exactly on their numeric
|
sense that implementations will agree exactly on their numeric
|
||||||
values.
|
values.
|
||||||
|
|
||||||
@@ -71,10 +71,13 @@ otherwise, it uses unsigned integer storage.
|
|||||||
|
|
||||||
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
- Numbers with a decimal digit or scientific notation are always stored as `#!c double`.
|
||||||
- The number types can be changed, see [Template number types](#template-number-types).
|
- The number types can be changed, see [Template number types](#template-number-types).
|
||||||
- As of version 3.9.1, the conversion is realized by
|
- The library converts integers and floating-point numbers itself, independent of the locale. Floating-point
|
||||||
[`std::strtoull`](https://en.cppreference.com/w/cpp/string/byte/strtoul),
|
numbers are correctly rounded (to nearest, ties to even). Only a `#!c long double` that is not IEEE 754 binary64
|
||||||
[`std::strtoll`](https://en.cppreference.com/w/cpp/string/byte/strtol), and
|
(e.g., the 80-bit x87 format) is converted with `#!cpp std::from_chars` where available, or else with
|
||||||
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof), respectively.
|
[`std::strtold`](https://en.cppreference.com/w/cpp/string/byte/strtof). For that call, the library temporarily
|
||||||
|
replaces the `.` with the decimal point of the current locale (which may be longer than one byte, e.g., in
|
||||||
|
`fa_IR.UTF-8`), so the result does not depend on the locale either. Changing the locale in another thread during
|
||||||
|
parsing is undefined behavior of the C library, though.
|
||||||
|
|
||||||
!!! example "Examples"
|
!!! example "Examples"
|
||||||
|
|
||||||
@@ -85,19 +88,19 @@ otherwise, it uses unsigned integer storage.
|
|||||||
### Number limits
|
### Number limits
|
||||||
|
|
||||||
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
||||||
- Numbers exceeding the limits of `#!c double` (i.e., numbers that after conversion via
|
- Numbers exceeding the limits of `#!c double` (i.e., numbers whose rounded value is not satisfying
|
||||||
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof) are not satisfying
|
|
||||||
[`std::isfinite`](https://en.cppreference.com/w/cpp/numeric/math/isfinite) such as `#!c 1E400`) will throw exception
|
[`std::isfinite`](https://en.cppreference.com/w/cpp/numeric/math/isfinite) such as `#!c 1E400`) will throw exception
|
||||||
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing.
|
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing. Numbers too
|
||||||
|
small for `#!c double` (such as `#!c 1E-400`) become zero, with the sign of the number.
|
||||||
- Floating-point numbers are rounded to the next number representable as `double`. For instance
|
- Floating-point numbers are rounded to the next number representable as `double`. For instance
|
||||||
`#!c 3.141592653589793238462643383279` is stored as [`0x400921fb54442d18`](https://float.exposed/0x400921fb54442d18).
|
`#!c 3.141592653589793238462643383279` is stored as [`0x400921fb54442d18`](https://float.exposed/0x400921fb54442d18).
|
||||||
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
||||||
|
|
||||||
!!! success "Interoperability"
|
!!! success "Interoperability"
|
||||||
|
|
||||||
- The library is interoperable with respect to the specification, because its supported range $[-2^{63}, 2^{64}-1]$ is
|
- The library is interoperable with respect to the specification, because its supported range [-2<sup>63</sup>, 2<sup>64</sup>-1] is
|
||||||
larger than the described range $[-2^{53}+1, 2^{53}-1]$.
|
larger than the described range [-2<sup>53</sup>+1, 2<sup>53</sup>-1].
|
||||||
- All integers outside the range $[-2^{63}, 2^{64}-1]$, as well as floating-point numbers are stored as `double`.
|
- All integers outside the range [-2<sup>63</sup>, 2<sup>64</sup>-1], as well as floating-point numbers are stored as `double`.
|
||||||
This also concurs with the specification above.
|
This also concurs with the specification above.
|
||||||
|
|
||||||
### Zeros
|
### Zeros
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ Requirements are split into two groups:
|
|||||||
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
diagnosed with dedicated error messages, and violating most of them results in a compiler error somewhere inside
|
||||||
the library. Four violations are not caught at compile time at all:
|
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,
|
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers
|
||||||
because the lexer hands the buffer to `#!cpp std::strtoull`/`#!cpp std::strtoll`/`#!cpp std::strtod`.
|
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,
|
- 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.
|
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. These abort on an assertion
|
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
||||||
@@ -389,6 +390,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
|||||||
| Functionality | Additional requirement |
|
| Functionality | Additional requirement |
|
||||||
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
|
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
|
||||||
|
| [`operator/(std::size_t)`](../../api/json_pointer/operator_slash.md) | the same conversion of a `#!cpp std::size_t` to `StringType` as `diff`, `items`, and `std::hash` above |
|
||||||
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
|
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
|
||||||
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
||||||
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
||||||
@@ -534,8 +536,10 @@ therefore silently changes parse results rather than raising an error. See
|
|||||||
|
|
||||||
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
||||||
|
|
||||||
- The [parser](../parsing/index.md) converts number literals with `#!cpp std::strtof`, `#!cpp std::strtod`, or
|
- The [parser](../parsing/index.md) converts number literals to `#!cpp float`, `#!cpp double`, and a
|
||||||
`#!cpp std::strtold`; the library provides overloads for exactly these three types.
|
`#!cpp long double` that is IEEE 754 binary64 itself; other `#!cpp long double` formats are converted with
|
||||||
|
`#!cpp std::from_chars` where available, or with `#!cpp std::strtold`. The library provides overloads for exactly
|
||||||
|
these three types.
|
||||||
- [`dump`](../../api/basic_json/dump.md) falls back to `#!cpp std::snprintf` with the `%g` and `%Lg` conversion
|
- [`dump`](../../api/basic_json/dump.md) falls back to `#!cpp std::snprintf` with the `%g` and `%Lg` conversion
|
||||||
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
|
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
|
||||||
(`#!cpp float` is promoted to `#!cpp double`).
|
(`#!cpp float` is promoted to `#!cpp double`).
|
||||||
|
|||||||
@@ -343,13 +343,20 @@ A string could not be read from a [binary format](../features/binary_formats/ind
|
|||||||
string was read where one was required (for instance as a map key), the string's length specification is invalid, or
|
string was read where one was required (for instance as a map key), the string's length specification is invalid, or
|
||||||
the string's bytes are not valid UTF-8.
|
the string's bytes are not valid UTF-8.
|
||||||
|
|
||||||
|
CBOR and MessagePack allow map keys of any type, but JSON object keys are always strings. Maps with keys of any other
|
||||||
|
type (for instance integers or `null`) are therefore not supported; see the notes on
|
||||||
|
[CBOR](../features/binary_formats/cbor.md) and [MessagePack](../features/binary_formats/messagepack.md).
|
||||||
|
|
||||||
!!! failure "Example messages"
|
!!! failure "Example messages"
|
||||||
|
|
||||||
```
|
```
|
||||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||||
|
```
|
||||||
|
```
|
||||||
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x7C
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82
|
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82
|
||||||
|
|||||||
@@ -19,3 +19,5 @@ The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed und
|
|||||||
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
||||||
|
|
||||||
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||||
|
|
||||||
|
The class contains an adapted version of the Eisel-Lemire algorithm, its table of powers of five, and its digit comparison for long numbers from [fast_float](https://github.com/fastfloat/fast_float) by Daniel Lemire and contributors, which is available under the [MIT License](https://opensource.org/licenses/MIT) (used here), the Apache 2.0 License, and the Boost Software License. Copyright © 2021 The fast_float authors
|
||||||
|
|||||||
@@ -169,6 +169,12 @@ Enable position diagnostics by defining macro [`JSON_DIAGNOSTIC_POSITIONS`](../a
|
|||||||
Disable default `enum` serialization by defining the macro
|
Disable default `enum` serialization by defining the macro
|
||||||
[`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). This option is `OFF` by default.
|
[`JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md). This option is `OFF` by default.
|
||||||
|
|
||||||
|
### `JSON_DisableTupleReferenceConversion`
|
||||||
|
|
||||||
|
Disable the conversion from a one-element `std::tuple` holding a reference to a JSON value by defining the macro
|
||||||
|
[`JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md). This option is
|
||||||
|
`OFF` by default.
|
||||||
|
|
||||||
### `JSON_FastTests`
|
### `JSON_FastTests`
|
||||||
|
|
||||||
Skip expensive/slow test suites. This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
Skip expensive/slow test suites. This option is `OFF` by default. Depends on `JSON_BuildTests`.
|
||||||
|
|||||||
@@ -15,4 +15,7 @@ Clang).
|
|||||||
|
|
||||||
You can further use file
|
You can further use file
|
||||||
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
||||||
for forward declarations.
|
for forward declarations, and file
|
||||||
|
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
|
||||||
|
for the user-defined string literals if you define
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
||||||
|
|||||||
@@ -678,11 +678,11 @@ to install the [nlohmann-json](https://ports.macports.org/port/nlohmann-json/) p
|
|||||||
1. Create the following files:
|
1. Create the following files:
|
||||||
|
|
||||||
```cpp title="example.cpp"
|
```cpp title="example.cpp"
|
||||||
--8<-- "integration/homebrew/example.cpp"
|
--8<-- "integration/macports/example.cpp"
|
||||||
```
|
```
|
||||||
|
|
||||||
```cmake title="CMakeLists.txt"
|
```cmake title="CMakeLists.txt"
|
||||||
--8<-- "integration/homebrew/CMakeLists.txt"
|
--8<-- "integration/macports/CMakeLists.txt"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Install the package:
|
2. Install the package:
|
||||||
|
|||||||
@@ -287,12 +287,14 @@ nav:
|
|||||||
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
|
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
|
||||||
- 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.md
|
- 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.md
|
||||||
- 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md
|
- 'JSON_DISABLE_ENUM_SERIALIZATION': api/macros/json_disable_enum_serialization.md
|
||||||
|
- 'JSON_DISABLE_TUPLE_REFERENCE_CONVERSION': api/macros/json_disable_tuple_reference_conversion.md
|
||||||
- 'JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20': api/macros/json_has_cpp_11.md
|
- 'JSON_HAS_CPP_11, JSON_HAS_CPP_14, JSON_HAS_CPP_17, JSON_HAS_CPP_20': api/macros/json_has_cpp_11.md
|
||||||
- 'JSON_HAS_EXPERIMENTAL_FILESYSTEM, JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md
|
- 'JSON_HAS_EXPERIMENTAL_FILESYSTEM, JSON_HAS_FILESYSTEM': api/macros/json_has_filesystem.md
|
||||||
- 'JSON_HAS_RANGES': api/macros/json_has_ranges.md
|
- 'JSON_HAS_RANGES': api/macros/json_has_ranges.md
|
||||||
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
||||||
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
||||||
- 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md
|
- 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md
|
||||||
|
- 'JSON_NO_AUTOMATIC_UDLS': api/macros/json_no_automatic_udls.md
|
||||||
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
||||||
- 'JSON_NO_IO': api/macros/json_no_io.md
|
- 'JSON_NO_IO': api/macros/json_no_io.md
|
||||||
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
||||||
@@ -349,7 +351,6 @@ markdown_extensions:
|
|||||||
- toc:
|
- toc:
|
||||||
permalink: true
|
permalink: true
|
||||||
- md_in_html
|
- md_in_html
|
||||||
- pymdownx.arithmatex
|
|
||||||
- pymdownx.betterem:
|
- pymdownx.betterem:
|
||||||
smart_enable: all
|
smart_enable: all
|
||||||
- pymdownx.caret
|
- pymdownx.caret
|
||||||
@@ -441,6 +442,3 @@ plugins:
|
|||||||
|
|
||||||
extra_css:
|
extra_css:
|
||||||
- css/custom.css
|
- css/custom.css
|
||||||
|
|
||||||
extra_javascript:
|
|
||||||
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML
|
|
||||||
|
|||||||
@@ -79,9 +79,9 @@ def check_structure() -> None:
|
|||||||
report("whitespace/line_length", f"{file}:{lineno+1} ({current_section})", f"line is too long ({len(line)} vs. 160 chars)")
|
report("whitespace/line_length", f"{file}:{lineno+1} ({current_section})", f"line is too long ({len(line)} vs. 160 chars)")
|
||||||
|
|
||||||
# sections in `<!-- NOLINT -->` comments are treated as present
|
# sections in `<!-- NOLINT -->` comments are treated as present
|
||||||
if line.startswith("<!-- NOLINT"):
|
nolint_match = re.match(r"<!--\s*NOLINT\s+(.*?)\s*-->", line)
|
||||||
current_section = line.strip("<!-- NOLINT")
|
if nolint_match:
|
||||||
current_section = current_section.strip(" -->")
|
current_section = nolint_match.group(1)
|
||||||
existing_sections.append(current_section)
|
existing_sections.append(current_section)
|
||||||
|
|
||||||
# check if sections are correct
|
# check if sections are correct
|
||||||
@@ -97,7 +97,7 @@ def check_structure() -> None:
|
|||||||
if len(unexpected):
|
if len(unexpected):
|
||||||
report("style/numbering", f"{file}:{lineno} ({current_section})", f'unexpected overloads: {", ".join([f"({x})" for x in unexpected])}')
|
report("style/numbering", f"{file}:{lineno} ({current_section})", f'unexpected overloads: {", ".join([f"({x})" for x in unexpected])}')
|
||||||
|
|
||||||
current_section = line.strip("## ")
|
current_section = line[3:]
|
||||||
existing_sections.append(current_section)
|
existing_sections.append(current_section)
|
||||||
|
|
||||||
if current_section in expected_sections:
|
if current_section in expected_sections:
|
||||||
@@ -141,7 +141,7 @@ def check_structure() -> None:
|
|||||||
# check that non-example admonitions have titles
|
# check that non-example admonitions have titles
|
||||||
untitled_admonition = re.match(r"^(\?\?\?|!!!) ([^ ]+)$", line)
|
untitled_admonition = re.match(r"^(\?\?\?|!!!) ([^ ]+)$", line)
|
||||||
if untitled_admonition and untitled_admonition.group(2) != "example":
|
if untitled_admonition and untitled_admonition.group(2) != "example":
|
||||||
report("style/admonition_title", f"{file}:{lineno} ({current_section})", f'"{untitled_admonition.group(2)}" admonitions should have a title')
|
report("style/admonition_title", f"{file}:{lineno+1} ({current_section})", f'"{untitled_admonition.group(2)}" admonitions should have a title')
|
||||||
|
|
||||||
previous_line = line
|
previous_line = line
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // uint64_t
|
||||||
|
|
||||||
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
|
// Portable bit-level helpers for the number and string scanners. They use
|
||||||
|
// compiler builtins where available and plain C++ otherwise, so they need no
|
||||||
|
// platform headers and work regardless of byte order.
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
/// number of leading zero bits of x (x != 0)
|
||||||
|
inline int count_leading_zeros(std::uint64_t x) noexcept
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_clzll(x);
|
||||||
|
#else
|
||||||
|
int n = 0;
|
||||||
|
for (int shift = 32; shift != 0; shift >>= 1)
|
||||||
|
{
|
||||||
|
if ((x >> (64 - shift)) == 0)
|
||||||
|
{
|
||||||
|
n += shift;
|
||||||
|
x <<= shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// number of trailing zero bits of x (x != 0)
|
||||||
|
inline int count_trailing_zeros(std::uint64_t x) noexcept
|
||||||
|
{
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
return __builtin_ctzll(x);
|
||||||
|
#else
|
||||||
|
int n = 0;
|
||||||
|
for (int shift = 32; shift != 0; shift >>= 1)
|
||||||
|
{
|
||||||
|
if ((x << (64 - shift)) == 0)
|
||||||
|
{
|
||||||
|
n += shift;
|
||||||
|
x >>= shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the 128-bit product of two 64-bit numbers
|
||||||
|
struct uint128_parts
|
||||||
|
{
|
||||||
|
std::uint64_t low;
|
||||||
|
std::uint64_t high;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexcept
|
||||||
|
{
|
||||||
|
#if defined(__SIZEOF_INT128__)
|
||||||
|
__extension__ using uint128 = unsigned __int128;
|
||||||
|
const uint128 r = static_cast<uint128>(a) * b;
|
||||||
|
return {static_cast<std::uint64_t>(r), static_cast<std::uint64_t>(r >> 64u)};
|
||||||
|
#else
|
||||||
|
const std::uint64_t a_lo = a & 0xFFFFFFFFu;
|
||||||
|
const std::uint64_t a_hi = a >> 32u;
|
||||||
|
const std::uint64_t b_lo = b & 0xFFFFFFFFu;
|
||||||
|
const std::uint64_t b_hi = b >> 32u;
|
||||||
|
const std::uint64_t lo_lo = a_lo * b_lo;
|
||||||
|
const std::uint64_t hi_lo = a_hi * b_lo;
|
||||||
|
const std::uint64_t lo_hi = a_lo * b_hi;
|
||||||
|
const std::uint64_t hi_hi = a_hi * b_hi;
|
||||||
|
const std::uint64_t cross = (lo_lo >> 32u) + (hi_lo & 0xFFFFFFFFu) + lo_hi;
|
||||||
|
return {(cross << 32u) | (lo_lo & 0xFFFFFFFFu), (hi_lo >> 32u) + (cross >> 32u) + hi_hi};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// eight bytes as a little-endian word (compilers fold this into one load on
|
||||||
|
/// little-endian targets)
|
||||||
|
inline std::uint64_t read_eight_bytes(const unsigned char* b) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<std::uint64_t>(b[0]) | (static_cast<std::uint64_t>(b[1]) << 8u)
|
||||||
|
| (static_cast<std::uint64_t>(b[2]) << 16u) | (static_cast<std::uint64_t>(b[3]) << 24u)
|
||||||
|
| (static_cast<std::uint64_t>(b[4]) << 32u) | (static_cast<std::uint64_t>(b[5]) << 40u)
|
||||||
|
| (static_cast<std::uint64_t>(b[6]) << 48u) | (static_cast<std::uint64_t>(b[7]) << 56u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// eight bytes as a little-endian word
|
||||||
|
inline std::uint64_t read_eight_bytes(const char* p) noexcept
|
||||||
|
{
|
||||||
|
return read_eight_bytes(reinterpret_cast<const unsigned char*>(p)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
@@ -167,9 +167,13 @@ template<typename BasicJsonType, typename EnumType,
|
|||||||
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, EnumType& e)
|
inline void from_json(const BasicJsonType& j, EnumType& e)
|
||||||
{
|
{
|
||||||
typename std::underlying_type<EnumType>::type val;
|
using underlying_type = typename std::underlying_type<EnumType>::type;
|
||||||
|
// get_arithmetic_value() does not accept boolean_t; read the number that to_json() wrote instead
|
||||||
|
using value_type = typename std::conditional<std::is_same<underlying_type, typename BasicJsonType::boolean_t>::value,
|
||||||
|
typename BasicJsonType::number_unsigned_t, underlying_type>::type;
|
||||||
|
value_type val;
|
||||||
get_arithmetic_value(j, val);
|
get_arithmetic_value(j, val);
|
||||||
e = static_cast<EnumType>(val);
|
e = static_cast<EnumType>(static_cast<underlying_type>(val));
|
||||||
}
|
}
|
||||||
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
|
|
||||||
@@ -350,22 +354,22 @@ void())
|
|||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename T, std::size_t... Idx >
|
template < typename BasicJsonType, typename T, std::size_t... Idx >
|
||||||
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
|
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(const BasicJsonType& j,
|
||||||
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
|
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
|
||||||
{
|
{
|
||||||
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
|
return { { j.at(Idx).template get<T>()... } };
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename T, std::size_t N >
|
template < typename BasicJsonType, typename T, std::size_t N >
|
||||||
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
|
auto from_json(const BasicJsonType& j, identity_tag<std::array<T, N>> tag)
|
||||||
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
|
-> decltype(from_json_inplace_array_impl(j, tag, make_index_sequence<N> {}))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
|
return from_json_inplace_array_impl(j, tag, make_index_sequence<N> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
@@ -500,54 +504,54 @@ template<std::size_t PTagValue, typename BasicJsonType, typename... Types>
|
|||||||
using tuple_type = std::tuple < decltype(from_json_tuple_get_impl(std::declval<BasicJsonType>(), detail::identity_tag<Types> {}, detail::priority_tag<PTagValue> {}))... >;
|
using tuple_type = std::tuple < decltype(from_json_tuple_get_impl(std::declval<BasicJsonType>(), detail::identity_tag<Types> {}, detail::priority_tag<PTagValue> {}))... >;
|
||||||
|
|
||||||
template<std::size_t PTagValue, typename... Args, typename BasicJsonType, std::size_t... Idx>
|
template<std::size_t PTagValue, typename... Args, typename BasicJsonType, std::size_t... Idx>
|
||||||
tuple_type<PTagValue, BasicJsonType, Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
|
tuple_type<PTagValue, const BasicJsonType&, Args...> from_json_tuple_impl_base(const BasicJsonType& j, index_sequence<Idx...> /*unused*/)
|
||||||
{
|
{
|
||||||
return tuple_type<PTagValue, BasicJsonType, Args...>(from_json_tuple_get_impl(std::forward<BasicJsonType>(j).at(Idx), detail::identity_tag<Args> {}, detail::priority_tag<PTagValue> {})...);
|
return tuple_type<PTagValue, const BasicJsonType&, Args...>(from_json_tuple_get_impl(j.at(Idx), detail::identity_tag<Args> {}, detail::priority_tag<PTagValue> {})...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<std::size_t PTagValue, typename BasicJsonType>
|
template<std::size_t PTagValue, typename BasicJsonType>
|
||||||
std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
|
std::tuple<> from_json_tuple_impl_base(const BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, class A1, class A2 >
|
template < typename BasicJsonType, class A1, class A2 >
|
||||||
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
|
std::pair<A1, A2> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
|
||||||
{
|
{
|
||||||
return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
|
return {j.at(0).template get<A1>(),
|
||||||
std::forward<BasicJsonType>(j).at(1).template get<A2>()};
|
j.at(1).template get<A2>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename A1, typename A2>
|
template<typename BasicJsonType, typename A1, typename A2>
|
||||||
inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
|
inline void from_json_tuple_impl(const BasicJsonType& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
|
||||||
{
|
{
|
||||||
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
|
p = from_json_tuple_impl(j, identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
std::tuple<Args...> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
||||||
{
|
{
|
||||||
static_assert(cxpr_and<cxpr_or<cxpr_not<std::is_reference<Args>>, is_compatible_reference_type<BasicJsonType, Args>>...>::value,
|
static_assert(cxpr_and<cxpr_or<cxpr_not<std::is_reference<Args>>, is_compatible_reference_type<const BasicJsonType&, Args>>...>::value,
|
||||||
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
"Can not return a tuple containing references to types not contained in a Json, try Json::get_to()");
|
||||||
return from_json_tuple_impl_base<1, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
|
return from_json_tuple_impl_base<1, Args...>(j, index_sequence_for<Args...> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
|
inline void from_json_tuple_impl(const BasicJsonType& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
|
||||||
{
|
{
|
||||||
t = from_json_tuple_impl_base<2, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
|
t = from_json_tuple_impl_base<2, Args...>(j, index_sequence_for<Args...> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename TupleRelated>
|
template<typename BasicJsonType, typename TupleRelated>
|
||||||
auto from_json(BasicJsonType&& j, TupleRelated&& t)
|
auto from_json(const BasicJsonType& j, TupleRelated&& t)
|
||||||
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
|
-> decltype(from_json_tuple_impl(j, std::forward<TupleRelated>(t), priority_tag<3> {}))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
|
return from_json_tuple_impl(j, std::forward<TupleRelated>(t), priority_tag<3> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||||
@@ -564,7 +568,7 @@ inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allo
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||||
}
|
}
|
||||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||||
}
|
}
|
||||||
@@ -584,7 +588,7 @@ inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Has
|
|||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||||
}
|
}
|
||||||
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
|
||||||
}
|
}
|
||||||
@@ -632,7 +636,7 @@ struct from_json_fn
|
|||||||
/// namespace to hold default `from_json` function
|
/// namespace to hold default `from_json` function
|
||||||
/// to see why this is required:
|
/// to see why this is required:
|
||||||
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
||||||
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces,misc-anonymous-namespace-in-header)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
|
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ struct external_constructor<value_t::object>
|
|||||||
#ifdef JSON_HAS_CPP_17
|
#ifdef JSON_HAS_CPP_17
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
|
||||||
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
|
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept(std::is_nothrow_assignable<BasicJsonType&, const T&>::value)
|
||||||
{
|
{
|
||||||
if (opt.has_value())
|
if (opt.has_value())
|
||||||
{
|
{
|
||||||
@@ -471,11 +471,13 @@ inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<
|
|||||||
j = { std::get<Idx>(t)... };
|
j = { std::get<Idx>(t)... };
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JSON_BRACE_INIT_COPY_SEMANTICS
|
// A one-element braced list does not reliably wrap its element: with
|
||||||
// JSON_BRACE_INIT_COPY_SEMANTICS makes a one-element braced list copy its
|
// JSON_BRACE_INIT_COPY_SEMANTICS it copies it, which would serialize
|
||||||
// element instead of wrapping it, which would serialize std::tuple<int>{5} as 5
|
// std::tuple<int>{5} as 5 rather than [5], and some compilers (e.g., Apple clang
|
||||||
// rather than [5]. Build what the default deduction builds instead: an object
|
// 15 and 16) copy an element that is itself a basic_json even without it, so
|
||||||
// if the element is a [string, value] pair, a one-element array otherwise.
|
// std::tuple<json>{true} became true rather than [true]. Build what the default
|
||||||
|
// deduction builds instead: an object if the element is a [string, value] pair,
|
||||||
|
// a one-element array otherwise.
|
||||||
template<typename BasicJsonType, typename Tuple>
|
template<typename BasicJsonType, typename Tuple>
|
||||||
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<0> /*unused*/)
|
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<0> /*unused*/)
|
||||||
{
|
{
|
||||||
@@ -493,7 +495,6 @@ inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<
|
|||||||
j = BasicJsonType::array({std::move(element)});
|
j = BasicJsonType::array({std::move(element)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Tuple>
|
template<typename BasicJsonType, typename Tuple>
|
||||||
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
|
inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
|
||||||
@@ -546,7 +547,7 @@ struct to_json_fn
|
|||||||
/// namespace to hold default `to_json` function
|
/// namespace to hold default `to_json` function
|
||||||
/// to see why this is required:
|
/// to see why this is required:
|
||||||
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
||||||
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces,misc-anonymous-namespace-in-header)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
|
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm> // min
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
||||||
#include <memory> // shared_ptr, make_shared, addressof
|
|
||||||
#include <numeric> // accumulate
|
|
||||||
#include <streambuf> // streambuf
|
#include <streambuf> // streambuf
|
||||||
#include <string> // string, char_traits
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -82,8 +83,9 @@ class file_input_adapter
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
|
Input adapter for a (caching) istream. Does not skip a UTF Byte Order Mark
|
||||||
beginning of input. Does not support changing the underlying std::streambuf
|
itself; that is done by the lexer's skip_bom(). Does not support changing
|
||||||
|
the underlying std::streambuf
|
||||||
in mid-input. Maintains underlying std::istream and std::streambuf to support
|
in mid-input. Maintains underlying std::istream and std::streambuf to support
|
||||||
subsequent use of standard std::istream operations to process any input
|
subsequent use of standard std::istream operations to process any input
|
||||||
characters following those used in parsing the JSON input. Clears the
|
characters following those used in parsing the JSON input. Clears the
|
||||||
@@ -106,9 +108,15 @@ class input_stream_adapter
|
|||||||
// was given back with release_lookahead()
|
// was given back with release_lookahead()
|
||||||
commit_lookahead();
|
commit_lookahead();
|
||||||
#endif
|
#endif
|
||||||
|
// only call clear() if there is something to clear: it throws
|
||||||
|
// std::ios_base::failure if the stream has exceptions() enabled
|
||||||
|
// for a state bit that remains set, and a destructor must not throw
|
||||||
|
if ((is->rdstate() & ~std::ios::eofbit) != 0)
|
||||||
|
{
|
||||||
is->clear(is->rdstate() & std::ios::eofbit);
|
is->clear(is->rdstate() & std::ios::eofbit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
explicit input_stream_adapter(std::istream& i)
|
explicit input_stream_adapter(std::istream& i)
|
||||||
: is(&i), sb(i.rdbuf())
|
: is(&i), sb(i.rdbuf())
|
||||||
@@ -448,32 +456,14 @@ struct wide_string_input_helper<BaseInputAdapter, 4>
|
|||||||
// get the current character
|
// get the current character
|
||||||
const auto wc = input.get_character();
|
const auto wc = input.get_character();
|
||||||
|
|
||||||
|
if (wc <= 0x10FFFF)
|
||||||
|
{
|
||||||
// UTF-32 to UTF-8 encoding
|
// UTF-32 to UTF-8 encoding
|
||||||
if (wc < 0x80)
|
utf8_bytes_filled = 0;
|
||||||
|
encode_utf8(static_cast<std::uint32_t>(wc), [&utf8_bytes, &utf8_bytes_filled](std::uint32_t byte)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
utf8_bytes[utf8_bytes_filled++] = static_cast<std::char_traits<char>::int_type>(byte);
|
||||||
utf8_bytes_filled = 1;
|
});
|
||||||
}
|
|
||||||
else if (wc <= 0x7FF)
|
|
||||||
{
|
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
|
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
|
||||||
utf8_bytes_filled = 2;
|
|
||||||
}
|
|
||||||
else if (wc <= 0xFFFF)
|
|
||||||
{
|
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
|
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
|
||||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
|
||||||
utf8_bytes_filled = 3;
|
|
||||||
}
|
|
||||||
else if (wc <= 0x10FFFF)
|
|
||||||
{
|
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
|
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
|
|
||||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
|
||||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
|
||||||
utf8_bytes_filled = 4;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -510,24 +500,15 @@ struct wide_string_input_helper<BaseInputAdapter, 2>
|
|||||||
// get the current character
|
// get the current character
|
||||||
const auto wc = input.get_character();
|
const auto wc = input.get_character();
|
||||||
|
|
||||||
// UTF-16 to UTF-8 encoding
|
if (0xD800 > wc || wc >= 0xE000)
|
||||||
if (wc < 0x80)
|
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
// a UTF-16 code unit outside the surrogate range is a valid
|
||||||
utf8_bytes_filled = 1;
|
// code point (at most U+FFFF) on its own
|
||||||
}
|
utf8_bytes_filled = 0;
|
||||||
else if (wc <= 0x7FF)
|
encode_utf8(static_cast<std::uint32_t>(wc), [&utf8_bytes, &utf8_bytes_filled](std::uint32_t byte)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
|
utf8_bytes[utf8_bytes_filled++] = static_cast<std::char_traits<char>::int_type>(byte);
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
});
|
||||||
utf8_bytes_filled = 2;
|
|
||||||
}
|
|
||||||
else if (0xD800 > wc || wc >= 0xE000)
|
|
||||||
{
|
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
|
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
|
||||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
|
||||||
utf8_bytes_filled = 3;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -545,11 +526,11 @@ struct wide_string_input_helper<BaseInputAdapter, 2>
|
|||||||
if (0xDC00 <= wc2 && wc2 <= 0xDFFF)
|
if (0xDC00 <= wc2 && wc2 <= 0xDFFF)
|
||||||
{
|
{
|
||||||
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
|
utf8_bytes_filled = 0;
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
|
encode_utf8(charcode, [&utf8_bytes, &utf8_bytes_filled](std::uint32_t byte)
|
||||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
|
{
|
||||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
|
utf8_bytes[utf8_bytes_filled++] = static_cast<std::char_traits<char>::int_type>(byte);
|
||||||
utf8_bytes_filled = 4;
|
});
|
||||||
valid_pair = true;
|
valid_pair = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -763,6 +744,9 @@ struct container_input_adapter_factory< ContainerType,
|
|||||||
|
|
||||||
static adapter_type create(ContainerType&& container)
|
static adapter_type create(ContainerType&& container)
|
||||||
{
|
{
|
||||||
|
// container is forwarded twice on purpose: the resulting begin/end
|
||||||
|
// iterator types must match adapter_type, computed the same way
|
||||||
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
||||||
return input_adapter(begin(std::forward<ContainerType>(container)), end(std::forward<ContainerType>(container)));
|
return input_adapter(begin(std::forward<ContainerType>(container)), end(std::forward<ContainerType>(container)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -811,12 +795,16 @@ inline file_input_adapter input_adapter(std::FILE* file)
|
|||||||
|
|
||||||
inline input_stream_adapter input_adapter(std::istream& stream)
|
inline input_stream_adapter input_adapter(std::istream& stream)
|
||||||
{
|
{
|
||||||
|
if (stream.rdbuf() == nullptr)
|
||||||
|
{
|
||||||
|
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||||
|
}
|
||||||
return input_stream_adapter(stream);
|
return input_stream_adapter(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline input_stream_adapter input_adapter(std::istream&& stream)
|
inline input_stream_adapter input_adapter(std::istream&& stream)
|
||||||
{
|
{
|
||||||
return input_stream_adapter(stream);
|
return input_adapter(stream);
|
||||||
}
|
}
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
@@ -845,16 +833,28 @@ template<typename T, std::size_t N>
|
|||||||
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
{
|
{
|
||||||
#if JSON_STRICT_NUL_HANDLING
|
#if JSON_STRICT_NUL_HANDLING
|
||||||
// A `char` array from string-literal initialization (e.g. json::parse("123"))
|
// A text-literal array from string-literal initialization (e.g.
|
||||||
// carries a trailing '\0' contributed by the compiler, not by the source
|
// json::parse("123") or json::parse(L"123")) carries a trailing '\0'
|
||||||
// text; drop exactly that one byte so it is not mistaken for real trailing
|
// contributed by the compiler, not by the source text; drop exactly that
|
||||||
// data. Every other element type (unsigned char, std::uint8_t, ...) keeps
|
// one byte so it is not mistaken for real trailing data. This covers all
|
||||||
// the full extent unconditionally, since a trailing zero byte there is
|
// character types that string literals can use: char, wchar_t, char16_t,
|
||||||
// genuine data (e.g. CBOR/MessagePack). This intentionally does not
|
// char32_t, and (C++20) char8_t. Every other element type (unsigned char,
|
||||||
// strlen()-scan the array (as the pointer overload above does for a
|
// std::uint8_t, ...) keeps the full extent unconditionally, since a
|
||||||
// null-delimited string): for a `char` array that is not NUL-terminated
|
// trailing zero byte there is genuine data (e.g. CBOR/MessagePack). This
|
||||||
// within its bounds, that would read past the end of the array.
|
// intentionally does not strlen()-scan the array (as the pointer overload
|
||||||
if (std::is_same<typename std::remove_cv<T>::type, char>::value && N > 0 && array[N - 1] == 0)
|
// above does for a null-delimited string): for an array that is not
|
||||||
|
// NUL-terminated within its bounds, that would read past the end of the
|
||||||
|
// array.
|
||||||
|
using char_t = typename std::remove_cv<T>::type;
|
||||||
|
constexpr bool is_text_literal_type = std::is_same<char_t, char>::value
|
||||||
|
|| std::is_same<char_t, wchar_t>::value
|
||||||
|
|| std::is_same<char_t, char16_t>::value
|
||||||
|
|| std::is_same<char_t, char32_t>::value
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
|| std::is_same<char_t, char8_t>::value
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
if (is_text_literal_type && N > 0 && array[N - 1] == 0)
|
||||||
{
|
{
|
||||||
return input_adapter(array, array + N - 1);
|
return input_adapter(array, array + N - 1);
|
||||||
}
|
}
|
||||||
@@ -862,9 +862,9 @@ auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) /
|
|||||||
return input_adapter(array, array + N);
|
return input_adapter(array, array + N);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This class only handles inputs of input_buffer_adapter type.
|
// This class only handles inputs that construct a contiguous_bytes_input_adapter
|
||||||
// It's required so that expressions like {ptr, len} can be implicitly cast
|
// (e.g. span_input_adapter). It's required so that expressions like {ptr, len}
|
||||||
// to the correct adapter.
|
// can be implicitly cast to the correct adapter.
|
||||||
class span_input_adapter
|
class span_input_adapter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <algorithm> // find_if, min
|
#include <algorithm> // find_if, min
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <limits> // numeric_limits
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <type_traits> // enable_if_t
|
#include <type_traits> // enable_if_t
|
||||||
#include <utility> // move, pair
|
#include <utility> // move, pair
|
||||||
@@ -175,6 +176,88 @@ template<typename ArrayType>
|
|||||||
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
|
/*!
|
||||||
|
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
||||||
|
|
||||||
|
Shared by json_sax_dom_parser and json_sax_dom_callback_parser. basic_json
|
||||||
|
befriends this struct, as the position members are private.
|
||||||
|
*/
|
||||||
|
struct diagnostic_positions
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
@param[in,out] v the value that was just parsed
|
||||||
|
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||||
|
*/
|
||||||
|
template<typename BasicJsonType, typename LexerType>
|
||||||
|
static void set_from_lexer(BasicJsonType& v, LexerType* lexer)
|
||||||
|
{
|
||||||
|
if (lexer)
|
||||||
|
{
|
||||||
|
// Lexer has read past the current field value, so set the end position to the current position.
|
||||||
|
// The start position will be set below based on the length of the string representation
|
||||||
|
// of the value.
|
||||||
|
v.end_position = lexer->get_position();
|
||||||
|
|
||||||
|
switch (v.type())
|
||||||
|
{
|
||||||
|
case value_t::boolean:
|
||||||
|
{
|
||||||
|
// 4 and 5 are the string length of "true" and "false"
|
||||||
|
v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::null:
|
||||||
|
{
|
||||||
|
// 4 is the string length of "null"
|
||||||
|
v.start_position = v.end_position - 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::string:
|
||||||
|
{
|
||||||
|
// escape sequences make the token longer than the value it
|
||||||
|
// parses to, so the start position cannot be derived from
|
||||||
|
// the value; use the offset the lexer recorded instead
|
||||||
|
v.start_position = lexer->get_token_start_position();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::discarded:
|
||||||
|
{
|
||||||
|
// an object or array the callback of
|
||||||
|
// json_sax_dom_callback_parser rejected has no position
|
||||||
|
v.end_position = std::string::npos;
|
||||||
|
v.start_position = v.end_position;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::binary:
|
||||||
|
case value_t::number_integer:
|
||||||
|
case value_t::number_unsigned:
|
||||||
|
case value_t::number_float:
|
||||||
|
{
|
||||||
|
v.start_position = v.end_position - lexer->get_string().size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
// object and array are handled in start_object() and start_array() handlers
|
||||||
|
// skip setting the values here.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: // LCOV_EXCL_LINE
|
||||||
|
// Handle all possible types discretely, default handler should never be reached.
|
||||||
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief SAX implementation to create a JSON value from SAX events
|
@brief SAX implementation to create a JSON value from SAX events
|
||||||
|
|
||||||
@@ -376,76 +459,6 @@ class json_sax_dom_parser
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
|
||||||
void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
|
|
||||||
{
|
|
||||||
if (m_lexer_ref)
|
|
||||||
{
|
|
||||||
// Lexer has read past the current field value, so set the end position to the current position.
|
|
||||||
// The start position will be set below based on the length of the string representation
|
|
||||||
// of the value.
|
|
||||||
v.end_position = m_lexer_ref->get_position();
|
|
||||||
|
|
||||||
switch (v.type())
|
|
||||||
{
|
|
||||||
case value_t::boolean:
|
|
||||||
{
|
|
||||||
// 4 and 5 are the string length of "true" and "false"
|
|
||||||
v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
{
|
|
||||||
// 4 is the string length of "null"
|
|
||||||
v.start_position = v.end_position - 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::string:
|
|
||||||
{
|
|
||||||
// escape sequences make the token longer than the value it
|
|
||||||
// parses to, so the start position cannot be derived from
|
|
||||||
// the value; use the offset the lexer recorded instead
|
|
||||||
v.start_position = m_lexer_ref->get_token_start_position();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As we handle the start and end positions for values created during parsing,
|
|
||||||
// we do not expect the following value type to be called. Regardless, set the positions
|
|
||||||
// in case this is created manually or through a different constructor. Exclude from lcov
|
|
||||||
// since the exact condition of this switch is esoteric.
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
case value_t::discarded:
|
|
||||||
{
|
|
||||||
v.end_position = std::string::npos;
|
|
||||||
v.start_position = v.end_position;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
{
|
|
||||||
v.start_position = v.end_position - m_lexer_ref->get_string().size();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case value_t::object:
|
|
||||||
case value_t::array:
|
|
||||||
{
|
|
||||||
// object and array are handled in start_object() and start_array() handlers
|
|
||||||
// skip setting the values here.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: // LCOV_EXCL_LINE
|
|
||||||
// Handle all possible types discretely, default handler should never be reached.
|
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@invariant If the ref stack is empty, then the passed value will be the new
|
@invariant If the ref stack is empty, then the passed value will be the new
|
||||||
root.
|
root.
|
||||||
@@ -461,7 +474,7 @@ class json_sax_dom_parser
|
|||||||
root = BasicJsonType(std::forward<Value>(v));
|
root = BasicJsonType(std::forward<Value>(v));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
handle_diagnostic_positions_for_json_value(root);
|
diagnostic_positions::set_from_lexer(root, m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return &root;
|
return &root;
|
||||||
@@ -474,7 +487,7 @@ class json_sax_dom_parser
|
|||||||
ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
|
ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
|
diagnostic_positions::set_from_lexer(ref_stack.back()->m_data.m_value.array->back(), m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return &(ref_stack.back()->m_data.m_value.array->back());
|
return &(ref_stack.back()->m_data.m_value.array->back());
|
||||||
@@ -485,7 +498,7 @@ class json_sax_dom_parser
|
|||||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
handle_diagnostic_positions_for_json_value(*object_element);
|
diagnostic_positions::set_from_lexer(*object_element, m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return object_element;
|
return object_element;
|
||||||
@@ -582,8 +595,8 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
bool start_object(std::size_t len)
|
bool start_object(std::size_t len)
|
||||||
{
|
{
|
||||||
// check callback for object start
|
// check callback for object start; not called inside a discarded container
|
||||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
|
const bool keep = keep_stack.back() && callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
|
||||||
keep_stack.push_back(keep);
|
keep_stack.push_back(keep);
|
||||||
|
|
||||||
// the key this object will be stored under, read before handle_value()
|
// the key this object will be stored under, read before handle_value()
|
||||||
@@ -619,6 +632,18 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
bool key(string_t& val)
|
bool key(string_t& val)
|
||||||
{
|
{
|
||||||
|
if (!keep_stack.back() || !ref_stack.back())
|
||||||
|
{
|
||||||
|
// the object is not stored: the value of this key is dropped in
|
||||||
|
// handle_value() without touching the key stacks
|
||||||
|
if (keep_stack.back())
|
||||||
|
{
|
||||||
|
BasicJsonType k = BasicJsonType(val);
|
||||||
|
static_cast<void>(callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BasicJsonType k = BasicJsonType(val);
|
BasicJsonType k = BasicJsonType(val);
|
||||||
|
|
||||||
// check callback for the key
|
// check callback for the key
|
||||||
@@ -662,7 +687,7 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
// Set start/end positions for discarded object.
|
// Set start/end positions for discarded object.
|
||||||
handle_diagnostic_positions_for_json_value(*ref_stack.back());
|
diagnostic_positions::set_from_lexer(*ref_stack.back(), m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -704,7 +729,7 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
bool start_array(std::size_t len)
|
bool start_array(std::size_t len)
|
||||||
{
|
{
|
||||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
|
const bool keep = keep_stack.back() && callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
|
||||||
keep_stack.push_back(keep);
|
keep_stack.push_back(keep);
|
||||||
|
|
||||||
// see start_object()
|
// see start_object()
|
||||||
@@ -778,7 +803,7 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
// Set start/end positions for discarded array.
|
// Set start/end positions for discarded array.
|
||||||
handle_diagnostic_positions_for_json_value(*ref_stack.back());
|
diagnostic_positions::set_from_lexer(*ref_stack.back(), m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -831,72 +856,6 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
|
||||||
void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
|
|
||||||
{
|
|
||||||
if (m_lexer_ref)
|
|
||||||
{
|
|
||||||
// Lexer has read past the current field value, so set the end position to the current position.
|
|
||||||
// The start position will be set below based on the length of the string representation
|
|
||||||
// of the value.
|
|
||||||
v.end_position = m_lexer_ref->get_position();
|
|
||||||
|
|
||||||
switch (v.type())
|
|
||||||
{
|
|
||||||
case value_t::boolean:
|
|
||||||
{
|
|
||||||
// 4 and 5 are the string length of "true" and "false"
|
|
||||||
v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
|
||||||
{
|
|
||||||
// 4 is the string length of "null"
|
|
||||||
v.start_position = v.end_position - 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::string:
|
|
||||||
{
|
|
||||||
// escape sequences make the token longer than the value it
|
|
||||||
// parses to, so the start position cannot be derived from
|
|
||||||
// the value; use the offset the lexer recorded instead
|
|
||||||
v.start_position = m_lexer_ref->get_token_start_position();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::discarded:
|
|
||||||
{
|
|
||||||
v.end_position = std::string::npos;
|
|
||||||
v.start_position = v.end_position;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::binary:
|
|
||||||
case value_t::number_integer:
|
|
||||||
case value_t::number_unsigned:
|
|
||||||
case value_t::number_float:
|
|
||||||
{
|
|
||||||
v.start_position = v.end_position - m_lexer_ref->get_string().size();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::object:
|
|
||||||
case value_t::array:
|
|
||||||
{
|
|
||||||
// object and array are handled in start_object() and start_array() handlers
|
|
||||||
// skip setting the values here.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: // LCOV_EXCL_LINE
|
|
||||||
// Handle all possible types discretely, default handler should never be reached.
|
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// if there is a pending duplicate-key stash entry for this exact slot,
|
/// if there is a pending duplicate-key stash entry for this exact slot,
|
||||||
/// remove it from the stash; if restore_value is true, the stashed
|
/// remove it from the stash; if restore_value is true, the stashed
|
||||||
/// previous value is moved back into the slot first (use this when the
|
/// previous value is moved back into the slot first (use this when the
|
||||||
@@ -1018,7 +977,7 @@ class json_sax_dom_callback_parser
|
|||||||
auto value = BasicJsonType(std::forward<Value>(v));
|
auto value = BasicJsonType(std::forward<Value>(v));
|
||||||
|
|
||||||
#if JSON_DIAGNOSTIC_POSITIONS
|
#if JSON_DIAGNOSTIC_POSITIONS
|
||||||
handle_diagnostic_positions_for_json_value(value);
|
diagnostic_positions::set_from_lexer(value, m_lexer_ref);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check callback
|
// check callback
|
||||||
|
|||||||
@@ -9,10 +9,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <clocale> // localeconv
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <string> // char_traits, string
|
#include <string> // char_traits, string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
@@ -24,6 +23,7 @@
|
|||||||
#include <nlohmann/detail/input/string_scan.hpp>
|
#include <nlohmann/detail/input/string_scan.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -206,7 +206,6 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false, bool discard_number_values_ = false) noexcept
|
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false, bool discard_number_values_ = false) noexcept
|
||||||
: ia(std::move(adapter))
|
: ia(std::move(adapter))
|
||||||
, ignore_comments(ignore_comments_)
|
, ignore_comments(ignore_comments_)
|
||||||
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
|
|
||||||
, discard_number_values(discard_number_values_)
|
, discard_number_values(discard_number_values_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -218,27 +217,14 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
~lexer() = default;
|
~lexer() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/////////////////////
|
|
||||||
// locales
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
/// return the locale-dependent decimal point
|
|
||||||
JSON_HEDLEY_PURE
|
|
||||||
static char get_decimal_point() noexcept
|
|
||||||
{
|
|
||||||
const auto* loc = localeconv();
|
|
||||||
JSON_ASSERT(loc != nullptr);
|
|
||||||
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// scan functions
|
// scan functions
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get codepoint from 4 hex characters following `\u`
|
@brief get codepoint from 4 hex characters following `\\u`
|
||||||
|
|
||||||
For input "\u c1 c2 c3 c4" the codepoint is:
|
For input "\\u c1 c2 c3 c4" the codepoint is:
|
||||||
(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
|
(c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
|
||||||
= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
|
= (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
|
||||||
|
|
||||||
@@ -502,32 +488,10 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
|
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
|
||||||
|
|
||||||
// translate codepoint into bytes
|
// translate codepoint into bytes
|
||||||
if (codepoint < 0x80)
|
encode_utf8(static_cast<std::uint32_t>(codepoint), [this](std::uint32_t byte)
|
||||||
{
|
{
|
||||||
// 1-byte characters: 0xxxxxxx (ASCII)
|
add(static_cast<char_int_type>(byte));
|
||||||
add(static_cast<char_int_type>(codepoint));
|
});
|
||||||
}
|
|
||||||
else if (codepoint <= 0x7FF)
|
|
||||||
{
|
|
||||||
// 2-byte characters: 110xxxxx 10xxxxxx
|
|
||||||
add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
|
||||||
}
|
|
||||||
else if (codepoint <= 0xFFFF)
|
|
||||||
{
|
|
||||||
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
|
||||||
add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
||||||
add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
|
||||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1038,24 +1002,6 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
|
||||||
static void strtof(float& f, const char* str, char** endptr) noexcept
|
|
||||||
{
|
|
||||||
f = std::strtof(str, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
|
||||||
static void strtof(double& f, const char* str, char** endptr) noexcept
|
|
||||||
{
|
|
||||||
f = std::strtod(str, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
|
||||||
static void strtof(long double& f, const char* str, char** endptr) noexcept
|
|
||||||
{
|
|
||||||
f = std::strtold(str, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief scan a number literal
|
@brief scan a number literal
|
||||||
|
|
||||||
@@ -1092,9 +1038,12 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
token_type::value_float if number could be successfully scanned,
|
token_type::value_float if number could be successfully scanned,
|
||||||
token_type::parse_error otherwise
|
token_type::parse_error otherwise
|
||||||
|
|
||||||
@note The scanner is independent of the current locale. Internally, the
|
@note The scanner is independent of the current locale: token_buffer
|
||||||
locale's decimal point is used instead of `.` to work with the
|
always holds `.`. The conversion of float and double does not use
|
||||||
locale-dependent converters.
|
the locale either. Only the std::strtold fallback of
|
||||||
|
convert_number() for long double formats other than binary64
|
||||||
|
depends on it, and it looks up the decimal point right before
|
||||||
|
converting (see detail::convert_float_locale_aware()).
|
||||||
*/
|
*/
|
||||||
token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
|
token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
|
||||||
{
|
{
|
||||||
@@ -1107,7 +1056,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
|
|
||||||
// offset just past the last mantissa byte in token_buffer (i.e. the
|
// offset just past the last mantissa byte in token_buffer (i.e. the
|
||||||
// index of 'e'/'E', or the whole token when there is no exponent).
|
// index of 'e'/'E', or the whole token when there is no exponent).
|
||||||
// convert_number() uses it to count significant digits; npos means
|
// convert_number() uses it to split the token; npos means
|
||||||
// "not seen an exponent yet" and is resolved at scan_number_done
|
// "not seen an exponent yet" and is resolved at scan_number_done
|
||||||
std::size_t mantissa_end = std::string::npos;
|
std::size_t mantissa_end = std::string::npos;
|
||||||
|
|
||||||
@@ -1183,7 +1132,7 @@ scan_number_zero:
|
|||||||
{
|
{
|
||||||
case '.':
|
case '.':
|
||||||
{
|
{
|
||||||
add(decimal_point_char);
|
add(current);
|
||||||
decimal_point_position = token_buffer.size() - 1;
|
decimal_point_position = token_buffer.size() - 1;
|
||||||
goto scan_number_decimal1;
|
goto scan_number_decimal1;
|
||||||
}
|
}
|
||||||
@@ -1220,7 +1169,7 @@ scan_number_any1:
|
|||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
{
|
{
|
||||||
add(decimal_point_char);
|
add(current);
|
||||||
decimal_point_position = token_buffer.size() - 1;
|
decimal_point_position = token_buffer.size() - 1;
|
||||||
goto scan_number_decimal1;
|
goto scan_number_decimal1;
|
||||||
}
|
}
|
||||||
@@ -1425,115 +1374,47 @@ scan_number_done:
|
|||||||
return token_type::uninitialized;
|
return token_type::uninitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief check whether Clinger's fast path can still succeed for this token
|
|
||||||
|
|
||||||
parse_float_fast() needs a significand below 2^53. A mantissa with 17 or
|
|
||||||
more significant digits is at least 10^16 and therefore always exceeds it,
|
|
||||||
so calling the fast path would walk the token one extra time only to
|
|
||||||
decline before strtod has to run anyway.
|
|
||||||
|
|
||||||
Significant digits are the mantissa's digits from the first nonzero one on;
|
|
||||||
the sign, the decimal point, leading zeros, and the exponent do not count.
|
|
||||||
The answer is derived from indices - the digits are not scanned again - so
|
|
||||||
this stays off the hot path of the number scanners.
|
|
||||||
|
|
||||||
@param[in] mantissa_end offset just past the last mantissa byte in
|
|
||||||
token_buffer
|
|
||||||
@return false if parse_float_fast() is guaranteed to decline
|
|
||||||
*/
|
|
||||||
bool mantissa_fits_clinger(std::size_t mantissa_end) const
|
|
||||||
{
|
|
||||||
// 10^16 already exceeds 2^53, so 17 digits can never fit
|
|
||||||
constexpr std::size_t limit = 17;
|
|
||||||
|
|
||||||
const std::size_t neg = (!token_buffer.empty() && token_buffer[0] == '-') ? 1u : 0u;
|
|
||||||
const std::size_t has_dot = (decimal_point_position != std::string::npos) ? 1u : 0u;
|
|
||||||
// the JSON grammar restricts the integer part to "0" or [1-9][0-9]*, so
|
|
||||||
// a leading zero can only be a lone "0", which is not significant
|
|
||||||
const std::size_t lead_zero = (token_buffer[neg] == '0') ? 1u : 0u;
|
|
||||||
JSON_ASSERT(mantissa_end >= neg + has_dot + lead_zero);
|
|
||||||
std::size_t digits = mantissa_end - neg - has_dot - lead_zero;
|
|
||||||
|
|
||||||
if (JSON_HEDLEY_LIKELY(digits < limit))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only a number below 1 can carry further insignificant zeros, and only
|
|
||||||
// while the count stays at the limit does removing them change the
|
|
||||||
// answer - so this loop is skipped for all but a few tokens. Note
|
|
||||||
// token_buffer holds the locale's decimal point, so the fraction is
|
|
||||||
// located through decimal_point_position rather than by searching '.'.
|
|
||||||
if (lead_zero != 0)
|
|
||||||
{
|
|
||||||
JSON_ASSERT(has_dot != 0); // an integer "0" cannot reach the limit
|
|
||||||
for (std::size_t i = decimal_point_position + 1;
|
|
||||||
digits >= limit && i < mantissa_end && token_buffer[i] == '0'; ++i)
|
|
||||||
{
|
|
||||||
--digits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return digits < limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief convert the number text in token_buffer to its value and token type
|
@brief convert the number text in token_buffer to its value and token type
|
||||||
|
|
||||||
The digit sequence in token_buffer has already been validated (by the
|
The digit sequence in token_buffer has already been validated (by the
|
||||||
scan_number() state machine or by the contiguous fast path) and holds the
|
scan_number() state machine or by the contiguous fast path) and holds '.'
|
||||||
locale decimal point in place of '.'. Integers are parsed first and fall
|
as decimal point, independent of the locale. Integers are parsed first and fall
|
||||||
back to floating point on overflow. This is shared so both scanners produce
|
back to floating point on overflow. This is shared so both scanners produce
|
||||||
identical results.
|
identical results.
|
||||||
|
|
||||||
@param[in] mantissa_end offset just past the last mantissa byte in
|
@param[in] mantissa_end offset just past the last mantissa byte in
|
||||||
token_buffer (the index of 'e'/'E', or
|
token_buffer (the index of 'e'/'E', or
|
||||||
token_buffer.size() when there is no exponent);
|
token_buffer.size() when there is no exponent);
|
||||||
used to skip Clinger's fast path when it cannot
|
with decimal_point_position, it locates the parts
|
||||||
possibly succeed - see mantissa_fits_clinger()
|
of a float token without scanning it again
|
||||||
*/
|
*/
|
||||||
token_type convert_number(token_type number_type, std::size_t mantissa_end)
|
token_type convert_number(token_type number_type, std::size_t mantissa_end)
|
||||||
{
|
{
|
||||||
// If the caller does not need the converted value (only whether the
|
// accept() only needs to know whether the input is valid, so it sets
|
||||||
// input is syntactically valid; see json_sax_acceptor/accept()), an
|
// discard_number_values (see json.hpp), and an integer token whose
|
||||||
// unsigned/integer token can be reported without calling
|
// digit count shows that it fits is reported without calling
|
||||||
// strtoull()/strtoll() at all, *provided* we can already tell from
|
// convert_integer(). A number with up to 18 digits always fits into
|
||||||
// the digit count alone that the conversion cannot overflow 64 bits.
|
// both std::uint64_t and std::int64_t (18 nines is about 1e18, below
|
||||||
// Such tokens are always finite and are accepted unconditionally by
|
// INT64_MAX, which is about 9.2e18). Longer tokens take the exact path
|
||||||
// the parser regardless of their actual value (parser::sax_parse_internal()
|
// below, including the fallback to floating point when the value does
|
||||||
// never checks finiteness for value_unsigned/value_integer), so the
|
// not fit.
|
||||||
// classification below is all that is needed.
|
|
||||||
//
|
//
|
||||||
// A decimal number with up to 18 digits is always representable in
|
// With a narrower number_unsigned_t/number_integer_t (e.g.
|
||||||
// both std::uint64_t and std::int64_t (18 nines is ~1e18, well below
|
// std::uint32_t), the exact path would reclassify some of these tokens
|
||||||
// both UINT64_MAX ~1.8e19 and INT64_MAX ~9.2e18), so strtoull()/strtoll()
|
// as (finite) floats, while this check reports integers. That does not
|
||||||
// could not have set errno to ERANGE for it. Numbers with more digits
|
// change the result of accept(): it always parses through
|
||||||
// (rare in practice) fall through to the exact code below, unchanged,
|
// json_sax_acceptor, whose number callbacks discard their argument and
|
||||||
// so their handling -- including reclassification to value_float when
|
// return true, and the parser rejects neither integers nor finite
|
||||||
// the value overflows 64 bits, and rejection when it is not even
|
// floats. value_unsigned/value_integer are left unset here, so a caller
|
||||||
// finite as a double -- is bit-for-bit identical to before this
|
// that reads the converted value must not set discard_number_values.
|
||||||
// optimization.
|
|
||||||
//
|
//
|
||||||
// Note this reasons about std::uint64_t/std::int64_t, not about
|
// On contiguous input, scan_number_bulk_contiguous() converts integer
|
||||||
// number_unsigned_t/number_integer_t (BasicJsonType's own, possibly
|
// tokens itself and does not pass them to this function, unless
|
||||||
// narrower, template parameters -- e.g. std::uint32_t). That is fine
|
// JSON_DIAGNOSTIC_POSITIONS is enabled. This check is therefore only
|
||||||
// *only* because discard_number_values is exclusively set by
|
// reached for input without bulk access (e.g. streams), with
|
||||||
// accept() (see json.hpp), and accept() always parses through the
|
// JSON_DIAGNOSTIC_POSITIONS, or when scan_number_bulk_contiguous()
|
||||||
// library's own json_sax_acceptor -- never a user-supplied SAX
|
// falls back to scan_number().
|
||||||
// consumer -- whose number_unsigned()/number_integer()/number_float()
|
|
||||||
// callbacks unconditionally discard their argument and return true.
|
|
||||||
// So for every caller that can reach this branch, neither the token
|
|
||||||
// classification below nor the eventual (possibly narrowed, and on
|
|
||||||
// this fast path left stale/unset) value_unsigned/value_integer is
|
|
||||||
// ever consulted -- an unsigned/integer token is accepted outright,
|
|
||||||
// and even a >18-digit token that this fast path deliberately falls
|
|
||||||
// through for is, once reclassified to value_float, still finite
|
|
||||||
// (and thus accepted) for any digit count that fits in number_unsigned_t
|
|
||||||
// or number_integer_t regardless of that type's width. If this
|
|
||||||
// function is ever taught to run with discard_number_values true for
|
|
||||||
// a caller that *does* read the converted value, this reasoning (and
|
|
||||||
// the fast path below) would need to be revisited.
|
|
||||||
if (discard_number_values)
|
if (discard_number_values)
|
||||||
{
|
{
|
||||||
constexpr std::size_t safe_digit_count = 18;
|
constexpr std::size_t safe_digit_count = 18;
|
||||||
@@ -1560,29 +1441,17 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this code is reached if we parse a floating-point number or if an
|
// this code is reached if we parse a floating-point number or if an
|
||||||
// integer conversion above overflowed. Prefer std::from_chars
|
// integer conversion above overflowed. float and double (and long
|
||||||
// (Eisel-Lemire, locale-independent, correctly rounded) when available;
|
// double where it is binary64) are converted by the library itself,
|
||||||
// otherwise the exact Clinger fast path (double only); otherwise the
|
// correctly rounded and independent of the locale; other long double
|
||||||
// locale-aware strtof/strtod.
|
// formats use std::from_chars when available, otherwise the
|
||||||
if (parse_float_from_chars(num_begin, num_end, value_float))
|
// locale-aware strtold.
|
||||||
{
|
if (convert_float_fast(num_begin, num_end, decimal_point_position, mantissa_end, value_float))
|
||||||
return token_type::value_float;
|
|
||||||
}
|
|
||||||
// Skipping a fast path that cannot succeed is lossless and saves a full
|
|
||||||
// extra pass over the token's bytes, which otherwise shows up on
|
|
||||||
// high-precision inputs such as canada.json
|
|
||||||
if (mantissa_fits_clinger(mantissa_end)
|
|
||||||
&& parse_float_fast(num_begin, num_end, decimal_point_char, value_float))
|
|
||||||
{
|
{
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
convert_float_locale_aware(token_buffer, decimal_point_position, value_float);
|
||||||
strtof(value_float, token_buffer.data(), &endptr);
|
|
||||||
|
|
||||||
// we checked the number format before
|
|
||||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
|
||||||
|
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1591,7 +1460,7 @@ scan_number_done:
|
|||||||
|
|
||||||
Parses the whole number token straight from the input buffer, avoiding the
|
Parses the whole number token straight from the input buffer, avoiding the
|
||||||
per-character get()/add() of scan_number(). On success it fills token_buffer
|
per-character get()/add() of scan_number(). On success it fills token_buffer
|
||||||
(with the locale decimal point substituted, as scan_number() does) and
|
(as scan_number() does) and
|
||||||
returns the token type. On anything it does not fully recognize as a
|
returns the token type. On anything it does not fully recognize as a
|
||||||
well-formed number it makes no state change and returns
|
well-formed number it makes no state change and returns
|
||||||
token_type::uninitialized, so the caller falls back to scan_number(), which
|
token_type::uninitialized, so the caller falls back to scan_number(), which
|
||||||
@@ -1707,16 +1576,11 @@ scan_number_done:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// materialize the token exactly as scan_number() would, substituting the
|
// materialize the token exactly as scan_number() would. reset() already
|
||||||
// locale decimal point so convert_number()'s strtof fallback stays valid.
|
// cleared token_buffer, so append() fills it (assign() is avoided
|
||||||
// reset() already cleared token_buffer, so append() fills it (assign() is
|
// because custom string_t types need not provide it)
|
||||||
// avoided because custom string_t types need not provide it)
|
|
||||||
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
token_buffer.append(reinterpret_cast<const typename string_t::value_type*>(data), len);
|
||||||
if (dot_index != std::string::npos)
|
|
||||||
{
|
|
||||||
token_buffer[dot_index] = static_cast<typename string_t::value_type>(decimal_point_char);
|
|
||||||
decimal_point_position = dot_index;
|
decimal_point_position = dot_index;
|
||||||
}
|
|
||||||
|
|
||||||
ia.bulk_skip(len - 1);
|
ia.bulk_skip(len - 1);
|
||||||
position.chars_read_total += (len - 1);
|
position.chars_read_total += (len - 1);
|
||||||
@@ -1980,14 +1844,10 @@ scan_number_done:
|
|||||||
return value_float;
|
return value_float;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return current string value (implicitly resets the token; useful only once)
|
/// return current string value
|
||||||
string_t& get_string()
|
string_t& get_string()
|
||||||
{
|
{
|
||||||
// translate decimal points from locale back to '.' (#4084)
|
// a number token holds '.' regardless of the locale (#4084)
|
||||||
if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
|
|
||||||
{
|
|
||||||
token_buffer[decimal_point_position] = '.';
|
|
||||||
}
|
|
||||||
return token_buffer;
|
return token_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2283,16 +2143,14 @@ scan_number_done:
|
|||||||
number_unsigned_t value_unsigned = 0;
|
number_unsigned_t value_unsigned = 0;
|
||||||
number_float_t value_float = 0;
|
number_float_t value_float = 0;
|
||||||
|
|
||||||
/// the decimal point
|
/// the position of the decimal point in token_buffer
|
||||||
const char_int_type decimal_point_char = '.';
|
|
||||||
/// the position of the decimal point in the input
|
|
||||||
std::size_t decimal_point_position = std::string::npos;
|
std::size_t decimal_point_position = std::string::npos;
|
||||||
|
|
||||||
/// whether the caller (e.g. accept()/json_sax_acceptor) only needs the
|
/// whether the caller only needs the token types and never looks at the
|
||||||
/// token classification and never looks at the converted numeric value;
|
/// converted numeric values; set only by accept(), which parses through
|
||||||
/// when set, scan_number() may skip strtoull()/strtoll() for
|
/// json_sax_acceptor. When set, convert_number() skips converting integer
|
||||||
/// value_unsigned/value_integer tokens whose digit count guarantees they
|
/// tokens whose digit count guarantees that they fit into 64 bits (see
|
||||||
/// fit into 64 bits (see scan_number())
|
/// there)
|
||||||
const bool discard_number_values = false;
|
const bool discard_number_values = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,8 @@ using parser_callback_t =
|
|||||||
/*!
|
/*!
|
||||||
@brief syntax analysis
|
@brief syntax analysis
|
||||||
|
|
||||||
This class implements a recursive descent parser.
|
This class implements an iterative parser that keeps the open containers on
|
||||||
|
an explicit stack and reports what it reads as SAX events.
|
||||||
*/
|
*/
|
||||||
template<typename BasicJsonType, typename InputAdapterType>
|
template<typename BasicJsonType, typename InputAdapterType>
|
||||||
class parser
|
class parser
|
||||||
@@ -98,28 +99,9 @@ class parser
|
|||||||
if (callback)
|
if (callback)
|
||||||
{
|
{
|
||||||
json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
|
json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
|
||||||
sax_parse_internal(&sdp);
|
|
||||||
|
|
||||||
if (strict)
|
|
||||||
{
|
|
||||||
// in strict mode, input must be completely read
|
|
||||||
if (get_token() != token_type::end_of_input)
|
|
||||||
{
|
|
||||||
sdp.parse_error(m_lexer.get_position(),
|
|
||||||
m_lexer.get_token_string(),
|
|
||||||
parse_error::create(101, m_lexer.get_position(),
|
|
||||||
exception_message(token_type::end_of_input, "value"), nullptr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the caller keeps using the input: position it right after
|
|
||||||
// the value by leaving the character that terminated it
|
|
||||||
m_lexer.release_lookahead();
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case of an error, return a discarded value
|
// in case of an error, return a discarded value
|
||||||
if (sdp.is_errored())
|
if (!parse_dom(sdp, strict))
|
||||||
{
|
{
|
||||||
result = value_t::discarded;
|
result = value_t::discarded;
|
||||||
return;
|
return;
|
||||||
@@ -135,26 +117,9 @@ class parser
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
|
json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
|
||||||
sax_parse_internal(&sdp);
|
|
||||||
|
|
||||||
if (strict)
|
|
||||||
{
|
|
||||||
// in strict mode, input must be completely read
|
|
||||||
if (get_token() != token_type::end_of_input)
|
|
||||||
{
|
|
||||||
sdp.parse_error(m_lexer.get_position(),
|
|
||||||
m_lexer.get_token_string(),
|
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// see above
|
|
||||||
m_lexer.release_lookahead();
|
|
||||||
}
|
|
||||||
|
|
||||||
// in case of an error, return a discarded value
|
// in case of an error, return a discarded value
|
||||||
if (sdp.is_errored())
|
if (!parse_dom(sdp, strict))
|
||||||
{
|
{
|
||||||
result = value_t::discarded;
|
result = value_t::discarded;
|
||||||
return;
|
return;
|
||||||
@@ -207,6 +172,46 @@ class parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*!
|
||||||
|
@brief run a DOM SAX parser to completion and position the lexer
|
||||||
|
|
||||||
|
Shared by both branches of @ref parse(): builds no SAX parser itself,
|
||||||
|
but drives an already-constructed @a json_sax_dom_parser or
|
||||||
|
@ref json_sax_dom_callback_parser through @ref sax_parse_internal(),
|
||||||
|
then applies the strict-EOF check (reporting parse_error.101 through
|
||||||
|
@a sdp on failure) or, in non-strict mode, releases the lookahead so
|
||||||
|
the caller can keep reading the input right after the parsed value.
|
||||||
|
|
||||||
|
@param[in,out] sdp the DOM SAX parser to run
|
||||||
|
@param[in] strict whether to expect the last token to be EOF
|
||||||
|
@return whether @a sdp did not report an error
|
||||||
|
*/
|
||||||
|
template<typename DomSax>
|
||||||
|
bool parse_dom(DomSax& sdp, const bool strict)
|
||||||
|
{
|
||||||
|
sax_parse_internal(&sdp);
|
||||||
|
|
||||||
|
if (strict)
|
||||||
|
{
|
||||||
|
// in strict mode, input must be completely read
|
||||||
|
if (get_token() != token_type::end_of_input)
|
||||||
|
{
|
||||||
|
sdp.parse_error(m_lexer.get_position(),
|
||||||
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(),
|
||||||
|
exception_message(token_type::end_of_input, "value"), nullptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the caller keeps using the input: position it right after
|
||||||
|
// the value by leaving the character that terminated it
|
||||||
|
m_lexer.release_lookahead();
|
||||||
|
}
|
||||||
|
|
||||||
|
return !sdp.is_errored();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename SAX>
|
template<typename SAX>
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
bool sax_parse_internal(SAX* sax)
|
bool sax_parse_internal(SAX* sax)
|
||||||
@@ -439,8 +444,9 @@ class parser
|
|||||||
|
|
||||||
// We are done with this array. Before we can parse a
|
// We are done with this array. Before we can parse a
|
||||||
// new value, we need to evaluate the new state first.
|
// new value, we need to evaluate the new state first.
|
||||||
// By setting skip_to_state_evaluation to false, we
|
// By setting skip_to_state_evaluation to true, the next
|
||||||
// are effectively jumping to the beginning of this if.
|
// iteration skips parsing a value and evaluates the
|
||||||
|
// enclosing state directly.
|
||||||
JSON_ASSERT(!states.empty());
|
JSON_ASSERT(!states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_state_evaluation = true;
|
skip_to_state_evaluation = true;
|
||||||
@@ -500,8 +506,9 @@ class parser
|
|||||||
|
|
||||||
// We are done with this object. Before we can parse a
|
// We are done with this object. Before we can parse a
|
||||||
// new value, we need to evaluate the new state first.
|
// new value, we need to evaluate the new state first.
|
||||||
// By setting skip_to_state_evaluation to false, we
|
// By setting skip_to_state_evaluation to true, the next
|
||||||
// are effectively jumping to the beginning of this if.
|
// iteration skips parsing a value and evaluates the
|
||||||
|
// enclosing state directly.
|
||||||
JSON_ASSERT(!states.empty());
|
JSON_ASSERT(!states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_state_evaluation = true;
|
skip_to_state_evaluation = true;
|
||||||
|
|||||||
@@ -0,0 +1,371 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2021 The fast_float authors <https://github.com/fastfloat/fast_float>
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array> // array
|
||||||
|
#include <cstdint> // int64_t, uint64_t
|
||||||
|
|
||||||
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
/// the range of decimal exponents covered by pow5_128()
|
||||||
|
constexpr std::int64_t pow5_128_smallest_power = -342;
|
||||||
|
constexpr std::int64_t pow5_128_largest_power = 308;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief 128-bit approximations of 5^q for q in [-342, 308]
|
||||||
|
|
||||||
|
Entry q (at index 2 * (q + 342)) holds the most significant 128 bits of 5^q,
|
||||||
|
normalized so that the highest bit is set: for q >= 0 the truncated value, for
|
||||||
|
q < 0 the value rounded up. This is the table of fast_float (Daniel Lemire and
|
||||||
|
contributors, used under the MIT license), generated like its
|
||||||
|
script/table_generation.py; unit-class_lexer.cpp recomputes every entry.
|
||||||
|
*/
|
||||||
|
inline const std::array<std::uint64_t, 1302>& pow5_128() noexcept
|
||||||
|
{
|
||||||
|
static const std::array<std::uint64_t, 1302> table =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
0xeef453d6923bd65au, 0x113faa2906a13b3fu, 0x9558b4661b6565f8u, 0x4ac7ca59a424c507u,
|
||||||
|
0xbaaee17fa23ebf76u, 0x5d79bcf00d2df649u, 0xe95a99df8ace6f53u, 0xf4d82c2c107973dcu,
|
||||||
|
0x91d8a02bb6c10594u, 0x79071b9b8a4be869u, 0xb64ec836a47146f9u, 0x9748e2826cdee284u,
|
||||||
|
0xe3e27a444d8d98b7u, 0xfd1b1b2308169b25u, 0x8e6d8c6ab0787f72u, 0xfe30f0f5e50e20f7u,
|
||||||
|
0xb208ef855c969f4fu, 0xbdbd2d335e51a935u, 0xde8b2b66b3bc4723u, 0xad2c788035e61382u,
|
||||||
|
0x8b16fb203055ac76u, 0x4c3bcb5021afcc31u, 0xaddcb9e83c6b1793u, 0xdf4abe242a1bbf3du,
|
||||||
|
0xd953e8624b85dd78u, 0xd71d6dad34a2af0du, 0x87d4713d6f33aa6bu, 0x8672648c40e5ad68u,
|
||||||
|
0xa9c98d8ccb009506u, 0x680efdaf511f18c2u, 0xd43bf0effdc0ba48u, 0x0212bd1b2566def2u,
|
||||||
|
0x84a57695fe98746du, 0x014bb630f7604b57u, 0xa5ced43b7e3e9188u, 0x419ea3bd35385e2du,
|
||||||
|
0xcf42894a5dce35eau, 0x52064cac828675b9u, 0x818995ce7aa0e1b2u, 0x7343efebd1940993u,
|
||||||
|
0xa1ebfb4219491a1fu, 0x1014ebe6c5f90bf8u, 0xca66fa129f9b60a6u, 0xd41a26e077774ef6u,
|
||||||
|
0xfd00b897478238d0u, 0x8920b098955522b4u, 0x9e20735e8cb16382u, 0x55b46e5f5d5535b0u,
|
||||||
|
0xc5a890362fddbc62u, 0xeb2189f734aa831du, 0xf712b443bbd52b7bu, 0xa5e9ec7501d523e4u,
|
||||||
|
0x9a6bb0aa55653b2du, 0x47b233c92125366eu, 0xc1069cd4eabe89f8u, 0x999ec0bb696e840au,
|
||||||
|
0xf148440a256e2c76u, 0xc00670ea43ca250du, 0x96cd2a865764dbcau, 0x380406926a5e5728u,
|
||||||
|
0xbc807527ed3e12bcu, 0xc605083704f5ecf2u, 0xeba09271e88d976bu, 0xf7864a44c633682eu,
|
||||||
|
0x93445b8731587ea3u, 0x7ab3ee6afbe0211du, 0xb8157268fdae9e4cu, 0x5960ea05bad82964u,
|
||||||
|
0xe61acf033d1a45dfu, 0x6fb92487298e33bdu, 0x8fd0c16206306babu, 0xa5d3b6d479f8e056u,
|
||||||
|
0xb3c4f1ba87bc8696u, 0x8f48a4899877186cu, 0xe0b62e2929aba83cu, 0x331acdabfe94de87u,
|
||||||
|
0x8c71dcd9ba0b4925u, 0x9ff0c08b7f1d0b14u, 0xaf8e5410288e1b6fu, 0x07ecf0ae5ee44dd9u,
|
||||||
|
0xdb71e91432b1a24au, 0xc9e82cd9f69d6150u, 0x892731ac9faf056eu, 0xbe311c083a225cd2u,
|
||||||
|
0xab70fe17c79ac6cau, 0x6dbd630a48aaf406u, 0xd64d3d9db981787du, 0x092cbbccdad5b108u,
|
||||||
|
0x85f0468293f0eb4eu, 0x25bbf56008c58ea5u, 0xa76c582338ed2621u, 0xaf2af2b80af6f24eu,
|
||||||
|
0xd1476e2c07286faau, 0x1af5af660db4aee1u, 0x82cca4db847945cau, 0x50d98d9fc890ed4du,
|
||||||
|
0xa37fce126597973cu, 0xe50ff107bab528a0u, 0xcc5fc196fefd7d0cu, 0x1e53ed49a96272c8u,
|
||||||
|
0xff77b1fcbebcdc4fu, 0x25e8e89c13bb0f7au, 0x9faacf3df73609b1u, 0x77b191618c54e9acu,
|
||||||
|
0xc795830d75038c1du, 0xd59df5b9ef6a2417u, 0xf97ae3d0d2446f25u, 0x4b0573286b44ad1du,
|
||||||
|
0x9becce62836ac577u, 0x4ee367f9430aec32u, 0xc2e801fb244576d5u, 0x229c41f793cda73fu,
|
||||||
|
0xf3a20279ed56d48au, 0x6b43527578c1110fu, 0x9845418c345644d6u, 0x830a13896b78aaa9u,
|
||||||
|
0xbe5691ef416bd60cu, 0x23cc986bc656d553u, 0xedec366b11c6cb8fu, 0x2cbfbe86b7ec8aa8u,
|
||||||
|
0x94b3a202eb1c3f39u, 0x7bf7d71432f3d6a9u, 0xb9e08a83a5e34f07u, 0xdaf5ccd93fb0cc53u,
|
||||||
|
0xe858ad248f5c22c9u, 0xd1b3400f8f9cff68u, 0x91376c36d99995beu, 0x23100809b9c21fa1u,
|
||||||
|
0xb58547448ffffb2du, 0xabd40a0c2832a78au, 0xe2e69915b3fff9f9u, 0x16c90c8f323f516cu,
|
||||||
|
0x8dd01fad907ffc3bu, 0xae3da7d97f6792e3u, 0xb1442798f49ffb4au, 0x99cd11cfdf41779cu,
|
||||||
|
0xdd95317f31c7fa1du, 0x40405643d711d583u, 0x8a7d3eef7f1cfc52u, 0x482835ea666b2572u,
|
||||||
|
0xad1c8eab5ee43b66u, 0xda3243650005eecfu, 0xd863b256369d4a40u, 0x90bed43e40076a82u,
|
||||||
|
0x873e4f75e2224e68u, 0x5a7744a6e804a291u, 0xa90de3535aaae202u, 0x711515d0a205cb36u,
|
||||||
|
0xd3515c2831559a83u, 0x0d5a5b44ca873e03u, 0x8412d9991ed58091u, 0xe858790afe9486c2u,
|
||||||
|
0xa5178fff668ae0b6u, 0x626e974dbe39a872u, 0xce5d73ff402d98e3u, 0xfb0a3d212dc8128fu,
|
||||||
|
0x80fa687f881c7f8eu, 0x7ce66634bc9d0b99u, 0xa139029f6a239f72u, 0x1c1fffc1ebc44e80u,
|
||||||
|
0xc987434744ac874eu, 0xa327ffb266b56220u, 0xfbe9141915d7a922u, 0x4bf1ff9f0062baa8u,
|
||||||
|
0x9d71ac8fada6c9b5u, 0x6f773fc3603db4a9u, 0xc4ce17b399107c22u, 0xcb550fb4384d21d3u,
|
||||||
|
0xf6019da07f549b2bu, 0x7e2a53a146606a48u, 0x99c102844f94e0fbu, 0x2eda7444cbfc426du,
|
||||||
|
0xc0314325637a1939u, 0xfa911155fefb5308u, 0xf03d93eebc589f88u, 0x793555ab7eba27cau,
|
||||||
|
0x96267c7535b763b5u, 0x4bc1558b2f3458deu, 0xbbb01b9283253ca2u, 0x9eb1aaedfb016f16u,
|
||||||
|
0xea9c227723ee8bcbu, 0x465e15a979c1cadcu, 0x92a1958a7675175fu, 0x0bfacd89ec191ec9u,
|
||||||
|
0xb749faed14125d36u, 0xcef980ec671f667bu, 0xe51c79a85916f484u, 0x82b7e12780e7401au,
|
||||||
|
0x8f31cc0937ae58d2u, 0xd1b2ecb8b0908810u, 0xb2fe3f0b8599ef07u, 0x861fa7e6dcb4aa15u,
|
||||||
|
0xdfbdcece67006ac9u, 0x67a791e093e1d49au, 0x8bd6a141006042bdu, 0xe0c8bb2c5c6d24e0u,
|
||||||
|
0xaecc49914078536du, 0x58fae9f773886e18u, 0xda7f5bf590966848u, 0xaf39a475506a899eu,
|
||||||
|
0x888f99797a5e012du, 0x6d8406c952429603u, 0xaab37fd7d8f58178u, 0xc8e5087ba6d33b83u,
|
||||||
|
0xd5605fcdcf32e1d6u, 0xfb1e4a9a90880a64u, 0x855c3be0a17fcd26u, 0x5cf2eea09a55067fu,
|
||||||
|
0xa6b34ad8c9dfc06fu, 0xf42faa48c0ea481eu, 0xd0601d8efc57b08bu, 0xf13b94daf124da26u,
|
||||||
|
0x823c12795db6ce57u, 0x76c53d08d6b70858u, 0xa2cb1717b52481edu, 0x54768c4b0c64ca6eu,
|
||||||
|
0xcb7ddcdda26da268u, 0xa9942f5dcf7dfd09u, 0xfe5d54150b090b02u, 0xd3f93b35435d7c4cu,
|
||||||
|
0x9efa548d26e5a6e1u, 0xc47bc5014a1a6dafu, 0xc6b8e9b0709f109au, 0x359ab6419ca1091bu,
|
||||||
|
0xf867241c8cc6d4c0u, 0xc30163d203c94b62u, 0x9b407691d7fc44f8u, 0x79e0de63425dcf1du,
|
||||||
|
0xc21094364dfb5636u, 0x985915fc12f542e4u, 0xf294b943e17a2bc4u, 0x3e6f5b7b17b2939du,
|
||||||
|
0x979cf3ca6cec5b5au, 0xa705992ceecf9c42u, 0xbd8430bd08277231u, 0x50c6ff782a838353u,
|
||||||
|
0xece53cec4a314ebdu, 0xa4f8bf5635246428u, 0x940f4613ae5ed136u, 0x871b7795e136be99u,
|
||||||
|
0xb913179899f68584u, 0x28e2557b59846e3fu, 0xe757dd7ec07426e5u, 0x331aeada2fe589cfu,
|
||||||
|
0x9096ea6f3848984fu, 0x3ff0d2c85def7621u, 0xb4bca50b065abe63u, 0x0fed077a756b53a9u,
|
||||||
|
0xe1ebce4dc7f16dfbu, 0xd3e8495912c62894u, 0x8d3360f09cf6e4bdu, 0x64712dd7abbbd95cu,
|
||||||
|
0xb080392cc4349decu, 0xbd8d794d96aacfb3u, 0xdca04777f541c567u, 0xecf0d7a0fc5583a0u,
|
||||||
|
0x89e42caaf9491b60u, 0xf41686c49db57244u, 0xac5d37d5b79b6239u, 0x311c2875c522ced5u,
|
||||||
|
0xd77485cb25823ac7u, 0x7d633293366b828bu, 0x86a8d39ef77164bcu, 0xae5dff9c02033197u,
|
||||||
|
0xa8530886b54dbdebu, 0xd9f57f830283fdfcu, 0xd267caa862a12d66u, 0xd072df63c324fd7bu,
|
||||||
|
0x8380dea93da4bc60u, 0x4247cb9e59f71e6du, 0xa46116538d0deb78u, 0x52d9be85f074e608u,
|
||||||
|
0xcd795be870516656u, 0x67902e276c921f8bu, 0x806bd9714632dff6u, 0x00ba1cd8a3db53b6u,
|
||||||
|
0xa086cfcd97bf97f3u, 0x80e8a40eccd228a4u, 0xc8a883c0fdaf7df0u, 0x6122cd128006b2cdu,
|
||||||
|
0xfad2a4b13d1b5d6cu, 0x796b805720085f81u, 0x9cc3a6eec6311a63u, 0xcbe3303674053bb0u,
|
||||||
|
0xc3f490aa77bd60fcu, 0xbedbfc4411068a9cu, 0xf4f1b4d515acb93bu, 0xee92fb5515482d44u,
|
||||||
|
0x991711052d8bf3c5u, 0x751bdd152d4d1c4au, 0xbf5cd54678eef0b6u, 0xd262d45a78a0635du,
|
||||||
|
0xef340a98172aace4u, 0x86fb897116c87c34u, 0x9580869f0e7aac0eu, 0xd45d35e6ae3d4da0u,
|
||||||
|
0xbae0a846d2195712u, 0x8974836059cca109u, 0xe998d258869facd7u, 0x2bd1a438703fc94bu,
|
||||||
|
0x91ff83775423cc06u, 0x7b6306a34627ddcfu, 0xb67f6455292cbf08u, 0x1a3bc84c17b1d542u,
|
||||||
|
0xe41f3d6a7377eecau, 0x20caba5f1d9e4a93u, 0x8e938662882af53eu, 0x547eb47b7282ee9cu,
|
||||||
|
0xb23867fb2a35b28du, 0xe99e619a4f23aa43u, 0xdec681f9f4c31f31u, 0x6405fa00e2ec94d4u,
|
||||||
|
0x8b3c113c38f9f37eu, 0xde83bc408dd3dd04u, 0xae0b158b4738705eu, 0x9624ab50b148d445u,
|
||||||
|
0xd98ddaee19068c76u, 0x3badd624dd9b0957u, 0x87f8a8d4cfa417c9u, 0xe54ca5d70a80e5d6u,
|
||||||
|
0xa9f6d30a038d1dbcu, 0x5e9fcf4ccd211f4cu, 0xd47487cc8470652bu, 0x7647c3200069671fu,
|
||||||
|
0x84c8d4dfd2c63f3bu, 0x29ecd9f40041e073u, 0xa5fb0a17c777cf09u, 0xf468107100525890u,
|
||||||
|
0xcf79cc9db955c2ccu, 0x7182148d4066eeb4u, 0x81ac1fe293d599bfu, 0xc6f14cd848405530u,
|
||||||
|
0xa21727db38cb002fu, 0xb8ada00e5a506a7cu, 0xca9cf1d206fdc03bu, 0xa6d90811f0e4851cu,
|
||||||
|
0xfd442e4688bd304au, 0x908f4a166d1da663u, 0x9e4a9cec15763e2eu, 0x9a598e4e043287feu,
|
||||||
|
0xc5dd44271ad3cdbau, 0x40eff1e1853f29fdu, 0xf7549530e188c128u, 0xd12bee59e68ef47cu,
|
||||||
|
0x9a94dd3e8cf578b9u, 0x82bb74f8301958ceu, 0xc13a148e3032d6e7u, 0xe36a52363c1faf01u,
|
||||||
|
0xf18899b1bc3f8ca1u, 0xdc44e6c3cb279ac1u, 0x96f5600f15a7b7e5u, 0x29ab103a5ef8c0b9u,
|
||||||
|
0xbcb2b812db11a5deu, 0x7415d448f6b6f0e7u, 0xebdf661791d60f56u, 0x111b495b3464ad21u,
|
||||||
|
0x936b9fcebb25c995u, 0xcab10dd900beec34u, 0xb84687c269ef3bfbu, 0x3d5d514f40eea742u,
|
||||||
|
0xe65829b3046b0afau, 0x0cb4a5a3112a5112u, 0x8ff71a0fe2c2e6dcu, 0x47f0e785eaba72abu,
|
||||||
|
0xb3f4e093db73a093u, 0x59ed216765690f56u, 0xe0f218b8d25088b8u, 0x306869c13ec3532cu,
|
||||||
|
0x8c974f7383725573u, 0x1e414218c73a13fbu, 0xafbd2350644eeacfu, 0xe5d1929ef90898fau,
|
||||||
|
0xdbac6c247d62a583u, 0xdf45f746b74abf39u, 0x894bc396ce5da772u, 0x6b8bba8c328eb783u,
|
||||||
|
0xab9eb47c81f5114fu, 0x066ea92f3f326564u, 0xd686619ba27255a2u, 0xc80a537b0efefebdu,
|
||||||
|
0x8613fd0145877585u, 0xbd06742ce95f5f36u, 0xa798fc4196e952e7u, 0x2c48113823b73704u,
|
||||||
|
0xd17f3b51fca3a7a0u, 0xf75a15862ca504c5u, 0x82ef85133de648c4u, 0x9a984d73dbe722fbu,
|
||||||
|
0xa3ab66580d5fdaf5u, 0xc13e60d0d2e0ebbau, 0xcc963fee10b7d1b3u, 0x318df905079926a8u,
|
||||||
|
0xffbbcfe994e5c61fu, 0xfdf17746497f7052u, 0x9fd561f1fd0f9bd3u, 0xfeb6ea8bedefa633u,
|
||||||
|
0xc7caba6e7c5382c8u, 0xfe64a52ee96b8fc0u, 0xf9bd690a1b68637bu, 0x3dfdce7aa3c673b0u,
|
||||||
|
0x9c1661a651213e2du, 0x06bea10ca65c084eu, 0xc31bfa0fe5698db8u, 0x486e494fcff30a62u,
|
||||||
|
0xf3e2f893dec3f126u, 0x5a89dba3c3efccfau, 0x986ddb5c6b3a76b7u, 0xf89629465a75e01cu,
|
||||||
|
0xbe89523386091465u, 0xf6bbb397f1135823u, 0xee2ba6c0678b597fu, 0x746aa07ded582e2cu,
|
||||||
|
0x94db483840b717efu, 0xa8c2a44eb4571cdcu, 0xba121a4650e4ddebu, 0x92f34d62616ce413u,
|
||||||
|
0xe896a0d7e51e1566u, 0x77b020baf9c81d17u, 0x915e2486ef32cd60u, 0x0ace1474dc1d122eu,
|
||||||
|
0xb5b5ada8aaff80b8u, 0x0d819992132456bau, 0xe3231912d5bf60e6u, 0x10e1fff697ed6c69u,
|
||||||
|
0x8df5efabc5979c8fu, 0xca8d3ffa1ef463c1u, 0xb1736b96b6fd83b3u, 0xbd308ff8a6b17cb2u,
|
||||||
|
0xddd0467c64bce4a0u, 0xac7cb3f6d05ddbdeu, 0x8aa22c0dbef60ee4u, 0x6bcdf07a423aa96bu,
|
||||||
|
0xad4ab7112eb3929du, 0x86c16c98d2c953c6u, 0xd89d64d57a607744u, 0xe871c7bf077ba8b7u,
|
||||||
|
0x87625f056c7c4a8bu, 0x11471cd764ad4972u, 0xa93af6c6c79b5d2du, 0xd598e40d3dd89bcfu,
|
||||||
|
0xd389b47879823479u, 0x4aff1d108d4ec2c3u, 0x843610cb4bf160cbu, 0xcedf722a585139bau,
|
||||||
|
0xa54394fe1eedb8feu, 0xc2974eb4ee658828u, 0xce947a3da6a9273eu, 0x733d226229feea32u,
|
||||||
|
0x811ccc668829b887u, 0x0806357d5a3f525fu, 0xa163ff802a3426a8u, 0xca07c2dcb0cf26f7u,
|
||||||
|
0xc9bcff6034c13052u, 0xfc89b393dd02f0b5u, 0xfc2c3f3841f17c67u, 0xbbac2078d443ace2u,
|
||||||
|
0x9d9ba7832936edc0u, 0xd54b944b84aa4c0du, 0xc5029163f384a931u, 0x0a9e795e65d4df11u,
|
||||||
|
0xf64335bcf065d37du, 0x4d4617b5ff4a16d5u, 0x99ea0196163fa42eu, 0x504bced1bf8e4e45u,
|
||||||
|
0xc06481fb9bcf8d39u, 0xe45ec2862f71e1d6u, 0xf07da27a82c37088u, 0x5d767327bb4e5a4cu,
|
||||||
|
0x964e858c91ba2655u, 0x3a6a07f8d510f86fu, 0xbbe226efb628afeau, 0x890489f70a55368bu,
|
||||||
|
0xeadab0aba3b2dbe5u, 0x2b45ac74ccea842eu, 0x92c8ae6b464fc96fu, 0x3b0b8bc90012929du,
|
||||||
|
0xb77ada0617e3bbcbu, 0x09ce6ebb40173744u, 0xe55990879ddcaabdu, 0xcc420a6a101d0515u,
|
||||||
|
0x8f57fa54c2a9eab6u, 0x9fa946824a12232du, 0xb32df8e9f3546564u, 0x47939822dc96abf9u,
|
||||||
|
0xdff9772470297ebdu, 0x59787e2b93bc56f7u, 0x8bfbea76c619ef36u, 0x57eb4edb3c55b65au,
|
||||||
|
0xaefae51477a06b03u, 0xede622920b6b23f1u, 0xdab99e59958885c4u, 0xe95fab368e45ecedu,
|
||||||
|
0x88b402f7fd75539bu, 0x11dbcb0218ebb414u, 0xaae103b5fcd2a881u, 0xd652bdc29f26a119u,
|
||||||
|
0xd59944a37c0752a2u, 0x4be76d3346f0495fu, 0x857fcae62d8493a5u, 0x6f70a4400c562ddbu,
|
||||||
|
0xa6dfbd9fb8e5b88eu, 0xcb4ccd500f6bb952u, 0xd097ad07a71f26b2u, 0x7e2000a41346a7a7u,
|
||||||
|
0x825ecc24c873782fu, 0x8ed400668c0c28c8u, 0xa2f67f2dfa90563bu, 0x728900802f0f32fau,
|
||||||
|
0xcbb41ef979346bcau, 0x4f2b40a03ad2ffb9u, 0xfea126b7d78186bcu, 0xe2f610c84987bfa8u,
|
||||||
|
0x9f24b832e6b0f436u, 0x0dd9ca7d2df4d7c9u, 0xc6ede63fa05d3143u, 0x91503d1c79720dbbu,
|
||||||
|
0xf8a95fcf88747d94u, 0x75a44c6397ce912au, 0x9b69dbe1b548ce7cu, 0xc986afbe3ee11abau,
|
||||||
|
0xc24452da229b021bu, 0xfbe85badce996168u, 0xf2d56790ab41c2a2u, 0xfae27299423fb9c3u,
|
||||||
|
0x97c560ba6b0919a5u, 0xdccd879fc967d41au, 0xbdb6b8e905cb600fu, 0x5400e987bbc1c920u,
|
||||||
|
0xed246723473e3813u, 0x290123e9aab23b68u, 0x9436c0760c86e30bu, 0xf9a0b6720aaf6521u,
|
||||||
|
0xb94470938fa89bceu, 0xf808e40e8d5b3e69u, 0xe7958cb87392c2c2u, 0xb60b1d1230b20e04u,
|
||||||
|
0x90bd77f3483bb9b9u, 0xb1c6f22b5e6f48c2u, 0xb4ecd5f01a4aa828u, 0x1e38aeb6360b1af3u,
|
||||||
|
0xe2280b6c20dd5232u, 0x25c6da63c38de1b0u, 0x8d590723948a535fu, 0x579c487e5a38ad0eu,
|
||||||
|
0xb0af48ec79ace837u, 0x2d835a9df0c6d851u, 0xdcdb1b2798182244u, 0xf8e431456cf88e65u,
|
||||||
|
0x8a08f0f8bf0f156bu, 0x1b8e9ecb641b58ffu, 0xac8b2d36eed2dac5u, 0xe272467e3d222f3fu,
|
||||||
|
0xd7adf884aa879177u, 0x5b0ed81dcc6abb0fu, 0x86ccbb52ea94baeau, 0x98e947129fc2b4e9u,
|
||||||
|
0xa87fea27a539e9a5u, 0x3f2398d747b36224u, 0xd29fe4b18e88640eu, 0x8eec7f0d19a03aadu,
|
||||||
|
0x83a3eeeef9153e89u, 0x1953cf68300424acu, 0xa48ceaaab75a8e2bu, 0x5fa8c3423c052dd7u,
|
||||||
|
0xcdb02555653131b6u, 0x3792f412cb06794du, 0x808e17555f3ebf11u, 0xe2bbd88bbee40bd0u,
|
||||||
|
0xa0b19d2ab70e6ed6u, 0x5b6aceaeae9d0ec4u, 0xc8de047564d20a8bu, 0xf245825a5a445275u,
|
||||||
|
0xfb158592be068d2eu, 0xeed6e2f0f0d56712u, 0x9ced737bb6c4183du, 0x55464dd69685606bu,
|
||||||
|
0xc428d05aa4751e4cu, 0xaa97e14c3c26b886u, 0xf53304714d9265dfu, 0xd53dd99f4b3066a8u,
|
||||||
|
0x993fe2c6d07b7fabu, 0xe546a8038efe4029u, 0xbf8fdb78849a5f96u, 0xde98520472bdd033u,
|
||||||
|
0xef73d256a5c0f77cu, 0x963e66858f6d4440u, 0x95a8637627989aadu, 0xdde7001379a44aa8u,
|
||||||
|
0xbb127c53b17ec159u, 0x5560c018580d5d52u, 0xe9d71b689dde71afu, 0xaab8f01e6e10b4a6u,
|
||||||
|
0x9226712162ab070du, 0xcab3961304ca70e8u, 0xb6b00d69bb55c8d1u, 0x3d607b97c5fd0d22u,
|
||||||
|
0xe45c10c42a2b3b05u, 0x8cb89a7db77c506au, 0x8eb98a7a9a5b04e3u, 0x77f3608e92adb242u,
|
||||||
|
0xb267ed1940f1c61cu, 0x55f038b237591ed3u, 0xdf01e85f912e37a3u, 0x6b6c46dec52f6688u,
|
||||||
|
0x8b61313bbabce2c6u, 0x2323ac4b3b3da015u, 0xae397d8aa96c1b77u, 0xabec975e0a0d081au,
|
||||||
|
0xd9c7dced53c72255u, 0x96e7bd358c904a21u, 0x881cea14545c7575u, 0x7e50d64177da2e54u,
|
||||||
|
0xaa242499697392d2u, 0xdde50bd1d5d0b9e9u, 0xd4ad2dbfc3d07787u, 0x955e4ec64b44e864u,
|
||||||
|
0x84ec3c97da624ab4u, 0xbd5af13bef0b113eu, 0xa6274bbdd0fadd61u, 0xecb1ad8aeacdd58eu,
|
||||||
|
0xcfb11ead453994bau, 0x67de18eda5814af2u, 0x81ceb32c4b43fcf4u, 0x80eacf948770ced7u,
|
||||||
|
0xa2425ff75e14fc31u, 0xa1258379a94d028du, 0xcad2f7f5359a3b3eu, 0x096ee45813a04330u,
|
||||||
|
0xfd87b5f28300ca0du, 0x8bca9d6e188853fcu, 0x9e74d1b791e07e48u, 0x775ea264cf55347eu,
|
||||||
|
0xc612062576589ddau, 0x95364afe032a819eu, 0xf79687aed3eec551u, 0x3a83ddbd83f52205u,
|
||||||
|
0x9abe14cd44753b52u, 0xc4926a9672793543u, 0xc16d9a0095928a27u, 0x75b7053c0f178294u,
|
||||||
|
0xf1c90080baf72cb1u, 0x5324c68b12dd6339u, 0x971da05074da7beeu, 0xd3f6fc16ebca5e04u,
|
||||||
|
0xbce5086492111aeau, 0x88f4bb1ca6bcf585u, 0xec1e4a7db69561a5u, 0x2b31e9e3d06c32e6u,
|
||||||
|
0x9392ee8e921d5d07u, 0x3aff322e62439fd0u, 0xb877aa3236a4b449u, 0x09befeb9fad487c3u,
|
||||||
|
0xe69594bec44de15bu, 0x4c2ebe687989a9b4u, 0x901d7cf73ab0acd9u, 0x0f9d37014bf60a11u,
|
||||||
|
0xb424dc35095cd80fu, 0x538484c19ef38c95u, 0xe12e13424bb40e13u, 0x2865a5f206b06fbau,
|
||||||
|
0x8cbccc096f5088cbu, 0xf93f87b7442e45d4u, 0xafebff0bcb24aafeu, 0xf78f69a51539d749u,
|
||||||
|
0xdbe6fecebdedd5beu, 0xb573440e5a884d1cu, 0x89705f4136b4a597u, 0x31680a88f8953031u,
|
||||||
|
0xabcc77118461cefcu, 0xfdc20d2b36ba7c3eu, 0xd6bf94d5e57a42bcu, 0x3d32907604691b4du,
|
||||||
|
0x8637bd05af6c69b5u, 0xa63f9a49c2c1b110u, 0xa7c5ac471b478423u, 0x0fcf80dc33721d54u,
|
||||||
|
0xd1b71758e219652bu, 0xd3c36113404ea4a9u, 0x83126e978d4fdf3bu, 0x645a1cac083126eau,
|
||||||
|
0xa3d70a3d70a3d70au, 0x3d70a3d70a3d70a4u, 0xccccccccccccccccu, 0xcccccccccccccccdu,
|
||||||
|
0x8000000000000000u, 0x0000000000000000u, 0xa000000000000000u, 0x0000000000000000u,
|
||||||
|
0xc800000000000000u, 0x0000000000000000u, 0xfa00000000000000u, 0x0000000000000000u,
|
||||||
|
0x9c40000000000000u, 0x0000000000000000u, 0xc350000000000000u, 0x0000000000000000u,
|
||||||
|
0xf424000000000000u, 0x0000000000000000u, 0x9896800000000000u, 0x0000000000000000u,
|
||||||
|
0xbebc200000000000u, 0x0000000000000000u, 0xee6b280000000000u, 0x0000000000000000u,
|
||||||
|
0x9502f90000000000u, 0x0000000000000000u, 0xba43b74000000000u, 0x0000000000000000u,
|
||||||
|
0xe8d4a51000000000u, 0x0000000000000000u, 0x9184e72a00000000u, 0x0000000000000000u,
|
||||||
|
0xb5e620f480000000u, 0x0000000000000000u, 0xe35fa931a0000000u, 0x0000000000000000u,
|
||||||
|
0x8e1bc9bf04000000u, 0x0000000000000000u, 0xb1a2bc2ec5000000u, 0x0000000000000000u,
|
||||||
|
0xde0b6b3a76400000u, 0x0000000000000000u, 0x8ac7230489e80000u, 0x0000000000000000u,
|
||||||
|
0xad78ebc5ac620000u, 0x0000000000000000u, 0xd8d726b7177a8000u, 0x0000000000000000u,
|
||||||
|
0x878678326eac9000u, 0x0000000000000000u, 0xa968163f0a57b400u, 0x0000000000000000u,
|
||||||
|
0xd3c21bcecceda100u, 0x0000000000000000u, 0x84595161401484a0u, 0x0000000000000000u,
|
||||||
|
0xa56fa5b99019a5c8u, 0x0000000000000000u, 0xcecb8f27f4200f3au, 0x0000000000000000u,
|
||||||
|
0x813f3978f8940984u, 0x4000000000000000u, 0xa18f07d736b90be5u, 0x5000000000000000u,
|
||||||
|
0xc9f2c9cd04674edeu, 0xa400000000000000u, 0xfc6f7c4045812296u, 0x4d00000000000000u,
|
||||||
|
0x9dc5ada82b70b59du, 0xf020000000000000u, 0xc5371912364ce305u, 0x6c28000000000000u,
|
||||||
|
0xf684df56c3e01bc6u, 0xc732000000000000u, 0x9a130b963a6c115cu, 0x3c7f400000000000u,
|
||||||
|
0xc097ce7bc90715b3u, 0x4b9f100000000000u, 0xf0bdc21abb48db20u, 0x1e86d40000000000u,
|
||||||
|
0x96769950b50d88f4u, 0x1314448000000000u, 0xbc143fa4e250eb31u, 0x17d955a000000000u,
|
||||||
|
0xeb194f8e1ae525fdu, 0x5dcfab0800000000u, 0x92efd1b8d0cf37beu, 0x5aa1cae500000000u,
|
||||||
|
0xb7abc627050305adu, 0xf14a3d9e40000000u, 0xe596b7b0c643c719u, 0x6d9ccd05d0000000u,
|
||||||
|
0x8f7e32ce7bea5c6fu, 0xe4820023a2000000u, 0xb35dbf821ae4f38bu, 0xdda2802c8a800000u,
|
||||||
|
0xe0352f62a19e306eu, 0xd50b2037ad200000u, 0x8c213d9da502de45u, 0x4526f422cc340000u,
|
||||||
|
0xaf298d050e4395d6u, 0x9670b12b7f410000u, 0xdaf3f04651d47b4cu, 0x3c0cdd765f114000u,
|
||||||
|
0x88d8762bf324cd0fu, 0xa5880a69fb6ac800u, 0xab0e93b6efee0053u, 0x8eea0d047a457a00u,
|
||||||
|
0xd5d238a4abe98068u, 0x72a4904598d6d880u, 0x85a36366eb71f041u, 0x47a6da2b7f864750u,
|
||||||
|
0xa70c3c40a64e6c51u, 0x999090b65f67d924u, 0xd0cf4b50cfe20765u, 0xfff4b4e3f741cf6du,
|
||||||
|
0x82818f1281ed449fu, 0xbff8f10e7a8921a4u, 0xa321f2d7226895c7u, 0xaff72d52192b6a0du,
|
||||||
|
0xcbea6f8ceb02bb39u, 0x9bf4f8a69f764490u, 0xfee50b7025c36a08u, 0x02f236d04753d5b4u,
|
||||||
|
0x9f4f2726179a2245u, 0x01d762422c946590u, 0xc722f0ef9d80aad6u, 0x424d3ad2b7b97ef5u,
|
||||||
|
0xf8ebad2b84e0d58bu, 0xd2e0898765a7deb2u, 0x9b934c3b330c8577u, 0x63cc55f49f88eb2fu,
|
||||||
|
0xc2781f49ffcfa6d5u, 0x3cbf6b71c76b25fbu, 0xf316271c7fc3908au, 0x8bef464e3945ef7au,
|
||||||
|
0x97edd871cfda3a56u, 0x97758bf0e3cbb5acu, 0xbde94e8e43d0c8ecu, 0x3d52eeed1cbea317u,
|
||||||
|
0xed63a231d4c4fb27u, 0x4ca7aaa863ee4bddu, 0x945e455f24fb1cf8u, 0x8fe8caa93e74ef6au,
|
||||||
|
0xb975d6b6ee39e436u, 0xb3e2fd538e122b44u, 0xe7d34c64a9c85d44u, 0x60dbbca87196b616u,
|
||||||
|
0x90e40fbeea1d3a4au, 0xbc8955e946fe31cdu, 0xb51d13aea4a488ddu, 0x6babab6398bdbe41u,
|
||||||
|
0xe264589a4dcdab14u, 0xc696963c7eed2dd1u, 0x8d7eb76070a08aecu, 0xfc1e1de5cf543ca2u,
|
||||||
|
0xb0de65388cc8ada8u, 0x3b25a55f43294bcbu, 0xdd15fe86affad912u, 0x49ef0eb713f39ebeu,
|
||||||
|
0x8a2dbf142dfcc7abu, 0x6e3569326c784337u, 0xacb92ed9397bf996u, 0x49c2c37f07965404u,
|
||||||
|
0xd7e77a8f87daf7fbu, 0xdc33745ec97be906u, 0x86f0ac99b4e8dafdu, 0x69a028bb3ded71a3u,
|
||||||
|
0xa8acd7c0222311bcu, 0xc40832ea0d68ce0cu, 0xd2d80db02aabd62bu, 0xf50a3fa490c30190u,
|
||||||
|
0x83c7088e1aab65dbu, 0x792667c6da79e0fau, 0xa4b8cab1a1563f52u, 0x577001b891185938u,
|
||||||
|
0xcde6fd5e09abcf26u, 0xed4c0226b55e6f86u, 0x80b05e5ac60b6178u, 0x544f8158315b05b4u,
|
||||||
|
0xa0dc75f1778e39d6u, 0x696361ae3db1c721u, 0xc913936dd571c84cu, 0x03bc3a19cd1e38e9u,
|
||||||
|
0xfb5878494ace3a5fu, 0x04ab48a04065c723u, 0x9d174b2dcec0e47bu, 0x62eb0d64283f9c76u,
|
||||||
|
0xc45d1df942711d9au, 0x3ba5d0bd324f8394u, 0xf5746577930d6500u, 0xca8f44ec7ee36479u,
|
||||||
|
0x9968bf6abbe85f20u, 0x7e998b13cf4e1ecbu, 0xbfc2ef456ae276e8u, 0x9e3fedd8c321a67eu,
|
||||||
|
0xefb3ab16c59b14a2u, 0xc5cfe94ef3ea101eu, 0x95d04aee3b80ece5u, 0xbba1f1d158724a12u,
|
||||||
|
0xbb445da9ca61281fu, 0x2a8a6e45ae8edc97u, 0xea1575143cf97226u, 0xf52d09d71a3293bdu,
|
||||||
|
0x924d692ca61be758u, 0x593c2626705f9c56u, 0xb6e0c377cfa2e12eu, 0x6f8b2fb00c77836cu,
|
||||||
|
0xe498f455c38b997au, 0x0b6dfb9c0f956447u, 0x8edf98b59a373fecu, 0x4724bd4189bd5eacu,
|
||||||
|
0xb2977ee300c50fe7u, 0x58edec91ec2cb657u, 0xdf3d5e9bc0f653e1u, 0x2f2967b66737e3edu,
|
||||||
|
0x8b865b215899f46cu, 0xbd79e0d20082ee74u, 0xae67f1e9aec07187u, 0xecd8590680a3aa11u,
|
||||||
|
0xda01ee641a708de9u, 0xe80e6f4820cc9495u, 0x884134fe908658b2u, 0x3109058d147fdcddu,
|
||||||
|
0xaa51823e34a7eedeu, 0xbd4b46f0599fd415u, 0xd4e5e2cdc1d1ea96u, 0x6c9e18ac7007c91au,
|
||||||
|
0x850fadc09923329eu, 0x03e2cf6bc604ddb0u, 0xa6539930bf6bff45u, 0x84db8346b786151cu,
|
||||||
|
0xcfe87f7cef46ff16u, 0xe612641865679a63u, 0x81f14fae158c5f6eu, 0x4fcb7e8f3f60c07eu,
|
||||||
|
0xa26da3999aef7749u, 0xe3be5e330f38f09du, 0xcb090c8001ab551cu, 0x5cadf5bfd3072cc5u,
|
||||||
|
0xfdcb4fa002162a63u, 0x73d9732fc7c8f7f6u, 0x9e9f11c4014dda7eu, 0x2867e7fddcdd9afau,
|
||||||
|
0xc646d63501a1511du, 0xb281e1fd541501b8u, 0xf7d88bc24209a565u, 0x1f225a7ca91a4226u,
|
||||||
|
0x9ae757596946075fu, 0x3375788de9b06958u, 0xc1a12d2fc3978937u, 0x0052d6b1641c83aeu,
|
||||||
|
0xf209787bb47d6b84u, 0xc0678c5dbd23a49au, 0x9745eb4d50ce6332u, 0xf840b7ba963646e0u,
|
||||||
|
0xbd176620a501fbffu, 0xb650e5a93bc3d898u, 0xec5d3fa8ce427affu, 0xa3e51f138ab4cebeu,
|
||||||
|
0x93ba47c980e98cdfu, 0xc66f336c36b10137u, 0xb8a8d9bbe123f017u, 0xb80b0047445d4184u,
|
||||||
|
0xe6d3102ad96cec1du, 0xa60dc059157491e5u, 0x9043ea1ac7e41392u, 0x87c89837ad68db2fu,
|
||||||
|
0xb454e4a179dd1877u, 0x29babe4598c311fbu, 0xe16a1dc9d8545e94u, 0xf4296dd6fef3d67au,
|
||||||
|
0x8ce2529e2734bb1du, 0x1899e4a65f58660cu, 0xb01ae745b101e9e4u, 0x5ec05dcff72e7f8fu,
|
||||||
|
0xdc21a1171d42645du, 0x76707543f4fa1f73u, 0x899504ae72497ebau, 0x6a06494a791c53a8u,
|
||||||
|
0xabfa45da0edbde69u, 0x0487db9d17636892u, 0xd6f8d7509292d603u, 0x45a9d2845d3c42b6u,
|
||||||
|
0x865b86925b9bc5c2u, 0x0b8a2392ba45a9b2u, 0xa7f26836f282b732u, 0x8e6cac7768d7141eu,
|
||||||
|
0xd1ef0244af2364ffu, 0x3207d795430cd926u, 0x8335616aed761f1fu, 0x7f44e6bd49e807b8u,
|
||||||
|
0xa402b9c5a8d3a6e7u, 0x5f16206c9c6209a6u, 0xcd036837130890a1u, 0x36dba887c37a8c0fu,
|
||||||
|
0x802221226be55a64u, 0xc2494954da2c9789u, 0xa02aa96b06deb0fdu, 0xf2db9baa10b7bd6cu,
|
||||||
|
0xc83553c5c8965d3du, 0x6f92829494e5acc7u, 0xfa42a8b73abbf48cu, 0xcb772339ba1f17f9u,
|
||||||
|
0x9c69a97284b578d7u, 0xff2a760414536efbu, 0xc38413cf25e2d70du, 0xfef5138519684abau,
|
||||||
|
0xf46518c2ef5b8cd1u, 0x7eb258665fc25d69u, 0x98bf2f79d5993802u, 0xef2f773ffbd97a61u,
|
||||||
|
0xbeeefb584aff8603u, 0xaafb550ffacfd8fau, 0xeeaaba2e5dbf6784u, 0x95ba2a53f983cf38u,
|
||||||
|
0x952ab45cfa97a0b2u, 0xdd945a747bf26183u, 0xba756174393d88dfu, 0x94f971119aeef9e4u,
|
||||||
|
0xe912b9d1478ceb17u, 0x7a37cd5601aab85du, 0x91abb422ccb812eeu, 0xac62e055c10ab33au,
|
||||||
|
0xb616a12b7fe617aau, 0x577b986b314d6009u, 0xe39c49765fdf9d94u, 0xed5a7e85fda0b80bu,
|
||||||
|
0x8e41ade9fbebc27du, 0x14588f13be847307u, 0xb1d219647ae6b31cu, 0x596eb2d8ae258fc8u,
|
||||||
|
0xde469fbd99a05fe3u, 0x6fca5f8ed9aef3bbu, 0x8aec23d680043beeu, 0x25de7bb9480d5854u,
|
||||||
|
0xada72ccc20054ae9u, 0xaf561aa79a10ae6au, 0xd910f7ff28069da4u, 0x1b2ba1518094da04u,
|
||||||
|
0x87aa9aff79042286u, 0x90fb44d2f05d0842u, 0xa99541bf57452b28u, 0x353a1607ac744a53u,
|
||||||
|
0xd3fa922f2d1675f2u, 0x42889b8997915ce8u, 0x847c9b5d7c2e09b7u, 0x69956135febada11u,
|
||||||
|
0xa59bc234db398c25u, 0x43fab9837e699095u, 0xcf02b2c21207ef2eu, 0x94f967e45e03f4bbu,
|
||||||
|
0x8161afb94b44f57du, 0x1d1be0eebac278f5u, 0xa1ba1ba79e1632dcu, 0x6462d92a69731732u,
|
||||||
|
0xca28a291859bbf93u, 0x7d7b8f7503cfdcfeu, 0xfcb2cb35e702af78u, 0x5cda735244c3d43eu,
|
||||||
|
0x9defbf01b061adabu, 0x3a0888136afa64a7u, 0xc56baec21c7a1916u, 0x088aaa1845b8fdd0u,
|
||||||
|
0xf6c69a72a3989f5bu, 0x8aad549e57273d45u, 0x9a3c2087a63f6399u, 0x36ac54e2f678864bu,
|
||||||
|
0xc0cb28a98fcf3c7fu, 0x84576a1bb416a7ddu, 0xf0fdf2d3f3c30b9fu, 0x656d44a2a11c51d5u,
|
||||||
|
0x969eb7c47859e743u, 0x9f644ae5a4b1b325u, 0xbc4665b596706114u, 0x873d5d9f0dde1feeu,
|
||||||
|
0xeb57ff22fc0c7959u, 0xa90cb506d155a7eau, 0x9316ff75dd87cbd8u, 0x09a7f12442d588f2u,
|
||||||
|
0xb7dcbf5354e9beceu, 0x0c11ed6d538aeb2fu, 0xe5d3ef282a242e81u, 0x8f1668c8a86da5fau,
|
||||||
|
0x8fa475791a569d10u, 0xf96e017d694487bcu, 0xb38d92d760ec4455u, 0x37c981dcc395a9acu,
|
||||||
|
0xe070f78d3927556au, 0x85bbe253f47b1417u, 0x8c469ab843b89562u, 0x93956d7478ccec8eu,
|
||||||
|
0xaf58416654a6babbu, 0x387ac8d1970027b2u, 0xdb2e51bfe9d0696au, 0x06997b05fcc0319eu,
|
||||||
|
0x88fcf317f22241e2u, 0x441fece3bdf81f03u, 0xab3c2fddeeaad25au, 0xd527e81cad7626c3u,
|
||||||
|
0xd60b3bd56a5586f1u, 0x8a71e223d8d3b074u, 0x85c7056562757456u, 0xf6872d5667844e49u,
|
||||||
|
0xa738c6bebb12d16cu, 0xb428f8ac016561dbu, 0xd106f86e69d785c7u, 0xe13336d701beba52u,
|
||||||
|
0x82a45b450226b39cu, 0xecc0024661173473u, 0xa34d721642b06084u, 0x27f002d7f95d0190u,
|
||||||
|
0xcc20ce9bd35c78a5u, 0x31ec038df7b441f4u, 0xff290242c83396ceu, 0x7e67047175a15271u,
|
||||||
|
0x9f79a169bd203e41u, 0x0f0062c6e984d386u, 0xc75809c42c684dd1u, 0x52c07b78a3e60868u,
|
||||||
|
0xf92e0c3537826145u, 0xa7709a56ccdf8a82u, 0x9bbcc7a142b17ccbu, 0x88a66076400bb691u,
|
||||||
|
0xc2abf989935ddbfeu, 0x6acff893d00ea435u, 0xf356f7ebf83552feu, 0x0583f6b8c4124d43u,
|
||||||
|
0x98165af37b2153deu, 0xc3727a337a8b704au, 0xbe1bf1b059e9a8d6u, 0x744f18c0592e4c5cu,
|
||||||
|
0xeda2ee1c7064130cu, 0x1162def06f79df73u, 0x9485d4d1c63e8be7u, 0x8addcb5645ac2ba8u,
|
||||||
|
0xb9a74a0637ce2ee1u, 0x6d953e2bd7173692u, 0xe8111c87c5c1ba99u, 0xc8fa8db6ccdd0437u,
|
||||||
|
0x910ab1d4db9914a0u, 0x1d9c9892400a22a2u, 0xb54d5e4a127f59c8u, 0x2503beb6d00cab4bu,
|
||||||
|
0xe2a0b5dc971f303au, 0x2e44ae64840fd61du, 0x8da471a9de737e24u, 0x5ceaecfed289e5d2u,
|
||||||
|
0xb10d8e1456105dadu, 0x7425a83e872c5f47u, 0xdd50f1996b947518u, 0xd12f124e28f77719u,
|
||||||
|
0x8a5296ffe33cc92fu, 0x82bd6b70d99aaa6fu, 0xace73cbfdc0bfb7bu, 0x636cc64d1001550bu,
|
||||||
|
0xd8210befd30efa5au, 0x3c47f7e05401aa4eu, 0x8714a775e3e95c78u, 0x65acfaec34810a71u,
|
||||||
|
0xa8d9d1535ce3b396u, 0x7f1839a741a14d0du, 0xd31045a8341ca07cu, 0x1ede48111209a050u,
|
||||||
|
0x83ea2b892091e44du, 0x934aed0aab460432u, 0xa4e4b66b68b65d60u, 0xf81da84d5617853fu,
|
||||||
|
0xce1de40642e3f4b9u, 0x36251260ab9d668eu, 0x80d2ae83e9ce78f3u, 0xc1d72b7c6b426019u,
|
||||||
|
0xa1075a24e4421730u, 0xb24cf65b8612f81fu, 0xc94930ae1d529cfcu, 0xdee033f26797b627u,
|
||||||
|
0xfb9b7cd9a4a7443cu, 0x169840ef017da3b1u, 0x9d412e0806e88aa5u, 0x8e1f289560ee864eu,
|
||||||
|
0xc491798a08a2ad4eu, 0xf1a6f2bab92a27e2u, 0xf5b5d7ec8acb58a2u, 0xae10af696774b1dbu,
|
||||||
|
0x9991a6f3d6bf1765u, 0xacca6da1e0a8ef29u, 0xbff610b0cc6edd3fu, 0x17fd090a58d32af3u,
|
||||||
|
0xeff394dcff8a948eu, 0xddfc4b4cef07f5b0u, 0x95f83d0a1fb69cd9u, 0x4abdaf101564f98eu,
|
||||||
|
0xbb764c4ca7a4440fu, 0x9d6d1ad41abe37f1u, 0xea53df5fd18d5513u, 0x84c86189216dc5edu,
|
||||||
|
0x92746b9be2f8552cu, 0x32fd3cf5b4e49bb4u, 0xb7118682dbb66a77u, 0x3fbc8c33221dc2a1u,
|
||||||
|
0xe4d5e82392a40515u, 0x0fabaf3feaa5334au, 0x8f05b1163ba6832du, 0x29cb4d87f2a7400eu,
|
||||||
|
0xb2c71d5bca9023f8u, 0x743e20e9ef511012u, 0xdf78e4b2bd342cf6u, 0x914da9246b255416u,
|
||||||
|
0x8bab8eefb6409c1au, 0x1ad089b6c2f7548eu, 0xae9672aba3d0c320u, 0xa184ac2473b529b1u,
|
||||||
|
0xda3c0f568cc4f3e8u, 0xc9e5d72d90a2741eu, 0x8865899617fb1871u, 0x7e2fa67c7a658892u,
|
||||||
|
0xaa7eebfb9df9de8du, 0xddbb901b98feeab7u, 0xd51ea6fa85785631u, 0x552a74227f3ea565u,
|
||||||
|
0x8533285c936b35deu, 0xd53a88958f87275fu, 0xa67ff273b8460356u, 0x8a892abaf368f137u,
|
||||||
|
0xd01fef10a657842cu, 0x2d2b7569b0432d85u, 0x8213f56a67f6b29bu, 0x9c3b29620e29fc73u,
|
||||||
|
0xa298f2c501f45f42u, 0x8349f3ba91b47b8fu, 0xcb3f2f7642717713u, 0x241c70a936219a73u,
|
||||||
|
0xfe0efb53d30dd4d7u, 0xed238cd383aa0110u, 0x9ec95d1463e8a506u, 0xf4363804324a40aau,
|
||||||
|
0xc67bb4597ce2ce48u, 0xb143c6053edcd0d5u, 0xf81aa16fdc1b81dau, 0xdd94b7868e94050au,
|
||||||
|
0x9b10a4e5e9913128u, 0xca7cf2b4191c8326u, 0xc1d4ce1f63f57d72u, 0xfd1c2f611f63a3f0u,
|
||||||
|
0xf24a01a73cf2dccfu, 0xbc633b39673c8cecu, 0x976e41088617ca01u, 0xd5be0503e085d813u,
|
||||||
|
0xbd49d14aa79dbc82u, 0x4b2d8644d8a74e18u, 0xec9c459d51852ba2u, 0xddf8e7d60ed1219eu,
|
||||||
|
0x93e1ab8252f33b45u, 0xcabb90e5c942b503u, 0xb8da1662e7b00a17u, 0x3d6a751f3b936243u,
|
||||||
|
0xe7109bfba19c0c9du, 0x0cc512670a783ad4u, 0x906a617d450187e2u, 0x27fb2b80668b24c5u,
|
||||||
|
0xb484f9dc9641e9dau, 0xb1f9f660802dedf6u, 0xe1a63853bbd26451u, 0x5e7873f8a0396973u,
|
||||||
|
0x8d07e33455637eb2u, 0xdb0b487b6423e1e8u, 0xb049dc016abc5e5fu, 0x91ce1a9a3d2cda62u,
|
||||||
|
0xdc5c5301c56b75f7u, 0x7641a140cc7810fbu, 0x89b9b3e11b6329bau, 0xa9e904c87fcb0a9du,
|
||||||
|
0xac2820d9623bf429u, 0x546345fa9fbdcd44u, 0xd732290fbacaf133u, 0xa97c177947ad4095u,
|
||||||
|
0x867f59a9d4bed6c0u, 0x49ed8eabcccc485du, 0xa81f301449ee8c70u, 0x5c68f256bfff5a74u,
|
||||||
|
0xd226fc195c6a2f8cu, 0x73832eec6fff3111u, 0x83585d8fd9c25db7u, 0xc831fd53c5ff7eabu,
|
||||||
|
0xa42e74f3d032f525u, 0xba3e7ca8b77f5e55u, 0xcd3a1230c43fb26fu, 0x28ce1bd2e55f35ebu,
|
||||||
|
0x80444b5e7aa7cf85u, 0x7980d163cf5b81b3u, 0xa0555e361951c366u, 0xd7e105bcc332621fu,
|
||||||
|
0xc86ab5c39fa63440u, 0x8dd9472bf3fefaa7u, 0xfa856334878fc150u, 0xb14f98f6f0feb951u,
|
||||||
|
0x9c935e00d4b9d8d2u, 0x6ed1bf9a569f33d3u, 0xc3b8358109e84f07u, 0x0a862f80ec4700c8u,
|
||||||
|
0xf4a642e14c6262c8u, 0xcd27bb612758c0fau, 0x98e7e9cccfbd7dbdu, 0x8038d51cb897789cu,
|
||||||
|
0xbf21e44003acdd2cu, 0xe0470a63e6bd56c3u, 0xeeea5d5004981478u, 0x1858ccfce06cac74u,
|
||||||
|
0x95527a5202df0ccbu, 0x0f37801e0c43ebc8u, 0xbaa718e68396cffdu, 0xd30560258f54e6bau,
|
||||||
|
0xe950df20247c83fdu, 0x47c6b82ef32a2069u, 0x91d28b7416cdd27eu, 0x4cdc331d57fa5441u,
|
||||||
|
0xb6472e511c81471du, 0xe0133fe4adf8e952u, 0xe3d8f9e563a198e5u, 0x58180fddd97723a6u,
|
||||||
|
0x8e679c2f5e44ff8fu, 0x570f09eaa7ea7648u,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <cstdint> // uint64_t
|
#include <cstdint> // uint64_t
|
||||||
#include <cstring> // memcpy
|
#include <cstring> // memcpy
|
||||||
|
|
||||||
|
#include <nlohmann/detail/bit_ops.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
// Optional SIMD backend for bulk UTF-8 validation. This is an opt-in external
|
// Optional SIMD backend for bulk UTF-8 validation. This is an opt-in external
|
||||||
@@ -69,18 +70,12 @@ inline std::size_t find_string_special(const unsigned char* data, std::size_t n)
|
|||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
for (; i + 8 <= n; i += 8)
|
for (; i + 8 <= n; i += 8)
|
||||||
{
|
{
|
||||||
std::uint64_t word = 0;
|
const std::uint64_t special = swar_string_special(read_eight_bytes(data + i));
|
||||||
std::memcpy(&word, data + i, sizeof(word));
|
if (special != 0)
|
||||||
if (swar_string_special(word) != 0)
|
|
||||||
{
|
{
|
||||||
// a special byte is in this word; locate it (endian-agnostic)
|
// the lowest flagged byte is the first special one: the borrows of
|
||||||
for (std::size_t j = 0; j < 8; ++j)
|
// the subtractions can only flag bytes above a true hit
|
||||||
{
|
return i + (static_cast<std::size_t>(count_trailing_zeros(special)) / 8);
|
||||||
if (is_string_special(data[i + j]))
|
|
||||||
{
|
|
||||||
return i + j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < n; ++i)
|
for (; i < n; ++i)
|
||||||
@@ -114,8 +109,7 @@ inline std::size_t find_ascii_copyable_run(const unsigned char* data, std::size_
|
|||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
for (; i + 8 <= n; i += 8)
|
for (; i + 8 <= n; i += 8)
|
||||||
{
|
{
|
||||||
std::uint64_t v = 0;
|
const std::uint64_t v = read_eight_bytes(data + i);
|
||||||
std::memcpy(&v, data + i, sizeof(v));
|
|
||||||
const std::uint64_t q = v ^ 0x2222222222222222ull; // '"' (0x22)
|
const std::uint64_t q = v ^ 0x2222222222222222ull; // '"' (0x22)
|
||||||
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull; // '\\' (0x5C)
|
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull; // '\\' (0x5C)
|
||||||
const std::uint64_t d = v ^ 0x7F7F7F7F7F7F7F7Full; // DEL (0x7F)
|
const std::uint64_t d = v ^ 0x7F7F7F7F7F7F7F7Full; // DEL (0x7F)
|
||||||
@@ -126,7 +120,9 @@ inline std::size_t find_ascii_copyable_run(const unsigned char* data, std::size_
|
|||||||
| (v & high); // >= 0x80
|
| (v & high); // >= 0x80
|
||||||
if (stop != 0)
|
if (stop != 0)
|
||||||
{
|
{
|
||||||
break;
|
// the lowest flagged byte is the first one to stop at (see
|
||||||
|
// find_string_special())
|
||||||
|
return i + (static_cast<std::size_t>(count_trailing_zeros(stop)) / 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < n; ++i)
|
for (; i < n; ++i)
|
||||||
@@ -253,13 +249,19 @@ inline std::size_t scalar_string_bulk_run(const unsigned char* data, std::size_t
|
|||||||
{
|
{
|
||||||
break; // end of buffer, or a quote/escape/control byte
|
break; // end of buffer, or a quote/escape/control byte
|
||||||
}
|
}
|
||||||
|
// a run of multi-byte sequences (e.g. CJK text) is validated sequence
|
||||||
|
// by sequence without searching for the next special byte in between
|
||||||
|
do
|
||||||
|
{
|
||||||
const std::size_t seq = validate_one_utf8(data + pos, n - pos);
|
const std::size_t seq = validate_one_utf8(data + pos, n - pos);
|
||||||
if (seq == 0)
|
if (seq == 0)
|
||||||
{
|
{
|
||||||
break; // ill-formed or truncated: let the byte path diagnose it
|
return pos; // ill-formed or truncated: let the byte path diagnose it
|
||||||
}
|
}
|
||||||
pos += seq;
|
pos += seq;
|
||||||
}
|
}
|
||||||
|
while (pos < n && data[pos] >= 0x80u);
|
||||||
|
}
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,8 +275,7 @@ inline std::size_t find_string_delimiter(const unsigned char* data, std::size_t
|
|||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
for (; i + 8 <= n; i += 8)
|
for (; i + 8 <= n; i += 8)
|
||||||
{
|
{
|
||||||
std::uint64_t v = 0;
|
const std::uint64_t v = read_eight_bytes(data + i);
|
||||||
std::memcpy(&v, data + i, sizeof(v));
|
|
||||||
const std::uint64_t q = v ^ 0x2222222222222222ull;
|
const std::uint64_t q = v ^ 0x2222222222222222ull;
|
||||||
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull;
|
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull;
|
||||||
const std::uint64_t hit = ((q - ones) & ~q & high)
|
const std::uint64_t hit = ((q - ones) & ~q & high)
|
||||||
@@ -282,14 +283,8 @@ inline std::size_t find_string_delimiter(const unsigned char* data, std::size_t
|
|||||||
| ((v - 0x2020202020202020ull) & ~v & high);
|
| ((v - 0x2020202020202020ull) & ~v & high);
|
||||||
if (hit != 0)
|
if (hit != 0)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < 8; ++j)
|
// the lowest flagged byte is the first delimiter (see find_string_special())
|
||||||
{
|
return i + (static_cast<std::size_t>(count_trailing_zeros(hit)) / 8);
|
||||||
const unsigned char c = data[i + j];
|
|
||||||
if (c == '\"' || c == '\\' || c < 0x20u)
|
|
||||||
{
|
|
||||||
return i + j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i < n; ++i)
|
for (; i < n; ++i)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ This class implements a both iterators (iterator and const_iterator) for the
|
|||||||
been set (e.g., by a constructor or a copy assignment). If the iterator is
|
been set (e.g., by a constructor or a copy assignment). If the iterator is
|
||||||
default-constructed, it is *uninitialized* and most methods are undefined.
|
default-constructed, it is *uninitialized* and most methods are undefined.
|
||||||
**The library uses assertions to detect calls on uninitialized iterators.**
|
**The library uses assertions to detect calls on uninitialized iterators.**
|
||||||
@requirement REQ-JSON-01 The class satisfies the following concept requirements:
|
This class satisfies the following concept requirements (REQ-JSON-01):
|
||||||
-
|
-
|
||||||
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
|
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
|
||||||
The iterator that can be moved can be moved in both directions (i.e.
|
The iterator that can be moved can be moved in both directions (i.e.
|
||||||
|
|||||||
@@ -213,11 +213,11 @@ namespace std
|
|||||||
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wmismatched-tags")
|
JSON_HEDLEY_PRAGMA(clang diagnostic ignored "-Wmismatched-tags")
|
||||||
#endif
|
#endif
|
||||||
template<typename IteratorType>
|
template<typename IteratorType>
|
||||||
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
|
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp,bugprone-std-namespace-modification)
|
||||||
: public std::integral_constant<std::size_t, 2> {};
|
: public std::integral_constant<std::size_t, 2> {};
|
||||||
|
|
||||||
template<std::size_t N, typename IteratorType>
|
template<std::size_t N, typename IteratorType>
|
||||||
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
|
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp,bugprone-std-namespace-modification)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using type = decltype(
|
using type = decltype(
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace detail
|
|||||||
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
|
iterator (to create @ref reverse_iterator) and @ref const_iterator (to
|
||||||
create @ref const_reverse_iterator).
|
create @ref const_reverse_iterator).
|
||||||
|
|
||||||
@requirement REQ-JSON-02 The class satisfies the following concept requirements:
|
This class satisfies the following concept requirements (REQ-JSON-02):
|
||||||
-
|
-
|
||||||
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
|
[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
|
||||||
The iterator that can be moved can be moved in both directions (i.e.
|
The iterator that can be moved can be moved in both directions (i.e.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
#include <nlohmann/detail/string_escape.hpp>
|
#include <nlohmann/detail/string_escape.hpp>
|
||||||
|
#include <nlohmann/detail/string_utils.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
@@ -116,7 +117,7 @@ class json_pointer
|
|||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||||
json_pointer& operator/=(std::size_t array_idx)
|
json_pointer& operator/=(std::size_t array_idx)
|
||||||
{
|
{
|
||||||
return *this /= std::to_string(array_idx);
|
return *this /= detail::to_string<string_t>(array_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||||
@@ -277,11 +278,11 @@ class json_pointer
|
|||||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
|
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// only triggered on special platforms (like 32bit), see also
|
// the index does not fit into size_type; on 64-bit platforms this is
|
||||||
// https://github.com/nlohmann/json/pull/2203
|
// only SIZE_MAX itself (see #2203 and #5395)
|
||||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
|
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
|
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<size_type>(res);
|
return static_cast<size_type>(res);
|
||||||
@@ -315,7 +316,7 @@ class json_pointer
|
|||||||
/*!
|
/*!
|
||||||
@brief create and return a reference to the pointed to value
|
@brief create and return a reference to the pointed to value
|
||||||
|
|
||||||
@complexity Linear in the number of reference tokens.
|
Complexity: Linear in the number of reference tokens.
|
||||||
|
|
||||||
@throw parse_error.106 if an array index begins with '0'
|
@throw parse_error.106 if an array index begins with '0'
|
||||||
@throw parse_error.109 if array index is not a number
|
@throw parse_error.109 if array index is not a number
|
||||||
@@ -402,7 +403,7 @@ class json_pointer
|
|||||||
|
|
||||||
@return reference to the JSON value pointed to by the JSON pointer
|
@return reference to the JSON value pointed to by the JSON pointer
|
||||||
|
|
||||||
@complexity Linear in the length of the JSON pointer.
|
Complexity: Linear in the length of the JSON pointer.
|
||||||
|
|
||||||
@throw parse_error.106 if an array index begins with '0'
|
@throw parse_error.106 if an array index begins with '0'
|
||||||
@throw parse_error.109 if an array index was not a number
|
@throw parse_error.109 if an array index was not a number
|
||||||
@@ -746,7 +747,13 @@ class json_pointer
|
|||||||
// "-" always fails the range check
|
// "-" always fails the range check
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
if (JSON_HEDLEY_UNLIKELY(reference_token.empty()))
|
||||||
|
{
|
||||||
|
// an empty reference token is not an array index; array_index()
|
||||||
|
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !('0' <= reference_token[0] && reference_token[0] <= '9')))
|
||||||
{
|
{
|
||||||
// invalid char
|
// invalid char
|
||||||
return false;
|
return false;
|
||||||
@@ -774,7 +781,7 @@ class json_pointer
|
|||||||
// not throw (see #5395), so such a reference token is treated as "not found"
|
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||||
errno = 0; // strtoull() does not reset errno on success
|
errno = 0; // strtoull() does not reset errno on success
|
||||||
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||||
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||||
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -195,13 +195,6 @@
|
|||||||
#define JSON_NO_THREAD_LOCAL 1
|
#define JSON_NO_THREAD_LOCAL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// disable documentation warnings on clang
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
||||||
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// allow disabling exceptions
|
// allow disabling exceptions
|
||||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
||||||
#define JSON_THROW(exception) throw exception
|
#define JSON_THROW(exception) throw exception
|
||||||
@@ -260,7 +253,7 @@
|
|||||||
{ \
|
{ \
|
||||||
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
||||||
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
||||||
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
/* NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
||||||
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
||||||
auto it = std::find_if(std::begin(m), std::end(m), \
|
auto it = std::find_if(std::begin(m), std::end(m), \
|
||||||
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
||||||
@@ -274,7 +267,7 @@
|
|||||||
{ \
|
{ \
|
||||||
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
||||||
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
||||||
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
/* NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
||||||
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
||||||
auto it = std::find_if(std::begin(m), std::end(m), \
|
auto it = std::find_if(std::begin(m), std::end(m), \
|
||||||
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
||||||
@@ -313,7 +306,7 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
{ \
|
{ \
|
||||||
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
||||||
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
||||||
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
/* NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
||||||
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
||||||
auto it = std::find_if(std::begin(m), std::end(m), \
|
auto it = std::find_if(std::begin(m), std::end(m), \
|
||||||
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
||||||
@@ -328,7 +321,7 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
{ \
|
{ \
|
||||||
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
/* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
|
||||||
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
|
||||||
/* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
/* NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) we don't want to depend on <array> */ \
|
||||||
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
|
||||||
auto it = std::find_if(std::begin(m), std::end(m), \
|
auto it = std::find_if(std::begin(m), std::end(m), \
|
||||||
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
|
||||||
@@ -336,7 +329,7 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
return ej_pair.second == j; \
|
return ej_pair.second == j; \
|
||||||
}); \
|
}); \
|
||||||
if (it != std::end(m)) e = it->first; \
|
if (it != std::end(m)) e = it->first; \
|
||||||
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \
|
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace)), &j)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
||||||
@@ -359,6 +352,7 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
|
|
||||||
// Macros to simplify conversion from/to types
|
// Macros to simplify conversion from/to types
|
||||||
|
|
||||||
|
// NLOHMANN_JSON_EXPAND to NLOHMANN_JSON_DOUBLE_PASTE63 are generated by tools/macro_builder (see its README.md)
|
||||||
#define NLOHMANN_JSON_EXPAND( x ) x
|
#define NLOHMANN_JSON_EXPAND( x ) x
|
||||||
#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
|
#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
|
||||||
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
||||||
@@ -621,6 +615,10 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
// arguments, so dispatching on Type,BaseType,member... directly would run out
|
// arguments, so dispatching on Type,BaseType,member... directly would run out
|
||||||
// one slot early and cap the derived-type macros at 62 members instead of the
|
// one slot early and cap the derived-type macros at 62 members instead of the
|
||||||
// 63 that NLOHMANN_JSON_PASTE supports.
|
// 63 that NLOHMANN_JSON_PASTE supports.
|
||||||
|
//
|
||||||
|
// The slot table below (down to the closing NLOHMANN_JSON_TYPE_BODY_SENTINEL))
|
||||||
|
// is generated by tools/macro_builder (see its README.md; run with the
|
||||||
|
// "type_body" argument).
|
||||||
#define NLOHMANN_JSON_TYPE_BODY(Prefix, ...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
#define NLOHMANN_JSON_TYPE_BODY(Prefix, ...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
||||||
Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, \
|
Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, \
|
||||||
Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, \
|
Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, Prefix ## MEMBERS, \
|
||||||
@@ -916,6 +914,6 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef JSON_USE_GLOBAL_UDLS
|
#ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
|
||||||
#define JSON_USE_GLOBAL_UDLS 1
|
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,11 +8,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// restore clang diagnostic settings
|
|
||||||
#if defined(__clang__)
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
#undef JSON_ASSERT
|
#undef JSON_ASSERT
|
||||||
#undef JSON_INTERNAL_CATCH
|
#undef JSON_INTERNAL_CATCH
|
||||||
@@ -25,7 +20,7 @@
|
|||||||
#undef JSON_INLINE_VARIABLE
|
#undef JSON_INLINE_VARIABLE
|
||||||
#undef JSON_NO_UNIQUE_ADDRESS
|
#undef JSON_NO_UNIQUE_ADDRESS
|
||||||
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
#undef JSON_USE_GLOBAL_UDLS
|
#undef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
|
||||||
|
|
||||||
#ifndef JSON_TEST_KEEP_MACROS
|
#ifndef JSON_TEST_KEEP_MACROS
|
||||||
#undef JSON_CATCH
|
#undef JSON_CATCH
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
||||||
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
|
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
|
||||||
@@ -161,11 +160,5 @@ struct static_const
|
|||||||
constexpr T static_const<T>::value;
|
constexpr T static_const<T>::value;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
|
|
||||||
{
|
|
||||||
return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|||||||
@@ -636,6 +636,18 @@ template<typename BasicJsonType, typename CompatibleType>
|
|||||||
struct is_compatible_type
|
struct is_compatible_type
|
||||||
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
|
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
|
||||||
|
|
||||||
|
// a one-element std::tuple holding a reference to BasicJsonType, as created by
|
||||||
|
// std::forward_as_tuple(j); see JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
struct is_basic_json_reference_tuple : std::false_type {};
|
||||||
|
|
||||||
|
template<typename BasicJsonType, typename T>
|
||||||
|
struct is_basic_json_reference_tuple<BasicJsonType, std::tuple<T>>
|
||||||
|
{
|
||||||
|
static constexpr bool value =
|
||||||
|
std::is_reference<T>::value && std::is_same<uncvref_t<T>, BasicJsonType>::value;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||||
struct is_compatible_binary_type
|
struct is_compatible_binary_type
|
||||||
{
|
{
|
||||||
@@ -725,7 +737,7 @@ std::is_constructible <decltype(std::declval<Compare>()(std::declval<A>(), std::
|
|||||||
// avoid their instantiation on all compilers, even when the first operand
|
// avoid their instantiation on all compilers, even when the first operand
|
||||||
// is false. The dispatch on is_json_pointer_of can be removed once the
|
// is false. The dispatch on is_json_pointer_of can be removed once the
|
||||||
// deprecated json_pointer comparison operators have been removed.
|
// deprecated json_pointer comparison operators have been removed.
|
||||||
template<typename Compare, typename A, typename B, bool = is_json_pointer_of<A, B>::value>
|
template<typename Compare, typename A, typename B, bool = is_json_pointer_of<uncvref_t<A>, uncvref_t<B>>::value>
|
||||||
struct is_comparable : std::false_type {};
|
struct is_comparable : std::false_type {};
|
||||||
|
|
||||||
template<typename Compare, typename A, typename B>
|
template<typename Compare, typename A, typename B>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,11 +8,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // copy
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iterator> // back_inserter
|
|
||||||
#include <memory> // shared_ptr, make_shared
|
#include <memory> // shared_ptr, make_shared
|
||||||
#include <string> // basic_string
|
#include <string> // basic_string
|
||||||
|
#include <type_traits> // conditional, integral_constant, is_same
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
@@ -31,6 +30,10 @@ namespace detail
|
|||||||
template<typename CharType> struct output_adapter_protocol
|
template<typename CharType> struct output_adapter_protocol
|
||||||
{
|
{
|
||||||
virtual void write_character(CharType c) = 0;
|
virtual void write_character(CharType c) = 0;
|
||||||
|
/// @param[in] s pointer to the characters to write; binary_writer legitimately
|
||||||
|
/// passes a null pointer together with length 0 for an empty
|
||||||
|
/// string or binary value, so implementations must tolerate that
|
||||||
|
/// @param[in] length number of characters at @a s
|
||||||
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
||||||
virtual ~output_adapter_protocol() = default;
|
virtual ~output_adapter_protocol() = default;
|
||||||
|
|
||||||
@@ -97,7 +100,6 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
|
|||||||
sink.write_character(c);
|
sink.write_character(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
|
||||||
void write_characters(const CharType* s, std::size_t length) override
|
void write_characters(const CharType* s, std::size_t length) override
|
||||||
{
|
{
|
||||||
sink.write_characters(s, length);
|
sink.write_characters(s, length);
|
||||||
@@ -117,12 +119,13 @@ class output_stream_adapter : public output_adapter_protocol<CharType>
|
|||||||
: stream(s)
|
: stream(s)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(portability-template-virtual-member-function)
|
||||||
void write_character(CharType c) override
|
void write_character(CharType c) override
|
||||||
{
|
{
|
||||||
stream.put(c);
|
stream.put(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
// NOLINTNEXTLINE(portability-template-virtual-member-function)
|
||||||
void write_characters(const CharType* s, std::size_t length) override
|
void write_characters(const CharType* s, std::size_t length) override
|
||||||
{
|
{
|
||||||
stream.write(s, static_cast<std::streamsize>(length));
|
stream.write(s, static_cast<std::streamsize>(length));
|
||||||
@@ -147,7 +150,6 @@ class output_string_adapter : public output_adapter_protocol<CharType>
|
|||||||
str.push_back(c);
|
str.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
|
||||||
void write_characters(const CharType* s, std::size_t length) override
|
void write_characters(const CharType* s, std::size_t length) override
|
||||||
{
|
{
|
||||||
str.append(s, length);
|
str.append(s, length);
|
||||||
@@ -190,7 +192,82 @@ class output_adapter_sink
|
|||||||
output_adapter_t<CharType> oa;
|
output_adapter_t<CharType> oa;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename CharType, typename StringType = std::basic_string<CharType>>
|
/// @brief whether std::basic_string<CharType> has a non-deprecated std::char_traits
|
||||||
|
/// specialization, and is therefore usable as output_adapter's default StringType
|
||||||
|
///
|
||||||
|
/// std::char_traits is only guaranteed (and, on some standard libraries, only
|
||||||
|
/// implemented without a deprecation warning) for the character types listed
|
||||||
|
/// below; std::char_traits<T> for any other T (e.g. std::uint8_t, as used by the
|
||||||
|
/// binary writers) is a non-standard extension some standard libraries deprecate.
|
||||||
|
/// See https://github.com/nlohmann/json/issues/5725 item 2.
|
||||||
|
template<typename CharType>
|
||||||
|
struct is_output_adapter_string_char_type : std::integral_constant < bool,
|
||||||
|
std::is_same<CharType, char>::value ||
|
||||||
|
std::is_same<CharType, wchar_t>::value ||
|
||||||
|
std::is_same<CharType, char16_t>::value ||
|
||||||
|
std::is_same<CharType, char32_t>::value
|
||||||
|
#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
|
||||||
|
|| std::is_same<CharType, char8_t>::value
|
||||||
|
#endif
|
||||||
|
> {};
|
||||||
|
|
||||||
|
/// @brief placeholder type for output_adapter's StringType and (with JSON_NO_IO
|
||||||
|
/// undefined) its std::basic_ostream constructor parameter, for CharType
|
||||||
|
/// with no non-deprecated std::char_traits specialization
|
||||||
|
///
|
||||||
|
/// Never actually used: the StringType- and std::basic_ostream-based
|
||||||
|
/// output_adapter constructors are neither documented nor tested for such
|
||||||
|
/// CharType (only the std::vector-based constructor is used for them, by the
|
||||||
|
/// binary writers). Naming std::basic_string<CharType> or
|
||||||
|
/// std::basic_ostream<CharType> anywhere such a constructor would otherwise be
|
||||||
|
/// declared - even as an unused default template argument or an unused,
|
||||||
|
/// never-called overload - instantiates std::char_traits<CharType> merely to
|
||||||
|
/// name the type, which is exactly what triggers the deprecation warning this
|
||||||
|
/// placeholder avoids.
|
||||||
|
template<typename CharType>
|
||||||
|
struct output_adapter_no_string_type {};
|
||||||
|
|
||||||
|
// Select output_adapter's default StringType (and, below, its ostream
|
||||||
|
// constructor's parameter type) via partial specialization, not
|
||||||
|
// std::conditional: std::conditional<B, T, F> requires both T and F to be named
|
||||||
|
// as template arguments up front, which would still instantiate (and thus name)
|
||||||
|
// std::basic_string<CharType> / std::basic_ostream<CharType> for every CharType,
|
||||||
|
// defeating the point. A bool non-type parameter with two specializations only
|
||||||
|
// ever names the type that is actually selected.
|
||||||
|
template<typename CharType, bool = is_output_adapter_string_char_type<CharType>::value>
|
||||||
|
struct output_adapter_default_string_type
|
||||||
|
{
|
||||||
|
using type = output_adapter_no_string_type<CharType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
struct output_adapter_default_string_type<CharType, true>
|
||||||
|
{
|
||||||
|
using type = std::basic_string<CharType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef JSON_NO_IO
|
||||||
|
/// distinct from output_adapter_no_string_type, so the placeholder overloads of
|
||||||
|
/// output_adapter's constructor (used when CharType is not a character type)
|
||||||
|
/// stay distinct overloads instead of colliding into a single redeclaration
|
||||||
|
template<typename CharType>
|
||||||
|
struct output_adapter_no_ostream_type {};
|
||||||
|
|
||||||
|
template<typename CharType, bool = is_output_adapter_string_char_type<CharType>::value>
|
||||||
|
struct output_adapter_ostream_type
|
||||||
|
{
|
||||||
|
using type = output_adapter_no_ostream_type<CharType>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename CharType>
|
||||||
|
struct output_adapter_ostream_type<CharType, true>
|
||||||
|
{
|
||||||
|
using type = std::basic_ostream<CharType>;
|
||||||
|
};
|
||||||
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
|
template < typename CharType, typename StringType =
|
||||||
|
typename output_adapter_default_string_type<CharType>::type >
|
||||||
class output_adapter
|
class output_adapter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -199,7 +276,7 @@ class output_adapter
|
|||||||
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
|
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
|
||||||
|
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
output_adapter(std::basic_ostream<CharType>& s)
|
output_adapter(typename output_adapter_ostream_type<CharType>::type& s)
|
||||||
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
|
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
|
|||||||
@@ -3,24 +3,23 @@
|
|||||||
// | | |__ | | | | | | version 3.12.0
|
// | | |__ | | | | | | version 3.12.0
|
||||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
//
|
//
|
||||||
// SPDX-FileCopyrightText: 2008, 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
|
|
||||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // reverse, remove, fill, find, none_of, min
|
#include <algorithm> // remove, fill, find, none_of, min
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <clocale> // localeconv, lconv
|
#include <clocale> // localeconv, lconv
|
||||||
#include <cmath> // labs, isfinite, isnan, signbit
|
#include <cmath> // isfinite
|
||||||
#include <cstddef> // size_t, ptrdiff_t
|
#include <cstddef> // size_t, ptrdiff_t
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
#include <cstring> // memcpy, memset
|
#include <cstring> // memcpy, memset
|
||||||
|
#include <iterator> // next
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <string> // string, char_traits
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // is_same
|
#include <type_traits> // is_same
|
||||||
#include <utility> // move
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||||
@@ -28,7 +27,6 @@
|
|||||||
#include <nlohmann/detail/input/string_scan.hpp>
|
#include <nlohmann/detail/input/string_scan.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/output/binary_writer.hpp>
|
|
||||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
#include <nlohmann/detail/output/output_adapters.hpp>
|
||||||
#include <nlohmann/detail/recursion_depth_limit.hpp>
|
#include <nlohmann/detail/recursion_depth_limit.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
@@ -67,7 +65,7 @@ class serializer
|
|||||||
@param[in] ichar indentation character to use
|
@param[in] ichar indentation character to use
|
||||||
@param[in] pretty_print_ whether the output shall be pretty-printed
|
@param[in] pretty_print_ whether the output shall be pretty-printed
|
||||||
@param[in] ensure_ascii_ If @a ensure_ascii_ is true, all non-ASCII
|
@param[in] ensure_ascii_ If @a ensure_ascii_ is true, all non-ASCII
|
||||||
characters in the output are escaped with `\uXXXX` sequences, and the
|
characters in the output are escaped with `\\uXXXX` sequences, and the
|
||||||
result consists of ASCII characters only.
|
result consists of ASCII characters only.
|
||||||
@param[in] indent_step_ the indent level
|
@param[in] indent_step_ the indent level
|
||||||
@param[in] error_handler_ how to react on decoding errors
|
@param[in] error_handler_ how to react on decoding errors
|
||||||
@@ -83,7 +81,6 @@ class serializer
|
|||||||
const std::size_t indent_step_ = 0,
|
const std::size_t indent_step_ = 0,
|
||||||
error_handler_t error_handler_ = error_handler_t::strict)
|
error_handler_t error_handler_ = error_handler_t::strict)
|
||||||
: o(&s)
|
: o(&s)
|
||||||
, locale(std::localeconv())
|
|
||||||
, indent_char(ichar)
|
, indent_char(ichar)
|
||||||
, pretty_print(pretty_print_)
|
, pretty_print(pretty_print_)
|
||||||
, ensure_ascii(ensure_ascii_)
|
, ensure_ascii(ensure_ascii_)
|
||||||
@@ -106,9 +103,10 @@ class serializer
|
|||||||
additional parameter. Arrays and objects are serialized without recursion,
|
additional parameter. Arrays and objects are serialized without recursion,
|
||||||
however deeply they are nested.
|
however deeply they are nested.
|
||||||
|
|
||||||
- strings and object keys are escaped using `escape_string()`
|
- strings and object keys are escaped using @ref dump_escaped
|
||||||
- integer numbers are converted implicitly via `operator<<`
|
- integer numbers are converted using a digit-pair lookup table (@ref dump_integer)
|
||||||
- floating-point numbers are converted to a string using `"%g"` format
|
- floating-point numbers are converted to a string using @ref dump_float, which
|
||||||
|
uses `to_chars` for IEEE-754 types and `snprintf` otherwise
|
||||||
- binary values are serialized as objects containing the subtype and the
|
- binary values are serialized as objects containing the subtype and the
|
||||||
byte array
|
byte array
|
||||||
|
|
||||||
@@ -283,128 +281,17 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
case value_t::string:
|
case value_t::string:
|
||||||
{
|
|
||||||
put_char('"');
|
|
||||||
dump_escaped(*val.m_data.m_value.string);
|
|
||||||
put_char('"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
{
|
|
||||||
if (pretty_print)
|
|
||||||
{
|
|
||||||
put_literal("{\n");
|
|
||||||
|
|
||||||
// variable to hold indentation for recursive calls
|
|
||||||
const auto new_indent = next_indent(current_indent, indent_step);
|
|
||||||
|
|
||||||
put_indent(new_indent);
|
|
||||||
|
|
||||||
put_literal("\"bytes\": [");
|
|
||||||
|
|
||||||
if (!val.m_data.m_value.binary->empty())
|
|
||||||
{
|
|
||||||
for (auto i = val.m_data.m_value.binary->cbegin();
|
|
||||||
i != val.m_data.m_value.binary->cend() - 1; ++i)
|
|
||||||
{
|
|
||||||
dump_byte(*i);
|
|
||||||
put_literal(", ");
|
|
||||||
}
|
|
||||||
dump_byte(val.m_data.m_value.binary->back());
|
|
||||||
}
|
|
||||||
|
|
||||||
put_literal("],\n");
|
|
||||||
put_indent(new_indent);
|
|
||||||
|
|
||||||
put_literal("\"subtype\": ");
|
|
||||||
if (val.m_data.m_value.binary->has_subtype())
|
|
||||||
{
|
|
||||||
dump_integer(val.m_data.m_value.binary->subtype());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
put_literal("null");
|
|
||||||
}
|
|
||||||
put_char('\n');
|
|
||||||
put_indent(current_indent);
|
|
||||||
put_char('}');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
put_literal("{\"bytes\":[");
|
|
||||||
|
|
||||||
if (!val.m_data.m_value.binary->empty())
|
|
||||||
{
|
|
||||||
for (auto i = val.m_data.m_value.binary->cbegin();
|
|
||||||
i != val.m_data.m_value.binary->cend() - 1; ++i)
|
|
||||||
{
|
|
||||||
dump_byte(*i);
|
|
||||||
put_char(',');
|
|
||||||
}
|
|
||||||
dump_byte(val.m_data.m_value.binary->back());
|
|
||||||
}
|
|
||||||
|
|
||||||
put_literal("],\"subtype\":");
|
|
||||||
if (val.m_data.m_value.binary->has_subtype())
|
|
||||||
{
|
|
||||||
dump_integer(val.m_data.m_value.binary->subtype());
|
|
||||||
put_char('}');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
put_literal("null}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::boolean:
|
case value_t::boolean:
|
||||||
{
|
|
||||||
if (val.m_data.m_value.boolean)
|
|
||||||
{
|
|
||||||
put_literal("true");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
put_literal("false");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::number_integer:
|
case value_t::number_integer:
|
||||||
{
|
|
||||||
dump_integer(val.m_data.m_value.number_integer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
{
|
|
||||||
dump_integer(val.m_data.m_value.number_unsigned);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
{
|
|
||||||
dump_float(val.m_data.m_value.number_float);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
{
|
|
||||||
put_literal("<discarded>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case value_t::null:
|
case value_t::null:
|
||||||
{
|
default:
|
||||||
put_literal("null");
|
dump_scalar(val, current_indent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -560,9 +447,9 @@ class serializer
|
|||||||
@brief serialize the value @a val, but not the elements of a container
|
@brief serialize the value @a val, but not the elements of a container
|
||||||
|
|
||||||
An object or array with elements is opened and pushed onto @a stack for
|
An object or array with elements is opened and pushed onto @a stack for
|
||||||
@ref dump_internal to walk; everything else - including a binary value,
|
@ref dump_iteratively to walk; everything else - including a binary value,
|
||||||
which looks like an object but has no elements to descend into - is written
|
which looks like an object but has no elements to descend into - is written
|
||||||
out here in full.
|
out in full by @ref dump_scalar.
|
||||||
*/
|
*/
|
||||||
void dump_value(const BasicJsonType& val,
|
void dump_value(const BasicJsonType& val,
|
||||||
const std::size_t current_indent,
|
const std::size_t current_indent,
|
||||||
@@ -620,6 +507,35 @@ class serializer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case value_t::string:
|
||||||
|
case value_t::binary:
|
||||||
|
case value_t::boolean:
|
||||||
|
case value_t::number_integer:
|
||||||
|
case value_t::number_unsigned:
|
||||||
|
case value_t::number_float:
|
||||||
|
case value_t::discarded:
|
||||||
|
case value_t::null:
|
||||||
|
default:
|
||||||
|
dump_scalar(val, current_indent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief serialize the value @a val, which is neither an object nor an array
|
||||||
|
|
||||||
|
Shared by @ref dump_internal and @ref dump_value, so that a value is written
|
||||||
|
the same way however deeply it is nested. A binary value is written out here
|
||||||
|
in full: it looks like an object, but has no elements to descend into.
|
||||||
|
|
||||||
|
@param[in] val value to serialize; not an object or array
|
||||||
|
@param[in] current_indent the indentation of @a val, used for a
|
||||||
|
pretty-printed binary value
|
||||||
|
*/
|
||||||
|
void dump_scalar(const BasicJsonType& val, const std::size_t current_indent)
|
||||||
|
{
|
||||||
|
switch (val.m_data.m_type)
|
||||||
|
{
|
||||||
case value_t::string:
|
case value_t::string:
|
||||||
{
|
{
|
||||||
put_char('"');
|
put_char('"');
|
||||||
@@ -740,6 +656,8 @@ class serializer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case value_t::object: // LCOV_EXCL_LINE
|
||||||
|
case value_t::array: // LCOV_EXCL_LINE
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
@@ -768,11 +686,11 @@ class serializer
|
|||||||
Escape a string by replacing certain special characters by a sequence of an
|
Escape a string by replacing certain special characters by a sequence of an
|
||||||
escape character (backslash) and another character and other control
|
escape character (backslash) and another character and other control
|
||||||
characters by a sequence of "\u" followed by a four-digit hex
|
characters by a sequence of "\u" followed by a four-digit hex
|
||||||
representation. The escaped string is written to output stream @a o.
|
representation. The escaped string is appended to @ref write_buffer.
|
||||||
|
|
||||||
@param[in] s the string to escape
|
@param[in] s the string to escape
|
||||||
|
|
||||||
@complexity Linear in the length of string @a s.
|
Complexity: Linear in the length of string @a s.
|
||||||
*/
|
*/
|
||||||
void dump_escaped(const string_t& s)
|
void dump_escaped(const string_t& s)
|
||||||
{
|
{
|
||||||
@@ -962,7 +880,7 @@ class serializer
|
|||||||
{
|
{
|
||||||
case error_handler_t::strict:
|
case error_handler_t::strict:
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
|
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", detail::hex_byte(byte)), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
case error_handler_t::ignore:
|
case error_handler_t::ignore:
|
||||||
@@ -995,9 +913,9 @@ class serializer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
|
string_buffer[bytes++] = '\xEF';
|
||||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
|
string_buffer[bytes++] = '\xBF';
|
||||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
|
string_buffer[bytes++] = '\xBD';
|
||||||
}
|
}
|
||||||
|
|
||||||
// write buffer and reset index; there must be 13 bytes
|
// write buffer and reset index; there must be 13 bytes
|
||||||
@@ -1054,7 +972,7 @@ class serializer
|
|||||||
{
|
{
|
||||||
case error_handler_t::strict:
|
case error_handler_t::strict:
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s[s.size() - 1] | 0))), nullptr));
|
JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", detail::hex_byte(static_cast<std::uint8_t>(s[s.size() - 1]))), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
case error_handler_t::ignore:
|
case error_handler_t::ignore:
|
||||||
@@ -1276,21 +1194,7 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief convert a byte to a uppercase hex representation
|
* @brief write a lowercase "\\uXXXX" escape sequence into @a string_buffer
|
||||||
* @param[in] byte byte to represent
|
|
||||||
* @return representation ("00".."FF")
|
|
||||||
*/
|
|
||||||
static std::string hex_bytes(std::uint8_t byte)
|
|
||||||
{
|
|
||||||
std::string result = "FF";
|
|
||||||
constexpr const char* nibble_to_hex = "0123456789ABCDEF";
|
|
||||||
result[0] = nibble_to_hex[byte / 16];
|
|
||||||
result[1] = nibble_to_hex[byte % 16];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* @brief write a lowercase "\uXXXX" escape sequence into @a string_buffer
|
|
||||||
*
|
*
|
||||||
* Branch-free replacement for `snprintf(buf, 7, "\\u%04x", codeunit)` in the
|
* Branch-free replacement for `snprintf(buf, 7, "\\u%04x", codeunit)` in the
|
||||||
* string escaping hot path. It writes exactly six characters ('\\', 'u' and
|
* string escaping hot path. It writes exactly six characters ('\\', 'u' and
|
||||||
@@ -1402,7 +1306,7 @@ class serializer
|
|||||||
/*!
|
/*!
|
||||||
@brief dump an integer
|
@brief dump an integer
|
||||||
|
|
||||||
Dump a given integer to output stream @a o. Works internally with
|
Dump a given integer, appending it to @ref write_buffer. Works internally with
|
||||||
@a number_buffer.
|
@a number_buffer.
|
||||||
|
|
||||||
@param[in] x integer number (signed or unsigned) to dump
|
@param[in] x integer number (signed or unsigned) to dump
|
||||||
@@ -1439,7 +1343,7 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use a pointer to fill the buffer
|
// use a pointer to fill the buffer
|
||||||
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto)
|
||||||
|
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
|
||||||
@@ -1493,7 +1397,7 @@ class serializer
|
|||||||
/*!
|
/*!
|
||||||
@brief dump a floating-point number
|
@brief dump a floating-point number
|
||||||
|
|
||||||
Dump a given floating-point number to output stream @a o. Works internally
|
Dump a given floating-point number, appending it to @ref write_buffer. Works internally
|
||||||
with @a number_buffer.
|
with @a number_buffer.
|
||||||
|
|
||||||
@param[in] x floating-point number to dump
|
@param[in] x floating-point number to dump
|
||||||
@@ -1554,21 +1458,28 @@ class serializer
|
|||||||
// check if the buffer was large enough
|
// check if the buffer was large enough
|
||||||
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
|
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
|
||||||
|
|
||||||
|
// look up the locale's thousands separator and decimal point now,
|
||||||
|
// matching what snprintf_float() just used (see lexer::get_decimal_point())
|
||||||
|
const auto* loc = std::localeconv();
|
||||||
|
JSON_ASSERT(loc != nullptr);
|
||||||
|
const char thousands_sep = (loc->thousands_sep == nullptr) ? '\0' : *loc->thousands_sep;
|
||||||
|
const char decimal_point = (loc->decimal_point == nullptr) ? '\0' : *loc->decimal_point;
|
||||||
|
|
||||||
// erase thousands separators
|
// erase thousands separators
|
||||||
if (locale.thousands_sep != '\0')
|
if (thousands_sep != '\0')
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
|
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
|
||||||
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, locale.thousands_sep);
|
const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
|
||||||
std::fill(end, number_buffer.end(), '\0');
|
std::fill(end, number_buffer.end(), '\0');
|
||||||
JSON_ASSERT((end - number_buffer.begin()) <= len);
|
JSON_ASSERT((end - number_buffer.begin()) <= len);
|
||||||
len = (end - number_buffer.begin());
|
len = (end - number_buffer.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert decimal point to '.'
|
// convert decimal point to '.'
|
||||||
if (locale.decimal_point != '\0' && locale.decimal_point != '.')
|
if (decimal_point != '\0' && decimal_point != '.')
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
|
// NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
|
||||||
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), locale.decimal_point);
|
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
|
||||||
if (dec_pos != number_buffer.end())
|
if (dec_pos != number_buffer.end())
|
||||||
{
|
{
|
||||||
*dec_pos = '.';
|
*dec_pos = '.';
|
||||||
@@ -1613,34 +1524,17 @@ class serializer
|
|||||||
*/
|
*/
|
||||||
number_unsigned_t remove_sign(number_integer_t x) noexcept
|
number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||||
{
|
{
|
||||||
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
|
JSON_ASSERT(x < 0);
|
||||||
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the locale's thousand separator and decimal point characters
|
|
||||||
struct locale_chars
|
|
||||||
{
|
|
||||||
explicit locale_chars(const std::lconv* loc) noexcept
|
|
||||||
: thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
|
|
||||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
|
|
||||||
{}
|
|
||||||
|
|
||||||
const char thousands_sep;
|
|
||||||
const char decimal_point;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// the output of the serializer (non-owning; the adapter lives at the call site)
|
/// the output of the serializer (non-owning; the adapter lives at the call site)
|
||||||
output_adapter_protocol<char>* o = nullptr;
|
output_adapter_protocol<char>* o = nullptr;
|
||||||
|
|
||||||
/// a (hopefully) large enough character buffer
|
/// a (hopefully) large enough character buffer
|
||||||
std::array<char, 64> number_buffer{{}};
|
std::array<char, 64> number_buffer{{}};
|
||||||
|
|
||||||
/// computed once from std::localeconv() at construction; @ref
|
|
||||||
/// locale_chars keeps std::localeconv()'s pointer from having to be held
|
|
||||||
/// past the constructor, while still letting these stay const
|
|
||||||
const locale_chars locale;
|
|
||||||
|
|
||||||
/// string buffer
|
/// string buffer
|
||||||
std::array<char, 512> string_buffer{{}};
|
std::array<char, 512> string_buffer{{}};
|
||||||
|
|
||||||
@@ -1650,7 +1544,7 @@ class serializer
|
|||||||
/// whether to pretty-print the output
|
/// whether to pretty-print the output
|
||||||
const bool pretty_print;
|
const bool pretty_print;
|
||||||
|
|
||||||
/// whether to escape non-ASCII characters with \uXXXX sequences
|
/// whether to escape non-ASCII characters with \\uXXXX sequences
|
||||||
const bool ensure_ascii;
|
const bool ensure_ascii;
|
||||||
|
|
||||||
/// the indent level
|
/// the indent level
|
||||||
|
|||||||
@@ -19,11 +19,17 @@ namespace detail
|
|||||||
/*!
|
/*!
|
||||||
@brief the number of nesting levels an operation recurses into
|
@brief the number of nesting levels an operation recurses into
|
||||||
|
|
||||||
Operations that walk a value (serializing, hashing, merging, ...) recurse once
|
Operations that walk a value (copying, comparing, serializing, hashing, merging,
|
||||||
|
...) recurse once
|
||||||
per nesting level, which is fastest, but a value nested deeply enough would
|
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
|
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.
|
whatever lies below with an explicit stack. All of them share this limit.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
@sa https://github.com/nlohmann/json/issues/5387
|
@sa https://github.com/nlohmann/json/issues/5387
|
||||||
*/
|
*/
|
||||||
constexpr std::size_t recursion_depth_limit() noexcept
|
constexpr std::size_t recursion_depth_limit() noexcept
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ inline StringType escape(const StringType& s)
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief string unescaping as described in RFC 6901 (Sect. 4)
|
* @brief string unescaping as described in RFC 6901 (Sect. 4)
|
||||||
* @param[in] s string to unescape
|
* @param[in,out] s string to unescape in place
|
||||||
* @return unescaped string
|
|
||||||
*
|
*
|
||||||
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
|
* Note the order of escaping "~1" to "/" and "~0" to "~" is important.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// | | |__ | | | | | | version 3.12.0
|
// | | |__ | | | | | | version 3.12.0
|
||||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
//
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2008, 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
|
||||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
@@ -36,6 +37,71 @@ StringType to_string(std::size_t value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return a byte as two uppercase hexadecimal digits
|
||||||
|
inline std::string hex_byte(const std::uint8_t byte)
|
||||||
|
{
|
||||||
|
std::string result = "00";
|
||||||
|
constexpr const char* nibble_to_hex = "0123456789ABCDEF";
|
||||||
|
result[0] = nibble_to_hex[byte / 16];
|
||||||
|
result[1] = nibble_to_hex[byte % 16];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
// UTF-8 encoding //
|
||||||
|
///////////////////
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief encode a Unicode code point as UTF-8
|
||||||
|
|
||||||
|
Used to turn a decoded code point back into bytes: by the wide-string input
|
||||||
|
adapters in input_adapters.hpp (one code point per UTF-32 unit, per UTF-16
|
||||||
|
unit outside the surrogate range, and per valid UTF-16 surrogate pair), and
|
||||||
|
by the lexer's `\uXXXX`/`\uXXXX\uYYYY` handling in lexer.hpp. Passing a
|
||||||
|
code point above U+10FFFF, or one in the surrogate range U+D800..U+DFFF, is
|
||||||
|
undefined behavior; callers are expected to have rejected those already
|
||||||
|
(the wide-string adapters pass malformed units through unencoded instead of
|
||||||
|
calling this function, and the lexer rejects unpaired surrogates before
|
||||||
|
reaching it).
|
||||||
|
|
||||||
|
@tparam Out a callable invoked with one byte (as std::uint32_t, 0x00..0xFF)
|
||||||
|
at a time, most significant byte first
|
||||||
|
@param[in] cp the code point to encode (at most U+10FFFF)
|
||||||
|
@param[in] out called once for each byte of the UTF-8 encoding of @a cp
|
||||||
|
*/
|
||||||
|
template<typename Out>
|
||||||
|
void encode_utf8(std::uint32_t cp, Out&& out)
|
||||||
|
{
|
||||||
|
JSON_ASSERT(cp <= 0x10FFFF);
|
||||||
|
|
||||||
|
if (cp < 0x80)
|
||||||
|
{
|
||||||
|
// 1-byte characters: 0xxxxxxx (ASCII)
|
||||||
|
out(cp);
|
||||||
|
}
|
||||||
|
else if (cp <= 0x7FF)
|
||||||
|
{
|
||||||
|
// 2-byte characters: 110xxxxx 10xxxxxx
|
||||||
|
out(0xC0u | (cp >> 6u));
|
||||||
|
out(0x80u | (cp & 0x3Fu));
|
||||||
|
}
|
||||||
|
else if (cp <= 0xFFFF)
|
||||||
|
{
|
||||||
|
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
out(0xE0u | (cp >> 12u));
|
||||||
|
out(0x80u | ((cp >> 6u) & 0x3Fu));
|
||||||
|
out(0x80u | (cp & 0x3Fu));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
out(0xF0u | (cp >> 18u));
|
||||||
|
out(0x80u | ((cp >> 12u) & 0x3Fu));
|
||||||
|
out(0x80u | ((cp >> 6u) & 0x3Fu));
|
||||||
|
out(0x80u | (cp & 0x3Fu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// UTF-8 decoding //
|
// UTF-8 decoding //
|
||||||
///////////////////
|
///////////////////
|
||||||
@@ -51,11 +117,23 @@ This is a single-byte step of a "shift-based" UTF-8 decoder originally
|
|||||||
written by Björn Hoehrmann. See
|
written by Björn Hoehrmann. See
|
||||||
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
|
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
|
||||||
|
|
||||||
This decoder is the single source of truth for UTF-8 validation in this
|
The library checks UTF-8 well-formedness (RFC 3629, section 4) in four
|
||||||
library: it is used both by the serializer (to escape and, in strict mode,
|
places, which differ in speed, diagnostics, and how they read the input:
|
||||||
reject ill-formed UTF-8 when dumping a string) and by the binary readers
|
|
||||||
(to reject ill-formed UTF-8 in CBOR/MessagePack/BSON/UBJSON text strings at
|
- decode() and @ref is_valid_utf8 below: the serializer (to escape and, in
|
||||||
decode time; see @ref is_valid_utf8 below).
|
strict mode, reject ill-formed UTF-8 when dumping a string) and the CBOR,
|
||||||
|
MessagePack, BSON, UBJSON and BJData readers (to reject ill-formed UTF-8 in
|
||||||
|
text strings at decode time).
|
||||||
|
- the per-lead-byte switch in lexer::scan_string(): JSON text, with a
|
||||||
|
diagnostic for each kind of error.
|
||||||
|
- validate_one_utf8() and valid_utf8_prefix() in string_scan.hpp: the lexer's
|
||||||
|
bulk string scan, the bulk path of the BON8 reader, and the BON8 writer.
|
||||||
|
They must accept exactly what the lexer's switch accepts.
|
||||||
|
- the byte path of binary_reader::get_bon8_string(): BON8 input without bulk
|
||||||
|
access, and the bytes the bulk path leaves to it.
|
||||||
|
|
||||||
|
All four must accept the same set of sequences, so a change to one needs a
|
||||||
|
matching change to the others.
|
||||||
|
|
||||||
@param[in,out] state the current decoder state
|
@param[in,out] state the current decoder state
|
||||||
@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
|
@param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
|
||||||
|
|||||||
+817
-329
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <string> // allocator, string
|
||||||
#include <string> // string
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -32,7 +31,7 @@ This serializer ignores the template arguments and uses ADL
|
|||||||
for serialization.
|
for serialization.
|
||||||
*/
|
*/
|
||||||
template<typename T = void, typename SFINAE = void>
|
template<typename T = void, typename SFINAE = void>
|
||||||
struct adl_serializer;
|
struct adl_serializer; // IWYU pragma: keep
|
||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
@@ -48,12 +47,12 @@ template<template<typename U, typename V, typename... Args> class ObjectType =
|
|||||||
adl_serializer,
|
adl_serializer,
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||||
template<typename RefStringType>
|
template<typename RefStringType>
|
||||||
class json_pointer;
|
class json_pointer; // IWYU pragma: keep
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief default specialization
|
@brief default specialization
|
||||||
@@ -64,7 +63,7 @@ using json = basic_json<>;
|
|||||||
/// @brief a minimal map-like container that preserves insertion order
|
/// @brief a minimal map-like container that preserves insertion order
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||||
struct ordered_map;
|
struct ordered_map; // IWYU pragma: keep
|
||||||
|
|
||||||
/// @brief specialization that maintains the insertion order of object keys
|
/// @brief specialization that maintains the insertion order of object keys
|
||||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
#define INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(misc-header-include-cycle): json.hpp includes this header at its end
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
// This header is included at the end of <nlohmann/json.hpp> unless
|
||||||
|
// JSON_NO_AUTOMATIC_UDLS is defined, and can be included on its own after that.
|
||||||
|
// Either way, the library's internal macros are no longer defined here (and the
|
||||||
|
// amalgamation inlines macro_scope.hpp only once), so only standard and public
|
||||||
|
// macros may be used below.
|
||||||
|
|
||||||
|
// declares the literal operator for the given suffix; GCC 4.8 requires a space
|
||||||
|
// between "" and the suffix, which newer compilers deprecate (CWG 2521)
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
#define NLOHMANN_JSON_LITERAL_OPERATOR(suffix) operator""##suffix
|
||||||
|
#else
|
||||||
|
#define NLOHMANN_JSON_LITERAL_OPERATOR(suffix) operator"" suffix
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
inline namespace json_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON values
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json/
|
||||||
|
inline nlohmann::json NLOHMANN_JSON_LITERAL_OPERATOR(_json)(const char* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(s, s + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
||||||
|
reinterpret_cast<const char*>(s) + n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON pointer
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json_pointer/
|
||||||
|
inline nlohmann::json::json_pointer NLOHMANN_JSON_LITERAL_OPERATOR(_json_pointer)(const char* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(s, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace json_literals
|
||||||
|
} // namespace literals
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !defined(JSON_USE_GLOBAL_UDLS) || JSON_USE_GLOBAL_UDLS
|
||||||
|
using nlohmann::literals::json_literals::NLOHMANN_JSON_LITERAL_OPERATOR(_json); // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::NLOHMANN_JSON_LITERAL_OPERATOR(_json_pointer); //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef NLOHMANN_JSON_LITERAL_OPERATOR
|
||||||
|
|
||||||
|
#endif // INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user