mirror of
https://github.com/nlohmann/json.git
synced 2026-10-07 23:17:14 +00:00
Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0908edf8be | ||
|
|
fce8a8949f | ||
|
|
a5f5d3059b | ||
|
|
43fe8928e1 | ||
|
|
3c465beb61 | ||
|
|
e752688b52 | ||
|
|
069ace74af | ||
|
|
c3068e9f95 | ||
|
|
546350440f | ||
|
|
367336c83d | ||
|
|
30e542e52a | ||
|
|
24dd7c63f0 | ||
|
|
e6f32bd28a | ||
|
|
e4e7d657ef | ||
|
|
ef570827e3 | ||
|
|
1c754cfe31 | ||
|
|
ff6f3d7d4a | ||
|
|
675e519966 | ||
|
|
21a69230bd | ||
|
|
0c2329d0e2 | ||
|
|
1a4c9dea73 | ||
|
|
162e13b86f | ||
|
|
69874e4544 | ||
|
|
a7d387a762 | ||
|
|
d41887511b | ||
|
|
9b179cee1e | ||
|
|
6d4543e743 | ||
|
|
5ecb704f6b | ||
|
|
0490778fc3 | ||
|
|
0a365865f9 | ||
|
|
5379e04ce4 | ||
|
|
8a142bc436 | ||
|
|
23d3b373e1 | ||
|
|
c5a7a4b46d | ||
|
|
4f69be80d6 | ||
|
|
8c1f60a45e | ||
|
|
6b4b825af2 |
No files matched your search
@@ -205,6 +205,9 @@ API of the 3.x.y version is broken. This includes:
|
||||
- Changing access specifiers.
|
||||
- Changing default arguments.
|
||||
|
||||
What is and is not covered by this guarantee is described in the
|
||||
[roadmap](https://json.nlohmann.me/community/roadmap/#api-stability).
|
||||
|
||||
Although these guidelines may seem restrictive, they are essential for maintaining the library’s utility.
|
||||
|
||||
Breaking changes may be introduced when they are guarded with a feature macro such as
|
||||
|
||||
@@ -16,6 +16,9 @@ only_commits:
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
# The Visual Studio 2017 jobs compile everything with /std:c++17, so they
|
||||
# only build the C++17 variant of each test, split into two jobs each to
|
||||
# stay below AppVeyor's 60-minute limit per job.
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
configuration: Debug
|
||||
platform: x86
|
||||
@@ -34,7 +37,13 @@ environment:
|
||||
configuration: Release
|
||||
platform: x86
|
||||
CXX_FLAGS: "/permissive- /std:c++17 /utf-8 /W4 /WX"
|
||||
CMAKE_OPTIONS: ""
|
||||
CMAKE_OPTIONS: "-DJSON_TestStandards=17 -DJSON_TestShard=0/2"
|
||||
GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
configuration: Release
|
||||
platform: x86
|
||||
CXX_FLAGS: "/permissive- /std:c++17 /utf-8 /W4 /WX"
|
||||
CMAKE_OPTIONS: "-DJSON_TestStandards=17 -DJSON_TestShard=1/2"
|
||||
GENERATOR: Visual Studio 15 2017
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
@@ -55,7 +64,13 @@ environment:
|
||||
configuration: Release
|
||||
platform: x64
|
||||
CXX_FLAGS: "/permissive- /std:c++17 /Zc:__cplusplus /utf-8 /W4 /WX"
|
||||
CMAKE_OPTIONS: ""
|
||||
CMAKE_OPTIONS: "-DJSON_TestStandards=17 -DJSON_TestShard=0/2"
|
||||
GENERATOR: Visual Studio 15 2017
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
configuration: Release
|
||||
platform: x64
|
||||
CXX_FLAGS: "/permissive- /std:c++17 /Zc:__cplusplus /utf-8 /W4 /WX"
|
||||
CMAKE_OPTIONS: "-DJSON_TestStandards=17 -DJSON_TestShard=1/2"
|
||||
GENERATOR: Visual Studio 15 2017
|
||||
|
||||
init:
|
||||
@@ -66,15 +81,10 @@ install:
|
||||
- if "%platform%"=="x86" set GENERATOR_PLATFORM=Win32
|
||||
|
||||
before_build:
|
||||
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%"
|
||||
- cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On %CMAKE_OPTIONS%
|
||||
|
||||
build_script:
|
||||
- cmake --build . --config "%configuration%" --parallel 2
|
||||
|
||||
test_script:
|
||||
- if "%configuration%"=="Release" ctest -C "%configuration%" --parallel 2 --output-on-failure
|
||||
# On Debug builds, skip test-unicode_all
|
||||
# as it is extremely slow to run and cause
|
||||
# occasional timeouts on AppVeyor.
|
||||
# More info: https://github.com/nlohmann/json/pull/1570
|
||||
- if "%configuration%"=="Debug" ctest --exclude-regex "test-unicode" -C "%configuration%" --parallel 2 --output-on-failure
|
||||
- ctest -C "%configuration%" --parallel 2 --output-on-failure
|
||||
@@ -149,6 +149,13 @@ jobs:
|
||||
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]\+')
|
||||
# The template is what this check verifies the committed natvis
|
||||
# file against, so take it from this PR rather than from the
|
||||
# develop checkout: generate_natvis.py loads the template from its
|
||||
# own directory, and with develop's copy a PR that changes the
|
||||
# template could never pass. Like the macro_builder step above,
|
||||
# this only renders PR content in a job without credentials.
|
||||
cp tools/generate_natvis/nlohmann_json.natvis.j2 $NATVIS_TOOL_DIR/
|
||||
python3 $NATVIS_TOOL_DIR/generate_natvis.py --version "$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH" $MAIN_DIR
|
||||
|
||||
- name: Build patch and check for differences
|
||||
|
||||
@@ -17,11 +17,11 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
macos-14:
|
||||
runs-on: macos-14 # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md
|
||||
macos-15:
|
||||
runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
|
||||
strategy:
|
||||
matrix:
|
||||
xcode: ['15.0.1', '15.1', '15.2', '15.3', '15.4']
|
||||
xcode: ['16.0', '16.1', '16.2', '16.3', '16.4', '26.0.1', '26.1.1', '26.2', '26.3']
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
|
||||
|
||||
@@ -36,11 +36,11 @@ jobs:
|
||||
- name: Test
|
||||
run: cd build ; ctest -j 10 --output-on-failure
|
||||
|
||||
macos-15:
|
||||
runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
|
||||
macos-26:
|
||||
runs-on: macos-26 # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md
|
||||
strategy:
|
||||
matrix:
|
||||
xcode: ['16.0', '16.1', '16.2', '16.3', '16.4', '26.0.1']
|
||||
xcode: ['26.4.1', '26.5', '26.6']
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
|
||||
|
||||
@@ -71,3 +71,38 @@ jobs:
|
||||
run: cmake --build build --parallel 10
|
||||
- name: Test
|
||||
run: cd build ; ctest -j 10 --output-on-failure
|
||||
|
||||
swiftpm:
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Check that Package.swift resolves without a deprecation warning
|
||||
run: swift package dump-package
|
||||
- name: Build the SwiftPM documentation example against this checkout
|
||||
run: |
|
||||
mkdir -p /tmp/json-swiftpm-consumer/Sources/MyLibrary
|
||||
cp docs/mkdocs/docs/integration/swift/example.cpp /tmp/json-swiftpm-consumer/Sources/MyLibrary/example.cpp
|
||||
cat > /tmp/json-swiftpm-consumer/Package.swift << EOF
|
||||
// swift-tools-version: 5.9
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "MyPackage",
|
||||
dependencies: [
|
||||
.package(path: "${{ github.workspace }}")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "MyLibrary",
|
||||
dependencies: [
|
||||
.product(name: "json", package: "json")
|
||||
],
|
||||
publicHeadersPath: "."
|
||||
)
|
||||
]
|
||||
)
|
||||
EOF
|
||||
cd /tmp/json-swiftpm-consumer
|
||||
swift build
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
container: ubuntu:24.04
|
||||
strategy:
|
||||
matrix:
|
||||
target: [ci_cmake_flags, ci_test_diagnostics, ci_test_diagnostic_positions, ci_test_noexceptions, ci_test_noimplicitconversions, ci_test_legacycomparison, ci_test_noglobaludls, ci_test_disableenumserialization, ci_test_disabletuplereferenceconversion, ci_test_skiplibraryversioncheck, ci_test_simdutf, ci_test_strict_nul_handling, ci_test_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_delete_deprecated_functions, ci_test_no_thread_local]
|
||||
steps:
|
||||
- name: Install build-essential
|
||||
run: apt-get update ; apt-get install -y build-essential unzip wget git
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
# older GCC docker images (4, 5, 6) fail to check out code
|
||||
compiler: ['7', '8', '9', '10', '11', '12', '13', '14', '15', 'latest']
|
||||
compiler: ['7', '8', '9', '10', '11', '12', '13', '14', '15', '16', 'latest']
|
||||
container: gcc:${{ matrix.compiler }}
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build build --parallel 10
|
||||
- name: Test
|
||||
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
|
||||
run: cd build ; ctest -j 10 -C Debug --output-on-failure
|
||||
|
||||
clang-cl-12:
|
||||
runs-on: windows-2022
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
- name: Build
|
||||
run: cmake --build build --config Debug --parallel 10
|
||||
- name: Test
|
||||
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
|
||||
run: cd build ; ctest -j 10 -C Debug --output-on-failure
|
||||
|
||||
ci_module_cpp20:
|
||||
runs-on: windows-2022
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"_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.",
|
||||
"_comment_pulse": "Pulse stops exploring paths after pulse-max-disjuncts (default 20). With the default, basic_json::replace_value() (destroy + assert_invariant) exceeds the limit, Pulse loses the stored type, and reports false NULLPTR_DEREFERENCE findings for get_ptr() results in tests/src/unit-pointer_access.cpp.",
|
||||
"pulse-max-disjuncts": 40,
|
||||
"fail-on-issue": true,
|
||||
"disable-issue-type": [
|
||||
"PULSE_UNNECESSARY_COPY_ASSIGNMENT",
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: json
|
||||
Upstream-Contact: Niels Lohmann <mail@nlohmann.me>
|
||||
Source: https://github.com/nlohmann/json
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
License: MIT
|
||||
|
||||
Files: include/nlohmann/thirdparty/hedley.hpp
|
||||
Copyright: 2016-2021 Evan Nemerson <evan@nemerson.com>
|
||||
License: CC0
|
||||
|
||||
Files: include/nlohmann/detail/meta/cpp_future.hpp
|
||||
Copyright: 2013-2026 Niels Lohmann <https://nlohmann.me> and 2018 The Abseil Authors
|
||||
License: MIT AND Apache-2.0
|
||||
|
||||
Files: tests/thirdparty/doctest/*
|
||||
Copyright: 2016-2023 Viktor Kirilov
|
||||
License: MIT
|
||||
|
||||
Files: tests/thirdparty/fifo_map/*
|
||||
Copyright: 2015-2017 Niels Lohmann
|
||||
License: MIT
|
||||
|
||||
Files: tests/thirdparty/imapdl/*
|
||||
Copyright: 2017 Georg Sauthoff <mail@gms.tf>
|
||||
License: GPL-3.0-only
|
||||
|
||||
Files: tools/amalgamate/*
|
||||
Copyright: 2012 Erik Edlund <erik.edlund@32767.se>
|
||||
License: BSD-3-Clause
|
||||
|
||||
Files: tools/gdb_pretty_printer/*
|
||||
Copyright: 2020 Hannes Domani <https://github.com/ssbssa>
|
||||
License: MIT
|
||||
@@ -80,6 +80,7 @@ cc_library(
|
||||
name = "singleheader-json",
|
||||
hdrs = [
|
||||
"single_include/nlohmann/json.hpp",
|
||||
"single_include/nlohmann/json_fwd.hpp",
|
||||
],
|
||||
includes = ["single_include"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ title: "JSON for Modern C++"
|
||||
version: 3.12.0
|
||||
date-released: 2025-04-07
|
||||
license: MIT
|
||||
repository-code: "https://github.com/nlohmann"
|
||||
repository-code: "https://github.com/nlohmann/json"
|
||||
url: https://json.nlohmann.me
|
||||
+10
-1
@@ -42,8 +42,11 @@ endif()
|
||||
## OPTIONS
|
||||
##
|
||||
|
||||
# Build the tests by default only for the main project and only if the tests
|
||||
# directory exists (the release archive json.tar.xz does not contain it).
|
||||
# VERSION_GREATER_EQUAL is not available in older CMake (< 3.7)
|
||||
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13))
|
||||
if(${MAIN_PROJECT} AND (${CMAKE_VERSION} VERSION_EQUAL 3.13 OR ${CMAKE_VERSION} VERSION_GREATER 3.13)
|
||||
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
|
||||
set(JSON_BuildTests_INIT ON)
|
||||
else()
|
||||
set(JSON_BuildTests_INIT OFF)
|
||||
@@ -62,6 +65,7 @@ option(JSON_MultipleHeaders "Use non-amalgamated version of the l
|
||||
option(JSON_SystemInclude "Include as system headers (skip for clang-tidy)." OFF)
|
||||
option(JSON_StrictNulHandling "Build with strict NUL-byte handling enabled." OFF)
|
||||
option(JSON_StrictBinaryUTF8 "Build with UTF-8 checks in the CBOR, UBJSON, BJData, and BSON writers enabled." OFF)
|
||||
option(JSON_DeleteDeprecatedFunctions "Delete the deprecated functions instead of only deprecating them." OFF)
|
||||
|
||||
if (JSON_CI)
|
||||
include(ci)
|
||||
@@ -123,6 +127,10 @@ if (JSON_StrictBinaryUTF8)
|
||||
message(STATUS "Strict UTF-8 checks in binary writers enabled (JSON_STRICT_BINARY_UTF8=1)")
|
||||
endif()
|
||||
|
||||
if (JSON_DeleteDeprecatedFunctions)
|
||||
message(STATUS "Deprecated functions are deleted (JSON_DELETE_DEPRECATED_FUNCTIONS=1)")
|
||||
endif()
|
||||
|
||||
if (JSON_Diagnostic_Positions)
|
||||
message(STATUS "Diagnostic positions enabled (JSON_DIAGNOSTIC_POSITIONS=1)")
|
||||
endif()
|
||||
@@ -159,6 +167,7 @@ target_compile_definitions(
|
||||
$<$<BOOL:${JSON_LegacyDiscardedValueComparison}>:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1>
|
||||
$<$<BOOL:${JSON_StrictNulHandling}>:JSON_STRICT_NUL_HANDLING=1>
|
||||
$<$<BOOL:${JSON_StrictBinaryUTF8}>:JSON_STRICT_BINARY_UTF8=1>
|
||||
$<$<BOOL:${JSON_DeleteDeprecatedFunctions}>:JSON_DELETE_DEPRECATED_FUNCTIONS=1>
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
|
||||
@@ -196,19 +196,19 @@ Further documentation:
|
||||
|
||||
## REUSE
|
||||
|
||||
### `.reuse/dep5`
|
||||
### `REUSE.toml`
|
||||
|
||||
The file defines the licenses of certain third-party components in the repository. The root `Makefile` contains a target `reuse` that checks for compliance.
|
||||
|
||||
Further documentation:
|
||||
|
||||
- [DEP5](https://reuse.software/spec-3.2/#dep5-deprecated)
|
||||
- [REUSE.toml](https://reuse.software/spec-3.3/#reusetoml)
|
||||
- [reuse command-line tool](https://pypi.org/project/reuse/)
|
||||
- [documentation of linting](https://reuse.readthedocs.io/en/stable/man/reuse-lint.html)
|
||||
- [REUSE](http://reuse.software)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The filename `.reuse/dep5` is predetermined by REUSE. Alternatively, a `REUSE.toml` file can be used.
|
||||
> The filename `REUSE.toml` is predetermined by REUSE. Alternatively, a `.reuse/dep5` file (deprecated) can be used.
|
||||
|
||||
### `.reuse/templates`
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# find GNU sed to use `-i` parameter
|
||||
SED:=$(shell command -v gsed || which sed)
|
||||
|
||||
# find GNU tar to use `--sort` and `--pax-option` parameters
|
||||
TAR:=$(shell command -v gtar || which tar)
|
||||
|
||||
|
||||
##########################################################################
|
||||
# source files
|
||||
@@ -174,8 +177,8 @@ ChangeLog.md:
|
||||
# archive is created according to the advices of <https://reproducible-builds.org/docs/archives/>.
|
||||
json.tar.xz:
|
||||
mkdir json
|
||||
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include -type f) json
|
||||
gtar --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
|
||||
rsync -R $(shell find LICENSE.MIT nlohmann_json.natvis CMakeLists.txt cmake/*.in include single_include src/modules -type f) json
|
||||
$(TAR) --sort=name --mtime="@$(shell git log -1 --pretty=%ct)" --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime --create --file - json | xz --compress -9e --threads=2 - > json.tar.xz
|
||||
rm -fr json
|
||||
|
||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import PackageDescription
|
||||
let package = Package(
|
||||
name: "nlohmann-json",
|
||||
platforms: [
|
||||
.iOS(.v12), .macOS(.v10_13), .tvOS(.v12), .watchOS(.v4), .visionOS(.v1)
|
||||
.iOS(.v12), .macOS(.v10_13), .tvOS(.v12), .watchOS(.v9), .visionOS(.v1)
|
||||
],
|
||||
products: [
|
||||
.library(name: "json", targets: ["json"])
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[](https://coveralls.io/github/nlohmann/json?branch=develop)
|
||||
[](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://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:json)
|
||||
[](https://issues.oss-fuzz.com/issues?q=project:json)
|
||||
[](https://wandbox.org/permlink/1mp10JbaANo6FUc7)
|
||||
[](https://json.nlohmann.me)
|
||||
[](https://raw.githubusercontent.com/nlohmann/json/develop/LICENSE.MIT)
|
||||
@@ -361,7 +361,7 @@ std::cout << j_string << " == " << serialized_string << std::endl;
|
||||
|
||||
[`.dump()`](https://json.nlohmann.me/api/basic_json/dump/) returns the originally stored string value.
|
||||
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
|
||||
#### To/from streams (e.g., files, string streams)
|
||||
|
||||
@@ -1202,15 +1202,18 @@ language bindings, format converters, and the like. See the curated [Ecosystem](
|
||||
|
||||
Though it's 2026 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
|
||||
|
||||
- GCC 4.8 - 14.2 (and possibly later)
|
||||
- Clang 3.4 - 21.0 (and possibly later)
|
||||
- Apple Clang 9.1 - 16.0 (and possibly later)
|
||||
- Intel C++ Compiler 17.0.2 (and possibly later)
|
||||
- Nvidia CUDA Compiler 11.0.221 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
|
||||
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
|
||||
- Microsoft Visual C++ 2019 / Build Tools 16.3.1+1def00d3d (and possibly later)
|
||||
- Microsoft Visual C++ 2022 / Build Tools 19.30.30709.0 (and possibly later)
|
||||
- GCC 4.8 - 16.2 (and possibly later)
|
||||
- Clang 3.4 - 22.1 (and possibly later)
|
||||
- Apple Clang 15.0 - 21.0 (and possibly later)
|
||||
- Intel C++ Compiler Classic (icpc) 2021.10
|
||||
- Intel oneAPI DPC++/C++ Compiler (icpx) 2025.3 (and possibly later)
|
||||
- NVIDIA CUDA Compiler (nvcc) 11.8 - 12.6 (and possibly later)
|
||||
- NVIDIA HPC SDK C++ Compiler (nvc++) 25.5 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / MSVC 19.0 (and possibly later)
|
||||
- Microsoft Visual C++ 2017 / MSVC 19.16 (and possibly later)
|
||||
- Microsoft Visual C++ 2019 / MSVC 19.29 (and possibly later)
|
||||
- Microsoft Visual C++ 2022 / MSVC 19.44 (and possibly later)
|
||||
- Microsoft Visual C++ 2026 / MSVC 19.51 (and possibly later)
|
||||
|
||||
I would be happy to learn about other compilers/versions.
|
||||
|
||||
@@ -1393,7 +1396,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 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 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
|
||||
- The class contains an adapted version of the Eisel-Lemire algorithm and its table of powers of five 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">
|
||||
|
||||
@@ -1401,7 +1404,7 @@ The library is compliant to version 3.3 of the [**REUSE specification**](https:/
|
||||
|
||||
- Every source file contains an SPDX copyright header.
|
||||
- The full text of all licenses used in the repository can be found in the `LICENSES` folder.
|
||||
- File `.reuse/dep5` contains an overview of all files' copyrights and licenses.
|
||||
- File `REUSE.toml` contains an overview of all files' copyrights and licenses.
|
||||
- Run `pipx run reuse lint` to verify the project's REUSE compliance and `pipx run reuse spdx` to generate a SPDX SBOM.
|
||||
|
||||
## Contact
|
||||
@@ -1914,7 +1917,7 @@ The library supports **Unicode input** as follows:
|
||||
- [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library.
|
||||
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
||||
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://json.nlohmann.me/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
- To store wide strings (e.g., `std::wstring`), you need to convert them to a UTF-8 encoded `std::string` before, see [an example](https://json.nlohmann.me/home/faq/#wide-string-handling).
|
||||
|
||||
### Comments in JSON
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
version = 1
|
||||
SPDX-PackageName = "json"
|
||||
SPDX-PackageSupplier = "Niels Lohmann <mail@nlohmann.me>"
|
||||
SPDX-PackageDownloadLocation = "https://github.com/nlohmann/json"
|
||||
|
||||
[[annotations]]
|
||||
path = "**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2013-2026 Niels Lohmann <https://nlohmann.me>"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "include/nlohmann/thirdparty/hedley.hpp"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2016-2021 Evan Nemerson <evan@nemerson.com>"
|
||||
SPDX-License-Identifier = "CC0"
|
||||
|
||||
[[annotations]]
|
||||
path = "include/nlohmann/detail/meta/cpp_future.hpp"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2013-2026 Niels Lohmann <https://nlohmann.me> and 2018 The Abseil Authors"
|
||||
SPDX-License-Identifier = "MIT AND Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "tests/thirdparty/doctest/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2016-2023 Viktor Kirilov"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "tests/thirdparty/fifo_map/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2015-2017 Niels Lohmann"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "tests/thirdparty/imapdl/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2017 Georg Sauthoff <mail@gms.tf>"
|
||||
SPDX-License-Identifier = "GPL-3.0-only"
|
||||
|
||||
[[annotations]]
|
||||
path = "tools/amalgamate/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2012 Erik Edlund <erik.edlund@32767.se>"
|
||||
SPDX-License-Identifier = "BSD-3-Clause"
|
||||
|
||||
[[annotations]]
|
||||
path = "tools/gdb_pretty_printer/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2020 Hannes Domani <https://github.com/ssbssa>"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
+23
-8
@@ -249,6 +249,20 @@ add_custom_target(ci_test_strict_nul_handling
|
||||
COMMENT "Compile and test with strict NUL-byte handling enabled"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Delete the deprecated functions.
|
||||
###############################################################################
|
||||
|
||||
add_custom_target(ci_test_delete_deprecated_functions
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON -DJSON_DeleteDeprecatedFunctions=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_delete_deprecated_functions
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_delete_deprecated_functions
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_delete_deprecated_functions && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with the deprecated functions deleted"
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Disable global UDLs.
|
||||
###############################################################################
|
||||
@@ -362,7 +376,7 @@ add_custom_target(ci_test_coverage
|
||||
# Sanitizers.
|
||||
###############################################################################
|
||||
|
||||
set(CLANG_CXX_FLAGS_SANITIZER "-g -O1 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fno-sanitize=unsigned-integer-overflow -fno-sanitize=unsigned-shift-base")
|
||||
set(CLANG_CXX_FLAGS_SANITIZER "-g -O1 -fsanitize=address -fsanitize=undefined -fsanitize=integer -fsanitize=nullability -fno-omit-frame-pointer -fno-sanitize-recover=all -fno-sanitize=unsigned-integer-overflow -fno-sanitize=unsigned-shift-base -fsanitize-ignorelist=${PROJECT_SOURCE_DIR}/cmake/clang_sanitizer_ignorelist.txt")
|
||||
|
||||
add_custom_target(ci_test_clang_sanitizer
|
||||
COMMAND CXX=${CLANG_TOOL} CXXFLAGS=${CLANG_CXX_FLAGS_SANITIZER} ${CMAKE_COMMAND}
|
||||
@@ -442,13 +456,14 @@ add_custom_target(ci_test_single_header
|
||||
# Valgrind.
|
||||
###############################################################################
|
||||
|
||||
# The Unicode test (~17M assertions) is too slow under Valgrind.
|
||||
add_custom_target(ci_test_valgrind
|
||||
COMMAND CXX=${GCC_TOOL} ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_Valgrind=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_valgrind
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_valgrind
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_valgrind && ${CMAKE_CTEST_COMMAND} -L valgrind --parallel ${N} --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_valgrind && ${CMAKE_CTEST_COMMAND} -L valgrind --exclude-regex "test-unicode" --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with Valgrind"
|
||||
)
|
||||
|
||||
@@ -705,7 +720,7 @@ 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
|
||||
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_StrictNulHandling JSON_StrictBinaryUTF8)
|
||||
JSON_StrictNulHandling JSON_StrictBinaryUTF8 JSON_DeleteDeprecatedFunctions)
|
||||
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})
|
||||
|
||||
@@ -773,7 +788,7 @@ foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 cla
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
|
||||
${ADDITIONAL_FLAGS}
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER}
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_${COMPILER} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with ${COMPILER}"
|
||||
)
|
||||
endif()
|
||||
@@ -787,7 +802,7 @@ add_custom_target(ci_test_compiler_default
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_compiler_default
|
||||
${ADDITIONAL_FLAGS}
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_compiler_default --parallel ${N}
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_default && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" -LE git_required --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_compiler_default && ${CMAKE_CTEST_COMMAND} --parallel ${N} -LE git_required --output-on-failure
|
||||
COMMENT "Compile and test with default C++ compiler"
|
||||
)
|
||||
|
||||
@@ -825,7 +840,7 @@ add_custom_target(ci_icpc
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpc
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpc
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with ICPC"
|
||||
)
|
||||
|
||||
@@ -836,7 +851,7 @@ add_custom_target(ci_icpx
|
||||
-DJSON_BuildTests=ON -DJSON_FastTests=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_icpx
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_icpx
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpx && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode" --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_icpx && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
COMMENT "Compile and test with ICPX (Intel oneAPI DPC++/C++)"
|
||||
)
|
||||
|
||||
@@ -872,7 +887,7 @@ add_custom_target(ci_nvhpc
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_nvhpc
|
||||
# the pipes are escaped so the surrounding shell passes them to ctest verbatim
|
||||
# instead of treating them as shell pipe operators
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_nvhpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-unicode\\|test-comparison_cpp20\\|test-comparison_legacy_cpp20\\|test-constructor1_cpp11\\|test-deserialization_cpp20" --output-on-failure
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_nvhpc && ${CMAKE_CTEST_COMMAND} --parallel ${N} --exclude-regex "test-comparison_cpp20\\|test-comparison_legacy_cpp20\\|test-constructor1_cpp11\\|test-deserialization_cpp20" --output-on-failure
|
||||
COMMENT "Compile and test with NVIDIA HPC SDK (nvc++)"
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Sanitizer ignore list for ci_test_clang_sanitizer (-fsanitize-ignorelist).
|
||||
#
|
||||
# libstdc++ 14's <format> declares `_Scanner(basic_string_view<_CharT>, size_t __nargs = -1)`, so every std::format
|
||||
# call converts -1 to size_t, which -fsanitize=integer reports as implicit-integer-sign-change. This is
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119429, not a bug in this library. Only that check and only <format> are
|
||||
# excluded, so implicit sign changes in the library and the tests are still reported.
|
||||
[implicit-integer-sign-change]
|
||||
src:*/include/c++/*/format
|
||||
@@ -48,6 +48,7 @@ cc_library(
|
||||
name = "singleheader-json",
|
||||
hdrs = [
|
||||
"single_include/nlohmann/json.hpp",
|
||||
"single_include/nlohmann/json_fwd.hpp",
|
||||
],
|
||||
includes = ["single_include"],
|
||||
visibility = ["//visibility:public"],
|
||||
|
||||
@@ -64,7 +64,7 @@ if(MODE STREQUAL "undef")
|
||||
# recipe is self-contained and its output is byte-stable across reruns.
|
||||
# The embedded SPDX tags below are part of the *generated* file's
|
||||
# content, not a REUSE header for this .cmake script itself (which is
|
||||
# already covered by the blanket "Files: *" rule in .reuse/dep5) -- keep
|
||||
# already covered by the blanket path = "**" rule in REUSE.toml) -- keep
|
||||
# them wrapped in REUSE-IgnoreStart/End so `reuse lint` does not try to
|
||||
# parse "MIT\n")" as this file's own SPDX-License-Identifier value.
|
||||
# REUSE-IgnoreStart
|
||||
|
||||
@@ -131,6 +131,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_string', 'Meth
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::to_ubjson', 'Function', 'api/basic_json/to_ubjson/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value', 'Method', 'api/basic_json/value/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::value_t', 'Enum', 'api/basic_json/value_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::with_t', 'Type', 'api/basic_json/with_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::~basic_json', 'Method', 'api/basic_json/~basic_json/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json', 'Class', 'api/json/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('json_pointer', 'Class', 'api/json_pointer/index.html');
|
||||
@@ -219,6 +220,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('Supported Macros', 'Guide', '
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_ASSERT', 'Macro', 'api/macros/json_assert/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_BRACE_INIT_COPY_SEMANTICS', 'Macro', 'api/macros/json_brace_init_copy_semantics/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_CATCH_USER', 'Macro', 'api/macros/json_throw_user/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_DELETE_DEPRECATED_FUNCTIONS', 'Macro', 'api/macros/json_delete_deprecated_functions/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_DISABLE_ENUM_SERIALIZATION', 'Macro', 'api/macros/json_disable_enum_serialization/index.html');
|
||||
@@ -249,6 +251,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('JSON_TRY_USER', 'Macro', 'api
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_GLOBAL_UDLS', 'Macro', 'api/macros/json_use_global_udls/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_IMPLICIT_CONVERSIONS', 'Macro', 'api/macros/json_use_implicit_conversions/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON', 'Macro', 'api/macros/json_use_legacy_discarded_value_comparison/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS', 'Macro', 'api/macros/json_use_objects_for_enum_keyed_maps/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('JSON_USE_SIMDUTF', 'Macro', 'api/macros/json_use_simdutf/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('Macros', 'Macro', 'api/macros/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE', 'Macro', 'api/macros/nlohmann_define_derived_type/index.html');
|
||||
|
||||
@@ -9,10 +9,10 @@ enum class cbor_tag_handler_t
|
||||
};
|
||||
```
|
||||
|
||||
This enumeration is used in the [`from_cbor`](from_cbor.md) function to choose how to treat tags:
|
||||
This enumeration is used in [`from_cbor`](from_cbor.md) and [`sax_parse`](sax_parse.md) to choose how to treat tags:
|
||||
|
||||
error
|
||||
: throw a `parse_error` exception in case of a tag
|
||||
: report a parse error in case of a tag (the `from_cbor` overloads throw a `parse_error` exception by default)
|
||||
|
||||
ignore
|
||||
: ignore tags
|
||||
|
||||
@@ -8,7 +8,7 @@ static basic_json diff(const basic_json& source,
|
||||
Creates a [JSON Patch](http://jsonpatch.com) so that value `source` can be changed into the value `target` by calling
|
||||
[`patch`](patch.md) function.
|
||||
|
||||
For two JSON values `source` and `target`, the following code yields always `#!cpp true`:
|
||||
For two JSON values `source` and `target`, the following code always yields `#!cpp true`:
|
||||
```cpp
|
||||
source.patch(diff(source, target)) == target;
|
||||
```
|
||||
@@ -27,7 +27,7 @@ a JSON patch to convert the `source` to `target`
|
||||
|
||||
## Exception safety
|
||||
|
||||
Strong guarantee: if an exception is thrown, there are no changes in the JSON value.
|
||||
Strong guarantee: `source` and `target` are never modified.
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -120,3 +120,12 @@ Linear in the size of the input.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
- Added `error_handler` parameter in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- Overload (2) replaces calls to `from_bjdata` with a pointer and a length as first two parameters, which has been
|
||||
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
`#!cpp from_bjdata(ptr, len, ...);` with `#!cpp from_bjdata(ptr, ptr+len, ...);`.
|
||||
|
||||
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
|
||||
function.
|
||||
@@ -106,3 +106,12 @@ Linear in the size of the input.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
|
||||
!!! warning "Deprecation"
|
||||
|
||||
- Overload (2) replaces calls to `from_bon8` with a pointer and a length as first two parameters, which has been
|
||||
deprecated in version 3.13.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
||||
`#!cpp from_bon8(ptr, len, ...);` with `#!cpp from_bon8(ptr, ptr+len, ...);`.
|
||||
|
||||
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
|
||||
function.
|
||||
@@ -109,6 +109,9 @@ The class satisfies the following concept requirements:
|
||||
- **initializer_list_t** - type for initializer lists of `basic_json` values
|
||||
- [**input_format_t**](input_format_t.md) - type to choose the format to parse
|
||||
- [**json_sax_t**](../json_sax/index.md) - type for SAX events
|
||||
- [**with_object_t, with_array_t, with_string_t, with_boolean_t, with_integers_t, with_float_t, with_allocator_t,
|
||||
with_json_serializer_t, with_binary_t, with_base_class_t**](with_t.md) - types to create a `basic_json` type with
|
||||
one (or two) replaced template parameters
|
||||
|
||||
### Exceptions
|
||||
|
||||
|
||||
@@ -23,10 +23,9 @@ type to use.
|
||||
## Template parameters
|
||||
|
||||
`NumberFloatType`
|
||||
: the type to store floating-point numbers. The parser converts `#!cpp float`, `#!cpp double`, and a
|
||||
`#!cpp long double` that is IEEE 754 binary64 itself and other `#!cpp long double` formats with
|
||||
`#!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
|
||||
: the type to store floating-point numbers. Parsing and serialization are implemented in terms of
|
||||
`#!cpp std::strtof`/`#!cpp std::strtod`/`#!cpp std::strtold` and `#!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`,
|
||||
because they have no encoding for `#!cpp long double`. See
|
||||
[Template Parameter Requirements](../../features/types/template_parameters.md#numberfloattype).
|
||||
@@ -56,6 +55,10 @@ This implementation does exactly follow this approach, as it uses double precisi
|
||||
smaller than `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` will be stored as NaN internally
|
||||
and be serialized to `null`.
|
||||
|
||||
During deserialization (from JSON text or any of the binary formats), a finite number that does not fit into
|
||||
`number_float_t` is rejected with [`out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406), for
|
||||
example a double-precision number in a binary format when `number_float_t` is `#!cpp float`.
|
||||
|
||||
### Storage
|
||||
|
||||
Floating-point number values are stored directly inside a `basic_json` type.
|
||||
|
||||
@@ -47,8 +47,9 @@ With the default values for `NumberIntegerType` (`std::int64_t`), the default va
|
||||
|
||||
When the default type is used, the maximal integer number that can be stored is `9223372036854775807` (INT64_MAX) and
|
||||
the minimal integer number that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers that are out of
|
||||
range will yield over/underflow when used in a constructor. During deserialization, too large or small integer numbers
|
||||
will automatically be stored as [`number_unsigned_t`](number_unsigned_t.md) or [`number_float_t`](number_float_t.md).
|
||||
range will yield over/underflow when used in a constructor. During deserialization (from JSON text or any of the binary
|
||||
formats), too large or small integer numbers 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:
|
||||
> 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
|
||||
|
||||
@@ -48,8 +48,9 @@ With the default values for `NumberUnsignedType` (`std::uint64_t`), the default
|
||||
|
||||
When the default type is used, the maximal integer number that can be stored is `18446744073709551615` (UINT64_MAX) and
|
||||
the minimal integer number that can be stored is `0`. Integer numbers that are out of range will yield over/underflow
|
||||
when used in a constructor. During deserialization, too large or small integer numbers will automatically be stored
|
||||
as [`number_integer_t`](number_integer_t.md) or [`number_float_t`](number_float_t.md).
|
||||
when used in a constructor. During deserialization (from JSON text or any of the binary formats), too large or small
|
||||
integer numbers will automatically be stored 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:
|
||||
> 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
|
||||
|
||||
@@ -8,7 +8,8 @@ static bool sax_parse(InputType&& i,
|
||||
input_format_t format = input_format_t::json,
|
||||
const bool strict = true,
|
||||
const bool ignore_comments = false,
|
||||
const bool ignore_trailing_commas = false);
|
||||
const bool ignore_trailing_commas = false,
|
||||
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);
|
||||
|
||||
// (2)
|
||||
template<class IteratorType, class SAX, class SentinelType = IteratorType>
|
||||
@@ -17,13 +18,14 @@ static bool sax_parse(IteratorType first, SentinelType last,
|
||||
input_format_t format = input_format_t::json,
|
||||
const bool strict = true,
|
||||
const bool ignore_comments = false,
|
||||
const bool ignore_trailing_commas = false);
|
||||
const bool ignore_trailing_commas = false,
|
||||
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error);
|
||||
```
|
||||
|
||||
Read from input and generate SAX events
|
||||
|
||||
1. Read from a compatible input.
|
||||
2. Read from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
|
||||
2. Read from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support).
|
||||
|
||||
The value_type of the iterator must be an integral type with a size of 1, 2, or 4 bytes, which will be interpreted
|
||||
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
|
||||
@@ -82,6 +84,10 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
|
||||
: whether trailing commas in arrays or objects should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
|
||||
(`#!cpp false`); (optional, `#!cpp false` by default)
|
||||
|
||||
`tag_handler` (in)
|
||||
: how to handle CBOR tags; see [`cbor_tag_handler_t`](cbor_tag_handler_t.md). Ignored for formats other than CBOR
|
||||
(optional, `cbor_tag_handler_t::error` by default).
|
||||
|
||||
`first` (in)
|
||||
: iterator to the start of a character range
|
||||
|
||||
@@ -137,6 +143,7 @@ A UTF-8 byte order mark is silently ignored.
|
||||
- Added in version 3.2.0.
|
||||
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
||||
- Added `ignore_trailing_commas` in version 3.13.0.
|
||||
- Added `tag_handler` in version 3.13.0.
|
||||
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
||||
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
||||
- `JSON_PRECISE_STREAM_POSITION` added in version 3.13.0 to optionally leave a `#!cpp std::istream` positioned right
|
||||
|
||||
@@ -7,8 +7,14 @@ namespace std {
|
||||
```
|
||||
|
||||
Return a hash value for a JSON object. The hash function tries to rely on `std::hash` where possible. Furthermore, the
|
||||
type of the JSON value is taken into account to have different hash values for `#!json null`, `#!cpp 0`, `#!cpp 0U`, and
|
||||
`#!cpp false`, etc.
|
||||
type of the JSON value is taken into account, so `#!json null`, `#!cpp false`, and numbers may hash differently from
|
||||
each other. Numbers that compare equal under [`operator==`](operator_eq.md) always hash equally, regardless of
|
||||
whether they are stored as signed integer, unsigned integer, or floating-point number.
|
||||
|
||||
Numbers are hashed by their value converted to `number_float_t`. Converting an integer to `number_float_t` therefore
|
||||
keeps its hash, but converting a floating-point number to an integer type is lossy and can change it: `#!cpp 0.5`
|
||||
converts to `#!cpp 0`, which need not have the same hash. Unequal numbers can also share a hash value, for example two
|
||||
large integers that convert to the same `number_float_t`.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -26,7 +32,8 @@ type of the JSON value is taken into account to have different hash values for `
|
||||
--8<-- "examples/std_hash.output"
|
||||
```
|
||||
|
||||
Note the output is platform-dependent.
|
||||
The hash values shown are examples only. They depend on the platform, the compiler, and the compiler version, and
|
||||
they can change between versions of this library. Do not persist them or rely on specific values.
|
||||
|
||||
## See also
|
||||
|
||||
@@ -36,3 +43,5 @@ type of the JSON value is taken into account to have different hash values for `
|
||||
|
||||
- Added in version 1.0.0.
|
||||
- Extended for arbitrary basic_json types in version 3.10.5.
|
||||
- Numbers that compare equal hash equally since version 3.13.0; before, `#!cpp 0`, `#!cpp 0U`, and `#!cpp 0.0` had
|
||||
different hash values.
|
||||
@@ -68,6 +68,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if a string or object key in `j` is
|
||||
not valid UTF-8 and `error_handler` is `strict` (the default only if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled)
|
||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is
|
||||
discarded; example: `"cannot serialize discarded value to BJData"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -119,4 +121,6 @@ Linear in the size of the JSON value `j`.
|
||||
- BJData version parameter (for draft3 binary encoding) added in version 3.12.0.
|
||||
- Added `error_handler` parameter in version 3.13.0. Its default, `keep`, writes the bytes of a string or object key
|
||||
that is not valid UTF-8 unchanged, as before; `strict` (the default if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316`.
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316`.
|
||||
- Throws `type_error.321` for a discarded value since version 3.13.0; previously, a discarded value nested in an
|
||||
array or object was silently skipped, producing invalid BJData.
|
||||
@@ -58,6 +58,9 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if a string or object key is
|
||||
not valid UTF-8 and `error_handler` is `strict` (the default only if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled)
|
||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if a value nested in `j` is discarded
|
||||
(the top-level value itself is covered by `type_error.317` above, since it must be an object); example:
|
||||
`"cannot serialize discarded value to BSON"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -110,6 +113,8 @@ pass before anything is written.
|
||||
- Throws `out_of_range.412` and `out_of_range.415` 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.
|
||||
- Throws `type_error.321` for a discarded value nested in `j` since version 3.13.0; previously, it was silently
|
||||
skipped, producing a document whose declared size did not match what was actually written.
|
||||
- Added `error_handler` parameter in version 3.13.0. Its default, `keep`, writes the bytes of a string or object key
|
||||
that is not valid UTF-8 unchanged, as before; `strict` (the default if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316` before anything
|
||||
|
||||
@@ -49,6 +49,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if a string or object key in `j` is
|
||||
not valid UTF-8 and `error_handler` is `strict` (the default only if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled)
|
||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is
|
||||
discarded; example: `"cannot serialize discarded value to CBOR"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -86,3 +88,5 @@ Linear in the size of the JSON value `j`.
|
||||
- Added `error_handler` parameter in version 3.13.0. Its default, `keep`, writes the bytes of a string or object key
|
||||
that is not valid UTF-8 unchanged, as before; `strict` (the default if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316`.
|
||||
- Throws `type_error.321` for a discarded value since version 3.13.0; previously, a discarded value nested in an
|
||||
array or object was silently skipped, producing invalid CBOR.
|
||||
@@ -54,6 +54,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
`"subtype 70000 is too large for the MessagePack ext type (max 255)"`
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if a string or object key in `j` is
|
||||
not valid UTF-8 and `error_handler` is `strict`
|
||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is
|
||||
discarded; example: `"cannot serialize discarded value to MessagePack"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -108,3 +110,5 @@ Linear in the size of the JSON value `j`.
|
||||
- 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`.
|
||||
- Throws `type_error.321` for a discarded value since version 3.13.0; previously, a discarded value nested in an
|
||||
array or object was silently skipped, producing invalid MessagePack.
|
||||
@@ -61,6 +61,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
- Throws [type_error.316](../../home/exceptions.md#jsonexceptiontype_error316) if a string or object key in `j` is
|
||||
not valid UTF-8 and `error_handler` is `strict` (the default only if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled)
|
||||
- Throws [type_error.321](../../home/exceptions.md#jsonexceptiontype_error321) if `j` or a value nested in it is
|
||||
discarded; example: `"cannot serialize discarded value to UBJSON"`
|
||||
|
||||
## Complexity
|
||||
|
||||
@@ -112,3 +114,5 @@ Linear in the size of the JSON value `j`.
|
||||
- Added `error_handler` parameter in version 3.13.0. Its default, `keep`, writes the bytes of a string or object key
|
||||
that is not valid UTF-8 unchanged, as before; `strict` (the default if
|
||||
[`JSON_STRICT_BINARY_UTF8`](../macros/json_strict_binary_utf8.md) is enabled) throws `type_error.316`.
|
||||
- Throws `type_error.321` for a discarded value since version 3.13.0; previously, a discarded value nested in an
|
||||
array or object was silently skipped, producing invalid UBJSON.
|
||||
@@ -0,0 +1,136 @@
|
||||
# <small>nlohmann::basic_json::</small>with_t
|
||||
|
||||
Member alias templates `with_object_t`, `with_array_t`, `with_string_t`, `with_boolean_t`, `with_integers_t`,
|
||||
`with_float_t`, `with_allocator_t`, `with_json_serializer_t`, `with_binary_t`, and `with_base_class_t`.
|
||||
|
||||
```cpp
|
||||
template<template<typename, typename, typename...> class ObjectType2>
|
||||
using with_object_t = basic_json<ObjectType2, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<template<typename, typename...> class ArrayType2>
|
||||
using with_array_t = basic_json<ObjectType, ArrayType2, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<class StringType2>
|
||||
using with_string_t = basic_json<ObjectType, ArrayType, StringType2, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<class BooleanType2>
|
||||
using with_boolean_t = basic_json<ObjectType, ArrayType, StringType, BooleanType2,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<class NumberIntegerType2, class NumberUnsignedType2>
|
||||
using with_integers_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType2, NumberUnsignedType2, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<class NumberFloatType2>
|
||||
using with_float_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType2,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<template<typename> class AllocatorType2>
|
||||
using with_allocator_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType2, JSONSerializer, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<template<typename, typename = void> class JSONSerializer2>
|
||||
using with_json_serializer_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer2, BinaryType, CustomBaseClass>;
|
||||
|
||||
template<class BinaryType2>
|
||||
using with_binary_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType2, CustomBaseClass>;
|
||||
|
||||
template<class CustomBaseClass2>
|
||||
using with_base_class_t = basic_json<ObjectType, ArrayType, StringType, BooleanType,
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType,
|
||||
AllocatorType, JSONSerializer, BinaryType, CustomBaseClass2>;
|
||||
```
|
||||
|
||||
These member alias templates make it easier to create a `basic_json` type that is identical to the current type except
|
||||
for one (or, in the case of `with_integers_t`, two) of its [template parameters](index.md#template-parameters).
|
||||
Spelling out all 11 template parameters of `basic_json` just to change a single one is verbose and error-prone; these
|
||||
aliases only require the replacement type(s).
|
||||
|
||||
with_object_t<ObjectType2>
|
||||
: replaces `ObjectType`
|
||||
|
||||
with_array_t<ArrayType2>
|
||||
: replaces `ArrayType`
|
||||
|
||||
with_string_t<StringType2>
|
||||
: replaces `StringType`
|
||||
|
||||
with_boolean_t<BooleanType2>
|
||||
: replaces `BooleanType`
|
||||
|
||||
with_integers_t<NumberIntegerType2, NumberUnsignedType2>
|
||||
: replaces both `NumberIntegerType` and `NumberUnsignedType`; the two are combined into a single alias because they
|
||||
are usually changed together (for instance, when switching to fixed-width integer types)
|
||||
|
||||
with_float_t<NumberFloatType2>
|
||||
: replaces `NumberFloatType`
|
||||
|
||||
with_allocator_t<AllocatorType2>
|
||||
: replaces `AllocatorType`
|
||||
|
||||
with_json_serializer_t<JSONSerializer2>
|
||||
: replaces `JSONSerializer`
|
||||
|
||||
with_binary_t<BinaryType2>
|
||||
: replaces `BinaryType`
|
||||
|
||||
with_base_class_t<CustomBaseClass2>
|
||||
: replaces `CustomBaseClass`; see also [`json_base_class_t`](json_base_class_t.md)
|
||||
|
||||
## Notes
|
||||
|
||||
All other template parameters are kept unchanged, so the resulting type still uses, for instance, the same
|
||||
`ObjectType` unless `with_object_t` itself is used.
|
||||
|
||||
The aliases are members of every `basic_json` specialization, including [`ordered_json`](../ordered_json.md), and the
|
||||
type they produce is again a `basic_json` specialization. They can therefore be chained to replace several template
|
||||
parameters at once:
|
||||
|
||||
```cpp
|
||||
using my_json = nlohmann::json::with_integers_t<int, unsigned int>::with_float_t<float>;
|
||||
using my_ordered_json = nlohmann::ordered_json::with_string_t<std::wstring>;
|
||||
```
|
||||
|
||||
The result is the same type as spelling out all template parameters, so the order of the chained aliases does not
|
||||
matter. For instance, `nlohmann::json::with_object_t<nlohmann::ordered_map>` is `nlohmann::ordered_json`.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The following code shows how `with_object_t` can be used to create a JSON type that stores object elements in a
|
||||
`std::map` and therefore keeps them sorted by key, unlike the default type which preserves insertion order
|
||||
only when `nlohmann::ordered_json` is used.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/with_t.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/with_t.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [basic_json](index.md#template-parameters) - the template parameters that can be replaced
|
||||
- [json_base_class_t](json_base_class_t.md) - the type used for `CustomBaseClass`
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -58,6 +58,13 @@ header. See also the [macro overview page](../../features/macros.md).
|
||||
- [**JSON_DISABLE_ENUM_SERIALIZATION**](json_disable_enum_serialization.md) - switch off default serialization/deserialization functions for enums
|
||||
- [**JSON_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_OBJECTS_FOR_ENUM_KEYED_MAPS**](json_use_objects_for_enum_keyed_maps.md) - opt in to storing maps with enum
|
||||
keys as objects
|
||||
|
||||
## Deprecated functions
|
||||
|
||||
- [**JSON_DELETE_DEPRECATED_FUNCTIONS**](json_delete_deprecated_functions.md) - opt in to deleting the deprecated
|
||||
functions ahead of their removal in version 4.0.0
|
||||
|
||||
## Comparison behavior
|
||||
|
||||
|
||||
@@ -50,9 +50,11 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
```
|
||||
|
||||
Code that relies on these producing arrays must use `json::array()` instead (see below). Lists with more than one
|
||||
element, and a single `[string, value]` pair such as `{{"key", "value"}}`, which still creates an object, are not
|
||||
affected. The library's own conversions are not affected either: for example, `std::tuple<int>{5}` still becomes
|
||||
`[5]`.
|
||||
element, and a single `[string, value]` pair *written as a braced list*, such as `{{"key", "value"}}`, which still
|
||||
creates an object, are not affected. This exception is based on how the pair is written, not on the shape of its
|
||||
value: an existing JSON value that happens to be a two-element array with a string as its first element, such as
|
||||
`json arr = {"key", 42};`, is still copied by `json j{arr};` rather than turned into an object. The library's own
|
||||
conversions are not affected either: for example, `std::tuple<int>{5}` still becomes `[5]`.
|
||||
|
||||
!!! note "ABI compatibility"
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
|
||||
```cpp
|
||||
#define JSON_DELETE_DEPRECATED_FUNCTIONS /* value */
|
||||
```
|
||||
|
||||
When defined to `1`, all [deprecated functions](../../community/roadmap.md#removal-of-deprecated-functions) of the
|
||||
library are declared as deleted (`= delete`) instead of only being marked as deprecated. Code that still calls one of
|
||||
them no longer compiles. This way, you can find all calls that need to be replaced before version 4.0.0 removes these
|
||||
functions; the [migration guide](../../integration/migration_guide.md#replace-deprecated-functions) describes how.
|
||||
|
||||
A deleted function, unlike a removed one, still takes part in overload resolution. A call that would select it
|
||||
therefore fails to compile instead of silently selecting another overload. This matters for the deprecated
|
||||
`from_*(ptr, len)` overloads of [`from_cbor`](../basic_json/from_cbor.md), [`from_msgpack`](../basic_json/from_msgpack.md),
|
||||
[`from_ubjson`](../basic_json/from_ubjson.md), [`from_bjdata`](../basic_json/from_bjdata.md),
|
||||
[`from_bon8`](../basic_json/from_bon8.md), and [`from_bson`](../basic_json/from_bson.md): without them, a call like
|
||||
`from_cbor(ptr, len)` would compile, read `ptr` as a NUL-terminated string, and convert `len` to the `strict` parameter.
|
||||
|
||||
The macro does not affect the deprecated legacy comparison of discarded values, which is controlled by
|
||||
[`JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](json_use_legacy_discarded_value_comparison.md).
|
||||
|
||||
## Default definition
|
||||
|
||||
The default value is `0` (disabled, the deprecated functions can still be called, and the compiler warns about it).
|
||||
|
||||
```cpp
|
||||
#define JSON_DELETE_DEPRECATED_FUNCTIONS 0
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
!!! info "CMake option"
|
||||
|
||||
The macro can also be set with the CMake option
|
||||
[`JSON_DeleteDeprecatedFunctions`](../../integration/cmake.md#json_deletedeprecatedfunctions) (`OFF` by default).
|
||||
|
||||
!!! warning "Opt-in only"
|
||||
|
||||
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
|
||||
effect. Define it for the whole project to avoid different declarations of the same class in different
|
||||
translation units.
|
||||
|
||||
!!! note "ABI compatibility"
|
||||
|
||||
The macro only turns calls that compile into calls that do not; it does not change the layout or the behavior of
|
||||
any type. Its value is therefore not encoded in the [namespace](../../features/namespace.md).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: default behavior (macro not defined)"
|
||||
|
||||
Without the macro, the deprecated overload is called, and the compiler warns about it:
|
||||
|
||||
```cpp
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::vector<std::uint8_t> v = {0x82, 0x01, 0x02};
|
||||
auto j = json::from_cbor(v.data(), v.size());
|
||||
// warning: 'from_cbor' is deprecated: Since 3.8.0; use from_cbor(ptr, ptr + len)
|
||||
}
|
||||
```
|
||||
|
||||
??? example "Example: deleted deprecated functions (macro defined to 1)"
|
||||
|
||||
With the macro, the call does not compile:
|
||||
|
||||
```cpp
|
||||
#define JSON_DELETE_DEPRECATED_FUNCTIONS 1
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
int main()
|
||||
{
|
||||
const std::vector<std::uint8_t> v = {0x82, 0x01, 0x02};
|
||||
auto j = json::from_cbor(v.data(), v.size());
|
||||
// error: call to deleted function 'from_cbor'
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Roadmap: removal of deprecated functions](../../community/roadmap.md#removal-of-deprecated-functions) - the
|
||||
deprecated functions and the version they were deprecated in
|
||||
- [Migration guide: replace deprecated functions](../../integration/migration_guide.md#replace-deprecated-functions) -
|
||||
how to replace each deprecated function
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
- Planned to be removed in version 4.0.0, which removes the deprecated functions. The deprecated `from_*(ptr, len)`
|
||||
overloads stay deleted in version 4.0.0.
|
||||
@@ -112,3 +112,4 @@ The default value is `0` (disabled — existing behavior is preserved).
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
- Planned to become the default (with the macro removed) in version 4.0.0.
|
||||
@@ -44,7 +44,7 @@ By default, implicit conversions are enabled.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: implicit conversion"
|
||||
??? example "Example: implicit and explicit conversions"
|
||||
|
||||
This is an example for an implicit conversion:
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
|
||||
```cpp
|
||||
#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS /* value */
|
||||
```
|
||||
|
||||
When defined to `1`, maps whose keys are enums (such as `std::map<E, T>` or `std::unordered_map<E, T>`) are stored as
|
||||
JSON objects, using the enum's own conversion for the keys. By default, they are stored as arrays of `[key, value]`
|
||||
pairs.
|
||||
|
||||
## Default definition
|
||||
|
||||
The default value is `0` (disabled — existing behavior is preserved).
|
||||
|
||||
```cpp
|
||||
#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
!!! note "Background"
|
||||
|
||||
JSON object keys are strings, so a map is only stored as an object if its keys can be converted to a string type.
|
||||
Enums are not, even if [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps them to strings, so a
|
||||
map with enum keys becomes an array of `[key, value]` pairs:
|
||||
|
||||
```json
|
||||
[["stopped", "aa"], ["completed", "bb"]]
|
||||
```
|
||||
|
||||
With this macro, the same map becomes an object
|
||||
(see [#4378](https://github.com/nlohmann/json/issues/4378)):
|
||||
|
||||
```json
|
||||
{"completed": "bb", "stopped": "aa"}
|
||||
```
|
||||
|
||||
!!! note "Maps with non-unique keys"
|
||||
|
||||
Maps that allow duplicate keys, such as `std::multimap<E, T>` or `std::unordered_multimap<E, T>`, are not affected
|
||||
by the macro and are still stored as arrays of `[key, value]` pairs, as an object cannot hold duplicate keys.
|
||||
|
||||
!!! note "Reading"
|
||||
|
||||
Reading is not affected by the macro: a map with enum keys can always be read from both an array of pairs and an
|
||||
object. For the latter, each key is converted to the enum with its `from_json` function, e.g., the one defined by
|
||||
[`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md). Data written without the macro can therefore
|
||||
still be read after enabling it.
|
||||
|
||||
!!! warning "Keys must serialize to distinct strings"
|
||||
|
||||
Each key is converted with the enum's `to_json` function. If a key is not converted to a string (for instance, an
|
||||
enum without [`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md), which is stored as an integer, or an
|
||||
enumerator mapped to `nullptr`), [`type_error.302`](../../home/exceptions.md#jsonexceptiontype_error302) is thrown.
|
||||
If two keys are converted to the same string (for instance, because
|
||||
[`NLOHMANN_JSON_SERIALIZE_ENUM`](nlohmann_json_serialize_enum.md) maps an unlisted enumerator to the first entry),
|
||||
[`type_error.318`](../../home/exceptions.md#jsonexceptiontype_error318) is thrown. In both cases, the target value
|
||||
is not changed.
|
||||
|
||||
!!! warning "Opt-in only"
|
||||
|
||||
This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no effect.
|
||||
|
||||
!!! note "ABI compatibility"
|
||||
|
||||
The value of this macro is encoded in the [namespace](../../features/namespace.md) (tag `_ekmo`), resulting in
|
||||
distinct symbol names. Translation units compiled with and without it can therefore be linked into the same program
|
||||
without One Definition Rule (ODR) violations, but they cannot exchange instances of library types.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: default behavior (macro not defined)"
|
||||
|
||||
Without the macro, a map with enum keys is stored as an array of pairs:
|
||||
|
||||
```cpp
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
enum TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED };
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, {
|
||||
{TS_STOPPED, "stopped"},
|
||||
{TS_RUNNING, "running"},
|
||||
{TS_COMPLETED, "completed"},
|
||||
})
|
||||
|
||||
int main()
|
||||
{
|
||||
std::map<TaskState, std::string> m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}};
|
||||
|
||||
json j = m;
|
||||
// j is [["stopped","aa"],["completed","bb"]]
|
||||
}
|
||||
```
|
||||
|
||||
??? example "Example: objects for enum-keyed maps (macro defined to 1)"
|
||||
|
||||
With the macro, the same map is stored as an object:
|
||||
|
||||
```cpp
|
||||
#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 1
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
enum TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED };
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState, {
|
||||
{TS_STOPPED, "stopped"},
|
||||
{TS_RUNNING, "running"},
|
||||
{TS_COMPLETED, "completed"},
|
||||
})
|
||||
|
||||
int main()
|
||||
{
|
||||
std::map<TaskState, std::string> m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}};
|
||||
|
||||
json j = m;
|
||||
// j is {"completed":"bb","stopped":"aa"}
|
||||
|
||||
auto m2 = j.get<std::map<TaskState, std::string>>();
|
||||
// m2 == m
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Specializing enum conversion](../../features/enum_conversion.md)
|
||||
- [**NLOHMANN_JSON_SERIALIZE_ENUM**](nlohmann_json_serialize_enum.md) - serialize/deserialize an enum
|
||||
- [**NLOHMANN_JSON_SERIALIZE_ENUM_STRICT**](nlohmann_json_serialize_enum_strict.md) - serialize/deserialize an enum with
|
||||
exceptions
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -41,6 +41,9 @@ inline void from_json(const BasicJsonType& j, type& e);
|
||||
conversion. Select this default pair carefully. See example 1 below.
|
||||
- If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the
|
||||
list will be returned when converting to or from JSON. See example 2 below.
|
||||
- Maps with enum keys (e.g., `std::map<ENUM_TYPE, T>`) are stored as arrays of `[key, value]` pairs by default.
|
||||
Define [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) to store them as objects
|
||||
with the converted keys. Such maps can be read from both forms.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -80,6 +83,7 @@ inline void from_json(const BasicJsonType& j, type& e);
|
||||
- [Specializing enum conversion](../../features/enum_conversion.md)
|
||||
- [`NLOHMANN_JSON_SERIALIZE_ENUM_STRICT`](./nlohmann_json_serialize_enum_strict.md)
|
||||
- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md)
|
||||
- [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md)
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ inline void from_json(const BasicJsonType& j, type& e);
|
||||
`"enum value out of range for <type>"`.
|
||||
- If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the
|
||||
list will be returned when converting to or from JSON. See example 2 below.
|
||||
- Maps with enum keys (e.g., `std::map<ENUM_TYPE, T>`) are stored as arrays of `[key, value]` pairs by default.
|
||||
Define [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md) to store them as objects
|
||||
with the converted keys. Such maps can be read from both forms.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -99,6 +102,7 @@ inline void from_json(const BasicJsonType& j, type& e);
|
||||
- [Specializing enum conversion](../../features/enum_conversion.md)
|
||||
- [`NLOHMANN_JSON_SERIALIZE_ENUM`](./nlohmann_json_serialize_enum.md)
|
||||
- [`JSON_DISABLE_ENUM_SERIALIZATION`](json_disable_enum_serialization.md)
|
||||
- [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](json_use_objects_for_enum_keyed_maps.md)
|
||||
|
||||
## Version history
|
||||
|
||||
|
||||
@@ -21,17 +21,18 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
||||
|
||||
| Compiler | Architecture | Operating System | CI |
|
||||
|----------------------------------------------|--------------|-----------------------------------|-----------|
|
||||
| AppleClang 15.0.0.15000040; Xcode 15.0.1 | arm64 | macOS 14.7.2 (Sonoma) | GitHub |
|
||||
| AppleClang 15.0.0.15000100; Xcode 15.1 | arm64 | macOS 14.7.2 (Sonoma) | GitHub |
|
||||
| AppleClang 15.0.0.15000100; Xcode 15.2 | arm64 | macOS 14.7.2 (Sonoma) | GitHub |
|
||||
| AppleClang 15.0.0.15000309; Xcode 15.3 | arm64 | macOS 14.7.2 (Sonoma) | GitHub |
|
||||
| AppleClang 15.0.0.15000309; Xcode 15.4 | arm64 | macOS 14.7.2 (Sonoma) | GitHub |
|
||||
| AppleClang 16.0.0.16000026; Xcode 16 | arm64 | macOS 15.2 (Sequoia) | GitHub |
|
||||
| AppleClang 16.0.0.16000026; Xcode 16.1 | arm64 | macOS 15.2 (Sequoia) | GitHub |
|
||||
| AppleClang 16.0.0.16000026; Xcode 16.2 | arm64 | macOS 15.2 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000013; Xcode 16.3 | arm64 | macOS 15.5 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000013; Xcode 16.4 | arm64 | macOS 15.5 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000319; Xcode 26.0.1 | arm64 | macOS 15.5 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000404; Xcode 26.1.1 | arm64 | macOS 15.7.9 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000603; Xcode 26.2 | arm64 | macOS 15.7.9 (Sequoia) | GitHub |
|
||||
| AppleClang 17.0.0.17000604; Xcode 26.3 | arm64 | macOS 15.7.9 (Sequoia) | GitHub |
|
||||
| AppleClang 21.0.0.21000099; Xcode 26.4.1 | arm64 | macOS 26.6.2 (Tahoe) | GitHub |
|
||||
| AppleClang 21.0.0.21000101; Xcode 26.5 | arm64 | macOS 26.6.2 (Tahoe) | GitHub |
|
||||
| AppleClang 21.0.0.21000101; Xcode 26.6 | arm64 | macOS 26.6.2 (Tahoe) | GitHub |
|
||||
| Clang 3.4.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| Clang 3.5.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| Clang 3.6.2 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
@@ -89,7 +90,7 @@ Note: Some modern features (like C++20 ranges or filesystem support) may be disa
|
||||
| GNU 13.3.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 16.1.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 16.2.0 | x86_64 | Ubuntu 22.04.1 LTS | GitHub |
|
||||
| GNU 16.1.0 | arm64 | Ubuntu 24.04 | 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 |
|
||||
|
||||
@@ -25,9 +25,7 @@ work items are tracked in the [GitHub milestones](https://github.com/nlohmann/js
|
||||
|
||||
## What the project will not do
|
||||
|
||||
- **Break the public API of version 3.x.** See the
|
||||
[contribution guidelines](https://github.com/nlohmann/json/blob/develop/.github/CONTRIBUTING.md#break-the-public-api)
|
||||
for what counts as a breaking change.
|
||||
- **Break the public API of version 3.x.** See [API stability](#api-stability) for what this covers.
|
||||
- **Require a newer C++ standard than C++11.**
|
||||
- **Break JSON conformance** or enable non-standard extensions by default.
|
||||
- **Add dependencies** or require a build step. The library remains header-only, and the single header
|
||||
@@ -35,6 +33,32 @@ work items are tracked in the [GitHub milestones](https://github.com/nlohmann/js
|
||||
- **Trade simplicity for speed or memory efficiency.** Performance improvements are welcome, but the library is not
|
||||
meant to compete with the fastest JSON libraries, see [Design goals](../home/design_goals.md).
|
||||
|
||||
## API stability
|
||||
|
||||
Releases follow [semantic versioning](https://semver.org): a minor or patch release of version 3.x does not break code
|
||||
that uses the public API. In particular, a 3.x release does not:
|
||||
|
||||
- change the signature of a function (its parameter types, return type, number of parameters, or the const-ness of a
|
||||
member function);
|
||||
- remove or rename a function or class;
|
||||
- change which exceptions a function throws, or the [exception ids](../home/exceptions.md);
|
||||
- change access specifiers or default arguments.
|
||||
|
||||
Exceptions to these rules, for instance when fixing a bug requires changing the exception a function throws, are
|
||||
documented in the [release notes](../home/releases.md).
|
||||
|
||||
The following are **not** part of the public API and may change in any release, including patch releases:
|
||||
|
||||
- The text of exception messages returned by `what()`. Use the [exception id](../home/exceptions.md) to tell errors
|
||||
apart.
|
||||
- The ABI, including `sizeof(basic_json)` and the memory layout of its values. Recompile your code when you upgrade the
|
||||
library. The [versioned inline namespace](../features/namespace.md) turns mixing versions into a link error.
|
||||
- Everything in namespace `nlohmann::detail`, and macros and type traits that are not documented in the
|
||||
[API reference](../api/basic_json/index.md).
|
||||
|
||||
Changes that would break the public API are only added behind a macro whose default keeps the 3.x behavior, see
|
||||
[Version 4.0](#version-40).
|
||||
|
||||
## Version 4.0
|
||||
|
||||
There is no release date for version 4.0 yet. Proposals that need a major version, for instance stricter type
|
||||
@@ -64,6 +88,8 @@ The following macros guard changes that are planned to become the default in ver
|
||||
| [`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md) | `0` | `1`: reading from a stream does not consume the character after a number | – | 3.13.0 |
|
||||
| [`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md) | `0` | `1`: a NUL byte in the input is a parse error instead of the end of input | [`JSON_StrictNulHandling`](../integration/cmake.md#json_strictnulhandling) | 3.13.0 |
|
||||
| [`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) | `0` | `1`: `to_cbor`, `to_ubjson`, `to_bjdata`, and `to_bson` throw for strings that are not valid UTF-8 by default | [`JSON_StrictBinaryUTF8`](../integration/cmake.md#json_strictbinaryutf8) | 3.13.0 |
|
||||
| [`JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md) | `0` | `1`: a `basic_json` value can no longer be created from a one-element tuple of a reference to it, such as `std::forward_as_tuple(j)`| [`JSON_DisableTupleReferenceConversion`](../integration/cmake.md#json_disabletuplereferenceconversion) | 3.13.0 |
|
||||
| [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) | `0` | removed: the deprecated functions are removed (see below); the `from_*(ptr, len)` overloads stay deleted | [`JSON_DeleteDeprecatedFunctions`](../integration/cmake.md#json_deletedeprecatedfunctions) | 3.13.0 |
|
||||
|
||||
For example, the following makes a 3.x release behave like version 4.0 with respect to these changes:
|
||||
|
||||
@@ -75,6 +101,8 @@ For example, the following makes a 3.x release behave like version 4.0 with resp
|
||||
#define JSON_PRECISE_STREAM_POSITION 1
|
||||
#define JSON_STRICT_NUL_HANDLING 1
|
||||
#define JSON_STRICT_BINARY_UTF8 1
|
||||
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 1
|
||||
#define JSON_DELETE_DEPRECATED_FUNCTIONS 1
|
||||
#include <nlohmann/json.hpp>
|
||||
```
|
||||
|
||||
@@ -84,8 +112,13 @@ way to achieve this.
|
||||
### Removal of deprecated functions
|
||||
|
||||
Version 4.0 will remove all deprecated functions. Compiling with deprecation warnings enabled shows which of them your
|
||||
code still uses. The [migration guide](../integration/migration_guide.md#replace-deprecated-functions) shows how to
|
||||
replace each of them.
|
||||
code still uses. Defining [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) to
|
||||
`1` turns these warnings into errors, as the deprecated functions are then deleted. The
|
||||
[migration guide](../integration/migration_guide.md#replace-deprecated-functions) shows how to replace each of them.
|
||||
|
||||
The `from_*` overloads taking a pointer and a length are not removed in version 4.0, but stay deleted. Without them, a
|
||||
call like `from_cbor(ptr, len)` would still compile: it would read `ptr` as a NUL-terminated string and convert `len`
|
||||
to the `strict` parameter.
|
||||
|
||||
| Deprecated | Since | Migration |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|----------------------------------------------------------------------------------|
|
||||
@@ -97,6 +130,7 @@ replace each of them.
|
||||
| [`json_pointer::operator string_t`](../api/json_pointer/operator_string_t.md) | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
|
||||
| [`json_pointer`](../api/json_pointer/index.md) with a `basic_json` type as template argument, and the overloads of `value`, `contains`, `operator[]`, and `at` accepting such a pointer | 3.11.0 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
|
||||
| Comparing a [`json_pointer`](../api/json_pointer/index.md) with a string via [`operator==`](../api/json_pointer/operator_eq.md) or [`operator!=`](../api/json_pointer/operator_ne.md) | 3.11.2 | [JSON Pointers](../integration/migration_guide.md#json-pointers) |
|
||||
| [`from_bjdata`](../api/basic_json/from_bjdata.md) and [`from_bon8`](../api/basic_json/from_bon8.md) with `(ptr, len)` | 3.13.0 | [Parsing](../integration/migration_guide.md#parsing) |
|
||||
|
||||
The deprecated legacy comparison of discarded values is controlled by a macro and therefore listed in the table above.
|
||||
|
||||
|
||||
@@ -13,19 +13,7 @@ class visitor_adaptor_with_metadata
|
||||
void do_visit(const Ptr& ptr, const Fnc& fnc) const;
|
||||
};
|
||||
|
||||
using json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
visitor_adaptor_with_metadata
|
||||
>;
|
||||
using json = nlohmann::json::with_base_class_t<visitor_adaptor_with_metadata>;
|
||||
|
||||
template <class Fnc>
|
||||
void visitor_adaptor_with_metadata::visit(const Fnc& fnc) const
|
||||
|
||||
@@ -11,6 +11,7 @@ int main()
|
||||
<< "hash(false) = " << std::hash<json> {}(json(false)) << '\n'
|
||||
<< "hash(0) = " << std::hash<json> {}(json(0)) << '\n'
|
||||
<< "hash(0U) = " << std::hash<json> {}(json(0U)) << '\n'
|
||||
<< "hash(0.0) = " << std::hash<json> {}(json(0.0)) << '\n'
|
||||
<< "hash(\"\") = " << std::hash<json> {}(json("")) << '\n'
|
||||
<< "hash({}) = " << std::hash<json> {}(json::object()) << '\n'
|
||||
<< "hash([]) = " << std::hash<json> {}(json::array()) << '\n'
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
hash(null) = 2654435769
|
||||
hash(false) = 2654436030
|
||||
hash(0) = 2654436095
|
||||
hash(0U) = 2654436156
|
||||
hash("") = 6142509191626859748
|
||||
hash(0) = 2654436221
|
||||
hash(0U) = 2654436221
|
||||
hash(0.0) = 2654436221
|
||||
hash("") = 11160318156688833227
|
||||
hash({}) = 2654435832
|
||||
hash([]) = 2654435899
|
||||
hash({"hello": "world"}) = 4469488738203676328
|
||||
hash({"hello": "world"}) = 3701319991624763853
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// a JSON type that stores objects in a std::map (which keeps keys sorted)
|
||||
// instead of the default ordered associative container
|
||||
using sorted_json = nlohmann::json::with_object_t<std::map>;
|
||||
|
||||
int main()
|
||||
{
|
||||
sorted_json j;
|
||||
j["c"] = 1;
|
||||
j["a"] = 2;
|
||||
j["b"] = 3;
|
||||
|
||||
// keys are sorted, because std::map is used to store the object
|
||||
std::cout << j.dump() << std::endl;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"a":2,"b":3,"c":1}
|
||||
@@ -141,8 +141,14 @@ The library uses the following mapping from JSON values types to BJData types ac
|
||||
parsed back as a regular array,
|
||||
- every entry of `"_ArraySize_"` is a positive integer, and their product is representable as a `std::size_t`,
|
||||
- `"_ArrayData_"` is an array holding exactly that many elements, and
|
||||
- every element of `"_ArrayData_"` is a number of the kind named by `"_ArrayType_"` (a floating-point number for
|
||||
`single` and `double`, an integer otherwise).
|
||||
- every element of `"_ArrayData_"` is a number of the kind named by `"_ArrayType_"`: for the integer types, a
|
||||
value that fits the named width; for `double`, any value; for `single`, a value that survives narrowing to
|
||||
`float` and back without change (for instance, `0.1` does not, since it is not exactly representable as
|
||||
`float`).
|
||||
|
||||
An annotated object is always read back with its keys in the order shown above, `"_ArrayType_"`, `"_ArraySize_"`,
|
||||
`"_ArrayData_"`, regardless of the order the ND-array's header stores them in on the wire. This matters for
|
||||
`ordered_json`, whose comparison takes key order into account.
|
||||
|
||||
The current version of this library does not yet support automatic detection of and conversion from a nested JSON
|
||||
array input to a BJData ND-array.
|
||||
|
||||
@@ -131,6 +131,7 @@ The library maps CBOR types to JSON value types as follows:
|
||||
| Byte string | binary | 0x59 |
|
||||
| Byte string | binary | 0x5A |
|
||||
| Byte string | binary | 0x5B |
|
||||
| Byte string | binary | 0x5F |
|
||||
| UTF-8 string | string | 0x60..0x77 |
|
||||
| UTF-8 string | string | 0x78 |
|
||||
| UTF-8 string | string | 0x79 |
|
||||
@@ -156,6 +157,9 @@ The library maps CBOR types to JSON value types as follows:
|
||||
| Single-Precision Float | number_float | 0xFA |
|
||||
| Double-Precision Float | number_float | 0xFB |
|
||||
|
||||
Indefinite-length UTF-8 strings (0x7F) and byte strings (0x5F) are supported. Each chunk must be a definite-length
|
||||
string of the same major type, as required by [RFC 8949, Section 3.2.3](https://www.rfc-editor.org/rfc/rfc8949.html#section-3.2.3).
|
||||
|
||||
!!! warning "Incomplete mapping"
|
||||
|
||||
The mapping is **incomplete** in the sense that not all CBOR types can be converted to a JSON value. The following CBOR types are not supported and will yield parse errors:
|
||||
@@ -168,9 +172,9 @@ The library maps CBOR types to JSON value types as follows:
|
||||
!!! warning "Negative integer overflow"
|
||||
|
||||
CBOR negative integers (major type 1) are decoded as `-1 - n`. If the encoded magnitude `n` is too large for the
|
||||
result to fit into `number_integer_t` (`std::int64_t` by default), parsing fails with a
|
||||
[`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) exception rather than overflowing
|
||||
silently.
|
||||
result to fit into `number_integer_t` (`std::int64_t` by default), the result is stored as `number_float_t`, like
|
||||
a too small integer in JSON text. For example, `-18446744073709551616` (`0x3B` followed by eight `0xFF` bytes) is
|
||||
stored as `-1.8446744073709552e+19`.
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
|
||||
@@ -58,6 +58,23 @@ assert(jPi.get<TaskState>() == TS_INVALID );
|
||||
--8<-- "examples/nlohmann_json_serialize_enum.output"
|
||||
```
|
||||
|
||||
## Maps with enum keys
|
||||
|
||||
By default, maps with enum keys, such as `std::map<TaskState, std::string>`, are stored as arrays of `[key, value]`
|
||||
pairs, because JSON object keys must be strings. Define
|
||||
[`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md) before including the
|
||||
library to store them as objects, with the keys converted by the enum's `to_json()` function:
|
||||
|
||||
```cpp
|
||||
std::map<TaskState, std::string> m = {{TS_STOPPED, "aa"}, {TS_COMPLETED, "bb"}};
|
||||
|
||||
json j = m;
|
||||
// default: [["stopped","aa"],["completed","bb"]]
|
||||
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS: {"completed":"bb","stopped":"aa"}
|
||||
```
|
||||
|
||||
Either form can be read back, with or without the macro.
|
||||
|
||||
## Notes
|
||||
|
||||
Just as in [Arbitrary Type Conversions](arbitrary_types.md) above,
|
||||
|
||||
@@ -23,6 +23,17 @@ This macro overrides [`#!cpp catch`](https://en.cppreference.com/w/cpp/language/
|
||||
|
||||
See [full documentation of `JSON_CATCH_USER(exception)`](../api/macros/json_throw_user.md).
|
||||
|
||||
## `JSON_DELETE_DEPRECATED_FUNCTIONS`
|
||||
|
||||
When defined to `1`, all deprecated functions are declared as deleted instead of only being marked as deprecated, so
|
||||
code that still calls them no longer compiles. This way, you can find all calls that need to be replaced before version
|
||||
4.0.0 removes these functions.
|
||||
|
||||
The macro can also be set with the CMake option
|
||||
[`JSON_DeleteDeprecatedFunctions`](../integration/cmake.md#json_deletedeprecatedfunctions) (`OFF` by default).
|
||||
|
||||
See [full documentation of `JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md).
|
||||
|
||||
## `JSON_DIAGNOSTICS`
|
||||
|
||||
This macro enables extended diagnostics for exception messages. Possible values are `1` to enable or `0` to disable
|
||||
@@ -86,7 +97,8 @@ See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json
|
||||
## `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.
|
||||
value, such as the result of `std::forward_as_tuple(j)`. This lets `std::tuple` convert such tuples element-wise. This
|
||||
is planned to become the default in version 4.0.0.
|
||||
|
||||
See [full documentation of `JSON_DISABLE_TUPLE_REFERENCE_CONVERSION`](../api/macros/json_disable_tuple_reference_conversion.md).
|
||||
|
||||
@@ -198,6 +210,13 @@ default.
|
||||
|
||||
See [full documentation of `JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON`](../api/macros/json_use_legacy_discarded_value_comparison.md).
|
||||
|
||||
## `JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`
|
||||
|
||||
When defined to `1`, maps with enum keys (e.g., `std::map<E, T>`) are stored as objects, using the enum's conversion for
|
||||
the keys, instead of arrays of `[key, value]` pairs. It is switched off (`0`) by default.
|
||||
|
||||
See [full documentation of `JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md).
|
||||
|
||||
## `JSON_USE_SIMDUTF`
|
||||
|
||||
When defined, UTF-8 validation of JSON strings read from contiguous byte input is delegated to the
|
||||
|
||||
@@ -21,6 +21,8 @@ The complete default namespace name is derived as follows:
|
||||
- [`JSON_PRECISE_STREAM_POSITION`](../api/macros/json_precise_stream_position.md) defined non-zero appends `_psp`.
|
||||
- [`JSON_STRICT_NUL_HANDLING`](../api/macros/json_strict_nul_handling.md) defined non-zero appends `_snul`.
|
||||
- [`JSON_STRICT_BINARY_UTF8`](../api/macros/json_strict_binary_utf8.md) defined non-zero appends `_sbu8`.
|
||||
- [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md) defined non-zero
|
||||
appends `_ekmo`.
|
||||
- The inline namespace ends with the suffix `_v` followed by the 3 components of the version number separated by
|
||||
underscores. To omit the version component, see [Disabling the version component](#disabling-the-version-component)
|
||||
below.
|
||||
|
||||
@@ -64,6 +64,7 @@ serialization fails by default. The fourth argument of `dump` selects an
|
||||
- `strict` (default) — throw a [`type_error.316`](../home/exceptions.md#jsonexceptiontype_error316) exception.
|
||||
- `replace` — replace invalid bytes with the Unicode replacement character U+FFFD (`�`).
|
||||
- `ignore` — silently drop invalid bytes.
|
||||
- `keep` — copy invalid bytes to the output unchanged; the result is not valid UTF-8.
|
||||
|
||||
??? example "Example: serialize invalid UTF-8 with different error handlers"
|
||||
|
||||
|
||||
@@ -82,13 +82,12 @@ flowchart TD
|
||||
|
||||
- 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 library converts integers and floating-point numbers itself, independent of the locale. Floating-point
|
||||
numbers are correctly rounded (to nearest, ties to even). Only a `#!c long double` that is not IEEE 754 binary64
|
||||
(e.g., the 80-bit x87 format) is converted with `#!cpp std::from_chars` where available, or else with
|
||||
[`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. Before version 3.13.0, the conversion was realized by
|
||||
- Integers are converted by the library's own digit parser. Floating-point numbers are converted with
|
||||
[`std::from_chars`](https://en.cppreference.com/w/cpp/utility/from_chars) if the library is compiled with C++17
|
||||
and the standard library supports it, then with an exact fast path for `#!c double` values with few significant
|
||||
digits, and otherwise with the locale-aware
|
||||
[`std::strtod`](https://en.cppreference.com/w/cpp/string/byte/strtof) (`std::strtof`/`std::strtold` for the
|
||||
other floating-point types). Before version 3.13.0, the conversion was realized by
|
||||
[`std::strtoull`](https://en.cppreference.com/w/cpp/string/byte/strtoul),
|
||||
[`std::strtoll`](https://en.cppreference.com/w/cpp/string/byte/strtol), and `std::strtod`, respectively.
|
||||
|
||||
@@ -101,10 +100,10 @@ flowchart TD
|
||||
### Number limits
|
||||
|
||||
- Any 64-bit signed or unsigned integer can be stored without loss of precision.
|
||||
- Numbers exceeding the limits of `#!c double` (i.e., numbers whose rounded value is not satisfying
|
||||
- Numbers exceeding the limits of `#!c double` (i.e., numbers that after conversion via
|
||||
[`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
|
||||
[`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.
|
||||
[`json.exception.out_of_range.406`](../../home/exceptions.md#jsonexceptionout_of_range406) during parsing.
|
||||
- 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).
|
||||
This is the same behavior as the code `#!c double x = 3.141592653589793238462643383279;`.
|
||||
|
||||
@@ -26,9 +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
|
||||
the library. Four violations are not caught at compile time at all:
|
||||
|
||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and silently misparses numbers
|
||||
stored as a `#!cpp long double` that is not IEEE 754 binary64 (e.g., the 80-bit x87 format), because the lexer
|
||||
hands the buffer to `#!cpp std::strtold`.
|
||||
- A [`StringType`](#stringtype) whose `data()` is not null-terminated compiles and can silently misparse
|
||||
floating-point numbers, because the lexer may hand the buffer to `#!cpp std::strtod`, which reads up to the
|
||||
terminating null character.
|
||||
- A stateful [`AllocatorType`](#allocatortype) compiles and silently ignores its state: allocation, deallocation,
|
||||
and [`get_allocator()`](../../api/basic_json/get_allocator.md) each use a different default-constructed instance.
|
||||
- The two [cross-specialization conversions](#cross-specialization-conversions) below. These abort on an assertion
|
||||
@@ -537,10 +537,9 @@ therefore silently changes parse results rather than raising an error. See
|
||||
|
||||
`NumberFloatType` must be one of `#!cpp float`, `#!cpp double`, or `#!cpp long double`:
|
||||
|
||||
- The [parser](../parsing/index.md) converts number literals to `#!cpp float`, `#!cpp double`, and a
|
||||
`#!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.
|
||||
- The [parser](../parsing/index.md) converts number literals with `#!cpp std::from_chars` or, as a fallback, with
|
||||
`#!cpp std::strtof`, `#!cpp std::strtod`, or `#!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
|
||||
specifiers, for which the library likewise provides only `#!cpp double` and `#!cpp long double` overloads
|
||||
(`#!cpp float` is promoted to `#!cpp double`).
|
||||
|
||||
@@ -331,9 +331,6 @@ An unexpected byte was read in a [binary format](../features/binary_formats/inde
|
||||
[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: negative integer overflow
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.112] parse error at byte 5: syntax error while parsing BSON document: document size 6 does not match the number of bytes read (5)
|
||||
```
|
||||
|
||||
@@ -599,6 +596,9 @@ During implicit or explicit value conversion, the JSON type must be compatible w
|
||||
[json.exception.type_error.302] type must be string, but is object
|
||||
```
|
||||
|
||||
This exception is also thrown with [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md)
|
||||
if a key of a map with enum keys is not converted to a string, for instance, because the enum is stored as an integer.
|
||||
|
||||
### json.exception.type_error.303
|
||||
|
||||
To retrieve a reference to a value stored in a `basic_json` object with `get_ref`, the type of the reference must match the value type. For instance, for a JSON array, the `ReferenceType` must be `array_t &`.
|
||||
@@ -771,6 +771,7 @@ as well for a string value or object key that is not valid UTF-8 if their `error
|
||||
- Pass an error handler as last parameter to the `dump()` function to avoid this exception:
|
||||
- `json::error_handler_t::replace` will replace invalid bytes sequences with `U+FFFD`
|
||||
- `json::error_handler_t::ignore` will silently ignore invalid byte sequences
|
||||
- `json::error_handler_t::keep` will copy invalid byte sequences to the output unchanged
|
||||
|
||||
### json.exception.type_error.317
|
||||
|
||||
@@ -791,6 +792,33 @@ The dynamic type of the object cannot be represented in the requested serializat
|
||||
|
||||
Encapsulate the JSON value in an object. That is, instead of serializing `#!json true`, serialize `#!json {"value": true}`
|
||||
|
||||
### json.exception.type_error.318
|
||||
|
||||
With [`JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS`](../api/macros/json_use_objects_for_enum_keyed_maps.md), a map with enum
|
||||
keys is stored as an object. This exception is thrown if two of its keys are converted to the same string, so one of the
|
||||
entries would be lost. This happens, for instance, if [`NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md)
|
||||
does not list an enumerator and it is therefore converted like the first listed one.
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
```
|
||||
[json.exception.type_error.318] duplicate object key 'red'
|
||||
```
|
||||
|
||||
### json.exception.type_error.321
|
||||
|
||||
A discarded value (one created by [`parse()`](../api/basic_json/parse.md) with a callback that returns `false` for the
|
||||
value, or by default-constructing a [`basic_json`](../api/basic_json/index.md) with
|
||||
[`value_t::discarded`](../api/basic_json/value_t.md)) was passed to a binary serialization function, either directly or
|
||||
nested in an array or object. There is no way to represent a discarded value in CBOR, MessagePack, UBJSON, BJData, or BSON.
|
||||
|
||||
!!! failure "Example message"
|
||||
|
||||
Serializing `#!json [1, 2]` to CBOR, where the second element was discarded by a parser callback:
|
||||
```
|
||||
[json.exception.type_error.321] cannot serialize discarded value to CBOR
|
||||
```
|
||||
|
||||
## Out of range
|
||||
|
||||
This exception is thrown in case a library function is called on an input parameter that exceeds the expected range, for instance, in the case of array indices or nonexisting object keys.
|
||||
@@ -863,13 +891,18 @@ The JSON Patch operations 'remove' and 'add' cannot be applied to the root eleme
|
||||
|
||||
### json.exception.out_of_range.406
|
||||
|
||||
A parsed number could not be stored as without changing it to NaN or INF.
|
||||
A parsed number could not be stored without changing it to NaN or INF. For the binary formats, this happens when a
|
||||
finite floating-point number does not fit into [`number_float_t`](../api/basic_json/number_float_t.md), for example a
|
||||
double-precision number when `number_float_t` is `#!cpp float`.
|
||||
|
||||
!!! failure "Example message"
|
||||
!!! failure "Example messages"
|
||||
|
||||
```
|
||||
number overflow parsing '10E1000'
|
||||
```
|
||||
```
|
||||
[json.exception.out_of_range.406] syntax error while parsing CBOR value: number overflow
|
||||
```
|
||||
|
||||
### json.exception.out_of_range.407
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ The library supports **Unicode input** as follows:
|
||||
- The library will not replace [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1).
|
||||
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
||||
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](../api/basic_json/dump.md) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](../api/basic_json/dump.md) may throw an exception unless `json::error_handler_t::replace`, `json::error_handler_t::ignore`, or `json::error_handler_t::keep` are used as error handlers.
|
||||
|
||||
In most cases, the parser is right to complain, because the input is not UTF-8 encoded. This is especially true for Microsoft Windows, where Latin-1 or ISO 8859-1 is often the standard encoding.
|
||||
|
||||
|
||||
@@ -20,4 +20,4 @@ The class contains a slightly modified version of the Grisu2 algorithm from Flor
|
||||
|
||||
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
|
||||
The class contains an adapted version of the Eisel-Lemire algorithm and its table of powers of five 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
|
||||
@@ -126,12 +126,18 @@ automatically download a release as a dependency at configure time.
|
||||
|
||||
### `JSON_BuildTests`
|
||||
|
||||
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project. That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
|
||||
Build the unit tests when [`BUILD_TESTING`](https://cmake.org/cmake/help/latest/command/enable_testing.html) is enabled. This option is `ON` by default if the library's CMake project is the top project and the `tests` directory exists (the release archive `json.tar.xz` does not contain it). That is, when integrating the library as described above, the test suite is not built unless explicitly switched on with this option.
|
||||
|
||||
### `JSON_CI`
|
||||
|
||||
Enable CI build targets. The exact targets are used during the several CI steps and are subject to change without notice. This option is `OFF` by default.
|
||||
|
||||
### `JSON_DeleteDeprecatedFunctions`
|
||||
|
||||
Delete the deprecated functions instead of only deprecating them by defining the macro
|
||||
[`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md). This option is `OFF` by
|
||||
default.
|
||||
|
||||
### `JSON_Diagnostics`
|
||||
|
||||
Enable [extended diagnostic messages](../home/exceptions.md#extended-diagnostic-messages) by defining macro [`JSON_DIAGNOSTICS`](../api/macros/json_diagnostics.md). This option is `OFF` by default.
|
||||
|
||||
@@ -14,6 +14,13 @@ deprecations are annotated with
|
||||
[`HEDLEY_DEPRECATED_FOR`](https://nemequ.github.io/hedley/api-reference.html#HEDLEY_DEPRECATED_FOR) to report which
|
||||
function to use instead.
|
||||
|
||||
!!! tip "Find all calls of deprecated functions"
|
||||
|
||||
Define [`JSON_DELETE_DEPRECATED_FUNCTIONS`](../api/macros/json_delete_deprecated_functions.md) to `1` (or set the
|
||||
CMake option [`JSON_DeleteDeprecatedFunctions`](cmake.md#json_deletedeprecatedfunctions)) to delete all deprecated
|
||||
functions. Every remaining call then fails to compile, even if deprecation warnings are disabled, so your code is
|
||||
ready for version 4.0.0 once it compiles with the macro.
|
||||
|
||||
### Parsing
|
||||
|
||||
- Function `friend std::istream& operator<<(basic_json&, std::istream&)` is deprecated since 3.0.0. Please use
|
||||
@@ -41,8 +48,10 @@ function to use instead.
|
||||
[`from_ubjson`](../api/basic_json/from_ubjson.md), and [`from_bson`](../api/basic_json/from_bson.md)) via initializer
|
||||
lists is deprecated since 3.8.0. Instead, pass two iterators; for instance, call `from_cbor(ptr, ptr+len)` instead of
|
||||
`from_cbor({ptr, len})`. Likewise, passing a pointer and a length as two separate arguments to `from_cbor`,
|
||||
`from_msgpack`, `from_ubjson`, and `from_bson` is deprecated since 3.8.0; call `from_cbor(ptr, ptr+len)` instead of
|
||||
`from_cbor(ptr, len)`.
|
||||
`from_msgpack`, `from_ubjson`, and `from_bson` is deprecated since 3.8.0, and to
|
||||
[`from_bjdata`](../api/basic_json/from_bjdata.md) and [`from_bon8`](../api/basic_json/from_bon8.md) since 3.13.0; call
|
||||
`from_cbor(ptr, ptr+len)` instead of `from_cbor(ptr, len)`. These overloads will not be removed in version 4.0.0, but
|
||||
deleted, so a call like `from_cbor(ptr, len)` cannot compile and convert `len` to the `strict` parameter.
|
||||
|
||||
=== "Deprecated"
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ nav:
|
||||
- 'update': api/basic_json/update.md
|
||||
- 'value': api/basic_json/value.md
|
||||
- 'value_t': api/basic_json/value_t.md
|
||||
- 'with_t': api/basic_json/with_t.md
|
||||
- byte_container_with_subtype:
|
||||
- 'Overview': api/byte_container_with_subtype/index.md
|
||||
- '(constructor)': api/byte_container_with_subtype/byte_container_with_subtype.md
|
||||
@@ -292,6 +293,7 @@ nav:
|
||||
- 'JSON_BRACE_INIT_COPY_SEMANTICS': api/macros/json_brace_init_copy_semantics.md
|
||||
- 'JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER': api/macros/json_throw_user.md
|
||||
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
|
||||
- 'JSON_DELETE_DEPRECATED_FUNCTIONS': api/macros/json_delete_deprecated_functions.md
|
||||
- 'JSON_DIAGNOSTIC_POSITIONS': api/macros/json_diagnostic_positions.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
|
||||
@@ -313,6 +315,7 @@ nav:
|
||||
- 'JSON_USE_GLOBAL_UDLS': api/macros/json_use_global_udls.md
|
||||
- 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md
|
||||
- 'JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON': api/macros/json_use_legacy_discarded_value_comparison.md
|
||||
- 'JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS': api/macros/json_use_objects_for_enum_keyed_maps.md
|
||||
- 'JSON_USE_SIMDUTF': api/macros/json_use_simdutf.md
|
||||
- 'NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_derived_type.md
|
||||
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE': api/macros/nlohmann_define_type_intrusive.md
|
||||
|
||||
@@ -6,7 +6,7 @@ mkdocs-material==9.7.7 # theme for mkdocs
|
||||
mkdocs-material-extensions==1.3.1 # extensions
|
||||
mkdocs-minify-plugin==0.8.0 # plugin "minify"
|
||||
mkdocs-redirects==1.2.3 # plugin "redirects"
|
||||
mkdocs-htmlproofer-plugin==1.5.0 # plugin "htmlproofer"
|
||||
mkdocs-htmlproofer-plugin==1.6.0 # plugin "htmlproofer"
|
||||
mkdocs-llmstxt==0.5.0 # plugin "llmstxt"
|
||||
|
||||
PyYAML==6.0.3 # linter
|
||||
+3
-3
@@ -1454,9 +1454,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
|
||||
"integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
#define JSON_STRICT_BINARY_UTF8 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
@@ -92,14 +96,20 @@
|
||||
#define NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8
|
||||
#endif
|
||||
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS _ekmo
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) json_abi ## a ## b ## c ## d ## e ## f ## g
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g)
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) json_abi ## a ## b ## c ## d ## e ## f ## g ## h
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g, h) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
@@ -109,7 +119,8 @@
|
||||
NLOHMANN_JSON_ABI_TAG_BRACE_INIT_COPY_SEMANTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_PRECISE_STREAM_POSITION, \
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_NUL_HANDLING, \
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8)
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8, \
|
||||
NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
|
||||
@@ -39,25 +39,6 @@ inline int count_leading_zeros(std::uint64_t x) noexcept
|
||||
#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
|
||||
{
|
||||
@@ -87,19 +68,14 @@ inline uint128_parts full_multiplication(std::uint64_t a, std::uint64_t b) noexc
|
||||
|
||||
/// 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
|
||||
inline std::uint64_t read_eight_bytes(const char* p) noexcept
|
||||
{
|
||||
const auto* b = reinterpret_cast<const unsigned char*>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
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
|
||||
@@ -48,7 +48,7 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("null", j);
|
||||
}
|
||||
n = nullptr;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("number", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t&
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("boolean", j);
|
||||
}
|
||||
b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
|
||||
}
|
||||
@@ -121,7 +121,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t&
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||
}
|
||||
@@ -137,7 +137,7 @@ inline void from_json(const BasicJsonType& j, StringType& s)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
|
||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||
@@ -172,7 +172,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
||||
typename BasicJsonType::number_unsigned_t, underlying_type>::type;
|
||||
value_type val;
|
||||
get_arithmetic_value(j, val);
|
||||
e = static_cast<EnumType>(static_cast<underlying_type>(val));
|
||||
e = static_cast<EnumType>(bool_aware_static_cast<underlying_type>(val));
|
||||
}
|
||||
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
||||
|
||||
@@ -183,7 +183,7 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
l.clear();
|
||||
std::transform(j.rbegin(), j.rend(),
|
||||
@@ -200,7 +200,7 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
l.resize(j.size());
|
||||
std::transform(j.begin(), j.end(), std::begin(l),
|
||||
@@ -305,7 +305,7 @@ void())
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
from_json_array_impl(j, arr, priority_tag<3> {});
|
||||
@@ -324,7 +324,7 @@ auto from_json(const BasicJsonType& j, identity_tag<std::array<T, N>> tag)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
return from_json_inplace_array_impl(j, tag, make_index_sequence<N> {});
|
||||
@@ -335,7 +335,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("binary", j);
|
||||
}
|
||||
|
||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||
@@ -356,7 +356,7 @@ inline void from_json(const BasicJsonType& j, CompatibleArrayType& bin)
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be binary or array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("binary or array", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("object", j);
|
||||
}
|
||||
|
||||
ConstructibleObjectType ret;
|
||||
@@ -432,7 +432,7 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("number", j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,7 +504,7 @@ auto from_json(const BasicJsonType& j, TupleRelated&& t)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
|
||||
return from_json_tuple_impl(j, std::forward<TupleRelated>(t), priority_tag<3> {});
|
||||
@@ -517,24 +517,53 @@ void from_json_pair_array_to_map(const BasicJsonType& j, MapType& m)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("array", j);
|
||||
}
|
||||
m.clear();
|
||||
for (const auto& p : j)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &p));
|
||||
throw_type_must_be("array", p);
|
||||
}
|
||||
m.emplace(p.at(0).template get<typename MapType::key_type>(), p.at(1).template get<typename MapType::mapped_type>());
|
||||
}
|
||||
}
|
||||
|
||||
// read a map with enum keys from an object, using the enum's own from_json for
|
||||
// the keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); this is the form written
|
||||
// with JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
template<typename BasicJsonType, typename Map>
|
||||
inline bool from_json_enum_keyed_object(const BasicJsonType& j, Map& m, std::true_type /*key is enum*/)
|
||||
{
|
||||
if (!j.is_object())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m.clear();
|
||||
for (const auto& p : *j.template get_ptr<const typename BasicJsonType::object_t*>())
|
||||
{
|
||||
m.emplace(BasicJsonType(p.first).template get<typename Map::key_type>(), p.second.template get<typename Map::mapped_type>());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename Map>
|
||||
inline bool from_json_enum_keyed_object(const BasicJsonType& /*j*/, Map& /*m*/, std::false_type /*key is enum*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||
typename = enable_if_t < !std::is_constructible <
|
||||
typename BasicJsonType::string_t, Key >::value >>
|
||||
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||
{
|
||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||
if (from_json_enum_keyed_object(j, m, std::is_enum<Key> {}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
from_json_pair_array_to_map(j, m);
|
||||
}
|
||||
|
||||
@@ -543,6 +572,11 @@ template < typename BasicJsonType, typename Key, typename Value, typename Hash,
|
||||
typename BasicJsonType::string_t, Key >::value >>
|
||||
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
||||
{
|
||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||
if (from_json_enum_keyed_object(j, m, std::is_enum<Key> {}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
from_json_pair_array_to_map(j, m);
|
||||
}
|
||||
|
||||
@@ -557,7 +591,7 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
|
||||
throw_type_must_be("string", j);
|
||||
}
|
||||
const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||
// Checking for C++20 standard or later can be insufficient in case the
|
||||
|
||||
@@ -308,8 +308,8 @@ boundaries compute_boundaries(FloatType value)
|
||||
//
|
||||
// -e <= 60 or e >= -60 := alpha
|
||||
|
||||
constexpr int kAlpha = -60;
|
||||
constexpr int kGamma = -32;
|
||||
JSON_INLINE_VARIABLE constexpr int kAlpha = -60;
|
||||
JSON_INLINE_VARIABLE constexpr int kGamma = -32;
|
||||
|
||||
struct cached_power // c = f * 2^e ~= 10^k
|
||||
{
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <optional> // optional
|
||||
#endif
|
||||
|
||||
#include <algorithm> // copy
|
||||
#include <iterator> // begin, end
|
||||
#include <memory> // allocator_traits
|
||||
#include <string> // basic_string, char_traits
|
||||
@@ -23,6 +22,7 @@
|
||||
#include <valarray> // valarray
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/std_fs.hpp>
|
||||
@@ -38,10 +38,14 @@ namespace detail
|
||||
//////////////////
|
||||
|
||||
/*
|
||||
* Note all external_constructor<>::construct functions need to call
|
||||
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
|
||||
* allocated value (e.g., a string). See bug issue
|
||||
* Note all external_constructor<>::construct functions need to store the new
|
||||
* value with j.replace_value(), which destroys the old one to avoid a memory
|
||||
* leak in case j contains an allocated value (e.g., a string). See bug issue
|
||||
* https://github.com/nlohmann/json/issues/2865 for more information.
|
||||
*
|
||||
* A value that has to be allocated is created before the old one is destroyed:
|
||||
* were it the other way around, an exception while creating the new value would
|
||||
* leave j with the type of the new value, but the pointer to the destroyed old one.
|
||||
*/
|
||||
|
||||
template<value_t> struct external_constructor;
|
||||
@@ -52,10 +56,7 @@ struct external_constructor<value_t::boolean>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::boolean;
|
||||
j.m_data.m_value = b;
|
||||
j.assert_invariant();
|
||||
j.replace_value(value_t::boolean, b);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,19 +66,15 @@ struct external_constructor<value_t::string>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::string;
|
||||
j.m_data.m_value = s;
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(s);
|
||||
j.replace_value(value_t::string, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::string;
|
||||
j.m_data.m_value = std::move(s);
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(std::move(s));
|
||||
j.replace_value(value_t::string, value);
|
||||
}
|
||||
|
||||
template < typename BasicJsonType, typename CompatibleStringType,
|
||||
@@ -85,10 +82,8 @@ struct external_constructor<value_t::string>
|
||||
int > = 0 >
|
||||
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::string;
|
||||
j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::string_t>(str));
|
||||
j.replace_value(value_t::string, value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,19 +93,15 @@ struct external_constructor<value_t::binary>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::binary;
|
||||
j.m_data.m_value = typename BasicJsonType::binary_t(b);
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(b);
|
||||
j.replace_value(value_t::binary, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::binary;
|
||||
j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(std::move(b));
|
||||
j.replace_value(value_t::binary, value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,10 +111,7 @@ struct external_constructor<value_t::number_float>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::number_float;
|
||||
j.m_data.m_value = val;
|
||||
j.assert_invariant();
|
||||
j.replace_value(value_t::number_float, val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -133,10 +121,7 @@ struct external_constructor<value_t::number_unsigned>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::number_unsigned;
|
||||
j.m_data.m_value = val;
|
||||
j.assert_invariant();
|
||||
j.replace_value(value_t::number_unsigned, val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -146,10 +131,7 @@ struct external_constructor<value_t::number_integer>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::number_integer;
|
||||
j.m_data.m_value = val;
|
||||
j.assert_invariant();
|
||||
j.replace_value(value_t::number_integer, val);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -159,21 +141,15 @@ struct external_constructor<value_t::array>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value = arr;
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(arr);
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value = std::move(arr);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(std::move(arr));
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
|
||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||
@@ -187,39 +163,23 @@ struct external_constructor<value_t::array>
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr)));
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value = value_t::array;
|
||||
j.m_data.m_value.array->reserve(arr.size());
|
||||
for (const bool x : arr)
|
||||
{
|
||||
j.m_data.m_value.array->push_back(x);
|
||||
j.set_parent(j.m_data.m_value.array->back());
|
||||
}
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(arr.begin(), arr.end()));
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename T,
|
||||
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
||||
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value = value_t::array;
|
||||
j.m_data.m_value.array->resize(arr.size());
|
||||
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::array_t>(std::begin(arr), std::end(arr)));
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
|
||||
#if JSON_HAS_RANGE_VIEW_CONVERSION
|
||||
@@ -227,18 +187,15 @@ struct external_constructor<value_t::array>
|
||||
enable_if_t<is_compatible_range_view<std::remove_cvref_t<CompatibleArrayType>>::value, int> = 0>
|
||||
static void construct(BasicJsonType& j, CompatibleArrayType && arr)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::array;
|
||||
j.m_data.m_value = value_t::array;
|
||||
// no range constructor: a view's begin() and end() may have different
|
||||
// types, and the view may only be iterable once
|
||||
typename BasicJsonType::array_t elements;
|
||||
for (auto&& x : std::forward<CompatibleArrayType>(arr))
|
||||
{
|
||||
j.m_data.m_value.array->push_back(x);
|
||||
elements.push_back(x);
|
||||
}
|
||||
// set the parents only once all elements are in place: a push_back
|
||||
// that reallocates moves the earlier elements, which does not keep
|
||||
// their parent pointers
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(std::move(elements));
|
||||
j.replace_value(value_t::array, value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
@@ -249,21 +206,15 @@ struct external_constructor<value_t::object>
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::object;
|
||||
j.m_data.m_value = obj;
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(obj);
|
||||
j.replace_value(value_t::object, value);
|
||||
}
|
||||
|
||||
template<typename BasicJsonType>
|
||||
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||
{
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::object;
|
||||
j.m_data.m_value = std::move(obj);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(std::move(obj));
|
||||
j.replace_value(value_t::object, value);
|
||||
}
|
||||
|
||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
||||
@@ -273,11 +224,8 @@ struct external_constructor<value_t::object>
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||
j.m_data.m_type = value_t::object;
|
||||
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
const typename BasicJsonType::json_value value(j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj)));
|
||||
j.replace_value(value_t::object, value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -286,9 +234,20 @@ struct external_constructor<value_t::object>
|
||||
/////////////
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
// whether storing the value of a std::optional<T> cannot throw; MSVC 2017
|
||||
// evaluates std::is_nothrow_assignable as true even if T's to_json throws, so
|
||||
// the exception would call std::terminate (#5642)
|
||||
#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER < 1920
|
||||
template<typename BasicJsonType, typename T>
|
||||
using is_nothrow_optional_to_json = std::false_type;
|
||||
#else
|
||||
template<typename BasicJsonType, typename T>
|
||||
using is_nothrow_optional_to_json = std::is_nothrow_assignable<BasicJsonType&, const T&>;
|
||||
#endif
|
||||
|
||||
template<typename BasicJsonType, typename T,
|
||||
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
|
||||
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept(std::is_nothrow_assignable<BasicJsonType&, const T&>::value)
|
||||
void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept(is_nothrow_optional_to_json<BasicJsonType, T>::value)
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
@@ -364,7 +323,7 @@ inline void to_json(BasicJsonType& j, EnumType e) noexcept
|
||||
{
|
||||
using underlying_type = typename std::underlying_type<EnumType>::type;
|
||||
static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
|
||||
external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
|
||||
external_constructor<integral_value_t>::construct(j, bool_aware_static_cast<underlying_type>(e));
|
||||
}
|
||||
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
||||
|
||||
@@ -384,6 +343,9 @@ template < typename BasicJsonType, typename CompatibleArrayType,
|
||||
!is_basic_json<CompatibleArrayType>::value
|
||||
#if JSON_HAS_RANGE_VIEW_CONVERSION
|
||||
&& !is_compatible_range_view<CompatibleArrayType>::value
|
||||
#endif
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
&& !is_enum_keyed_map<CompatibleArrayType>::value
|
||||
#endif
|
||||
,
|
||||
int > = 0 >
|
||||
@@ -438,6 +400,33 @@ inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||
external_constructor<value_t::object>::construct(j, obj);
|
||||
}
|
||||
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
// store a map with enum keys as an object, using the enum's own to_json for the
|
||||
// keys (e.g., from NLOHMANN_JSON_SERIALIZE_ENUM); without the macro, such maps
|
||||
// are stored as arrays of [key, value] pairs
|
||||
template < typename BasicJsonType, typename EnumKeyedMap,
|
||||
enable_if_t < is_enum_keyed_map<EnumKeyedMap>::value&& !is_basic_json<EnumKeyedMap>::value, int > = 0 >
|
||||
inline void to_json(BasicJsonType& j, const EnumKeyedMap& map)
|
||||
{
|
||||
typename BasicJsonType::object_t obj;
|
||||
for (const auto& p : map)
|
||||
{
|
||||
BasicJsonType key = p.first;
|
||||
if (JSON_HEDLEY_UNLIKELY(!key.is_string()))
|
||||
{
|
||||
throw_type_must_be("string", key);
|
||||
}
|
||||
|
||||
auto& key_string = *key.template get_ptr<typename BasicJsonType::string_t*>();
|
||||
if (JSON_HEDLEY_UNLIKELY(!obj.emplace(key_string, BasicJsonType(p.second)).second))
|
||||
{
|
||||
JSON_THROW(type_error::create(exception_id::enum_key_duplicate, concat("duplicate object key '", key_string, "'"), &key));
|
||||
}
|
||||
}
|
||||
external_constructor<value_t::object>::construct(j, std::move(obj));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename BasicJsonType>
|
||||
inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||
{
|
||||
|
||||
@@ -45,6 +45,84 @@ namespace detail
|
||||
// exceptions //
|
||||
////////////////
|
||||
|
||||
/*!
|
||||
@brief the ids of the exceptions thrown by the library
|
||||
@note The values are part of the public API: they are the `id` member of the
|
||||
exceptions and appear in their `what()` messages.
|
||||
@sa https://json.nlohmann.me/home/exceptions/
|
||||
*/
|
||||
enum class exception_id : int
|
||||
{
|
||||
// parse_error
|
||||
syntax_error = 101, ///< unexpected token or invalid literal while parsing JSON
|
||||
patch_not_an_array = 104, ///< a JSON Patch document is not an array of objects
|
||||
patch_invalid_operation = 105, ///< a JSON Patch operation is malformed
|
||||
pointer_index_leading_zero = 106, ///< a JSON Pointer array index has a leading zero
|
||||
pointer_missing_slash = 107, ///< a JSON Pointer does not start with '/'
|
||||
pointer_invalid_escape = 108, ///< a JSON Pointer contains an escape other than ~0 and ~1
|
||||
pointer_index_not_a_number = 109, ///< a JSON Pointer array index is not a number
|
||||
unexpected_end_of_input = 110, ///< a binary input ends early, or has bytes left at its end
|
||||
unexpected_byte = 112, ///< a binary input contains an unexpected byte or invalid length
|
||||
invalid_string_or_size = 113, ///< a binary input contains an invalid string or size specification
|
||||
bson_unsupported_type = 114, ///< a BSON record type is not supported
|
||||
invalid_high_precision_number = 115, ///< a UBJSON/BJData high-precision number cannot be parsed
|
||||
// invalid_iterator
|
||||
iterators_incompatible = 201, ///< the iterators of a range belong to different values
|
||||
iterator_from_other_value = 202, ///< an iterator does not belong to the value it is used with
|
||||
iterator_range_from_other_value = 203, ///< an iterator range does not belong to the value it is used with
|
||||
iterator_range_out_of_range = 204, ///< an iterator range of a primitive value is not [begin, end)
|
||||
iterator_out_of_range = 205, ///< an iterator of a primitive value is not begin()
|
||||
iterator_range_of_null = 206, ///< an iterator range belongs to a null value
|
||||
iterator_key_not_object = 207, ///< key() is called on an iterator of a non-object
|
||||
iterator_subscript_on_object = 208, ///< operator[] is called on an iterator of an object
|
||||
iterator_arithmetic_on_object = 209, ///< an offset operator is used on an iterator of an object
|
||||
insert_range_incompatible = 210, ///< the iterators of an inserted range belong to different values
|
||||
insert_range_into_itself = 211, ///< an inserted range belongs to the value it is inserted into
|
||||
iterators_compare_different_values = 212, ///< iterators of different values are compared
|
||||
iterator_order_on_object = 213, ///< iterators of an object are compared by order
|
||||
iterator_value_unavailable = 214, ///< an iterator does not refer to a value
|
||||
// type_error
|
||||
object_from_non_pairs = 301, ///< an object is created from an initializer list that is not a list of pairs
|
||||
type_mismatch = 302, ///< a value has the wrong type for a conversion
|
||||
incompatible_reference_type = 303, ///< get_ref() is called with a reference type that does not match the value
|
||||
at_wrong_type = 304, ///< at() is called on a value of the wrong type
|
||||
subscript_wrong_type = 305, ///< operator[] is called on a value of the wrong type
|
||||
value_wrong_type = 306, ///< value() is called on a value of the wrong type
|
||||
erase_wrong_type = 307, ///< erase() is called on a value of the wrong type
|
||||
push_back_wrong_type = 308, ///< push_back() or operator+= is called on a value of the wrong type
|
||||
insert_wrong_type = 309, ///< insert() is called on a value of the wrong type
|
||||
swap_wrong_type = 310, ///< swap() is called on a value of the wrong type
|
||||
emplace_wrong_type = 311, ///< emplace() or emplace_back() is called on a value of the wrong type
|
||||
update_wrong_type = 312, ///< update() is called on a value of the wrong type
|
||||
unflatten_invalid_value = 313, ///< unflatten() finds conflicting paths
|
||||
unflatten_not_object = 314, ///< unflatten() is called on a non-object
|
||||
unflatten_value_not_primitive = 315, ///< unflatten() is called on an object with non-primitive values
|
||||
invalid_utf8 = 316, ///< dump() finds a string that is not valid UTF-8
|
||||
type_not_serializable = 317, ///< a value cannot be serialized to the requested binary format
|
||||
enum_key_duplicate = 318, ///< an enum-keyed map has two keys that serialize to the same string
|
||||
discarded_value_used = 321, ///< a discarded value is used
|
||||
// out_of_range
|
||||
array_index_out_of_range = 401, ///< an array index is out of range
|
||||
pointer_past_the_end_index = 402, ///< a JSON Pointer uses the array index '-'
|
||||
key_not_found = 403, ///< an object key is not found
|
||||
pointer_unresolved = 404, ///< a JSON Pointer reference token cannot be resolved
|
||||
patch_on_root = 405, ///< the root of a value has no parent, e.g. for a JSON Patch 'remove' or 'add' at the root
|
||||
number_overflow = 406, ///< a number cannot be stored without overflowing to NaN or INF
|
||||
integer_too_large = 407, ///< an integer cannot be represented in the binary format
|
||||
container_too_large = 408, ///< the size of a container in a binary input exceeds the maximal capacity
|
||||
bson_key_with_null = 409, ///< a BSON key contains U+0000
|
||||
value_out_of_range = 410, ///< an enum value is undefined, or a JSON Pointer array index exceeds size_type
|
||||
patch_add_parent_not_container = 411, ///< the parent of a JSON Patch 'add' target is not a container
|
||||
length_too_large = 412, ///< a length does not fit into the length field of a binary format
|
||||
patch_remove_parent_not_container = 413, ///< the parent of a JSON Patch 'remove' target is not a container
|
||||
patch_move_into_child = 414, ///< a JSON Patch 'move' moves a value into one of its children
|
||||
subtype_out_of_range = 415, ///< a binary subtype does not fit into one byte
|
||||
// other_error
|
||||
internal_error = 500, ///< unreachable code was reached
|
||||
patch_test_failed = 501, ///< a JSON Patch 'test' operation failed
|
||||
size_marker_required = 502 ///< UBJSON/BJData output with type markers requires size markers
|
||||
};
|
||||
|
||||
/// @brief general exception of the @ref basic_json class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/exception/
|
||||
class exception : public std::exception
|
||||
@@ -195,6 +273,18 @@ class parse_error : public exception
|
||||
return {id_, byte_, w.c_str()};
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static parse_error create(exception_id id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), pos, what_arg, context);
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static parse_error create(exception_id id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), byte_, what_arg, context);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief byte index of the parse error
|
||||
|
||||
@@ -229,6 +319,12 @@ class invalid_iterator : public exception
|
||||
return {id_, w.c_str()};
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static invalid_iterator create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), what_arg, context);
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
invalid_iterator(int id_, const char* what_arg)
|
||||
@@ -247,6 +343,12 @@ class type_error : public exception
|
||||
return {id_, w.c_str()};
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static type_error create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), what_arg, context);
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -264,6 +366,12 @@ class out_of_range : public exception
|
||||
return {id_, w.c_str()};
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static out_of_range create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), what_arg, context);
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -281,6 +389,12 @@ class other_error : public exception
|
||||
return {id_, w.c_str()};
|
||||
}
|
||||
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static other_error create(exception_id id_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
return create(static_cast<int>(id_), what_arg, context);
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
@@ -307,6 +421,36 @@ void templated_json_throw(ExceptionType exception)
|
||||
(void)exception;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief throws because @a j does not have the type a conversion expects
|
||||
@param[in] expected the expected type(s), e.g. "array" or "binary or array"
|
||||
@param[in] j the value with the wrong type
|
||||
@throw type_error.302 always
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
JSON_HEDLEY_NO_RETURN inline void throw_type_must_be(const char* expected, const BasicJsonType& j)
|
||||
{
|
||||
static_cast<void>(expected); // unused when JSON_NOEXCEPTION is defined
|
||||
static_cast<void>(j);
|
||||
JSON_THROW(type_error::create(exception_id::type_mismatch, concat("type must be ", expected, ", but is ", j.type_name()), &j));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief throws because an operation is not supported for the type of @a j
|
||||
@param[in] id_ the id of the type_error exception (at_wrong_type..update_wrong_type)
|
||||
@param[in] operation the operation, e.g. "erase()"
|
||||
@param[in] j the value the operation was called on
|
||||
@throw type_error always
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
JSON_HEDLEY_NO_RETURN inline void throw_cannot_use_with(const exception_id id_, const char* operation, const BasicJsonType& j)
|
||||
{
|
||||
static_cast<void>(id_); // unused when JSON_NOEXCEPTION is defined
|
||||
static_cast<void>(operation);
|
||||
static_cast<void>(j);
|
||||
JSON_THROW(type_error::create(id_, concat("cannot use ", operation, " with ", j.type_name()), &j));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
|
||||
@@ -35,8 +35,10 @@ std::size_t hash_iteratively(const BasicJsonType& j);
|
||||
@brief hash a JSON value
|
||||
|
||||
The hash function tries to rely on std::hash where possible. Furthermore, the
|
||||
type of the JSON value is taken into account to have different hash values for
|
||||
null, 0, 0U, and false, etc.
|
||||
type of the JSON value is taken into account, so null, false, and numbers may
|
||||
hash differently from each other, but any two numbers that compare equal
|
||||
under operator== hash equally regardless of which of number_integer,
|
||||
number_unsigned, or number_float actually holds the value.
|
||||
|
||||
Hashing an array or an object hashes its elements, which used to call this
|
||||
function again once per nesting level, so a value nested deeply enough
|
||||
@@ -55,8 +57,6 @@ template<typename BasicJsonType>
|
||||
std::size_t hash(const BasicJsonType& j, const std::size_t depth = 0)
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
const auto type = static_cast<std::size_t>(j.type());
|
||||
@@ -113,21 +113,24 @@ std::size_t hash(const BasicJsonType& j, const std::size_t depth = 0)
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::number_integer:
|
||||
{
|
||||
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::number_unsigned:
|
||||
{
|
||||
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::number_float:
|
||||
{
|
||||
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
||||
return combine(type, h);
|
||||
// operator== compares numbers by their mathematical value across
|
||||
// number_integer, number_unsigned, and number_float, so equal
|
||||
// numbers of different internal types (0, 0U, 0.0) must hash the
|
||||
// same. Two equal numbers have the same value, which converts to
|
||||
// the same number_float_t, so all numbers share one type tag and
|
||||
// hash that converted value. Adding zero turns -0.0 (equal to 0)
|
||||
// into 0.0, as std::hash need not map both to the same hash.
|
||||
// The converse does not hold: converting a number_float_t value
|
||||
// to an integer type is lossy, so the result can hash
|
||||
// differently, and unequal numbers that convert to the same
|
||||
// number_float_t (e.g., 2^53 and 2^53 + 1) share a hash.
|
||||
const auto number_type = static_cast<std::size_t>(BasicJsonType::value_t::number_float);
|
||||
const auto value = j.template get<number_float_t>() + static_cast<number_float_t>(0);
|
||||
const auto h = std::hash<number_float_t> {}(value);
|
||||
return combine(number_type, h);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::binary:
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -581,7 +581,7 @@ class wide_string_input_adapter
|
||||
template<class T>
|
||||
JSON_HEDLEY_NO_RETURN std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
|
||||
{
|
||||
JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::unexpected_byte, 1, "wide string type cannot be interpreted as binary data", nullptr));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -793,7 +793,7 @@ inline file_input_adapter input_adapter(std::FILE* file)
|
||||
{
|
||||
if (file == nullptr)
|
||||
{
|
||||
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
return file_input_adapter(file);
|
||||
}
|
||||
@@ -802,7 +802,7 @@ 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));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
return input_stream_adapter(stream);
|
||||
}
|
||||
@@ -827,7 +827,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||
{
|
||||
if (b == nullptr)
|
||||
{
|
||||
JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
JSON_THROW(parse_error::create(exception_id::syntax_error, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
}
|
||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||
|
||||
@@ -176,6 +176,27 @@ template<typename ArrayType>
|
||||
inline void reserve_array(ArrayType& /*arr*/, std::size_t /*len*/, priority_tag<0> /*unused*/)
|
||||
{}
|
||||
|
||||
/*!
|
||||
@brief reports an object or array whose announced size exceeds max_size()
|
||||
|
||||
Shared by json_sax_dom_parser and json_sax_dom_callback_parser.
|
||||
|
||||
@param[in] sax the SAX parser to report the error to
|
||||
@param[in] len the number of elements announced by the input, or unknown_size()
|
||||
@param[in] kind "object" or "array"
|
||||
@param[in] ref the object or array that was just created
|
||||
@return whether parsing should continue (false after reporting out_of_range.408)
|
||||
*/
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
bool check_container_size(SAX& sax, std::size_t len, const char* kind, BasicJsonType* ref)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref->max_size()))
|
||||
{
|
||||
return sax.parse_error(0, "", out_of_range::create(exception_id::container_too_large, concat("excessive ", kind, " size: ", std::to_string(len)), ref));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
/*!
|
||||
@brief set the diagnostic positions of a value the DOM SAX parsers just stored
|
||||
@@ -185,6 +206,35 @@ befriends this struct, as the position members are private.
|
||||
*/
|
||||
struct diagnostic_positions
|
||||
{
|
||||
/*!
|
||||
@param[in,out] v the object or array whose opening brace or bracket was just read
|
||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
*/
|
||||
template<typename BasicJsonType, typename LexerType>
|
||||
static void set_container_start(BasicJsonType& v, LexerType* lexer)
|
||||
{
|
||||
if (lexer)
|
||||
{
|
||||
// Lexer has read the first character of the container, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
v.start_position = lexer->get_position() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@param[in,out] v the object or array whose closing brace or bracket was just read
|
||||
@param[in] lexer the lexer that read it, or nullptr to leave @a v alone
|
||||
*/
|
||||
template<typename BasicJsonType, typename LexerType>
|
||||
static void set_container_end(BasicJsonType& v, LexerType* lexer)
|
||||
{
|
||||
if (lexer)
|
||||
{
|
||||
// Lexer's position is past the closing brace or bracket, so set that as the end position.
|
||||
v.end_position = lexer->get_position();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@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
|
||||
@@ -349,22 +399,11 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the object here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the object, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||
}
|
||||
|
||||
return true;
|
||||
return check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
|
||||
bool key(string_t& val)
|
||||
@@ -383,11 +422,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing brace, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -400,17 +435,13 @@ class json_sax_dom_parser
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the array here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -427,11 +458,7 @@ class json_sax_dom_parser
|
||||
JSON_ASSERT(ref_stack.back()->is_array());
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -611,21 +638,11 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the object here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the object, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// check object limit
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
|
||||
}
|
||||
return check_container_size(*this, len, "object", ref_stack.back());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -695,11 +712,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing brace, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -710,13 +723,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
const string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||
{
|
||||
@@ -742,20 +749,13 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// Manually set the start position of the array here.
|
||||
// Ensure this is after the call to handle_value to ensure correct start position.
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer has read the first character of the array, so
|
||||
// subtract 1 from the position to get the correct start position.
|
||||
ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
|
||||
}
|
||||
diagnostic_positions::set_container_start(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
// check array limit
|
||||
if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_container_size(*this, len, "array", ref_stack.back())))
|
||||
{
|
||||
return parse_error(0, "", out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != detail::unknown_size())
|
||||
@@ -779,11 +779,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
if (m_lexer_ref)
|
||||
{
|
||||
// Lexer's position is past the closing bracket, so set that as the end position.
|
||||
ref_stack.back()->end_position = m_lexer_ref->get_position();
|
||||
}
|
||||
diagnostic_positions::set_container_end(*ref_stack.back(), m_lexer_ref);
|
||||
#endif
|
||||
|
||||
ref_stack.back()->set_parents();
|
||||
@@ -809,13 +805,7 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
}
|
||||
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
const string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
const string_t object_key = pop_container();
|
||||
|
||||
// remove discarded value
|
||||
if (!ref_stack.empty() && ref_stack.back())
|
||||
@@ -902,6 +892,23 @@ class json_sax_dom_callback_parser
|
||||
return string_t{};
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief leave the object or array that end_object()/end_array() just closed
|
||||
@return the key the container is stored under in its parent (see
|
||||
container_key_stack)
|
||||
*/
|
||||
string_t pop_container()
|
||||
{
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
JSON_ASSERT(!container_key_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
string_t object_key = std::move(container_key_stack.back());
|
||||
container_key_stack.pop_back();
|
||||
return object_key;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief remove the discarded value the callback rejected from its parent,
|
||||
unless it is a duplicate key's slot with a stashed previous value, in
|
||||
|
||||
@@ -221,44 +221,6 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
// scan functions
|
||||
/////////////////////
|
||||
|
||||
/// contiguous input: try to decode the 4 hex digits following `\u`
|
||||
/// directly from the input buffer via hex_codepoint(), instead of 4 calls
|
||||
/// to get(). On success, advances the adapter and the position counters
|
||||
/// exactly as those 4 get() calls would (a hex digit is never '\n', so
|
||||
/// only the flat counters move) and leaves @a current holding the last of
|
||||
/// the 4 digits, just as the last such get() would; the codepoint is
|
||||
/// written to @a out. Makes no state change and returns false - for a
|
||||
/// pending unget, fewer than 4 remaining bytes, or any of the 4 bytes not
|
||||
/// being a hex digit - so the caller falls back unchanged to the
|
||||
/// per-character loop, which then reports the same diagnostic (stopping
|
||||
/// at the first invalid digit) as before this optimization.
|
||||
bool get_codepoint_bulk(std::true_type /*bulk*/, int& out)
|
||||
{
|
||||
if (next_unget || ia.bulk_remaining() < 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
const char_type* const raw = ia.bulk_data();
|
||||
const int codepoint = hex_codepoint(reinterpret_cast<const unsigned char*>(raw));
|
||||
if (codepoint < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ia.bulk_skip(4);
|
||||
// a hex digit is never a newline, so only the flat counters advance
|
||||
position.chars_read_total += 4;
|
||||
position.chars_read_current_line += 4;
|
||||
current = char_traits<char_type>::to_int_type(raw[3]);
|
||||
out = codepoint;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// streaming input: no bulk fast path
|
||||
bool get_codepoint_bulk(std::false_type /*bulk*/, int& /*out*/) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief get codepoint from 4 hex characters following `\\u`
|
||||
|
||||
@@ -278,14 +240,6 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
{
|
||||
// this function only makes sense after reading `\u`
|
||||
JSON_ASSERT(current == 'u');
|
||||
|
||||
// contiguous input: decode all 4 hex digits directly from the buffer
|
||||
int fast_codepoint = 0;
|
||||
if (get_codepoint_bulk(std::integral_constant<bool, bulk_scan> {}, fast_codepoint))
|
||||
{
|
||||
return fast_codepoint;
|
||||
}
|
||||
|
||||
int codepoint = 0;
|
||||
|
||||
const auto factors = { 12u, 8u, 4u, 0u };
|
||||
@@ -1090,11 +1044,9 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
token_type::parse_error otherwise
|
||||
|
||||
@note The scanner is independent of the current locale: token_buffer
|
||||
always holds `.`. The conversion of float and double does not use
|
||||
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()).
|
||||
always holds `.`. Only the std::strtod fallback of convert_number()
|
||||
depends on the locale, 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.
|
||||
{
|
||||
@@ -1107,7 +1059,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
|
||||
// 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).
|
||||
// convert_number() uses it to split the token; npos means
|
||||
// convert_number() uses it to count significant digits; npos means
|
||||
// "not seen an exponent yet" and is resolved at scan_number_done
|
||||
std::size_t mantissa_end = std::string::npos;
|
||||
|
||||
@@ -1437,8 +1389,8 @@ scan_number_done:
|
||||
@param[in] mantissa_end offset just past the last mantissa byte in
|
||||
token_buffer (the index of 'e'/'E', or
|
||||
token_buffer.size() when there is no exponent);
|
||||
with decimal_point_position, it locates the parts
|
||||
of a float token without scanning it again
|
||||
used to skip Clinger's fast path when it cannot
|
||||
possibly succeed - see detail::mantissa_fits_clinger()
|
||||
*/
|
||||
token_type convert_number(token_type number_type, std::size_t mantissa_end)
|
||||
{
|
||||
@@ -1492,11 +1444,10 @@ scan_number_done:
|
||||
}
|
||||
|
||||
// this code is reached if we parse a floating-point number or if an
|
||||
// integer conversion above overflowed. float and double (and long
|
||||
// double where it is binary64) are converted by the library itself,
|
||||
// correctly rounded and independent of the locale; other long double
|
||||
// formats use std::from_chars when available, otherwise the
|
||||
// locale-aware strtold.
|
||||
// integer conversion above overflowed. Prefer std::from_chars
|
||||
// (Eisel-Lemire, locale-independent, correctly rounded) when available;
|
||||
// otherwise the exact Clinger fast path (double only); otherwise the
|
||||
// locale-aware strtof/strtod/strtold.
|
||||
if (convert_float_fast(num_begin, num_end, decimal_point_position, mantissa_end, value_float))
|
||||
{
|
||||
return token_type::value_float;
|
||||
@@ -2070,6 +2021,39 @@ scan_number_done:
|
||||
// read the next character and ignore whitespace
|
||||
skip_whitespace();
|
||||
|
||||
return scan_after_whitespace();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief scan the next token when the caller expects a separator (':' or
|
||||
',') most of the time
|
||||
|
||||
After an object key the next token is almost always ':', after a value
|
||||
inside an object or array almost always ','. Testing for that character
|
||||
first is a compare and a well-predicted branch, where the switch in
|
||||
scan_after_whitespace() is an indirect jump through a table. Anything else
|
||||
goes through the switch, so the result is the same as scan()'s.
|
||||
|
||||
May only be called after scan() has run once (the BOM check is skipped).
|
||||
*/
|
||||
token_type scan_expecting(token_type expected_type)
|
||||
{
|
||||
JSON_ASSERT(expected_type == token_type::name_separator || expected_type == token_type::value_separator);
|
||||
JSON_ASSERT(position.chars_read_total > 0);
|
||||
const char_int_type expected_char = static_cast<unsigned char>((expected_type == token_type::name_separator) ? ':' : ',');
|
||||
skip_whitespace();
|
||||
if (JSON_HEDLEY_LIKELY(current == expected_char))
|
||||
{
|
||||
return expected_type;
|
||||
}
|
||||
return scan_after_whitespace();
|
||||
}
|
||||
|
||||
private:
|
||||
/// the part of scan() after the leading whitespace: skip comments and
|
||||
/// scan the token that starts with current
|
||||
token_type scan_after_whitespace()
|
||||
{
|
||||
// ignore comments
|
||||
while (ignore_comments && current == '/')
|
||||
{
|
||||
@@ -2149,7 +2133,6 @@ scan_number_done:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// input adapter
|
||||
InputAdapterType ia;
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -156,9 +156,7 @@ class parser
|
||||
// strict mode: next byte must be EOF
|
||||
if (get_token() != token_type::end_of_input)
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::end_of_input, "value"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -197,10 +195,7 @@ class parser
|
||||
// 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));
|
||||
syntax_error(sdp, exception_message(token_type::end_of_input, "value"));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -250,9 +245,7 @@ class parser
|
||||
// parse key
|
||||
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
{
|
||||
@@ -260,11 +253,9 @@ class parser
|
||||
}
|
||||
|
||||
// parse separator (:)
|
||||
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_token_expecting(token_type::name_separator)))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::name_separator, "object separator"));
|
||||
}
|
||||
|
||||
// remember we are now inside an object
|
||||
@@ -307,7 +298,7 @@ class parser
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
||||
out_of_range::create(exception_id::number_overflow, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
||||
@@ -375,23 +366,16 @@ class parser
|
||||
case token_type::parse_error:
|
||||
{
|
||||
// using "uninitialized" to avoid an "expected" message
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::uninitialized, "value"));
|
||||
}
|
||||
case token_type::end_of_input:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
||||
return syntax_error(*sax, "attempting to parse an empty input; check that your input string or stream contains the expected JSON");
|
||||
}
|
||||
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::literal_or_value, "value"));
|
||||
}
|
||||
case token_type::uninitialized:
|
||||
case token_type::end_array:
|
||||
@@ -401,9 +385,7 @@ class parser
|
||||
case token_type::literal_or_value:
|
||||
default: // the last token was unexpected
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::literal_or_value, "value"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,7 +405,7 @@ class parser
|
||||
{
|
||||
// comma -> next value
|
||||
// or end of array (ignore_trailing_commas = true)
|
||||
if (get_token() == token_type::value_separator)
|
||||
if (get_token_expecting(token_type::value_separator))
|
||||
{
|
||||
// parse a new value
|
||||
get_token();
|
||||
@@ -454,16 +436,14 @@ class parser
|
||||
continue;
|
||||
}
|
||||
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::end_array, "array"));
|
||||
}
|
||||
|
||||
// states.back() is false -> object
|
||||
|
||||
// comma -> next value
|
||||
// or end of object (ignore_trailing_commas = true)
|
||||
if (get_token() == token_type::value_separator)
|
||||
if (get_token_expecting(token_type::value_separator))
|
||||
{
|
||||
get_token();
|
||||
|
||||
@@ -473,9 +453,7 @@ class parser
|
||||
// parse key
|
||||
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::value_string, "object key"));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
@@ -484,11 +462,9 @@ class parser
|
||||
}
|
||||
|
||||
// parse separator (:)
|
||||
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_token_expecting(token_type::name_separator)))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::name_separator, "object separator"));
|
||||
}
|
||||
|
||||
// parse values
|
||||
@@ -516,9 +492,7 @@ class parser
|
||||
continue;
|
||||
}
|
||||
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
|
||||
return syntax_error(*sax, exception_message(token_type::end_object, "object"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,6 +502,26 @@ class parser
|
||||
return last_token = m_lexer.scan();
|
||||
}
|
||||
|
||||
/// get next token from lexer; true if it is the separator @a expected_type
|
||||
/// (name_separator or value_separator), which it usually is
|
||||
bool get_token_expecting(token_type expected_type)
|
||||
{
|
||||
return (last_token = m_lexer.scan_expecting(expected_type)) == expected_type;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reports a syntax error at the current token (parse_error.101)
|
||||
@param[in] sax the SAX parser to report the error to
|
||||
@param[in] message the error message
|
||||
@return the result of the SAX parser's parse_error()
|
||||
*/
|
||||
template<typename SAX>
|
||||
bool syntax_error(SAX& sax, const std::string& message)
|
||||
{
|
||||
return sax.parse_error(m_lexer.get_position(), m_lexer.get_token_string(),
|
||||
parse_error::create(exception_id::syntax_error, m_lexer.get_position(), message, nullptr));
|
||||
}
|
||||
|
||||
std::string exception_message(const token_type expected, const std::string& context)
|
||||
{
|
||||
std::string error_msg = "syntax error ";
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint64_t, uint8_t
|
||||
#include <cstdint> // uint64_t
|
||||
#include <cstring> // memcpy
|
||||
|
||||
#include <nlohmann/detail/bit_ops.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
// Optional SIMD backend for bulk UTF-8 validation. This is an opt-in external
|
||||
@@ -71,12 +69,18 @@ inline std::size_t find_string_special(const unsigned char* data, std::size_t n)
|
||||
std::size_t i = 0;
|
||||
for (; i + 8 <= n; i += 8)
|
||||
{
|
||||
const std::uint64_t special = swar_string_special(read_eight_bytes(data + i));
|
||||
if (special != 0)
|
||||
std::uint64_t word = 0;
|
||||
std::memcpy(&word, data + i, sizeof(word));
|
||||
if (swar_string_special(word) != 0)
|
||||
{
|
||||
// the lowest flagged byte is the first special one: the borrows of
|
||||
// the subtractions can only flag bytes above a true hit
|
||||
return i + (static_cast<std::size_t>(count_trailing_zeros(special)) / 8);
|
||||
// a special byte is in this word; locate it (endian-agnostic)
|
||||
for (std::size_t j = 0; j < 8; ++j)
|
||||
{
|
||||
if (is_string_special(data[i + j]))
|
||||
{
|
||||
return i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < n; ++i)
|
||||
@@ -110,7 +114,8 @@ inline std::size_t find_ascii_copyable_run(const unsigned char* data, std::size_
|
||||
std::size_t i = 0;
|
||||
for (; i + 8 <= n; i += 8)
|
||||
{
|
||||
const std::uint64_t v = read_eight_bytes(data + i);
|
||||
std::uint64_t v = 0;
|
||||
std::memcpy(&v, data + i, sizeof(v));
|
||||
const std::uint64_t q = v ^ 0x2222222222222222ull; // '"' (0x22)
|
||||
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull; // '\\' (0x5C)
|
||||
const std::uint64_t d = v ^ 0x7F7F7F7F7F7F7F7Full; // DEL (0x7F)
|
||||
@@ -121,9 +126,7 @@ inline std::size_t find_ascii_copyable_run(const unsigned char* data, std::size_
|
||||
| (v & high); // >= 0x80
|
||||
if (stop != 0)
|
||||
{
|
||||
// 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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < n; ++i)
|
||||
@@ -250,18 +253,12 @@ 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
|
||||
}
|
||||
// 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);
|
||||
if (seq == 0)
|
||||
{
|
||||
const std::size_t seq = validate_one_utf8(data + pos, n - pos);
|
||||
if (seq == 0)
|
||||
{
|
||||
return pos; // ill-formed or truncated: let the byte path diagnose it
|
||||
}
|
||||
pos += seq;
|
||||
break; // ill-formed or truncated: let the byte path diagnose it
|
||||
}
|
||||
while (pos < n && data[pos] >= 0x80u);
|
||||
pos += seq;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
@@ -276,7 +273,8 @@ inline std::size_t find_string_delimiter(const unsigned char* data, std::size_t
|
||||
std::size_t i = 0;
|
||||
for (; i + 8 <= n; i += 8)
|
||||
{
|
||||
const std::uint64_t v = read_eight_bytes(data + i);
|
||||
std::uint64_t v = 0;
|
||||
std::memcpy(&v, data + i, sizeof(v));
|
||||
const std::uint64_t q = v ^ 0x2222222222222222ull;
|
||||
const std::uint64_t b = v ^ 0x5C5C5C5C5C5C5C5Cull;
|
||||
const std::uint64_t hit = ((q - ones) & ~q & high)
|
||||
@@ -284,8 +282,14 @@ inline std::size_t find_string_delimiter(const unsigned char* data, std::size_t
|
||||
| ((v - 0x2020202020202020ull) & ~v & high);
|
||||
if (hit != 0)
|
||||
{
|
||||
// the lowest flagged byte is the first delimiter (see find_string_special())
|
||||
return i + (static_cast<std::size_t>(count_trailing_zeros(hit)) / 8);
|
||||
for (std::size_t j = 0; j < 8; ++j)
|
||||
{
|
||||
const unsigned char c = data[i + j];
|
||||
if (c == '\"' || c == '\\' || c < 0x20u)
|
||||
{
|
||||
return i + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (; i < n; ++i)
|
||||
@@ -316,50 +320,5 @@ inline std::size_t string_bulk_run(const unsigned char* data, std::size_t n) noe
|
||||
return scalar_string_bulk_run(data, n);
|
||||
}
|
||||
|
||||
// Decode the 4 hex digits at [data, data+4) - the digits following a `\u`
|
||||
// escape - into a codepoint 0x0000..0xFFFF via one table lookup per byte
|
||||
// (after yyjson's read_hex_u16), or return -1 if any of the 4 bytes is not a
|
||||
// hex digit ('0'..'9', 'A'..'F', 'a'..'f'). The caller must already have
|
||||
// checked that 4 bytes are available; used by lexer::get_codepoint()'s
|
||||
// contiguous fast path. On -1 it falls back to the byte-at-a-time loop, which
|
||||
// stops at the first invalid digit, so the reported error and position are
|
||||
// unaffected by this fast path.
|
||||
inline int hex_codepoint(const unsigned char* data) noexcept
|
||||
{
|
||||
static const std::array<std::uint8_t, 256> hex_digit_table = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
{
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 00..0F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 10..1F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 20..2F
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 30..3F ('0'..'9')
|
||||
0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 40..4F ('A'..'F')
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 50..5F
|
||||
0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 60..6F ('a'..'f')
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 70..7F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 80..8F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 90..9F
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // A0..AF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // B0..BF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // C0..CF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // D0..DF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // E0..EF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // F0..FF
|
||||
}
|
||||
};
|
||||
|
||||
const std::uint8_t d0 = hex_digit_table[data[0]];
|
||||
const std::uint8_t d1 = hex_digit_table[data[1]];
|
||||
const std::uint8_t d2 = hex_digit_table[data[2]];
|
||||
const std::uint8_t d3 = hex_digit_table[data[3]];
|
||||
// every valid digit is <= 0xF; the combined OR only exceeds it if at
|
||||
// least one of the four bytes was not a hex digit (looked up as 0xFF)
|
||||
if ((d0 | d1 | d2 | d3) > 0x0F)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return (d0 << 12) | (d1 << 8) | (d2 << 4) | d3;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
@@ -279,6 +279,12 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
}
|
||||
}
|
||||
|
||||
/// @throw invalid_iterator.214 always
|
||||
JSON_HEDLEY_NO_RETURN void throw_cannot_get_value() const
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_value_unavailable, "cannot get value", m_object));
|
||||
}
|
||||
|
||||
public:
|
||||
/*!
|
||||
@brief return a reference to the value pointed to by the iterator
|
||||
@@ -303,7 +309,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
}
|
||||
|
||||
case value_t::null:
|
||||
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
|
||||
throw_cannot_get_value();
|
||||
|
||||
case value_t::string:
|
||||
case value_t::boolean:
|
||||
@@ -319,7 +325,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
return *m_object;
|
||||
}
|
||||
|
||||
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
|
||||
throw_cannot_get_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,7 +367,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
return m_object;
|
||||
}
|
||||
|
||||
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
|
||||
throw_cannot_get_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +484,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
// if objects are not the same, the comparison is undefined
|
||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterators_compare_different_values, "cannot compare iterators of different containers", m_object));
|
||||
}
|
||||
|
||||
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
||||
@@ -527,7 +533,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
// if objects are not the same, the comparison is undefined
|
||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
||||
{
|
||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterators_compare_different_values, "cannot compare iterators of different containers", m_object));
|
||||
}
|
||||
|
||||
// value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
|
||||
@@ -540,7 +546,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
switch (m_object->m_data.m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_order_on_object, "cannot compare order of object iterators", m_object));
|
||||
|
||||
case value_t::array:
|
||||
return (m_it.array_iterator < other.m_it.array_iterator);
|
||||
@@ -596,7 +602,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
switch (m_object->m_data.m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object));
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
@@ -675,7 +681,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
switch (m_object->m_data.m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_arithmetic_on_object, "cannot use offsets with object iterators", m_object));
|
||||
|
||||
case value_t::array:
|
||||
return m_it.array_iterator - other.m_it.array_iterator;
|
||||
@@ -704,13 +710,13 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
switch (m_object->m_data.m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_subscript_on_object, "cannot use operator[] for object iterators", m_object));
|
||||
|
||||
case value_t::array:
|
||||
return *std::next(m_it.array_iterator, n);
|
||||
|
||||
case value_t::null:
|
||||
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
|
||||
throw_cannot_get_value();
|
||||
|
||||
case value_t::string:
|
||||
case value_t::boolean:
|
||||
@@ -726,7 +732,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
return *m_object;
|
||||
}
|
||||
|
||||
JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
|
||||
throw_cannot_get_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -744,7 +750,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
return m_it.object_iterator->first;
|
||||
}
|
||||
|
||||
JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
|
||||
JSON_THROW(invalid_iterator::create(exception_id::iterator_key_not_object, "cannot use key() for non-object iterators", m_object));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -81,9 +81,13 @@ class json_pointer
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_string_t/
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
|
||||
operator string_t() const
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return to_string();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef JSON_NO_IO
|
||||
/// @brief write string representation of the JSON pointer to stream
|
||||
@@ -162,7 +166,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
|
||||
throw_no_parent();
|
||||
}
|
||||
|
||||
reference_tokens.erase(reference_tokens.begin());
|
||||
@@ -174,7 +178,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
|
||||
throw_no_parent();
|
||||
}
|
||||
|
||||
return reference_tokens.front();
|
||||
@@ -200,7 +204,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
|
||||
throw_no_parent();
|
||||
}
|
||||
|
||||
reference_tokens.pop_back();
|
||||
@@ -212,7 +216,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
|
||||
throw_no_parent();
|
||||
}
|
||||
|
||||
return reference_tokens.back();
|
||||
@@ -240,6 +244,21 @@ class json_pointer
|
||||
}
|
||||
|
||||
private:
|
||||
/// @throw out_of_range.405 always
|
||||
JSON_HEDLEY_NO_RETURN static void throw_no_parent()
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::patch_on_root, "JSON pointer has no parent", nullptr));
|
||||
}
|
||||
|
||||
/// @throw out_of_range.404 always
|
||||
template<typename BasicJsonContext>
|
||||
JSON_HEDLEY_NO_RETURN static void throw_unresolved(const string_t& reference_token, BasicJsonContext context)
|
||||
{
|
||||
static_cast<void>(reference_token); // unused when JSON_NOEXCEPTION is defined
|
||||
static_cast<void>(context);
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::pointer_unresolved, detail::concat("unresolved reference token '", reference_token, "'"), context));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief result of @ref parse_array_index
|
||||
|
||||
@@ -325,13 +344,13 @@ class json_pointer
|
||||
// the branches differ in their messages, not after JSON_THROW's expansion
|
||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||
case array_index_status::leading_zero:
|
||||
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_index_leading_zero, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
|
||||
case array_index_status::not_a_number:
|
||||
JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_index_not_a_number, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
|
||||
case array_index_status::unresolved:
|
||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
|
||||
throw_unresolved(s, nullptr);
|
||||
case array_index_status::exceeds_size_type:
|
||||
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::value_out_of_range, detail::concat("array index ", s, " exceeds size_type"), nullptr));
|
||||
case array_index_status::ok:
|
||||
default:
|
||||
break;
|
||||
@@ -345,7 +364,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
|
||||
throw_no_parent();
|
||||
}
|
||||
|
||||
json_pointer result = *this;
|
||||
@@ -433,7 +452,7 @@ class json_pointer
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
|
||||
JSON_THROW(detail::type_error::create(detail::exception_id::unflatten_invalid_value, "invalid value to unflatten", &j));
|
||||
}
|
||||
|
||||
prefix.push_back(reference_token);
|
||||
@@ -516,7 +535,7 @@ class json_pointer
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
|
||||
throw_unresolved(reference_token, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +567,7 @@ class json_pointer
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||
{
|
||||
// "-" always fails the range check
|
||||
JSON_THROW(detail::out_of_range::create(402, detail::concat(
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::pointer_past_the_end_index, detail::concat(
|
||||
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
|
||||
") is out of range"), ptr));
|
||||
}
|
||||
@@ -557,7 +576,7 @@ class json_pointer
|
||||
// Bounds check before access to avoid exception with JSON_NOEXCEPTION
|
||||
if (JSON_HEDLEY_UNLIKELY(idx >= ptr->m_data.m_value.array->size()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(401, detail::concat(
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::array_index_out_of_range, detail::concat(
|
||||
"array index ", std::to_string(idx), " is out of range"), ptr));
|
||||
}
|
||||
ptr = &ptr->operator[](idx);
|
||||
@@ -573,7 +592,7 @@ class json_pointer
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
|
||||
throw_unresolved(reference_token, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,7 +636,7 @@ class json_pointer
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||
{
|
||||
// "-" cannot be used for const access
|
||||
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
|
||||
JSON_THROW(detail::out_of_range::create(detail::exception_id::pointer_past_the_end_index, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
|
||||
}
|
||||
|
||||
// use unchecked array access; the const operator[]
|
||||
@@ -635,7 +654,7 @@ class json_pointer
|
||||
case detail::value_t::binary:
|
||||
case detail::value_t::discarded:
|
||||
default:
|
||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
|
||||
throw_unresolved(reference_token, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -690,9 +709,9 @@ class json_pointer
|
||||
// the branches differ in their messages, not after JSON_THROW's expansion
|
||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||
case array_index_status::leading_zero:
|
||||
JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_index_leading_zero, 0, detail::concat("array index '", reference_token, "' must not begin with '0'"), nullptr));
|
||||
case array_index_status::not_a_number:
|
||||
JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", reference_token, "' is not a number"), nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_index_not_a_number, 0, detail::concat("array index '", reference_token, "' is not a number"), nullptr));
|
||||
case array_index_status::unresolved:
|
||||
case array_index_status::exceeds_size_type:
|
||||
return nullptr;
|
||||
@@ -819,7 +838,7 @@ class json_pointer
|
||||
// check if a nonempty reference string begins with slash
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_missing_slash, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
|
||||
}
|
||||
|
||||
// extract the reference tokens:
|
||||
@@ -855,7 +874,7 @@ class json_pointer
|
||||
(reference_token[pos + 1] != '0' &&
|
||||
reference_token[pos + 1] != '1')))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
|
||||
JSON_THROW(detail::parse_error::create(detail::exception_id::pointer_invalid_escape, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,7 +971,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
|
||||
JSON_THROW(detail::type_error::create(detail::exception_id::unflatten_not_object, "only objects can be unflattened", &value));
|
||||
}
|
||||
|
||||
BasicJsonType result;
|
||||
@@ -980,7 +999,7 @@ class json_pointer
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
|
||||
JSON_THROW(detail::type_error::create(detail::exception_id::unflatten_value_not_primitive, "values in object must be primitive", &element.second));
|
||||
}
|
||||
|
||||
// Assign the value to the reference pointed to by JSON pointer. Note
|
||||
@@ -1022,9 +1041,13 @@ class json_pointer
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
|
||||
bool operator==(const string_t& rhs) const
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return *this == json_pointer(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// @brief 3-way compares two JSON pointers
|
||||
template<typename RefStringTypeRhs>
|
||||
@@ -1102,18 +1125,26 @@ template<typename RefStringTypeLhs,
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
||||
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
|
||||
const StringType& rhs)
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return lhs == json_pointer<RefStringTypeLhs>(rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename RefStringTypeRhs,
|
||||
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
||||
inline bool operator==(const StringType& lhs,
|
||||
const json_pointer<RefStringTypeRhs>& rhs)
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return json_pointer<RefStringTypeRhs>(lhs) == rhs;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
||||
@@ -1127,18 +1158,26 @@ template<typename RefStringTypeLhs,
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
||||
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
||||
const StringType& rhs)
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename RefStringTypeRhs,
|
||||
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
||||
inline bool operator!=(const StringType& lhs,
|
||||
const json_pointer<RefStringTypeRhs>& rhs)
|
||||
#if JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
= delete;
|
||||
#else
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
|
||||
|
||||
@@ -34,6 +34,7 @@ class json_ref
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, braced_list(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@@ -69,9 +70,17 @@ class json_ref
|
||||
return &** this;
|
||||
}
|
||||
|
||||
/// whether the value was written as a braced list, such as {"key", 1},
|
||||
/// rather than given as a value
|
||||
bool is_braced_list() const noexcept
|
||||
{
|
||||
return braced_list;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type const* value_ref = nullptr;
|
||||
bool braced_list = false;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
return ej_pair.first == e; \
|
||||
}); \
|
||||
if (it != std::end(m)) j = it->second; \
|
||||
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE, nullptr)); \
|
||||
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range,"enum value out of range for " #ENUM_TYPE, nullptr)); \
|
||||
} \
|
||||
template<typename BasicJsonType> \
|
||||
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
|
||||
@@ -327,7 +327,7 @@
|
||||
return ej_pair.second == j; \
|
||||
}); \
|
||||
if (it != std::end(m)) e = it->first; \
|
||||
else ::nlohmann::detail::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)); \
|
||||
else ::nlohmann::detail::templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(nlohmann::detail::exception_id::value_out_of_range, 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
|
||||
@@ -888,6 +888,10 @@
|
||||
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
#define JSON_DELETE_DEPRECATED_FUNCTIONS 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_DISABLE_TUPLE_REFERENCE_CONVERSION
|
||||
#define JSON_DISABLE_TUPLE_REFERENCE_CONVERSION 0
|
||||
#endif
|
||||
@@ -43,6 +43,8 @@
|
||||
#undef JSON_PRECISE_STREAM_POSITION
|
||||
#undef JSON_STRICT_NUL_HANDLING
|
||||
#undef JSON_STRICT_BINARY_UTF8
|
||||
#undef JSON_DELETE_DEPRECATED_FUNCTIONS
|
||||
#undef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#endif
|
||||
|
||||
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
|
||||
@@ -438,6 +438,30 @@ template<typename BasicJsonType, typename CompatibleObjectType>
|
||||
struct is_compatible_object_type
|
||||
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
|
||||
|
||||
template<typename T>
|
||||
using insert_result_t = decltype(std::declval<T&>().insert(std::declval<const value_type_t<T>&>()));
|
||||
|
||||
template<typename T>
|
||||
using insert_result_second_t = decltype(std::declval<T&>().insert(std::declval<const value_type_t<T>&>()).second);
|
||||
|
||||
// a map-like type (std::map, std::unordered_map, ...) whose keys are enums; see
|
||||
// JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
template<typename T, typename = void>
|
||||
struct is_enum_keyed_map : std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct is_enum_keyed_map <
|
||||
T, enable_if_t < is_detected<mapped_type_t, T>::value&&
|
||||
is_detected<key_type_t, T>::value >>
|
||||
{
|
||||
// maps with non-unique keys (std::multimap, std::unordered_multimap, ...)
|
||||
// are excluded, because an object cannot hold duplicate keys; they are
|
||||
// detected by insert() returning an iterator instead of a pair<iterator, bool>
|
||||
// NOLINTNEXTLINE(modernize-type-traits) we use C++11
|
||||
static constexpr bool value = std::is_enum<typename T::key_type>::value &&
|
||||
!(is_detected<insert_result_t, T>::value && !is_detected<insert_result_second_t, T>::value);
|
||||
};
|
||||
|
||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||
typename = void>
|
||||
struct is_constructible_object_type_impl : std::false_type {};
|
||||
@@ -882,6 +906,21 @@ T conditional_static_cast(U value)
|
||||
return value;
|
||||
}
|
||||
|
||||
// like conditional_static_cast, but converts to bool by comparing with zero,
|
||||
// because MSVC 2015 warns about any conversion to bool (C4800), even with an
|
||||
// explicit cast; used for enums whose underlying type is bool
|
||||
template < typename T, typename U, enable_if_t < !std::is_same<T, bool>::value, int > = 0 >
|
||||
T bool_aware_static_cast(U value)
|
||||
{
|
||||
return conditional_static_cast<T>(value);
|
||||
}
|
||||
|
||||
template<typename T, typename U, enable_if_t<std::is_same<T, bool>::value, int> = 0>
|
||||
bool bool_aware_static_cast(U value)
|
||||
{
|
||||
return value != U();
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
using all_integral = conjunction<std::is_integral<Types>...>;
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -888,7 +888,7 @@ class serializer
|
||||
{
|
||||
case error_handler_t::strict:
|
||||
{
|
||||
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", detail::hex_byte(byte)), nullptr));
|
||||
JSON_THROW(type_error::create(exception_id::invalid_utf8, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", detail::hex_byte(byte)), nullptr));
|
||||
}
|
||||
|
||||
case error_handler_t::ignore:
|
||||
@@ -1021,7 +1021,7 @@ class serializer
|
||||
{
|
||||
case error_handler_t::strict:
|
||||
{
|
||||
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));
|
||||
JSON_THROW(type_error::create(exception_id::invalid_utf8, 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:
|
||||
|
||||
+553
-170
File diff suppressed because it is too large.
Load diff
@@ -90,6 +90,19 @@ private:
|
||||
return self.end();
|
||||
}
|
||||
|
||||
/// @brief shared implementation of the const and non-const at() overloads
|
||||
/// @throw std::out_of_range if @a key is not found
|
||||
template<typename Self, typename KeyType>
|
||||
static auto at_impl(Self& self, const KeyType& key) -> decltype((self.begin()->second))
|
||||
{
|
||||
const auto it = find_impl(self, key);
|
||||
if (it == self.end())
|
||||
{
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/// @brief remove the entry @a it points to, preserving order
|
||||
/// @note keys are not movable, so the tail is destroyed and re-constructed in place
|
||||
void erase_at(iterator it)
|
||||
@@ -156,46 +169,26 @@ public:
|
||||
|
||||
T& at(const key_type& key)
|
||||
{
|
||||
const auto it = find_impl(*this, key);
|
||||
if (it == this->end())
|
||||
{
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
return it->second;
|
||||
return at_impl(*this, key);
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||
{
|
||||
const auto it = find_impl(*this, key);
|
||||
if (it == this->end())
|
||||
{
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
return it->second;
|
||||
return at_impl(*this, key);
|
||||
}
|
||||
|
||||
const T& at(const key_type& key) const
|
||||
{
|
||||
const auto it = find_impl(*this, key);
|
||||
if (it == this->end())
|
||||
{
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
return it->second;
|
||||
return at_impl(*this, key);
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||
{
|
||||
const auto it = find_impl(*this, key);
|
||||
if (it == this->end())
|
||||
{
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
return it->second;
|
||||
return at_impl(*this, key);
|
||||
}
|
||||
|
||||
size_type erase(const key_type& key)
|
||||
@@ -259,6 +252,9 @@ public:
|
||||
|
||||
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
|
||||
{
|
||||
// false positive: Infer's model of std::string keeps the buffer of a
|
||||
// moved-from string, so it assumes a buffer is destroyed twice
|
||||
// @infer-ignore USE_AFTER_DELETE
|
||||
it->~value_type(); // destroy but keep allocation
|
||||
new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
|
||||
}
|
||||
|
||||
+30252
File diff suppressed because it is too large.
Load diff
+2680
-1873
File diff suppressed because it is too large.
Load diff
@@ -67,6 +67,10 @@
|
||||
#define JSON_STRICT_BINARY_UTF8 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#define JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
@@ -109,14 +113,20 @@
|
||||
#define NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8
|
||||
#endif
|
||||
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS _ekmo
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g) json_abi ## a ## b ## c ## d ## e ## f ## g
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g)
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h) json_abi ## a ## b ## c ## d ## e ## f ## g ## h
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c, d, e, f, g, h) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c, d, e, f, g, h)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
@@ -126,7 +136,8 @@
|
||||
NLOHMANN_JSON_ABI_TAG_BRACE_INIT_COPY_SEMANTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_PRECISE_STREAM_POSITION, \
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_NUL_HANDLING, \
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8)
|
||||
NLOHMANN_JSON_ABI_TAG_STRICT_BINARY_UTF8, \
|
||||
NLOHMANN_JSON_ABI_TAG_OBJECTS_FOR_ENUM_KEYED_MAPS)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
|
||||
+41
-3
@@ -8,6 +8,7 @@ set(JSON_SIMDUTF_VERSION 9.1.0 CACHE STRING "The simdutf version used by JSON_Te
|
||||
|
||||
set(JSON_32bitTest AUTO CACHE STRING "Enable the 32bit unit test (ON/OFF/AUTO/ONLY).")
|
||||
set(JSON_TestStandards "" CACHE STRING "The list of standards to test explicitly.")
|
||||
set(JSON_TestShard "" CACHE STRING "Build only a part of the unit tests, given as <index>/<count> (e.g. 0/2), to split them across CI jobs with a time limit.")
|
||||
|
||||
# using an env var, since this will also affect targets executing cmake (such as "ci_test_compiler_default")
|
||||
if (NOT "" STREQUAL "$ENV{JSON_FORCED_GLOBAL_COMPILE_OPTIONS}")
|
||||
@@ -134,12 +135,17 @@ json_test_set_test_options(test-disabled_exceptions
|
||||
#$<$<CXX_COMPILER_ID:MSVC>:/EH>
|
||||
)
|
||||
|
||||
# raise timeout of expensive Unicode test
|
||||
json_test_set_test_options(test-unicode4 TEST_PROPERTIES TIMEOUT 3000)
|
||||
|
||||
# only the #972 regression test needs thirdparty/fifo_map on its include path
|
||||
json_test_set_test_options(test-regression1 LINK_LIBRARIES fifo_map_include)
|
||||
|
||||
# GCC's false -Warray-bounds error with JSON_DIAGNOSTICS only shows up when optimizing (#5742).
|
||||
# -O3 makes the optimizer-driven warnings of the ci_test_gcc flag set (-Winline,
|
||||
# -Wsuggest-attribute=...) fire on the library's inline functions; they are not
|
||||
# what this test checks, so turn them off for it.
|
||||
json_test_set_test_options(test-diagnostics-optimized
|
||||
COMPILE_OPTIONS $<$<CXX_COMPILER_ID:GNU>:-O3 -Werror=array-bounds -Wno-inline -Wno-suggest-attribute=pure -Wno-suggest-attribute=const>
|
||||
)
|
||||
|
||||
#############################################################################
|
||||
# add unit tests
|
||||
#############################################################################
|
||||
@@ -288,6 +294,33 @@ elseif(NOT json_32bit_test)
|
||||
list(FILTER files EXCLUDE REGEX src/unit-32bit.cpp)
|
||||
endif()
|
||||
|
||||
# with JSON_TestShard=<index>/<count>, keep every <count>-th unit test file,
|
||||
# starting at <index> (the glob is sorted, so the split is stable)
|
||||
set(test_shard_index 0)
|
||||
if(NOT "${JSON_TestShard}" STREQUAL "")
|
||||
if(NOT JSON_TestShard MATCHES "^([0-9]+)/([1-9][0-9]*)$")
|
||||
message(FATAL_ERROR "JSON_TestShard must be <index>/<count>, e.g. 0/2, not '${JSON_TestShard}'.")
|
||||
endif()
|
||||
set(test_shard_index ${CMAKE_MATCH_1})
|
||||
set(test_shard_count ${CMAKE_MATCH_2})
|
||||
if(NOT test_shard_index LESS test_shard_count)
|
||||
message(FATAL_ERROR "JSON_TestShard: the index must be less than the count, not '${JSON_TestShard}'.")
|
||||
endif()
|
||||
list(LENGTH files test_file_count)
|
||||
set(shard_files "")
|
||||
set(file_position 0)
|
||||
foreach(file ${files})
|
||||
math(EXPR file_shard "${file_position} % ${test_shard_count}")
|
||||
if(file_shard EQUAL test_shard_index)
|
||||
list(APPEND shard_files ${file})
|
||||
endif()
|
||||
math(EXPR file_position "${file_position} + 1")
|
||||
endforeach()
|
||||
set(files ${shard_files})
|
||||
list(LENGTH files shard_file_count)
|
||||
message(STATUS "Test shard ${JSON_TestShard}: ${shard_file_count} of ${test_file_count} unit test files")
|
||||
endif()
|
||||
|
||||
foreach(file ${files})
|
||||
json_test_add_test_for(${file} MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force})
|
||||
endforeach()
|
||||
@@ -305,6 +338,9 @@ if(json_32bit_test_only)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# the following variants of single test files are only built in the first shard
|
||||
if(test_shard_index EQUAL 0)
|
||||
|
||||
# test legacy comparison of discarded values
|
||||
json_test_set_test_options(test-comparison_legacy
|
||||
COMPILE_DEFINITIONS JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1
|
||||
@@ -332,6 +368,8 @@ json_test_add_test_for(src/unit-diagnostic-positions.cpp
|
||||
MAIN test_main CXX_STANDARDS ${test_cxx_standards} ${test_force}
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
# *DO NOT* use json_test_set_test_options() below this line
|
||||
|
||||
#############################################################################
|
||||
|
||||
@@ -48,6 +48,10 @@ TEST_CASE("default namespace")
|
||||
expected += "_sbu8";
|
||||
#endif
|
||||
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
expected += "_ekmo";
|
||||
#endif
|
||||
|
||||
expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
|
||||
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
|
||||
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
|
||||
|
||||
@@ -49,6 +49,10 @@ TEST_CASE("default namespace without version component")
|
||||
expected += "_sbu8";
|
||||
#endif
|
||||
|
||||
#if JSON_USE_OBJECTS_FOR_ENUM_KEYED_MAPS
|
||||
expected += "_ekmo";
|
||||
#endif
|
||||
|
||||
expected += "::basic_json";
|
||||
|
||||
// fallback for Clang
|
||||
|
||||
+14
-1
@@ -3,6 +3,14 @@
|
||||
Each parser of the library (JSON, BJData, BON8, BSON, CBOR, MessagePack, and UBJSON) can be fuzz tested. Currently,
|
||||
[libFuzzer](https://llvm.org/docs/LibFuzzer.html) and [afl++](https://github.com/AFLplusplus/AFLplusplus) are supported.
|
||||
|
||||
## What the fuzzers check
|
||||
|
||||
Each fuzzer driver (`tests/src/fuzzer-parse_*.cpp`) parses its input twice: once with `allow_exceptions = false` and
|
||||
once with exceptions. Both calls must agree. Where parsing with exceptions fails, the call without exceptions must
|
||||
return a discarded value (or throw the same kind of non-parse error), and it must never throw a `parse_error`. Where
|
||||
parsing succeeds, both calls must return the same value. The drivers then serialize the value, parse the result back,
|
||||
and check that nothing was lost. The drivers check all of this with `assert`, so they refuse to build with `NDEBUG`.
|
||||
|
||||
## Corpus creation
|
||||
|
||||
For most effective fuzzing, a [corpus](https://llvm.org/docs/LibFuzzer.html#corpus) should be provided. A corpus is a
|
||||
@@ -54,6 +62,9 @@ Then pass the corpus directory as command-line argument (assuming it is located
|
||||
The fuzzer should be able to run indefinitely without crashing. In case of a crash, the tested input is dumped into
|
||||
a file starting with `crash-`.
|
||||
|
||||
To also detect memory leaks, build with AddressSanitizer (`FUZZER_ENGINE="-fsanitize=fuzzer,address"`): libFuzzer then
|
||||
runs LeakSanitizer by default (`-detect_leaks=1`). LeakSanitizer is not available with Apple Clang on macOS.
|
||||
|
||||
## afl++
|
||||
|
||||
To use afl++, you need to pass `-fsanitize=fuzzer` as `FUZZER_ENGINE`. It will be replaced by a `libAFLDriver.a` to
|
||||
@@ -76,7 +87,9 @@ directory `out`.
|
||||
|
||||
The library is further fuzz-tested 24/7 by Google's [OSS-Fuzz project](https://github.com/google/oss-fuzz). It uses
|
||||
the same `fuzzers` target as above and also relies on the `FUZZER_ENGINE` variable. See the used
|
||||
[build script](https://github.com/google/oss-fuzz/blob/master/projects/json/build.sh) for more information.
|
||||
[build script](https://github.com/google/oss-fuzz/blob/master/projects/json/build.sh) for more information. Its default
|
||||
`address` sanitizer includes LeakSanitizer, so OSS-Fuzz and the CIFuzz workflow (`.github/workflows/cifuzz.yml`) report
|
||||
memory leaks, too.
|
||||
|
||||
In case the build at OSS-Fuzz fails, an issue will be created automatically.
|
||||
|
||||
|
||||
@@ -1,599 +0,0 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cstdint> // uint32_t, uint64_t
|
||||
|
||||
// Number tokens that are hard to round correctly, with the IEEE-754 binary64
|
||||
// and binary32 bits of their correctly rounded values (ties to even; infinity
|
||||
// for an overflow, a signed zero for an underflow).
|
||||
//
|
||||
// For doubles and floats around 0, the smallest normal number, 1, 2^24, 2^53,
|
||||
// 0.1, and the largest finite number, and for random ones, the exact midpoint
|
||||
// m to the next number gives: m, m with one unit more and less in the last
|
||||
// digit, m with "01" and "0...01" appended, m with trailing zeros, and m cut
|
||||
// after 17 to 30 digits (rounded down and up, so that the rounding is decided
|
||||
// after the 19th digit), in fixed and exponent notation, 30% of them negative.
|
||||
// Tokens longer than 80 characters are left out, except for four of 700 digits
|
||||
// and more. Zeros, underflow, overflow, huge exponents, and integers beyond 64
|
||||
// bits complete the set. Of the 508 tokens, 134 (as double) and 150 (as
|
||||
// float) need the exact comparison with the midpoint (detail::digit_comparison()).
|
||||
//
|
||||
// The expected bits were computed with exact rational arithmetic in Python
|
||||
// (fractions.Fraction) and cross-checked with Python's float(); strtod_l and
|
||||
// strtof_l of Apple's libc and of glibc agree. Generated by
|
||||
// compact_hard_cases.py 5 (with hard_cases.py), see the pull request that
|
||||
// added this file.
|
||||
|
||||
namespace float_hard_cases
|
||||
{
|
||||
|
||||
struct hard_case
|
||||
{
|
||||
const char* token;
|
||||
std::uint64_t bits64;
|
||||
std::uint32_t bits32;
|
||||
};
|
||||
|
||||
inline const std::array<hard_case, 508>& cases()
|
||||
{
|
||||
static const std::array<hard_case, 508> table =
|
||||
{
|
||||
{
|
||||
{"-2.4703282292062327e-324", 0x8000000000000000u, 0x80000000u},
|
||||
{"24703282292062328e-340", 0x0000000000000001u, 0x00000000u},
|
||||
{"247032822920623272e-341", 0x0000000000000000u, 0x00000000u},
|
||||
{"-0.2470328229206232721e-323", 0x8000000000000001u, 0x80000000u},
|
||||
{"-0.24703282292062327208e-323", 0x8000000000000000u, 0x80000000u},
|
||||
{"-2.4703282292062327209e-324", 0x8000000000000001u, 0x80000000u},
|
||||
{"2.47032822920623272088e-324", 0x0000000000000000u, 0x00000000u},
|
||||
{"247032822920623272089e-344", 0x0000000000000001u, 0x00000000u},
|
||||
{"-247032822920623272088284396434e-353", 0x8000000000000000u, 0x80000000u},
|
||||
{"0.247032822920623272088284396435e-323", 0x0000000000000001u, 0x00000000u},
|
||||
{"-74109846876186981e-340", 0x8000000000000001u, 0x80000000u},
|
||||
{"0.74109846876186982e-323", 0x0000000000000002u, 0x00000000u},
|
||||
{"-0.7410984687618698162e-323", 0x8000000000000001u, 0x80000000u},
|
||||
{"-7.410984687618698163e-324", 0x8000000000000002u, 0x80000000u},
|
||||
{"7.4109846876186981626e-324", 0x0000000000000001u, 0x00000000u},
|
||||
{"-74109846876186981627e-343", 0x8000000000000002u, 0x80000000u},
|
||||
{"-741098468761869816264e-344", 0x8000000000000001u, 0x80000000u},
|
||||
{"0.741098468761869816265e-323", 0x0000000000000002u, 0x00000000u},
|
||||
{"0.741098468761869816264853189302e-323", 0x0000000000000001u, 0x00000000u},
|
||||
{"-7.41098468761869816264853189303e-324", 0x8000000000000002u, 0x80000000u},
|
||||
{"0.22250738585072006e-307", 0x000FFFFFFFFFFFFEu, 0x00000000u},
|
||||
{"2.2250738585072007e-308", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"2.225073858507200641e-308", 0x000FFFFFFFFFFFFEu, 0x00000000u},
|
||||
{"-2225073858507200642e-326", 0x800FFFFFFFFFFFFFu, 0x80000000u},
|
||||
{"22250738585072006419e-327", 0x000FFFFFFFFFFFFEu, 0x00000000u},
|
||||
{"0.2225073858507200642e-307", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"0.222507385850720064199e-307", 0x000FFFFFFFFFFFFEu, 0x00000000u},
|
||||
{"2.225073858507200642e-308", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"-2.22507385850720064199176395546e-308", 0x800FFFFFFFFFFFFEu, 0x80000000u},
|
||||
{"222507385850720064199176395547e-337", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"-2.2250738585072011e-308", 0x800FFFFFFFFFFFFFu, 0x80000000u},
|
||||
{"-22250738585072012e-324", 0x8010000000000000u, 0x80000000u},
|
||||
{"-2225073858507201136e-326", 0x800FFFFFFFFFFFFFu, 0x80000000u},
|
||||
{"0.2225073858507201137e-307", 0x0010000000000000u, 0x00000000u},
|
||||
{"0.2225073858507201136e-307", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"-2.2250738585072011361e-308", 0x8010000000000000u, 0x80000000u},
|
||||
{"2.22507385850720113605e-308", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"222507385850720113606e-328", 0x0010000000000000u, 0x00000000u},
|
||||
{"22250738585072011360574097967e-336", 0x000FFFFFFFFFFFFFu, 0x00000000u},
|
||||
{"0.222507385850720113605740979671e-307", 0x0010000000000000u, 0x00000000u},
|
||||
{"22250738585072016e-324", 0x0010000000000000u, 0x00000000u},
|
||||
{"0.22250738585072017e-307", 0x0010000000000001u, 0x00000000u},
|
||||
{"0.222507385850720163e-307", 0x0010000000000000u, 0x00000000u},
|
||||
{"2.225073858507201631e-308", 0x0010000000000001u, 0x00000000u},
|
||||
{"-2.2250738585072016301e-308", 0x8010000000000000u, 0x80000000u},
|
||||
{"22250738585072016302e-327", 0x0010000000000001u, 0x00000000u},
|
||||
{"-222507385850720163012e-328", 0x8010000000000000u, 0x80000000u},
|
||||
{"0.222507385850720163013e-307", 0x0010000000000001u, 0x00000000u},
|
||||
{"0.222507385850720163012305563795e-307", 0x0010000000000000u, 0x00000000u},
|
||||
{"-2.22507385850720163012305563796e-308", 0x8010000000000001u, 0x80000000u},
|
||||
{"0.17976931348623156E+309", 0x7FEFFFFFFFFFFFFEu, 0x7F800000u},
|
||||
{"1.7976931348623157e308", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"1.797693134862315608e308", 0x7FEFFFFFFFFFFFFEu, 0x7F800000u},
|
||||
{"-1797693134862315609e290", 0xFFEFFFFFFFFFFFFFu, 0xFF800000u},
|
||||
{"-17976931348623156083e289", 0xFFEFFFFFFFFFFFFEu, 0xFF800000u},
|
||||
{"-0.17976931348623156084E+309", 0xFFEFFFFFFFFFFFFFu, 0xFF800000u},
|
||||
{"0.179769313486231560835E+309", 0x7FEFFFFFFFFFFFFEu, 0x7F800000u},
|
||||
{"-1.79769313486231560836e308", 0xFFEFFFFFFFFFFFFFu, 0xFF800000u},
|
||||
{"1.79769313486231560835325876058e308", 0x7FEFFFFFFFFFFFFEu, 0x7F800000u},
|
||||
{"179769313486231560835325876059e279", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"1.7976931348623158e308", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"17976931348623159e292", 0x7FF0000000000000u, 0x7F800000u},
|
||||
{"1797693134862315807e290", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"0.1797693134862315808E+309", 0x7FF0000000000000u, 0x7F800000u},
|
||||
{"0.17976931348623158079E+309", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"-1.797693134862315808e308", 0xFFF0000000000000u, 0xFF800000u},
|
||||
{"1.79769313486231580793e308", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"179769313486231580794e288", 0x7FF0000000000000u, 0x7F800000u},
|
||||
{"179769313486231580793728971405e279", 0x7FEFFFFFFFFFFFFFu, 0x7F800000u},
|
||||
{"-0.179769313486231580793728971406E+309", 0xFFF0000000000000u, 0xFF800000u},
|
||||
{"100000000000000011102230246251565404236316680908203125e-53", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"-1.00000000000000011102230246251565404236316680908203126", 0xBFF0000000000001u, 0xBF800000u},
|
||||
{"1.00000000000000011102230246251565404236316680908203124e0", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"10000000000000001110223024625156540423631668090820312501e-55", 0x3FF0000000000001u, 0x3F800000u},
|
||||
{"1.00000000000000011102230246251565404236316680908203125000000000000000000001", 0x3FF0000000000001u, 0x3F800000u},
|
||||
{"10000000000000001e-16", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"1.0000000000000002", 0x3FF0000000000001u, 0x3F800000u},
|
||||
{"1.000000000000000111", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"1.000000000000000112e0", 0x3FF0000000000001u, 0x3F800000u},
|
||||
{"1.000000000000000111e0", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"-10000000000000001111e-19", 0xBFF0000000000001u, 0xBF800000u},
|
||||
{"-100000000000000011102e-20", 0xBFF0000000000000u, 0xBF800000u},
|
||||
{"-1.00000000000000011103", 0xBFF0000000000001u, 0xBF800000u},
|
||||
{"1.00000000000000011102230246251", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"1.00000000000000011102230246252e0", 0x3FF0000000000001u, 0x3F800000u},
|
||||
{"-0.999999999999999944488848768742172978818416595458984375", 0xBFF0000000000000u, 0xBF800000u},
|
||||
{"-9.99999999999999944488848768742172978818416595458984376e-1", 0xBFF0000000000000u, 0xBF800000u},
|
||||
{"999999999999999944488848768742172978818416595458984374e-54", 0x3FEFFFFFFFFFFFFFu, 0x3F800000u},
|
||||
{"0.99999999999999994448884876874217297881841659545898437501", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"9.99999999999999944488848768742172978818416595458984375000000000000000000001e-1", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"-0.99999999999999994", 0xBFEFFFFFFFFFFFFFu, 0xBF800000u},
|
||||
{"9.9999999999999995e-1", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"9.999999999999999444e-1", 0x3FEFFFFFFFFFFFFFu, 0x3F800000u},
|
||||
{"9999999999999999445e-19", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"99999999999999994448e-20", 0x3FEFFFFFFFFFFFFFu, 0x3F800000u},
|
||||
{"-0.99999999999999994449", 0xBFF0000000000000u, 0xBF800000u},
|
||||
{"0.999999999999999944488", 0x3FEFFFFFFFFFFFFFu, 0x3F800000u},
|
||||
{"-9.99999999999999944489e-1", 0xBFF0000000000000u, 0xBF800000u},
|
||||
{"9.99999999999999944488848768742e-1", 0x3FEFFFFFFFFFFFFFu, 0x3F800000u},
|
||||
{"999999999999999944488848768743e-30", 0x3FF0000000000000u, 0x3F800000u},
|
||||
{"-9.007199254740993e15", 0xC340000000000000u, 0xDA000000u},
|
||||
{"9007199254740994e0", 0x4340000000000001u, 0x5A000000u},
|
||||
{"9007199254740992", 0x4340000000000000u, 0x5A000000u},
|
||||
{"9.00719925474099301e15", 0x4340000000000001u, 0x5A000000u},
|
||||
{"9007199254740993000000000000000000001e-21", 0x4340000000000001u, 0x5A000000u},
|
||||
{"-9007199254740993.000000000000000000000000000000", 0xC340000000000000u, 0xDA000000u},
|
||||
{"90071992547409915e-1", 0x4340000000000000u, 0x5A000000u},
|
||||
{"-9007199254740991.6", 0xC340000000000000u, 0xDA000000u},
|
||||
{"9.0071992547409914e15", 0x433FFFFFFFFFFFFFu, 0x5A000000u},
|
||||
{"-9007199254740991501e-3", 0xC340000000000000u, 0xDA000000u},
|
||||
{"9007199254740991.5000000000000000000001", 0x4340000000000000u, 0x5A000000u},
|
||||
{"9.0071992547409915000000000000000000000000000000e15", 0x4340000000000000u, 0x5A000000u},
|
||||
{"0.100000000000000012490009027033011079765856266021728515625", 0x3FB999999999999Au, 0x3DCCCCCDu},
|
||||
{"1.00000000000000012490009027033011079765856266021728515626e-1", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"100000000000000012490009027033011079765856266021728515624e-57", 0x3FB999999999999Au, 0x3DCCCCCDu},
|
||||
{"0.10000000000000001249000902703301107976585626602172851562501", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"0.10000000000000001", 0x3FB999999999999Au, 0x3DCCCCCDu},
|
||||
{"1.0000000000000002e-1", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"-1.000000000000000124e-1", 0xBFB999999999999Au, 0xBDCCCCCDu},
|
||||
{"1000000000000000125e-19", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"-10000000000000001249e-20", 0xBFB999999999999Au, 0xBDCCCCCDu},
|
||||
{"0.1000000000000000125", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"0.10000000000000001249", 0x3FB999999999999Au, 0x3DCCCCCDu},
|
||||
{"1.00000000000000012491e-1", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"1.00000000000000012490009027033e-1", 0x3FB999999999999Au, 0x3DCCCCCDu},
|
||||
{"100000000000000012490009027034e-30", 0x3FB999999999999Bu, 0x3DCCCCCDu},
|
||||
{"2.45134755833537796875e14", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"-245134755833537796876e-6", 0xC2EBDE5C4164D83Au, 0xD75EF2E2u},
|
||||
{"-245134755833537.796874", 0xC2EBDE5C4164D839u, 0xD75EF2E2u},
|
||||
{"2.4513475583353779687501e14", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"245134755833537796875000000000000000000001e-27", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"245134755833537.796875000000000000000000000000000000", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"2.4513475583353779e14", 0x42EBDE5C4164D839u, 0x575EF2E2u},
|
||||
{"2451347558335378e-1", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"2451347558335377968e-4", 0x42EBDE5C4164D839u, 0x575EF2E2u},
|
||||
{"245134755833537.7969", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"245134755833537.79687", 0x42EBDE5C4164D839u, 0x575EF2E2u},
|
||||
{"2.4513475583353779688e14", 0x42EBDE5C4164D83Au, 0x575EF2E2u},
|
||||
{"181510327827821147441864013671875e-23", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"-1815103278.27821147441864013671876", 0xC1DB0C11CB91CE38u, 0xCED8608Eu},
|
||||
{"1.81510327827821147441864013671874e9", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"18151032782782114744186401367187501e-25", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"1815103278.27821147441864013671875000000000000000000001", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"-1.81510327827821147441864013671875000000000000000000000000000000e9", 0xC1DB0C11CB91CE38u, 0xCED8608Eu},
|
||||
{"18151032782782114e-7", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"1815103278.2782115", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"1815103278.278211474", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"-1.815103278278211475e9", 0xC1DB0C11CB91CE38u, 0xCED8608Eu},
|
||||
{"1.8151032782782114744e9", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"-18151032782782114745e-10", 0xC1DB0C11CB91CE38u, 0xCED8608Eu},
|
||||
{"181510327827821147441e-11", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"1815103278.27821147442", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"1815103278.27821147441864013671", 0x41DB0C11CB91CE37u, 0x4ED8608Eu},
|
||||
{"1.81510327827821147441864013672e9", 0x41DB0C11CB91CE38u, 0x4ED8608Eu},
|
||||
{"3809325632181785344", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"3.809325632181785345e18", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"3809325632181785343e0", 0x43CA6EB8BD69FE29u, 0x5E5375C6u},
|
||||
{"3809325632181785344.01", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"3.809325632181785344000000000000000000001e18", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"3809325632181785344000000000000000000000000000000e-30", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"3809325632181785300", 0x43CA6EB8BD69FE29u, 0x5E5375C6u},
|
||||
{"3.8093256321817854e18", 0x43CA6EB8BD69FE2Au, 0x5E5375C6u},
|
||||
{"4.046966549916366943359375e12", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"4046966549916366943359376e-12", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"4046966549916.366943359374", 0x428D7210076CE2EFu, 0x546B9080u},
|
||||
{"4.04696654991636694335937501e12", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"4046966549916366943359375000000000000000000001e-33", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"-4046966549916.366943359375000000000000000000000000000000", 0xC28D7210076CE2F0u, 0xD46B9080u},
|
||||
{"4.0469665499163669e12", 0x428D7210076CE2EFu, 0x546B9080u},
|
||||
{"4046966549916367e-3", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"4046966549916366943e-6", 0x428D7210076CE2EFu, 0x546B9080u},
|
||||
{"4046966549916.366944", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"4046966549916.3669433", 0x428D7210076CE2EFu, 0x546B9080u},
|
||||
{"4.0469665499163669434e12", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"-4.04696654991636694335e12", 0xC28D7210076CE2EFu, 0xD46B9080u},
|
||||
{"404696654991636694336e-8", 0x428D7210076CE2F0u, 0x546B9080u},
|
||||
{"28093802557000874e154", 0x63529C3B77330BDBu, 0x7F800000u},
|
||||
{"0.28093802557000875E+171", 0x63529C3B77330BDCu, 0x7F800000u},
|
||||
{"0.2809380255700087447E+171", 0x63529C3B77330BDBu, 0x7F800000u},
|
||||
{"2.809380255700087448e170", 0x63529C3B77330BDCu, 0x7F800000u},
|
||||
{"2.8093802557000874472e170", 0x63529C3B77330BDBu, 0x7F800000u},
|
||||
{"28093802557000874473e151", 0x63529C3B77330BDCu, 0x7F800000u},
|
||||
{"280938025570008744728e150", 0x63529C3B77330BDBu, 0x7F800000u},
|
||||
{"-0.280938025570008744729E+171", 0xE3529C3B77330BDCu, 0xFF800000u},
|
||||
{"-0.280938025570008744728403667979E+171", 0xE3529C3B77330BDBu, 0xFF800000u},
|
||||
{"2.8093802557000874472840366798e170", 0x63529C3B77330BDCu, 0x7F800000u},
|
||||
{"0.39523280297734525e-154", 0x1FE0F51BF17FD374u, 0x00000000u},
|
||||
{"-3.9523280297734526e-155", 0x9FE0F51BF17FD375u, 0x80000000u},
|
||||
{"3.952328029773452547e-155", 0x1FE0F51BF17FD374u, 0x00000000u},
|
||||
{"3952328029773452548e-173", 0x1FE0F51BF17FD375u, 0x00000000u},
|
||||
{"-39523280297734525478e-174", 0x9FE0F51BF17FD374u, 0x80000000u},
|
||||
{"0.39523280297734525479e-154", 0x1FE0F51BF17FD375u, 0x00000000u},
|
||||
{"-0.395232802977345254787e-154", 0x9FE0F51BF17FD374u, 0x80000000u},
|
||||
{"-3.95232802977345254788e-155", 0x9FE0F51BF17FD375u, 0x80000000u},
|
||||
{"-3.95232802977345254787245825501e-155", 0x9FE0F51BF17FD374u, 0x80000000u},
|
||||
{"395232802977345254787245825502e-184", 0x1FE0F51BF17FD375u, 0x00000000u},
|
||||
{"-1.0790205420931879e-276", 0x86A3209CA6233255u, 0x80000000u},
|
||||
{"-1079020542093188e-291", 0x86A3209CA6233256u, 0x80000000u},
|
||||
{"-1079020542093187947e-294", 0x86A3209CA6233255u, 0x80000000u},
|
||||
{"0.1079020542093187948e-275", 0x06A3209CA6233256u, 0x00000000u},
|
||||
{"0.1079020542093187947e-275", 0x06A3209CA6233255u, 0x00000000u},
|
||||
{"1.0790205420931879471e-276", 0x06A3209CA6233256u, 0x00000000u},
|
||||
{"1.07902054209318794701e-276", 0x06A3209CA6233255u, 0x00000000u},
|
||||
{"-107902054209318794702e-296", 0x86A3209CA6233256u, 0x80000000u},
|
||||
{"107902054209318794701153285302e-305", 0x06A3209CA6233255u, 0x00000000u},
|
||||
{"-0.107902054209318794701153285303e-275", 0x86A3209CA6233256u, 0x80000000u},
|
||||
{"58530471071351308e-228", 0x1413B446E6A16A3Bu, 0x00000000u},
|
||||
{"-0.58530471071351309e-211", 0x9413B446E6A16A3Cu, 0x80000000u},
|
||||
{"0.5853047107135130893e-211", 0x1413B446E6A16A3Bu, 0x00000000u},
|
||||
{"-5.853047107135130894e-212", 0x9413B446E6A16A3Cu, 0x80000000u},
|
||||
{"5.853047107135130893e-212", 0x1413B446E6A16A3Bu, 0x00000000u},
|
||||
{"58530471071351308931e-231", 0x1413B446E6A16A3Cu, 0x00000000u},
|
||||
{"-585304710713513089304e-232", 0x9413B446E6A16A3Bu, 0x80000000u},
|
||||
{"0.585304710713513089305e-211", 0x1413B446E6A16A3Cu, 0x00000000u},
|
||||
{"-0.585304710713513089304248824438e-211", 0x9413B446E6A16A3Bu, 0x80000000u},
|
||||
{"5.85304710713513089304248824439e-212", 0x1413B446E6A16A3Cu, 0x00000000u},
|
||||
{"0.19334214893983531e-78", 0x2F96ECBF1CFB10F6u, 0x00000000u},
|
||||
{"1.9334214893983532e-79", 0x2F96ECBF1CFB10F7u, 0x00000000u},
|
||||
{"1.933421489398353102e-79", 0x2F96ECBF1CFB10F6u, 0x00000000u},
|
||||
{"1933421489398353103e-97", 0x2F96ECBF1CFB10F7u, 0x00000000u},
|
||||
{"19334214893983531023e-98", 0x2F96ECBF1CFB10F6u, 0x00000000u},
|
||||
{"0.19334214893983531024e-78", 0x2F96ECBF1CFB10F7u, 0x00000000u},
|
||||
{"0.193342148939835310231e-78", 0x2F96ECBF1CFB10F6u, 0x00000000u},
|
||||
{"1.93342148939835310232e-79", 0x2F96ECBF1CFB10F7u, 0x00000000u},
|
||||
{"-1.93342148939835310231359014704e-79", 0xAF96ECBF1CFB10F6u, 0x80000000u},
|
||||
{"193342148939835310231359014705e-108", 0x2F96ECBF1CFB10F7u, 0x00000000u},
|
||||
{"2.9873358928024455e227", 0x6F2938807814E8A2u, 0x7F800000u},
|
||||
{"29873358928024456e211", 0x6F2938807814E8A3u, 0x7F800000u},
|
||||
{"298733589280244551e210", 0x6F2938807814E8A2u, 0x7F800000u},
|
||||
{"0.2987335892802445511E+228", 0x6F2938807814E8A3u, 0x7F800000u},
|
||||
{"0.29873358928024455109E+228", 0x6F2938807814E8A2u, 0x7F800000u},
|
||||
{"2.987335892802445511e227", 0x6F2938807814E8A3u, 0x7F800000u},
|
||||
{"-2.98733589280244551098e227", 0xEF2938807814E8A2u, 0xFF800000u},
|
||||
{"-298733589280244551099e207", 0xEF2938807814E8A3u, 0xFF800000u},
|
||||
{"298733589280244551098081559931e198", 0x6F2938807814E8A2u, 0x7F800000u},
|
||||
{"0.298733589280244551098081559932E+228", 0x6F2938807814E8A3u, 0x7F800000u},
|
||||
{"7.0064923216240853e-46", 0x3690000000000000u, 0x00000000u},
|
||||
{"70064923216240854e-62", 0x3690000000000000u, 0x00000001u},
|
||||
{"7006492321624085354e-64", 0x3690000000000000u, 0x00000000u},
|
||||
{"-0.7006492321624085355e-45", 0xB690000000000000u, 0x80000001u},
|
||||
{"0.70064923216240853546e-45", 0x3690000000000000u, 0x00000000u},
|
||||
{"7.0064923216240853547e-46", 0x3690000000000000u, 0x00000001u},
|
||||
{"7.00649232162408535461e-46", 0x3690000000000000u, 0x00000000u},
|
||||
{"-700649232162408535462e-66", 0xB690000000000000u, 0x80000001u},
|
||||
{"-700649232162408535461864791644e-75", 0xB690000000000000u, 0x80000000u},
|
||||
{"0.700649232162408535461864791645e-45", 0x3690000000000000u, 0x00000001u},
|
||||
{"21019476964872256e-61", 0x36A8000000000000u, 0x00000001u},
|
||||
{"0.21019476964872257e-44", 0x36A8000000000000u, 0x00000002u},
|
||||
{"-0.2101947696487225606e-44", 0xB6A8000000000000u, 0x80000001u},
|
||||
{"-2.101947696487225607e-45", 0xB6A8000000000000u, 0x80000002u},
|
||||
{"2.1019476964872256063e-45", 0x36A8000000000000u, 0x00000001u},
|
||||
{"21019476964872256064e-64", 0x36A8000000000000u, 0x00000002u},
|
||||
{"-210194769648722560638e-65", 0xB6A8000000000000u, 0x80000001u},
|
||||
{"-0.210194769648722560639e-44", 0xB6A8000000000000u, 0x80000002u},
|
||||
{"-0.210194769648722560638559437493e-44", 0xB6A8000000000000u, 0x80000001u},
|
||||
{"2.10194769648722560638559437494e-45", 0x36A8000000000000u, 0x00000002u},
|
||||
{"0.11754941406275178e-37", 0x380FFFFFA0000000u, 0x007FFFFEu},
|
||||
{"1.1754941406275179e-38", 0x380FFFFFA0000000u, 0x007FFFFFu},
|
||||
{"-1.175494140627517859e-38", 0xB80FFFFFA0000000u, 0x807FFFFEu},
|
||||
{"117549414062751786e-55", 0x380FFFFFA0000000u, 0x007FFFFFu},
|
||||
{"-11754941406275178592e-57", 0xB80FFFFFA0000000u, 0x807FFFFEu},
|
||||
{"0.11754941406275178593e-37", 0x380FFFFFA0000000u, 0x007FFFFFu},
|
||||
{"0.117549414062751785924e-37", 0x380FFFFFA0000000u, 0x007FFFFEu},
|
||||
{"1.17549414062751785925e-38", 0x380FFFFFA0000000u, 0x007FFFFFu},
|
||||
{"-1.17549414062751785924617589866e-38", 0xB80FFFFFA0000000u, 0x807FFFFEu},
|
||||
{"117549414062751785924617589867e-67", 0x380FFFFFA0000000u, 0x007FFFFFu},
|
||||
{"1.1754942807573642e-38", 0x380FFFFFDFFFFFFFu, 0x007FFFFFu},
|
||||
{"11754942807573643e-54", 0x380FFFFFE0000000u, 0x00800000u},
|
||||
{"1175494280757364291e-56", 0x380FFFFFE0000000u, 0x007FFFFFu},
|
||||
{"0.1175494280757364292e-37", 0x380FFFFFE0000000u, 0x00800000u},
|
||||
{"0.11754942807573642917e-37", 0x380FFFFFE0000000u, 0x007FFFFFu},
|
||||
{"-1.1754942807573642918e-38", 0xB80FFFFFE0000000u, 0x80800000u},
|
||||
{"-1.17549428075736429172e-38", 0xB80FFFFFE0000000u, 0x807FFFFFu},
|
||||
{"-117549428075736429173e-58", 0xB80FFFFFE0000000u, 0x80800000u},
|
||||
{"117549428075736429172788299103e-67", 0x380FFFFFE0000000u, 0x007FFFFFu},
|
||||
{"0.117549428075736429172788299104e-37", 0x380FFFFFE0000000u, 0x00800000u},
|
||||
{"11754944208872107e-54", 0x3810000010000000u, 0x00800000u},
|
||||
{"-0.11754944208872108e-37", 0xB810000010000000u, 0x80800001u},
|
||||
{"0.1175494420887210724e-37", 0x3810000010000000u, 0x00800000u},
|
||||
{"1.175494420887210725e-38", 0x3810000010000000u, 0x00800001u},
|
||||
{"1.1754944208872107242e-38", 0x3810000010000000u, 0x00800000u},
|
||||
{"-11754944208872107243e-57", 0xB810000010000000u, 0x80800001u},
|
||||
{"-11754944208872107242e-57", 0xB810000010000000u, 0x80800000u},
|
||||
{"0.117549442088721072421e-37", 0x3810000010000000u, 0x00800001u},
|
||||
{"0.11754944208872107242095900834e-37", 0x3810000010000000u, 0x00800000u},
|
||||
{"-1.17549442088721072420959008341e-38", 0xB810000010000000u, 0x80800001u},
|
||||
{"340282336497324057985868971510891282432", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"-3.40282336497324057985868971510891282433e38", 0xC7EFFFFFD0000000u, 0xFF7FFFFFu},
|
||||
{"340282336497324057985868971510891282431e0", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"340282336497324057985868971510891282432.01", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"3.40282336497324057985868971510891282432000000000000000000001e38", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"340282336497324057985868971510891282432000000000000000000000000000000e-30", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"340282336497324050000000000000000000000", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"3.4028233649732406e38", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"3.402823364973240579e38", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"340282336497324058e21", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"34028233649732405798e19", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"340282336497324057990000000000000000000", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"340282336497324057985000000000000000000", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"3.40282336497324057986e38", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"3.4028233649732405798586897151e38", 0x47EFFFFFD0000000u, 0x7F7FFFFEu},
|
||||
{"340282336497324057985868971511e9", 0x47EFFFFFD0000000u, 0x7F7FFFFFu},
|
||||
{"3.40282356779733661637539395458142568448e38", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"-340282356779733661637539395458142568449e0", 0xC7EFFFFFF0000000u, 0xFF800000u},
|
||||
{"340282356779733661637539395458142568447", 0x47EFFFFFF0000000u, 0x7F7FFFFFu},
|
||||
{"3.4028235677973366163753939545814256844801e38", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"340282356779733661637539395458142568448000000000000000000001e-21", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"340282356779733661637539395458142568448.000000000000000000000000000000", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"3.4028235677973366e38", 0x47EFFFFFF0000000u, 0x7F7FFFFFu},
|
||||
{"-34028235677973367e22", 0xC7EFFFFFF0000000u, 0xFF800000u},
|
||||
{"3402823567797336616e20", 0x47EFFFFFF0000000u, 0x7F7FFFFFu},
|
||||
{"340282356779733661700000000000000000000", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"340282356779733661630000000000000000000", 0x47EFFFFFF0000000u, 0x7F7FFFFFu},
|
||||
{"3.4028235677973366164e38", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"3.40282356779733661637e38", 0x47EFFFFFF0000000u, 0x7F7FFFFFu},
|
||||
{"340282356779733661638e18", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"-340282356779733661637539395458e9", 0xC7EFFFFFF0000000u, 0xFF7FFFFFu},
|
||||
{"340282356779733661637539395459000000000", 0x47EFFFFFF0000000u, 0x7F800000u},
|
||||
{"-1000000059604644775390625e-24", 0xBFF0000010000000u, 0xBF800000u},
|
||||
{"-1.000000059604644775390626", 0xBFF0000010000000u, 0xBF800001u},
|
||||
{"-1.000000059604644775390624e0", 0xBFF0000010000000u, 0xBF800000u},
|
||||
{"100000005960464477539062501e-26", 0x3FF0000010000000u, 0x3F800001u},
|
||||
{"1.000000059604644775390625000000000000000000001", 0x3FF0000010000000u, 0x3F800001u},
|
||||
{"1.000000059604644775390625000000000000000000000000000000e0", 0x3FF0000010000000u, 0x3F800000u},
|
||||
{"-10000000596046447e-16", 0xBFF0000010000000u, 0xBF800000u},
|
||||
{"1.0000000596046448", 0x3FF0000010000000u, 0x3F800001u},
|
||||
{"1.000000059604644775", 0x3FF0000010000000u, 0x3F800000u},
|
||||
{"-1.000000059604644776e0", 0xBFF0000010000000u, 0xBF800001u},
|
||||
{"-1.0000000596046447753e0", 0xBFF0000010000000u, 0xBF800000u},
|
||||
{"10000000596046447754e-19", 0x3FF0000010000000u, 0x3F800001u},
|
||||
{"100000005960464477539e-20", 0x3FF0000010000000u, 0x3F800000u},
|
||||
{"-1.0000000596046447754", 0xBFF0000010000000u, 0xBF800001u},
|
||||
{"0.9999999701976776123046875", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"9.999999701976776123046876e-1", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"9999999701976776123046874e-25", 0x3FEFFFFFF0000000u, 0x3F7FFFFFu},
|
||||
{"0.999999970197677612304687501", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"-9.999999701976776123046875000000000000000000001e-1", 0xBFEFFFFFF0000000u, 0xBF800000u},
|
||||
{"-9999999701976776123046875000000000000000000000000000000e-55", 0xBFEFFFFFF0000000u, 0xBF800000u},
|
||||
{"0.99999997019767761", 0x3FEFFFFFF0000000u, 0x3F7FFFFFu},
|
||||
{"-9.9999997019767762e-1", 0xBFEFFFFFF0000000u, 0xBF800000u},
|
||||
{"-9.999999701976776123e-1", 0xBFEFFFFFF0000000u, 0xBF7FFFFFu},
|
||||
{"9999999701976776124e-19", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"9999999701976776123e-19", 0x3FEFFFFFF0000000u, 0x3F7FFFFFu},
|
||||
{"0.99999997019767761231", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"-0.999999970197677612304", 0xBFEFFFFFF0000000u, 0xBF7FFFFFu},
|
||||
{"9.99999970197677612305e-1", 0x3FEFFFFFF0000000u, 0x3F800000u},
|
||||
{"-1.6777217e7", 0xC170000010000000u, 0xCB800000u},
|
||||
{"16777218e0", 0x4170000020000000u, 0x4B800001u},
|
||||
{"16777216", 0x4170000000000000u, 0x4B800000u},
|
||||
{"-1.677721701e7", 0xC17000001028F5C3u, 0xCB800001u},
|
||||
{"-16777217000000000000000000001e-21", 0xC170000010000000u, 0xCB800001u},
|
||||
{"16777217.000000000000000000000000000000", 0x4170000010000000u, 0x4B800000u},
|
||||
{"167772155e-1", 0x416FFFFFF0000000u, 0x4B800000u},
|
||||
{"16777215.6", 0x416FFFFFF3333333u, 0x4B800000u},
|
||||
{"1.67772154e7", 0x416FFFFFECCCCCCDu, 0x4B7FFFFFu},
|
||||
{"16777215501e-3", 0x416FFFFFF0083127u, 0x4B800000u},
|
||||
{"-16777215.5000000000000000000001", 0xC16FFFFFF0000000u, 0xCB800000u},
|
||||
{"-1.67772155000000000000000000000000000000e7", 0xC16FFFFFF0000000u, 0xCB800000u},
|
||||
{"0.1000000052154064178466796875", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"1.000000052154064178466796876e-1", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"-1000000052154064178466796874e-28", 0xBFB99999B0000000u, 0xBDCCCCCDu},
|
||||
{"0.100000005215406417846679687501", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"1.000000052154064178466796875000000000000000000001e-1", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"-1000000052154064178466796875000000000000000000000000000000e-58", 0xBFB99999B0000000u, 0xBDCCCCCEu},
|
||||
{"-0.10000000521540641", 0xBFB99999AFFFFFFFu, 0xBDCCCCCDu},
|
||||
{"-1.0000000521540642e-1", 0xBFB99999B0000000u, 0xBDCCCCCEu},
|
||||
{"1.000000052154064178e-1", 0x3FB99999B0000000u, 0x3DCCCCCDu},
|
||||
{"-1000000052154064179e-19", 0xBFB99999B0000000u, 0xBDCCCCCEu},
|
||||
{"10000000521540641784e-20", 0x3FB99999B0000000u, 0x3DCCCCCDu},
|
||||
{"0.10000000521540641785", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"0.100000005215406417846", 0x3FB99999B0000000u, 0x3DCCCCCDu},
|
||||
{"1.00000005215406417847e-1", 0x3FB99999B0000000u, 0x3DCCCCCEu},
|
||||
{"5.429001220703125e3", 0x40B5350050000000u, 0x45A9A802u},
|
||||
{"-5429001220703126e-12", 0xC0B5350050000001u, 0xC5A9A803u},
|
||||
{"-5429.001220703124", 0xC0B535004FFFFFFFu, 0xC5A9A802u},
|
||||
{"5.42900122070312501e3", 0x40B5350050000000u, 0x45A9A803u},
|
||||
{"5429001220703125000000000000000000001e-33", 0x40B5350050000000u, 0x45A9A803u},
|
||||
{"-5429.001220703125000000000000000000000000000000", 0xC0B5350050000000u, 0xC5A9A802u},
|
||||
{"503719056e0", 0x41BE062490000000u, 0x4DF03124u},
|
||||
{"503719057", 0x41BE062491000000u, 0x4DF03125u},
|
||||
{"5.03719055e8", 0x41BE06248F000000u, 0x4DF03124u},
|
||||
{"50371905601e-2", 0x41BE062490028F5Cu, 0x4DF03125u},
|
||||
{"503719056.000000000000000000001", 0x41BE062490000000u, 0x4DF03125u},
|
||||
{"5.03719056000000000000000000000000000000e8", 0x41BE062490000000u, 0x4DF03124u},
|
||||
{"-92331620", 0xC196037990000000u, 0xCCB01BCCu},
|
||||
{"9.233163e7", 0x41960379B8000000u, 0x4CB01BCEu},
|
||||
{"9233161e1", 0x4196037968000000u, 0x4CB01BCBu},
|
||||
{"92331620.1", 0x4196037990666666u, 0x4CB01BCDu},
|
||||
{"9.233162000000000000000000001e7", 0x4196037990000000u, 0x4CB01BCDu},
|
||||
{"9233162000000000000000000000000000000e-29", 0x4196037990000000u, 0x4CB01BCCu},
|
||||
{"3.002458625e6", 0x4146E82D50000000u, 0x4A37416Au},
|
||||
{"3002458626e-3", 0x4146E82D5020C49Cu, 0x4A37416Bu},
|
||||
{"3002458.624", 0x4146E82D4FDF3B64u, 0x4A37416Au},
|
||||
{"-3.00245862501e6", 0xC146E82D500053E3u, 0xCA37416Bu},
|
||||
{"3002458625000000000000000000001e-24", 0x4146E82D50000000u, 0x4A37416Bu},
|
||||
{"3002458.625000000000000000000000000000000", 0x4146E82D50000000u, 0x4A37416Au},
|
||||
{"-1095485584696182596504479582065262592e1", 0xC7A07BA830000000u, 0xFD03DD42u},
|
||||
{"10954855846961825965044795820652625930", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"1.095485584696182596504479582065262591e37", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"109548558469618259650447958206526259201e-1", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"-10954855846961825965044795820652625920.00000000000000000001", 0xC7A07BA830000000u, 0xFD03DD42u},
|
||||
{"1.095485584696182596504479582065262592000000000000000000000000000000e37", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"10954855846961825e21", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"10954855846961826000000000000000000000", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"10954855846961825960000000000000000000", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"1.095485584696182597e37", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"1.0954855846961825965e37", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"-10954855846961825966e18", 0xC7A07BA830000000u, 0xFD03DD42u},
|
||||
{"10954855846961825965e18", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"10954855846961825965100000000000000000", 0x47A07BA830000000u, 0x7D03DD42u},
|
||||
{"10954855846961825965044795820600000000", 0x47A07BA830000000u, 0x7D03DD41u},
|
||||
{"-1.09548558469618259650447958207e37", 0xC7A07BA830000000u, 0xFD03DD42u},
|
||||
{"1.6449216019182103706535606608388384863861375606575165875256061553955078126e-21", 0x3B9F125A50000000u, 0x1CF892D3u},
|
||||
{"-16449216019182103706535606608388384863861375606575165875256061553955078124e-94", 0xBB9F125A50000000u, 0x9CF892D2u},
|
||||
{"-0.0000000000000000000016449216019182103", 0xBB9F125A50000000u, 0x9CF892D2u},
|
||||
{"-1.6449216019182104e-21", 0xBB9F125A50000000u, 0x9CF892D3u},
|
||||
{"-1.64492160191821037e-21", 0xBB9F125A50000000u, 0x9CF892D2u},
|
||||
{"-1644921601918210371e-39", 0xBB9F125A50000000u, 0x9CF892D3u},
|
||||
{"-16449216019182103706e-40", 0xBB9F125A50000000u, 0x9CF892D2u},
|
||||
{"0.0000000000000000000016449216019182103707", 0x3B9F125A50000000u, 0x1CF892D3u},
|
||||
{"0.00000000000000000000164492160191821037065", 0x3B9F125A50000000u, 0x1CF892D2u},
|
||||
{"1.64492160191821037066e-21", 0x3B9F125A50000000u, 0x1CF892D3u},
|
||||
{"1.64492160191821037065356066083e-21", 0x3B9F125A50000000u, 0x1CF892D2u},
|
||||
{"164492160191821037065356066084e-50", 0x3B9F125A50000000u, 0x1CF892D3u},
|
||||
{"6.565061509609222412109375e-1", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"6565061509609222412109376e-25", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"0.6565061509609222412109374", 0x3FE5021930000000u, 0x3F2810C9u},
|
||||
{"6.56506150960922241210937501e-1", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"6565061509609222412109375000000000000000000001e-46", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"-0.6565061509609222412109375000000000000000000000000000000", 0xBFE5021930000000u, 0xBF2810CAu},
|
||||
{"6.5650615096092224e-1", 0x3FE5021930000000u, 0x3F2810C9u},
|
||||
{"-65650615096092225e-17", 0xBFE5021930000000u, 0xBF2810CAu},
|
||||
{"6565061509609222412e-19", 0x3FE5021930000000u, 0x3F2810C9u},
|
||||
{"0.6565061509609222413", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"0.65650615096092224121", 0x3FE5021930000000u, 0x3F2810C9u},
|
||||
{"6.5650615096092224122e-1", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"-6.5650615096092224121e-1", 0xBFE5021930000000u, 0xBF2810C9u},
|
||||
{"656506150960922241211e-21", 0x3FE5021930000000u, 0x3F2810CAu},
|
||||
{"18014627239033005156980393746124491372029297053813934326171875e-77", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"0.00000000000000018014627239033005156980393746124491372029297053813934326171876", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"-1.8014627239033005156980393746124491372029297053813934326171874e-16", 0xBCA9F63970000000u, 0xA54FB1CBu},
|
||||
{"1801462723903300515698039374612449137202929705381393432617187501e-79", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"18014627239033005e-32", 0x3CA9F63970000000u, 0x254FB1CBu},
|
||||
{"0.00000000000000018014627239033006", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"0.0000000000000001801462723903300515", 0x3CA9F63970000000u, 0x254FB1CBu},
|
||||
{"-1.801462723903300516e-16", 0xBCA9F63970000000u, 0xA54FB1CCu},
|
||||
{"-1.8014627239033005156e-16", 0xBCA9F63970000000u, 0xA54FB1CBu},
|
||||
{"18014627239033005157e-35", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"180146272390330051569e-36", 0x3CA9F63970000000u, 0x254FB1CBu},
|
||||
{"-0.00000000000000018014627239033005157", 0xBCA9F63970000000u, 0xA54FB1CCu},
|
||||
{"0.000000000000000180146272390330051569803937461", 0x3CA9F63970000000u, 0x254FB1CBu},
|
||||
{"1.80146272390330051569803937462e-16", 0x3CA9F63970000000u, 0x254FB1CCu},
|
||||
{"0.05534819327294826507568359375", 0x3FAC569930000000u, 0x3D62B4CAu},
|
||||
{"-5.534819327294826507568359376e-2", 0xBFAC569930000000u, 0xBD62B4CAu},
|
||||
{"5534819327294826507568359374e-29", 0x3FAC569930000000u, 0x3D62B4C9u},
|
||||
{"-0.0553481932729482650756835937501", 0xBFAC569930000000u, 0xBD62B4CAu},
|
||||
{"5.534819327294826507568359375000000000000000000001e-2", 0x3FAC569930000000u, 0x3D62B4CAu},
|
||||
{"5534819327294826507568359375000000000000000000000000000000e-59", 0x3FAC569930000000u, 0x3D62B4CAu},
|
||||
{"0.055348193272948265", 0x3FAC569930000000u, 0x3D62B4C9u},
|
||||
{"5.5348193272948266e-2", 0x3FAC569930000000u, 0x3D62B4CAu},
|
||||
{"5.534819327294826507e-2", 0x3FAC569930000000u, 0x3D62B4C9u},
|
||||
{"5534819327294826508e-20", 0x3FAC569930000000u, 0x3D62B4CAu},
|
||||
{"55348193272948265075e-21", 0x3FAC569930000000u, 0x3D62B4C9u},
|
||||
{"-0.055348193272948265076", 0xBFAC569930000000u, 0xBD62B4CAu},
|
||||
{"0.0553481932729482650756", 0x3FAC569930000000u, 0x3D62B4C9u},
|
||||
{"-5.53481932729482650757e-2", 0xBFAC569930000000u, 0xBD62B4CAu},
|
||||
{"5.179692133247783258005389047985340416e36", 0x478F2C9450000000u, 0x7C7964A2u},
|
||||
{"5179692133247783258005389047985340417e0", 0x478F2C9450000000u, 0x7C7964A3u},
|
||||
{"5179692133247783258005389047985340415", 0x478F2C9450000000u, 0x7C7964A2u},
|
||||
{"-5.17969213324778325800538904798534041601e36", 0xC78F2C9450000000u, 0xFC7964A3u},
|
||||
{"-5179692133247783258005389047985340416000000000000000000001e-21", 0xC78F2C9450000000u, 0xFC7964A3u},
|
||||
{"-5179692133247783258005389047985340416.000000000000000000000000000000", 0xC78F2C9450000000u, 0xFC7964A2u},
|
||||
{"5.1796921332477832e36", 0x478F2C9450000000u, 0x7C7964A2u},
|
||||
{"51796921332477833e20", 0x478F2C9450000000u, 0x7C7964A3u},
|
||||
{"-5179692133247783258e18", 0xC78F2C9450000000u, 0xFC7964A2u},
|
||||
{"5179692133247783259000000000000000000", 0x478F2C9450000000u, 0x7C7964A3u},
|
||||
{"5179692133247783258000000000000000000", 0x478F2C9450000000u, 0x7C7964A2u},
|
||||
{"5.1796921332477832581e36", 0x478F2C9450000000u, 0x7C7964A3u},
|
||||
{"-5.179692133247783258e36", 0xC78F2C9450000000u, 0xFC7964A2u},
|
||||
{"-517969213324778325801e16", 0xC78F2C9450000000u, 0xFC7964A3u},
|
||||
{"517969213324778325800538904798e7", 0x478F2C9450000000u, 0x7C7964A2u},
|
||||
{"5179692133247783258005389047990000000", 0x478F2C9450000000u, 0x7C7964A3u},
|
||||
{
|
||||
"0.22250738585072011360574097967091319759348195463516456480234261097248222220210769455165295239081350"
|
||||
"8791414915891303962110687008643869459464552765720740782062174337998814106326732925355228688137214901"
|
||||
"2981122451451889849057222307285255133155755015914397476397983411801999323962548289017107081850690630"
|
||||
"6666559949382757725720157630626906633326475653000092458883164330377797918696120494973903778297049050"
|
||||
"5108060994073026293712895895000358379996720725430436028407889577179615094551674824347103070260914462"
|
||||
"1572289880258182545180325707018860872113128079512233426288368622321503775666622503982534335974568884"
|
||||
"4239002654981983854879482922068947216898310996983658468140228542433306603398508864458040010349339704"
|
||||
"2756718644338377048603786162277173854562306587467901408672332763671875e-307", 0x0010000000000000u, 0x00000000u
|
||||
},
|
||||
{
|
||||
"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508"
|
||||
"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012"
|
||||
"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306"
|
||||
"6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505"
|
||||
"1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621"
|
||||
"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844"
|
||||
"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042"
|
||||
"756718644338377048603786162277173854562306587467901408672332763671875000000000000000000001e-308", 0x0010000000000000u, 0x00000000u
|
||||
},
|
||||
{
|
||||
"0.11754942807573642917278829910357665133228589927589904276829631184250030649651730385585324256680905"
|
||||
"8189392089843750000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000e-37", 0x380FFFFFE0000000u, 0x00800000u
|
||||
},
|
||||
{
|
||||
"1175494280757364291727882991035766513322858992758990427682963118425003064965173038558532425668090581"
|
||||
"8939208984375000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000001e-751", 0x380FFFFFE0000000u, 0x00800000u
|
||||
},
|
||||
{"0", 0x0000000000000000u, 0x00000000u},
|
||||
{"-0", 0x8000000000000000u, 0x80000000u},
|
||||
{"0.0", 0x0000000000000000u, 0x00000000u},
|
||||
{"-0.0", 0x8000000000000000u, 0x80000000u},
|
||||
{"0e999999999999999999999", 0x0000000000000000u, 0x00000000u},
|
||||
{"-0.000e-99999", 0x8000000000000000u, 0x80000000u},
|
||||
{"1e-400", 0x0000000000000000u, 0x00000000u},
|
||||
{"-1e-400", 0x8000000000000000u, 0x80000000u},
|
||||
{"1e400", 0x7FF0000000000000u, 0x7F800000u},
|
||||
{"-1e400", 0xFFF0000000000000u, 0xFF800000u},
|
||||
{"1e-50", 0x358DEE7A4AD4B81Fu, 0x00000000u},
|
||||
{"-1e-50", 0xB58DEE7A4AD4B81Fu, 0x80000000u},
|
||||
{"1e39", 0x48078287F49C4A1Du, 0x7F800000u},
|
||||
{"-1e39", 0xC8078287F49C4A1Du, 0xFF800000u},
|
||||
{"1e99999999999999999999999999", 0x7FF0000000000000u, 0x7F800000u},
|
||||
{"1e-99999999999999999999999999", 0x0000000000000000u, 0x00000000u},
|
||||
{"1e0000000000000000000000000000000000000000308", 0x7FE1CCF385EBC8A0u, 0x7F800000u},
|
||||
{"123456789012345678901234567890e-30", 0x3FBF9ADD3746F65Fu, 0x3DFCD6EAu},
|
||||
{"18446744073709551615", 0x43F0000000000000u, 0x5F800000u},
|
||||
{"18446744073709551616", 0x43F0000000000000u, 0x5F800000u},
|
||||
{"-9223372036854775808", 0xC3E0000000000000u, 0xDF000000u},
|
||||
{"-9223372036854775809", 0xC3E0000000000000u, 0xDF000000u},
|
||||
}
|
||||
};
|
||||
return table;
|
||||
}
|
||||
|
||||
} // namespace float_hard_cases
|
||||
Loaded 100 of 148 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user