Merge branch 'release/3.9.0'
This commit is contained in:
commit
36e5ecf66d
147 changed files with 8984 additions and 5201 deletions
84
.clang-format
Normal file
84
.clang-format
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#AccessModifierOffset: 2
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
#AlignConsecutiveBitFields: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignConsecutiveMacros: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
#AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
#AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
#BitFieldColonSpacing: Both
|
||||||
|
BreakBeforeBraces: Custom # or Allman
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: true
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: Always
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: true
|
||||||
|
#BeforeLambdaBody: false
|
||||||
|
#BeforeWhile: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 0
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerIndentWidth: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
PointerAlignment: Left
|
||||||
|
FixNamespaceComments: true
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
#IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: BeforeHash
|
||||||
|
IndentWidth: 4
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ReflowComments: false
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: c++11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
27
.clang-tidy
27
.clang-tidy
|
@ -1,23 +1,20 @@
|
||||||
Checks: '-*,
|
Checks: '*,
|
||||||
bugprone-*,
|
-cppcoreguidelines-avoid-goto,
|
||||||
cert-*,
|
-cppcoreguidelines-avoid-magic-numbers,
|
||||||
clang-analyzer-*,
|
-cppcoreguidelines-macro-usage,
|
||||||
google-*,
|
-fuchsia-default-arguments-calls,
|
||||||
-google-runtime-references,
|
-fuchsia-default-arguments-declarations,
|
||||||
|
-fuchsia-overloaded-operator,
|
||||||
-google-explicit-constructor,
|
-google-explicit-constructor,
|
||||||
hicpp-*,
|
-google-runtime-references,
|
||||||
|
-hicpp-avoid-goto,
|
||||||
|
-hicpp-explicit-conversions,
|
||||||
-hicpp-no-array-decay,
|
-hicpp-no-array-decay,
|
||||||
-hicpp-uppercase-literal-suffix,
|
-hicpp-uppercase-literal-suffix,
|
||||||
-hicpp-explicit-conversions,
|
|
||||||
misc-*,
|
|
||||||
-misc-non-private-member-variables-in-classes,
|
|
||||||
llvm-*,
|
|
||||||
-llvm-header-guard,
|
-llvm-header-guard,
|
||||||
modernize-*,
|
-llvm-include-order,
|
||||||
|
-misc-non-private-member-variables-in-classes,
|
||||||
-modernize-use-trailing-return-type,
|
-modernize-use-trailing-return-type,
|
||||||
performance-*,
|
|
||||||
portability-*,
|
|
||||||
readability-*,
|
|
||||||
-readability-magic-numbers,
|
-readability-magic-numbers,
|
||||||
-readability-uppercase-literal-suffix'
|
-readability-uppercase-literal-suffix'
|
||||||
|
|
||||||
|
|
2
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
|
@ -47,7 +47,7 @@ assignees: ''
|
||||||
|
|
||||||
<!-- Please add an `x` to the respective line. -->
|
<!-- Please add an `x` to the respective line. -->
|
||||||
|
|
||||||
- [ ] latest release version 3.7.3
|
- [ ] latest release version 3.9.0
|
||||||
- [ ] other release - please state the version: ___
|
- [ ] other release - please state the version: ___
|
||||||
- [ ] the `develop` branch
|
- [ ] the `develop` branch
|
||||||
|
|
||||||
|
|
16
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
16
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
|
@ -1,16 +0,0 @@
|
||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: 'kind: enhancement/improvement'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Which feature do you want to see in the library?
|
|
||||||
|
|
||||||
<!-- Describe the feature in as much detail as possible. -->
|
|
||||||
|
|
||||||
#### How would the feature be usable for other users?
|
|
||||||
|
|
||||||
<!-- Include sample usage where appropriate. -->
|
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Ask a question
|
||||||
|
url: https://github.com/nlohmann/json/discussions
|
||||||
|
about: Ask questions and discuss with other community members
|
40
.github/ISSUE_TEMPLATE/question.md
vendored
40
.github/ISSUE_TEMPLATE/question.md
vendored
|
@ -1,40 +0,0 @@
|
||||||
---
|
|
||||||
name: Question
|
|
||||||
about: Ask a question regarding the library.
|
|
||||||
title: ''
|
|
||||||
labels: 'kind: question'
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<!-- Provide a concise summary of the issue in the title above. -->
|
|
||||||
|
|
||||||
#### What do you want to achieve?
|
|
||||||
|
|
||||||
<!-- Please describe the feature as detailed as possible. -->
|
|
||||||
|
|
||||||
#### What have you tried?
|
|
||||||
|
|
||||||
<!-- There are thousands of issues to search: https://github.com/nlohmann/json/issues?q=is%3Aissue+ -->
|
|
||||||
<!-- There is a full documentation of the API: https://nlohmann.github.io/json/ -->
|
|
||||||
<!-- There is a detailed README file: https://github.com/nlohmann/json/blob/develop/README.md -->
|
|
||||||
|
|
||||||
#### Can you provide a small code example?
|
|
||||||
|
|
||||||
<!-- Please understand that we cannot analyze and debug large code bases. -->
|
|
||||||
|
|
||||||
#### Which compiler and operating system are you using?
|
|
||||||
|
|
||||||
<!-- Include as many relevant details about the environment you experienced the bug in. -->
|
|
||||||
<!-- Make sure you use a supported compiler, see https://github.com/nlohmann/json#supported-compilers. -->
|
|
||||||
|
|
||||||
- Compiler: ___
|
|
||||||
- Operating system: ___
|
|
||||||
|
|
||||||
#### Which version of the library did you use?
|
|
||||||
|
|
||||||
<!-- Please add an `x` to the respective line. -->
|
|
||||||
|
|
||||||
- [ ] latest release version 3.7.3
|
|
||||||
- [ ] other release - please state the version: ___
|
|
||||||
- [ ] the `develop` branch
|
|
54
.github/workflows/codeql-analysis.yml
vendored
Normal file
54
.github/workflows/codeql-analysis.yml
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
name: "Code scanning - action"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [develop, ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [develop]
|
||||||
|
schedule:
|
||||||
|
- cron: '0 19 * * 1'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
CodeQL-Build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# We must fetch at least the immediate parents so that if this is
|
||||||
|
# a pull request then we can checkout the head.
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
# If this run was triggered by a pull request event, then checkout
|
||||||
|
# the head of the pull request instead of the merge commit.
|
||||||
|
- run: git checkout HEAD^2
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
# Override language selection by uncommenting this and choosing your languages
|
||||||
|
# with:
|
||||||
|
# languages: go, javascript, csharp, python, cpp, java
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
55
.github/workflows/windows.yml
vendored
55
.github/workflows/windows.yml
vendored
|
@ -3,8 +3,7 @@ name: Windows
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
msvc2019:
|
||||||
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -15,3 +14,55 @@ jobs:
|
||||||
run: cmake --build build --parallel 10
|
run: cmake --build build --parallel 10
|
||||||
- name: test
|
- 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 --exclude-regex "test-unicode" --output-on-failure
|
||||||
|
|
||||||
|
clang9:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: install Clang
|
||||||
|
run: curl -fsSL -o LLVM9.exe https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe ; 7z x LLVM9.exe -y -o"C:/Program Files/LLVM"
|
||||||
|
- name: cmake
|
||||||
|
run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
|
||||||
|
- 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
|
||||||
|
|
||||||
|
clang10:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: install Clang
|
||||||
|
run: curl -fsSL -o LLVM10.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/LLVM-10.0.0-win64.exe ; 7z x LLVM10.exe -y -o"C:/Program Files/LLVM"
|
||||||
|
- name: cmake
|
||||||
|
run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
|
||||||
|
- 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
|
||||||
|
|
||||||
|
clang-cl-10-x64:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: cmake
|
||||||
|
run: cmake -S . -B build -G "Visual Studio 16 2019" -A x64 -T ClangCL -DJSON_BuildTests=On
|
||||||
|
- 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
|
||||||
|
|
||||||
|
clang-cl-10-x86:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: cmake
|
||||||
|
run: cmake -S . -B build -G "Visual Studio 16 2019" -A Win32 -T ClangCL -DJSON_BuildTests=On
|
||||||
|
- 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
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -22,7 +22,7 @@ benchmarks/files/numbers/*.json
|
||||||
.wsjcpp/*
|
.wsjcpp/*
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
cmake-build-debug
|
/cmake-build-*
|
||||||
|
|
||||||
test/test-*
|
test/test-*
|
||||||
/.vs
|
/.vs
|
||||||
|
@ -32,3 +32,4 @@ doc/mkdocs/docs/images
|
||||||
doc/mkdocs/docs/examples
|
doc/mkdocs/docs/examples
|
||||||
doc/mkdocs/site
|
doc/mkdocs/site
|
||||||
doc/mkdocs/docs/__pycache__/
|
doc/mkdocs/docs/__pycache__/
|
||||||
|
doc/xml
|
||||||
|
|
36
.travis.yml
36
.travis.yml
|
@ -10,17 +10,6 @@ sudo: required
|
||||||
group: edge
|
group: edge
|
||||||
|
|
||||||
|
|
||||||
###################
|
|
||||||
# global settings #
|
|
||||||
###################
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
|
||||||
# via the "travis encrypt" command using the project repo's public key
|
|
||||||
- secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
|
|
||||||
|
|
||||||
|
|
||||||
################
|
################
|
||||||
# build matrix #
|
# build matrix #
|
||||||
################
|
################
|
||||||
|
@ -129,6 +118,9 @@ matrix:
|
||||||
env:
|
env:
|
||||||
- SPECIAL=coverity
|
- SPECIAL=coverity
|
||||||
- COMPILER=clang++-3.6
|
- COMPILER=clang++-3.6
|
||||||
|
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||||
|
# via the "travis encrypt" command using the project repo's public key
|
||||||
|
- secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
|
||||||
|
|
||||||
# OSX / Clang
|
# OSX / Clang
|
||||||
|
|
||||||
|
@ -150,6 +142,14 @@ matrix:
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode11.2
|
osx_image: xcode11.2
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12
|
||||||
|
env:
|
||||||
|
- IMPLICIT_CONVERSIONS=OFF
|
||||||
|
|
||||||
# Linux / GCC
|
# Linux / GCC
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
@ -208,6 +208,16 @@ matrix:
|
||||||
sources: ['ubuntu-toolchain-r-test']
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
packages: ['g++-9', 'ninja-build']
|
packages: ['g++-9', 'ninja-build']
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
- COMPILER=g++-9
|
||||||
|
- IMPLICIT_CONVERSIONS=OFF
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test']
|
||||||
|
packages: ['g++-9', 'ninja-build']
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
env:
|
env:
|
||||||
|
@ -320,10 +330,12 @@ script:
|
||||||
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
|
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
|
||||||
# by default, use the single-header version
|
# by default, use the single-header version
|
||||||
- if [[ "${MULTIPLE_HEADERS}" == "" ]]; then export MULTIPLE_HEADERS=OFF; fi
|
- if [[ "${MULTIPLE_HEADERS}" == "" ]]; then export MULTIPLE_HEADERS=OFF; fi
|
||||||
|
# by default, use implicit conversions
|
||||||
|
- if [[ "${IMPLICIT_CONVERSIONS}" == "" ]]; then export IMPLICIT_CONVERSIONS=ON; fi
|
||||||
|
|
||||||
# compile and execute unit tests
|
# compile and execute unit tests
|
||||||
- mkdir -p build && cd build
|
- mkdir -p build && cd build
|
||||||
- cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -DJSON_BuildTests=On -GNinja && cmake --build . --config Release
|
- cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -DJSON_ImplicitConversions=${IMPLICIT_CONVERSIONS} -DJSON_BuildTests=On -GNinja && cmake --build . --config Release
|
||||||
- ctest -C Release --timeout 2700 -V -j
|
- ctest -C Release --timeout 2700 -V -j
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1)
|
||||||
## PROJECT
|
## PROJECT
|
||||||
## name and version
|
## name and version
|
||||||
##
|
##
|
||||||
project(nlohmann_json VERSION 3.8.0 LANGUAGES CXX)
|
project(nlohmann_json VERSION 3.9.0 LANGUAGES CXX)
|
||||||
|
|
||||||
##
|
##
|
||||||
## INCLUDE
|
## INCLUDE
|
||||||
|
@ -15,9 +15,16 @@ include(ExternalProject)
|
||||||
##
|
##
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
##
|
##
|
||||||
|
|
||||||
|
if (POLICY CMP0077)
|
||||||
|
# Allow CMake 3.13+ to override options when using FetchContent / add_subdirectory.
|
||||||
|
cmake_policy(SET CMP0077 NEW)
|
||||||
|
endif ()
|
||||||
|
|
||||||
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
|
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
|
||||||
option(JSON_Install "Install CMake targets during install step." ON)
|
option(JSON_Install "Install CMake targets during install step." ON)
|
||||||
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
|
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
|
||||||
|
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
|
||||||
|
|
||||||
##
|
##
|
||||||
## CONFIGURATION
|
## CONFIGURATION
|
||||||
|
@ -42,6 +49,10 @@ else()
|
||||||
message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
|
message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT JSON_ImplicitConversions)
|
||||||
|
message(STATUS "Implicit conversions are disabled")
|
||||||
|
endif()
|
||||||
|
|
||||||
##
|
##
|
||||||
## TARGET
|
## TARGET
|
||||||
## create target and add include path
|
## create target and add include path
|
||||||
|
@ -54,6 +65,12 @@ else()
|
||||||
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
|
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(
|
||||||
|
${NLOHMANN_JSON_TARGET_NAME}
|
||||||
|
INTERFACE
|
||||||
|
JSON_USE_IMPLICIT_CONVERSIONS=$<BOOL:${JSON_ImplicitConversions}>
|
||||||
|
)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${NLOHMANN_JSON_TARGET_NAME}
|
${NLOHMANN_JSON_TARGET_NAME}
|
||||||
INTERFACE
|
INTERFACE
|
||||||
|
@ -73,6 +90,12 @@ if (MSVC)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Install a pkg-config file, so other tools can find this.
|
||||||
|
CONFIGURE_FILE(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||||
|
)
|
||||||
|
|
||||||
##
|
##
|
||||||
## TESTS
|
## TESTS
|
||||||
## create and configure the unit test target
|
## create and configure the unit test target
|
||||||
|
@ -133,4 +156,8 @@ endif()
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||||
|
DESTINATION lib/pkgconfig
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
148
ChangeLog.md
148
ChangeLog.md
|
@ -1,13 +1,129 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
|
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [v3.9.0](https://github.com/nlohmann/json/releases/tag/v3.9.0) (2020-07-27)
|
||||||
|
|
||||||
|
[Full Changelog](https://github.com/nlohmann/json/compare/v3.8.0...v3.9.0)
|
||||||
|
|
||||||
|
- Unknown Type Name clang error when using NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE [\#2313](https://github.com/nlohmann/json/issues/2313)
|
||||||
|
- Clang 10.0 / GCC 10.1 warnings on disabled exceptions [\#2304](https://github.com/nlohmann/json/issues/2304)
|
||||||
|
- Application stalls indefinitely with message byte size 10 [\#2293](https://github.com/nlohmann/json/issues/2293)
|
||||||
|
- linker error [\#2292](https://github.com/nlohmann/json/issues/2292)
|
||||||
|
- Add support for high-precision numbers in UBJSON encoding [\#2286](https://github.com/nlohmann/json/issues/2286)
|
||||||
|
- NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE fails if the length of the argument is 10 [\#2280](https://github.com/nlohmann/json/issues/2280)
|
||||||
|
- Custom types : MACRO expansion bug [\#2267](https://github.com/nlohmann/json/issues/2267)
|
||||||
|
- to/from\_json Failing To Convert String [\#2238](https://github.com/nlohmann/json/issues/2238)
|
||||||
|
- clang 9.0 report warning: unused type alias 'size\_type' \[-Wunused-local-typedef\] [\#2221](https://github.com/nlohmann/json/issues/2221)
|
||||||
|
- Enormous array created when working with map\<int,T\> [\#2220](https://github.com/nlohmann/json/issues/2220)
|
||||||
|
- Can I disable sorting of json values [\#2219](https://github.com/nlohmann/json/issues/2219)
|
||||||
|
- Getting Qt types to work [\#2217](https://github.com/nlohmann/json/issues/2217)
|
||||||
|
- Convert to Qt QVariant [\#2216](https://github.com/nlohmann/json/issues/2216)
|
||||||
|
- How to custom serialize same data type of vector? [\#2215](https://github.com/nlohmann/json/issues/2215)
|
||||||
|
- json constructor does not support std::optional [\#2214](https://github.com/nlohmann/json/issues/2214)
|
||||||
|
- Failing to Parse Valid JSON [\#2209](https://github.com/nlohmann/json/issues/2209)
|
||||||
|
- \(De-\)Serialization of std::variant with namespaces [\#2208](https://github.com/nlohmann/json/issues/2208)
|
||||||
|
- Addint support for complex type [\#2207](https://github.com/nlohmann/json/issues/2207)
|
||||||
|
- array\_index possible out of range [\#2205](https://github.com/nlohmann/json/issues/2205)
|
||||||
|
- Object deserialized as array [\#2204](https://github.com/nlohmann/json/issues/2204)
|
||||||
|
- Sending to a function a reference to a sub-branch [\#2200](https://github.com/nlohmann/json/issues/2200)
|
||||||
|
- How to Serialize derived class to JSON object? [\#2199](https://github.com/nlohmann/json/issues/2199)
|
||||||
|
- JSON incorrectly serialized [\#2198](https://github.com/nlohmann/json/issues/2198)
|
||||||
|
- Exception Unhandled out\_of\_range error [\#2197](https://github.com/nlohmann/json/issues/2197)
|
||||||
|
- msgpack serialisation : float is treated as 64bit float, not 32bit float. [\#2196](https://github.com/nlohmann/json/issues/2196)
|
||||||
|
- Is it possible to use compile-time type guarantees for JSON structures? [\#2195](https://github.com/nlohmann/json/issues/2195)
|
||||||
|
- Question : performance against python dict [\#2194](https://github.com/nlohmann/json/issues/2194)
|
||||||
|
- vs2017 compile error [\#2192](https://github.com/nlohmann/json/issues/2192)
|
||||||
|
- Check if a key exists [\#2191](https://github.com/nlohmann/json/issues/2191)
|
||||||
|
- Failed to run tests due to missing test data on builders without Internet access [\#2190](https://github.com/nlohmann/json/issues/2190)
|
||||||
|
- 3.8.0: unit-cbor.cpp test failures [\#2189](https://github.com/nlohmann/json/issues/2189)
|
||||||
|
- 'nlohmann/json.hpp' file not found [\#2188](https://github.com/nlohmann/json/issues/2188)
|
||||||
|
- How to send json data over the wire? [\#2185](https://github.com/nlohmann/json/issues/2185)
|
||||||
|
- Ubuntu 16 not supporting nlohmann/json? [\#2184](https://github.com/nlohmann/json/issues/2184)
|
||||||
|
- .get\<std::string\> causing emdash errors [\#2180](https://github.com/nlohmann/json/issues/2180)
|
||||||
|
- Object properties should not be re-sorted alphabetically [\#2179](https://github.com/nlohmann/json/issues/2179)
|
||||||
|
- Custom type registration : instrusive API [\#2175](https://github.com/nlohmann/json/issues/2175)
|
||||||
|
- Many version of the function "void to\_json\(json& j, const MyStruct& struct\)" [\#2171](https://github.com/nlohmann/json/issues/2171)
|
||||||
|
- How should strings be escaped? [\#2155](https://github.com/nlohmann/json/issues/2155)
|
||||||
|
- Adding a value to an existing json puts it at the beginning instead of the end [\#2149](https://github.com/nlohmann/json/issues/2149)
|
||||||
|
- The header file is big, can we use what we need. [\#2134](https://github.com/nlohmann/json/issues/2134)
|
||||||
|
- Changing the default format for unordered\_map \(or other set\) [\#2132](https://github.com/nlohmann/json/issues/2132)
|
||||||
|
- Getting size of deserialized bson document [\#2131](https://github.com/nlohmann/json/issues/2131)
|
||||||
|
- implicit conversion failure [\#2128](https://github.com/nlohmann/json/issues/2128)
|
||||||
|
- Error thrown when parsing in a subclass [\#2124](https://github.com/nlohmann/json/issues/2124)
|
||||||
|
- explicit conversion to string not considered for std::map keys in GCC8 [\#2096](https://github.com/nlohmann/json/issues/2096)
|
||||||
|
- Add support for JSONC [\#2061](https://github.com/nlohmann/json/issues/2061)
|
||||||
|
- Library provides template arg for string\_type but assumes std::string in some places [\#2059](https://github.com/nlohmann/json/issues/2059)
|
||||||
|
- incremental parsing with sax\_parser [\#2030](https://github.com/nlohmann/json/issues/2030)
|
||||||
|
- Question about flatten and unflatten [\#1989](https://github.com/nlohmann/json/issues/1989)
|
||||||
|
- CBOR parser doesn't skip tags [\#1968](https://github.com/nlohmann/json/issues/1968)
|
||||||
|
- Compilation failure using Clang on Windows [\#1898](https://github.com/nlohmann/json/issues/1898)
|
||||||
|
- Fail to build when including json.hpp as a system include [\#1818](https://github.com/nlohmann/json/issues/1818)
|
||||||
|
- Parsing string into json doesn't preserve the order correctly. [\#1817](https://github.com/nlohmann/json/issues/1817)
|
||||||
|
- \[C++17\] Allow std::optional to convert to nlohmann::json [\#1749](https://github.com/nlohmann/json/issues/1749)
|
||||||
|
- How can I save json object in file in order? [\#1717](https://github.com/nlohmann/json/issues/1717)
|
||||||
|
- Support for Comments [\#1513](https://github.com/nlohmann/json/issues/1513)
|
||||||
|
- clang compiler: error : unknown type name 'not' [\#1119](https://github.com/nlohmann/json/issues/1119)
|
||||||
|
- dump\(\) without alphabetical order [\#1106](https://github.com/nlohmann/json/issues/1106)
|
||||||
|
- operator T\(\) considered harmful [\#958](https://github.com/nlohmann/json/issues/958)
|
||||||
|
- Order of the elements in JSON object [\#952](https://github.com/nlohmann/json/issues/952)
|
||||||
|
- How to prevent alphabetical sorting of data? [\#727](https://github.com/nlohmann/json/issues/727)
|
||||||
|
- Why is an object ordering values by Alphabetical Order? [\#660](https://github.com/nlohmann/json/issues/660)
|
||||||
|
- Feature request: Comments [\#597](https://github.com/nlohmann/json/issues/597)
|
||||||
|
- Head Elements Sorting [\#543](https://github.com/nlohmann/json/issues/543)
|
||||||
|
- Automatic ordered JSON [\#424](https://github.com/nlohmann/json/issues/424)
|
||||||
|
- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376)
|
||||||
|
- Optional comment support. [\#363](https://github.com/nlohmann/json/issues/363)
|
||||||
|
- Strip comments / Minify [\#294](https://github.com/nlohmann/json/issues/294)
|
||||||
|
- maintaining order of keys during iteration [\#106](https://github.com/nlohmann/json/issues/106)
|
||||||
|
|
||||||
|
- Update documentation [\#2312](https://github.com/nlohmann/json/pull/2312) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Fix bug in CBOR tag handling [\#2308](https://github.com/nlohmann/json/pull/2308) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- added inline to NLOHMANN\_DEFINE\_TYPE\_NON\_INTRUSIVE macro [\#2306](https://github.com/nlohmann/json/pull/2306) ([jwittbrodt](https://github.com/jwittbrodt))
|
||||||
|
- fixes unused variable 'ex' for \#2304 [\#2305](https://github.com/nlohmann/json/pull/2305) ([AODQ](https://github.com/AODQ))
|
||||||
|
- Cleanup [\#2303](https://github.com/nlohmann/json/pull/2303) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add test with multiple translation units [\#2301](https://github.com/nlohmann/json/pull/2301) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Merge GitHub actions [\#2300](https://github.com/nlohmann/json/pull/2300) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Fix unused parameter [\#2299](https://github.com/nlohmann/json/pull/2299) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add support for high-precision numbers in UBJSON encoding [\#2297](https://github.com/nlohmann/json/pull/2297) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- fix eof for get\_binary and get\_string [\#2294](https://github.com/nlohmann/json/pull/2294) ([jprochazk](https://github.com/jprochazk))
|
||||||
|
- Serialisation macros: increase upper bound on number of member variables [\#2287](https://github.com/nlohmann/json/pull/2287) ([pfeatherstone](https://github.com/pfeatherstone))
|
||||||
|
- add inline specifier for detail::combine [\#2285](https://github.com/nlohmann/json/pull/2285) ([T0b1-iOS](https://github.com/T0b1-iOS))
|
||||||
|
- Add static assertion for missing binary function in SAX interface [\#2282](https://github.com/nlohmann/json/pull/2282) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add test for target\_include\_directories [\#2279](https://github.com/nlohmann/json/pull/2279) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Clean up maintainer Makefiles and fix some linter warnings [\#2274](https://github.com/nlohmann/json/pull/2274) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add option to ignore CBOR tags [\#2273](https://github.com/nlohmann/json/pull/2273) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Hash function without allocation [\#2269](https://github.com/nlohmann/json/pull/2269) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add ClangCL for MSVC [\#2268](https://github.com/nlohmann/json/pull/2268) ([t-b](https://github.com/t-b))
|
||||||
|
- Makefile: Always use SED variable [\#2264](https://github.com/nlohmann/json/pull/2264) ([t-b](https://github.com/t-b))
|
||||||
|
- Add Xcode 12 CI [\#2262](https://github.com/nlohmann/json/pull/2262) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Make library work with Clang on Windows [\#2259](https://github.com/nlohmann/json/pull/2259) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add ordered\_json specialization with ordered object keys [\#2258](https://github.com/nlohmann/json/pull/2258) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add pkg-config file [\#2253](https://github.com/nlohmann/json/pull/2253) ([ericonr](https://github.com/ericonr))
|
||||||
|
- Fix regression from \#2181 [\#2251](https://github.com/nlohmann/json/pull/2251) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Tag binary values in cbor if set [\#2244](https://github.com/nlohmann/json/pull/2244) ([matthewbauer](https://github.com/matthewbauer))
|
||||||
|
- Make assert configurable via JSON\_ASSERT [\#2242](https://github.com/nlohmann/json/pull/2242) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Add specialization of get\_to [\#2233](https://github.com/nlohmann/json/pull/2233) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Refine documentation of error\_handler parameter [\#2232](https://github.com/nlohmann/json/pull/2232) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Simplify conversion from/to custom types [\#2225](https://github.com/nlohmann/json/pull/2225) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Remove unused typedefs [\#2224](https://github.com/nlohmann/json/pull/2224) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Enable CMake policy CMP0077 [\#2222](https://github.com/nlohmann/json/pull/2222) ([alexreinking](https://github.com/alexreinking))
|
||||||
|
- Add option to ignore comments in parse/accept functions [\#2212](https://github.com/nlohmann/json/pull/2212) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Fix Clang-Tidy warnings [\#2211](https://github.com/nlohmann/json/pull/2211) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Simple ordered\_json that works on all supported compilers [\#2206](https://github.com/nlohmann/json/pull/2206) ([gatopeich](https://github.com/gatopeich))
|
||||||
|
- Use unsigned indizies for array index in json pointer [\#2203](https://github.com/nlohmann/json/pull/2203) ([t-b](https://github.com/t-b))
|
||||||
|
- Add option to not rely on Internet connectivity during test stage [\#2202](https://github.com/nlohmann/json/pull/2202) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Serialize floating-point numbers with 32 bit when possible \(MessagePack\) [\#2201](https://github.com/nlohmann/json/pull/2201) ([nlohmann](https://github.com/nlohmann))
|
||||||
|
- Fix consistency in function `int\_to\_string\(\)` [\#2193](https://github.com/nlohmann/json/pull/2193) ([dota17](https://github.com/dota17))
|
||||||
|
- Fix issue\#1275 [\#2181](https://github.com/nlohmann/json/pull/2181) ([dota17](https://github.com/dota17))
|
||||||
|
- C++20 support by removing swap specialization [\#2176](https://github.com/nlohmann/json/pull/2176) ([gracicot](https://github.com/gracicot))
|
||||||
|
- Feat/explicit conversion operator [\#1559](https://github.com/nlohmann/json/pull/1559) ([theodelrieu](https://github.com/theodelrieu))
|
||||||
|
|
||||||
## [v3.8.0](https://github.com/nlohmann/json/releases/tag/v3.8.0) (2020-06-14)
|
## [v3.8.0](https://github.com/nlohmann/json/releases/tag/v3.8.0) (2020-06-14)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.3...v3.8.0)
|
[Full Changelog](https://github.com/nlohmann/json/compare/v3.7.3...v3.8.0)
|
||||||
|
|
||||||
- sorry delete this issue, i'm stupid [\#2187](https://github.com/nlohmann/json/issues/2187)
|
- sorry delete this issue, i'm stupid [\#2187](https://github.com/nlohmann/json/issues/2187)
|
||||||
- Append to a std::nlohmann::json type [\#2186](https://github.com/nlohmann/json/issues/2186)
|
- Append to a std::nlohmann::json type [\#2186](https://github.com/nlohmann/json/issues/2186)
|
||||||
- Object properties should not be re-sorted alphabetically [\#2179](https://github.com/nlohmann/json/issues/2179)
|
|
||||||
- Some troubles to compile the last revision [\#2177](https://github.com/nlohmann/json/issues/2177)
|
- Some troubles to compile the last revision [\#2177](https://github.com/nlohmann/json/issues/2177)
|
||||||
- \# Top level CMakeLists.txt
|
- \# Top level CMakeLists.txt
|
||||||
project\(FOO\)
|
project\(FOO\)
|
||||||
|
@ -34,7 +150,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- test-cbor fails [\#2154](https://github.com/nlohmann/json/issues/2154)
|
- test-cbor fails [\#2154](https://github.com/nlohmann/json/issues/2154)
|
||||||
- Accessing array inside array syntax? [\#2151](https://github.com/nlohmann/json/issues/2151)
|
- Accessing array inside array syntax? [\#2151](https://github.com/nlohmann/json/issues/2151)
|
||||||
- Best way to catch errors when querying json [\#2150](https://github.com/nlohmann/json/issues/2150)
|
- Best way to catch errors when querying json [\#2150](https://github.com/nlohmann/json/issues/2150)
|
||||||
- Adding a value to an existing json puts it at the beginning instead of the end [\#2149](https://github.com/nlohmann/json/issues/2149)
|
|
||||||
- JSON Data Mapping Key-Value from other Key-Value [\#2148](https://github.com/nlohmann/json/issues/2148)
|
- JSON Data Mapping Key-Value from other Key-Value [\#2148](https://github.com/nlohmann/json/issues/2148)
|
||||||
- Conflicts with std \<any\> compiling with GCC 10 [\#2146](https://github.com/nlohmann/json/issues/2146)
|
- Conflicts with std \<any\> compiling with GCC 10 [\#2146](https://github.com/nlohmann/json/issues/2146)
|
||||||
- Incorrect CMake FetchContent example [\#2142](https://github.com/nlohmann/json/issues/2142)
|
- Incorrect CMake FetchContent example [\#2142](https://github.com/nlohmann/json/issues/2142)
|
||||||
|
@ -64,7 +179,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Can't ad an object in another objet [\#2101](https://github.com/nlohmann/json/issues/2101)
|
- Can't ad an object in another objet [\#2101](https://github.com/nlohmann/json/issues/2101)
|
||||||
- Implicit conversion causes "cannot use operator\[\] with a string argument with string" [\#2098](https://github.com/nlohmann/json/issues/2098)
|
- Implicit conversion causes "cannot use operator\[\] with a string argument with string" [\#2098](https://github.com/nlohmann/json/issues/2098)
|
||||||
- C++20: char8\_t [\#2097](https://github.com/nlohmann/json/issues/2097)
|
- C++20: char8\_t [\#2097](https://github.com/nlohmann/json/issues/2097)
|
||||||
- UTF8 [\#2095](https://github.com/nlohmann/json/issues/2095)
|
|
||||||
- Compilation issues when included in project [\#2094](https://github.com/nlohmann/json/issues/2094)
|
- Compilation issues when included in project [\#2094](https://github.com/nlohmann/json/issues/2094)
|
||||||
- string value with null character causes infinite loop [\#2093](https://github.com/nlohmann/json/issues/2093)
|
- string value with null character causes infinite loop [\#2093](https://github.com/nlohmann/json/issues/2093)
|
||||||
- corrupted size vs. prev\_size \(aborted\) [\#2092](https://github.com/nlohmann/json/issues/2092)
|
- corrupted size vs. prev\_size \(aborted\) [\#2092](https://github.com/nlohmann/json/issues/2092)
|
||||||
|
@ -91,7 +205,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Bug: returning reference to local temporary object [\#2064](https://github.com/nlohmann/json/issues/2064)
|
- Bug: returning reference to local temporary object [\#2064](https://github.com/nlohmann/json/issues/2064)
|
||||||
- Allow to use non strict parsing [\#2063](https://github.com/nlohmann/json/issues/2063)
|
- Allow to use non strict parsing [\#2063](https://github.com/nlohmann/json/issues/2063)
|
||||||
- Crashing on json::at [\#2062](https://github.com/nlohmann/json/issues/2062)
|
- Crashing on json::at [\#2062](https://github.com/nlohmann/json/issues/2062)
|
||||||
- Add support for JSONC [\#2061](https://github.com/nlohmann/json/issues/2061)
|
|
||||||
- How to convert a const std::vector\<char8\_t\> message to a json, to be able to parse it and extract information from it? Can you point to any examples? [\#2058](https://github.com/nlohmann/json/issues/2058)
|
- How to convert a const std::vector\<char8\_t\> message to a json, to be able to parse it and extract information from it? Can you point to any examples? [\#2058](https://github.com/nlohmann/json/issues/2058)
|
||||||
- Nice library [\#2057](https://github.com/nlohmann/json/issues/2057)
|
- Nice library [\#2057](https://github.com/nlohmann/json/issues/2057)
|
||||||
- json.hpp:15372:22: error: expected unqualified-id if \(not std::isfinite\(x\)\): Started getting this bug after updating my XCode [\#2056](https://github.com/nlohmann/json/issues/2056)
|
- json.hpp:15372:22: error: expected unqualified-id if \(not std::isfinite\(x\)\): Started getting this bug after updating my XCode [\#2056](https://github.com/nlohmann/json/issues/2056)
|
||||||
|
@ -197,7 +310,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- typo in a comment [\#1903](https://github.com/nlohmann/json/issues/1903)
|
- typo in a comment [\#1903](https://github.com/nlohmann/json/issues/1903)
|
||||||
- Watch JSON variables in Debug [\#1902](https://github.com/nlohmann/json/issues/1902)
|
- Watch JSON variables in Debug [\#1902](https://github.com/nlohmann/json/issues/1902)
|
||||||
- does Json sdk cares about dfc dfd utf8 issue? [\#1901](https://github.com/nlohmann/json/issues/1901)
|
- does Json sdk cares about dfc dfd utf8 issue? [\#1901](https://github.com/nlohmann/json/issues/1901)
|
||||||
- Compilation failure using Clang on Windows [\#1898](https://github.com/nlohmann/json/issues/1898)
|
|
||||||
- Allow multiple line string value in JSON [\#1897](https://github.com/nlohmann/json/issues/1897)
|
- Allow multiple line string value in JSON [\#1897](https://github.com/nlohmann/json/issues/1897)
|
||||||
- Writing map to json file [\#1896](https://github.com/nlohmann/json/issues/1896)
|
- Writing map to json file [\#1896](https://github.com/nlohmann/json/issues/1896)
|
||||||
- Small documentation mistake [\#1895](https://github.com/nlohmann/json/issues/1895)
|
- Small documentation mistake [\#1895](https://github.com/nlohmann/json/issues/1895)
|
||||||
|
@ -253,7 +365,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Serialize big data in json [\#1828](https://github.com/nlohmann/json/issues/1828)
|
- Serialize big data in json [\#1828](https://github.com/nlohmann/json/issues/1828)
|
||||||
- Backslash '\' in value causes exception [\#1827](https://github.com/nlohmann/json/issues/1827)
|
- Backslash '\' in value causes exception [\#1827](https://github.com/nlohmann/json/issues/1827)
|
||||||
- from\_json for non default constructible class with dependency injection [\#1819](https://github.com/nlohmann/json/issues/1819)
|
- from\_json for non default constructible class with dependency injection [\#1819](https://github.com/nlohmann/json/issues/1819)
|
||||||
- Fail to build when including json.hpp as a system include [\#1818](https://github.com/nlohmann/json/issues/1818)
|
|
||||||
- Semi-frequent timeouts in `test-unicode\_all` with 3.6.1 \(aarch64\) [\#1816](https://github.com/nlohmann/json/issues/1816)
|
- Semi-frequent timeouts in `test-unicode\_all` with 3.6.1 \(aarch64\) [\#1816](https://github.com/nlohmann/json/issues/1816)
|
||||||
- input\_adapter not user extensible [\#1813](https://github.com/nlohmann/json/issues/1813)
|
- input\_adapter not user extensible [\#1813](https://github.com/nlohmann/json/issues/1813)
|
||||||
- crash at json::destroy on android [\#1812](https://github.com/nlohmann/json/issues/1812)
|
- crash at json::destroy on android [\#1812](https://github.com/nlohmann/json/issues/1812)
|
||||||
|
@ -322,7 +433,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Fix issue\#1719 [\#2044](https://github.com/nlohmann/json/pull/2044) ([dota17](https://github.com/dota17))
|
- Fix issue\#1719 [\#2044](https://github.com/nlohmann/json/pull/2044) ([dota17](https://github.com/dota17))
|
||||||
- Add missing testcase about NaN in unit-constructor1.cpp [\#2043](https://github.com/nlohmann/json/pull/2043) ([dota17](https://github.com/dota17))
|
- Add missing testcase about NaN in unit-constructor1.cpp [\#2043](https://github.com/nlohmann/json/pull/2043) ([dota17](https://github.com/dota17))
|
||||||
- Templatize basic\_json constructor from json\_ref [\#2034](https://github.com/nlohmann/json/pull/2034) ([ArtemSarmini](https://github.com/ArtemSarmini))
|
- Templatize basic\_json constructor from json\_ref [\#2034](https://github.com/nlohmann/json/pull/2034) ([ArtemSarmini](https://github.com/ArtemSarmini))
|
||||||
- Replace deprecated std::is\_pod [\#2033](https://github.com/nlohmann/json/pull/2033) ([nlohmann](https://github.com/nlohmann))
|
|
||||||
- fix \#1982:json\_pointer.contains\(\) exception is incorrectly raised [\#2019](https://github.com/nlohmann/json/pull/2019) ([dota17](https://github.com/dota17))
|
- fix \#1982:json\_pointer.contains\(\) exception is incorrectly raised [\#2019](https://github.com/nlohmann/json/pull/2019) ([dota17](https://github.com/dota17))
|
||||||
- catch exceptions for json\_pointer : ..../+99 [\#1990](https://github.com/nlohmann/json/pull/1990) ([dota17](https://github.com/dota17))
|
- catch exceptions for json\_pointer : ..../+99 [\#1990](https://github.com/nlohmann/json/pull/1990) ([dota17](https://github.com/dota17))
|
||||||
- fix warnings in serializer.hpp for VS2019 [\#1969](https://github.com/nlohmann/json/pull/1969) ([dota17](https://github.com/dota17))
|
- fix warnings in serializer.hpp for VS2019 [\#1969](https://github.com/nlohmann/json/pull/1969) ([dota17](https://github.com/dota17))
|
||||||
|
@ -369,7 +479,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- json class should have a get\_or member function [\#1823](https://github.com/nlohmann/json/issues/1823)
|
- json class should have a get\_or member function [\#1823](https://github.com/nlohmann/json/issues/1823)
|
||||||
- NLOHMANN\_JSON\_SERIALIZE\_ENUM macro capture's json objects by value [\#1822](https://github.com/nlohmann/json/issues/1822)
|
- NLOHMANN\_JSON\_SERIALIZE\_ENUM macro capture's json objects by value [\#1822](https://github.com/nlohmann/json/issues/1822)
|
||||||
- Parse fails when number literals start with zero [\#1820](https://github.com/nlohmann/json/issues/1820)
|
- Parse fails when number literals start with zero [\#1820](https://github.com/nlohmann/json/issues/1820)
|
||||||
- Parsing string into json doesn't preserve the order correctly. [\#1817](https://github.com/nlohmann/json/issues/1817)
|
|
||||||
- Weird behaviour of `contains` with `json\_pointer` [\#1815](https://github.com/nlohmann/json/issues/1815)
|
- Weird behaviour of `contains` with `json\_pointer` [\#1815](https://github.com/nlohmann/json/issues/1815)
|
||||||
- strange behaviour with json\_pointer and .contains\(\) [\#1811](https://github.com/nlohmann/json/issues/1811)
|
- strange behaviour with json\_pointer and .contains\(\) [\#1811](https://github.com/nlohmann/json/issues/1811)
|
||||||
- Can \#1695 be re-opened? [\#1808](https://github.com/nlohmann/json/issues/1808)
|
- Can \#1695 be re-opened? [\#1808](https://github.com/nlohmann/json/issues/1808)
|
||||||
|
@ -426,7 +535,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- CMake not correctly finding the configuration package for 3.7.0 [\#1721](https://github.com/nlohmann/json/issues/1721)
|
- CMake not correctly finding the configuration package for 3.7.0 [\#1721](https://github.com/nlohmann/json/issues/1721)
|
||||||
- name typo in the "spack package management" section of README.md [\#1720](https://github.com/nlohmann/json/issues/1720)
|
- name typo in the "spack package management" section of README.md [\#1720](https://github.com/nlohmann/json/issues/1720)
|
||||||
- How to add json to another json? [\#1718](https://github.com/nlohmann/json/issues/1718)
|
- How to add json to another json? [\#1718](https://github.com/nlohmann/json/issues/1718)
|
||||||
- How can I save json object in file in order? [\#1717](https://github.com/nlohmann/json/issues/1717)
|
|
||||||
- json::parse\(\) ubsan regression with v3.7.0 [\#1716](https://github.com/nlohmann/json/issues/1716)
|
- json::parse\(\) ubsan regression with v3.7.0 [\#1716](https://github.com/nlohmann/json/issues/1716)
|
||||||
- What I am doing wrong?!? [\#1714](https://github.com/nlohmann/json/issues/1714)
|
- What I am doing wrong?!? [\#1714](https://github.com/nlohmann/json/issues/1714)
|
||||||
- Potential memory leak detected by Valgrind [\#1713](https://github.com/nlohmann/json/issues/1713)
|
- Potential memory leak detected by Valgrind [\#1713](https://github.com/nlohmann/json/issues/1713)
|
||||||
|
@ -633,8 +741,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Added to\_string and added basic tests [\#1585](https://github.com/nlohmann/json/pull/1585) ([Macr0Nerd](https://github.com/Macr0Nerd))
|
- Added to\_string and added basic tests [\#1585](https://github.com/nlohmann/json/pull/1585) ([Macr0Nerd](https://github.com/Macr0Nerd))
|
||||||
- Regression tests for MSVC [\#1570](https://github.com/nlohmann/json/pull/1570) ([nickaein](https://github.com/nickaein))
|
- Regression tests for MSVC [\#1570](https://github.com/nlohmann/json/pull/1570) ([nickaein](https://github.com/nickaein))
|
||||||
- Fix/1511 [\#1555](https://github.com/nlohmann/json/pull/1555) ([theodelrieu](https://github.com/theodelrieu))
|
- Fix/1511 [\#1555](https://github.com/nlohmann/json/pull/1555) ([theodelrieu](https://github.com/theodelrieu))
|
||||||
- Remove C++17 extension warning from clang; \#1535 [\#1551](https://github.com/nlohmann/json/pull/1551) ([heavywatal](https://github.com/heavywatal))
|
|
||||||
- moved from Catch to doctest for unit tests [\#1439](https://github.com/nlohmann/json/pull/1439) ([onqtam](https://github.com/onqtam))
|
|
||||||
|
|
||||||
## [v3.6.1](https://github.com/nlohmann/json/releases/tag/v3.6.1) (2019-03-20)
|
## [v3.6.1](https://github.com/nlohmann/json/releases/tag/v3.6.1) (2019-03-20)
|
||||||
|
|
||||||
|
@ -658,7 +764,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- how to precision to four decimal for double when use to\_json [\#1519](https://github.com/nlohmann/json/issues/1519)
|
- how to precision to four decimal for double when use to\_json [\#1519](https://github.com/nlohmann/json/issues/1519)
|
||||||
- error parse [\#1518](https://github.com/nlohmann/json/issues/1518)
|
- error parse [\#1518](https://github.com/nlohmann/json/issues/1518)
|
||||||
- Compile error: template argument deduction/substitution failed [\#1515](https://github.com/nlohmann/json/issues/1515)
|
- Compile error: template argument deduction/substitution failed [\#1515](https://github.com/nlohmann/json/issues/1515)
|
||||||
- Support for Comments [\#1513](https://github.com/nlohmann/json/issues/1513)
|
|
||||||
- std::complex type [\#1510](https://github.com/nlohmann/json/issues/1510)
|
- std::complex type [\#1510](https://github.com/nlohmann/json/issues/1510)
|
||||||
- CBOR byte string support [\#1509](https://github.com/nlohmann/json/issues/1509)
|
- CBOR byte string support [\#1509](https://github.com/nlohmann/json/issues/1509)
|
||||||
- Compilation error getting a std::pair\<\> on latest VS 2017 compiler [\#1506](https://github.com/nlohmann/json/issues/1506)
|
- Compilation error getting a std::pair\<\> on latest VS 2017 compiler [\#1506](https://github.com/nlohmann/json/issues/1506)
|
||||||
|
@ -738,6 +843,7 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Implicit type conversion error on MSVC [\#1333](https://github.com/nlohmann/json/issues/1333)
|
- Implicit type conversion error on MSVC [\#1333](https://github.com/nlohmann/json/issues/1333)
|
||||||
- NuGet Package [\#1132](https://github.com/nlohmann/json/issues/1132)
|
- NuGet Package [\#1132](https://github.com/nlohmann/json/issues/1132)
|
||||||
|
|
||||||
|
- Remove C++17 extension warning from clang; \#1535 [\#1551](https://github.com/nlohmann/json/pull/1551) ([heavywatal](https://github.com/heavywatal))
|
||||||
- Change macros to numeric\_limits [\#1514](https://github.com/nlohmann/json/pull/1514) ([naszta](https://github.com/naszta))
|
- Change macros to numeric\_limits [\#1514](https://github.com/nlohmann/json/pull/1514) ([naszta](https://github.com/naszta))
|
||||||
- fix GCC 7.1.1 - 7.2.1 on CentOS [\#1496](https://github.com/nlohmann/json/pull/1496) ([lieff](https://github.com/lieff))
|
- fix GCC 7.1.1 - 7.2.1 on CentOS [\#1496](https://github.com/nlohmann/json/pull/1496) ([lieff](https://github.com/lieff))
|
||||||
- Update Buckaroo instructions in README.md [\#1495](https://github.com/nlohmann/json/pull/1495) ([njlr](https://github.com/njlr))
|
- Update Buckaroo instructions in README.md [\#1495](https://github.com/nlohmann/json/pull/1495) ([njlr](https://github.com/njlr))
|
||||||
|
@ -753,6 +859,7 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- remove extra semicolon from readme [\#1451](https://github.com/nlohmann/json/pull/1451) ([Afforix](https://github.com/Afforix))
|
- remove extra semicolon from readme [\#1451](https://github.com/nlohmann/json/pull/1451) ([Afforix](https://github.com/Afforix))
|
||||||
- attempt to fix \#1445, flush buffer in serializer::dump\_escaped in UTF8\_REJECT case. [\#1446](https://github.com/nlohmann/json/pull/1446) ([scinart](https://github.com/scinart))
|
- attempt to fix \#1445, flush buffer in serializer::dump\_escaped in UTF8\_REJECT case. [\#1446](https://github.com/nlohmann/json/pull/1446) ([scinart](https://github.com/scinart))
|
||||||
- Use C++11 features supported by CMake 3.1. [\#1441](https://github.com/nlohmann/json/pull/1441) ([iwanders](https://github.com/iwanders))
|
- Use C++11 features supported by CMake 3.1. [\#1441](https://github.com/nlohmann/json/pull/1441) ([iwanders](https://github.com/iwanders))
|
||||||
|
- moved from Catch to doctest for unit tests [\#1439](https://github.com/nlohmann/json/pull/1439) ([onqtam](https://github.com/onqtam))
|
||||||
- :rotating\_light: fixed unused variable warning [\#1435](https://github.com/nlohmann/json/pull/1435) ([pboettch](https://github.com/pboettch))
|
- :rotating\_light: fixed unused variable warning [\#1435](https://github.com/nlohmann/json/pull/1435) ([pboettch](https://github.com/pboettch))
|
||||||
- allow push\_back\(\) and pop\_back\(\) calls on json\_pointer [\#1434](https://github.com/nlohmann/json/pull/1434) ([pboettch](https://github.com/pboettch))
|
- allow push\_back\(\) and pop\_back\(\) calls on json\_pointer [\#1434](https://github.com/nlohmann/json/pull/1434) ([pboettch](https://github.com/pboettch))
|
||||||
- Add instructions about using nlohmann/json with the conda package manager [\#1430](https://github.com/nlohmann/json/pull/1430) ([nicoddemus](https://github.com/nicoddemus))
|
- Add instructions about using nlohmann/json with the conda package manager [\#1430](https://github.com/nlohmann/json/pull/1430) ([nicoddemus](https://github.com/nicoddemus))
|
||||||
|
@ -824,7 +931,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Comparisons between large unsigned and negative signed integers [\#1295](https://github.com/nlohmann/json/issues/1295)
|
- Comparisons between large unsigned and negative signed integers [\#1295](https://github.com/nlohmann/json/issues/1295)
|
||||||
- CMake alias to `nlohmann::json` [\#1291](https://github.com/nlohmann/json/issues/1291)
|
- CMake alias to `nlohmann::json` [\#1291](https://github.com/nlohmann/json/issues/1291)
|
||||||
- Release zips without tests [\#1285](https://github.com/nlohmann/json/issues/1285)
|
- Release zips without tests [\#1285](https://github.com/nlohmann/json/issues/1285)
|
||||||
- Suggestion to improve value\(\) accessors with respect to move semantics [\#1275](https://github.com/nlohmann/json/issues/1275)
|
|
||||||
- separate object\_t::key\_type from basic\_json::key\_type, and use an allocator which returns object\_t::key\_type [\#1274](https://github.com/nlohmann/json/issues/1274)
|
- separate object\_t::key\_type from basic\_json::key\_type, and use an allocator which returns object\_t::key\_type [\#1274](https://github.com/nlohmann/json/issues/1274)
|
||||||
- Is there a nice way to associate external values with json elements? [\#1256](https://github.com/nlohmann/json/issues/1256)
|
- Is there a nice way to associate external values with json elements? [\#1256](https://github.com/nlohmann/json/issues/1256)
|
||||||
- Delete by json\_pointer [\#1248](https://github.com/nlohmann/json/issues/1248)
|
- Delete by json\_pointer [\#1248](https://github.com/nlohmann/json/issues/1248)
|
||||||
|
@ -1023,7 +1129,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- can't not parse "\\“ string [\#1123](https://github.com/nlohmann/json/issues/1123)
|
- can't not parse "\\“ string [\#1123](https://github.com/nlohmann/json/issues/1123)
|
||||||
- if json file contain Internationalization chars , get exception [\#1122](https://github.com/nlohmann/json/issues/1122)
|
- if json file contain Internationalization chars , get exception [\#1122](https://github.com/nlohmann/json/issues/1122)
|
||||||
- How to use a json::iterator dereferenced value in code? [\#1120](https://github.com/nlohmann/json/issues/1120)
|
- How to use a json::iterator dereferenced value in code? [\#1120](https://github.com/nlohmann/json/issues/1120)
|
||||||
- clang compiler: error : unknown type name 'not' [\#1119](https://github.com/nlohmann/json/issues/1119)
|
|
||||||
- Disable implicit conversions from json to std::initializer\_list\<T\> for any T [\#1118](https://github.com/nlohmann/json/issues/1118)
|
- Disable implicit conversions from json to std::initializer\_list\<T\> for any T [\#1118](https://github.com/nlohmann/json/issues/1118)
|
||||||
- Implicit conversions to complex types can lead to surprising and confusing errors [\#1116](https://github.com/nlohmann/json/issues/1116)
|
- Implicit conversions to complex types can lead to surprising and confusing errors [\#1116](https://github.com/nlohmann/json/issues/1116)
|
||||||
- How can I write from\_json for a complex datatype that is not default constructible? [\#1115](https://github.com/nlohmann/json/issues/1115)
|
- How can I write from\_json for a complex datatype that is not default constructible? [\#1115](https://github.com/nlohmann/json/issues/1115)
|
||||||
|
@ -1035,7 +1140,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- JSON representation for floating point values has too many digits [\#1109](https://github.com/nlohmann/json/issues/1109)
|
- JSON representation for floating point values has too many digits [\#1109](https://github.com/nlohmann/json/issues/1109)
|
||||||
- Not working for classes containing "\_declspec\(dllimport\)" in their declaration [\#1108](https://github.com/nlohmann/json/issues/1108)
|
- Not working for classes containing "\_declspec\(dllimport\)" in their declaration [\#1108](https://github.com/nlohmann/json/issues/1108)
|
||||||
- Get keys from json object [\#1107](https://github.com/nlohmann/json/issues/1107)
|
- Get keys from json object [\#1107](https://github.com/nlohmann/json/issues/1107)
|
||||||
- dump\(\) without alphabetical order [\#1106](https://github.com/nlohmann/json/issues/1106)
|
|
||||||
- Cannot deserialize types using std::ratio [\#1105](https://github.com/nlohmann/json/issues/1105)
|
- Cannot deserialize types using std::ratio [\#1105](https://github.com/nlohmann/json/issues/1105)
|
||||||
- i want to learn json [\#1104](https://github.com/nlohmann/json/issues/1104)
|
- i want to learn json [\#1104](https://github.com/nlohmann/json/issues/1104)
|
||||||
- Type checking during compile [\#1103](https://github.com/nlohmann/json/issues/1103)
|
- Type checking during compile [\#1103](https://github.com/nlohmann/json/issues/1103)
|
||||||
|
@ -1182,6 +1286,7 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
|
|
||||||
- Allowing for user-defined string type in lexer/parser [\#1009](https://github.com/nlohmann/json/pull/1009) ([nlohmann](https://github.com/nlohmann))
|
- Allowing for user-defined string type in lexer/parser [\#1009](https://github.com/nlohmann/json/pull/1009) ([nlohmann](https://github.com/nlohmann))
|
||||||
- dump to alternative string type, as defined in basic\_json template [\#1006](https://github.com/nlohmann/json/pull/1006) ([agrianius](https://github.com/agrianius))
|
- dump to alternative string type, as defined in basic\_json template [\#1006](https://github.com/nlohmann/json/pull/1006) ([agrianius](https://github.com/agrianius))
|
||||||
|
- Fix memory leak during parser callback [\#1001](https://github.com/nlohmann/json/pull/1001) ([nlohmann](https://github.com/nlohmann))
|
||||||
- fixed misprinted condition detected by PVS Studio. [\#992](https://github.com/nlohmann/json/pull/992) ([bogemic](https://github.com/bogemic))
|
- fixed misprinted condition detected by PVS Studio. [\#992](https://github.com/nlohmann/json/pull/992) ([bogemic](https://github.com/bogemic))
|
||||||
- Fix/basic json conversion [\#986](https://github.com/nlohmann/json/pull/986) ([theodelrieu](https://github.com/theodelrieu))
|
- Fix/basic json conversion [\#986](https://github.com/nlohmann/json/pull/986) ([theodelrieu](https://github.com/theodelrieu))
|
||||||
- Make integration section concise [\#981](https://github.com/nlohmann/json/pull/981) ([wla80](https://github.com/wla80))
|
- Make integration section concise [\#981](https://github.com/nlohmann/json/pull/981) ([wla80](https://github.com/wla80))
|
||||||
|
@ -1205,7 +1310,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- \[Request\] Macro generating from\_json\(\) and to\_json\(\) [\#895](https://github.com/nlohmann/json/issues/895)
|
- \[Request\] Macro generating from\_json\(\) and to\_json\(\) [\#895](https://github.com/nlohmann/json/issues/895)
|
||||||
- basic\_json::value throws exception instead of returning default value [\#871](https://github.com/nlohmann/json/issues/871)
|
- basic\_json::value throws exception instead of returning default value [\#871](https://github.com/nlohmann/json/issues/871)
|
||||||
|
|
||||||
- Fix memory leak during parser callback [\#1001](https://github.com/nlohmann/json/pull/1001) ([nlohmann](https://github.com/nlohmann))
|
|
||||||
- Fix constraints on from\_json\(CompatibleArrayType\) [\#969](https://github.com/nlohmann/json/pull/969) ([theodelrieu](https://github.com/theodelrieu))
|
- Fix constraints on from\_json\(CompatibleArrayType\) [\#969](https://github.com/nlohmann/json/pull/969) ([theodelrieu](https://github.com/theodelrieu))
|
||||||
- Make coveralls watch the include folder [\#957](https://github.com/nlohmann/json/pull/957) ([theodelrieu](https://github.com/theodelrieu))
|
- Make coveralls watch the include folder [\#957](https://github.com/nlohmann/json/pull/957) ([theodelrieu](https://github.com/theodelrieu))
|
||||||
- Fix links in README.md [\#955](https://github.com/nlohmann/json/pull/955) ([patrikhuber](https://github.com/patrikhuber))
|
- Fix links in README.md [\#955](https://github.com/nlohmann/json/pull/955) ([patrikhuber](https://github.com/patrikhuber))
|
||||||
|
@ -1219,7 +1323,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
|
|
||||||
[Full Changelog](https://github.com/nlohmann/json/compare/v3.0.1...3.1.0)
|
[Full Changelog](https://github.com/nlohmann/json/compare/v3.0.1...3.1.0)
|
||||||
|
|
||||||
- Order of the elements in JSON object [\#952](https://github.com/nlohmann/json/issues/952)
|
|
||||||
- I have a proposal [\#949](https://github.com/nlohmann/json/issues/949)
|
- I have a proposal [\#949](https://github.com/nlohmann/json/issues/949)
|
||||||
- VERSION define\(s\) [\#948](https://github.com/nlohmann/json/issues/948)
|
- VERSION define\(s\) [\#948](https://github.com/nlohmann/json/issues/948)
|
||||||
- v3.0.1 compile error in icc 16.0.4 [\#947](https://github.com/nlohmann/json/issues/947)
|
- v3.0.1 compile error in icc 16.0.4 [\#947](https://github.com/nlohmann/json/issues/947)
|
||||||
|
@ -1421,7 +1524,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Project's name is too generic and hard to search for [\#730](https://github.com/nlohmann/json/issues/730)
|
- Project's name is too generic and hard to search for [\#730](https://github.com/nlohmann/json/issues/730)
|
||||||
- Visual Studio 2015 IntelliTrace problems [\#729](https://github.com/nlohmann/json/issues/729)
|
- Visual Studio 2015 IntelliTrace problems [\#729](https://github.com/nlohmann/json/issues/729)
|
||||||
- How to erase nested objects inside other objects? [\#728](https://github.com/nlohmann/json/issues/728)
|
- How to erase nested objects inside other objects? [\#728](https://github.com/nlohmann/json/issues/728)
|
||||||
- How to prevent alphabetical sorting of data? [\#727](https://github.com/nlohmann/json/issues/727)
|
|
||||||
- Serialization for CBOR [\#726](https://github.com/nlohmann/json/issues/726)
|
- Serialization for CBOR [\#726](https://github.com/nlohmann/json/issues/726)
|
||||||
- Using json Object as value in a map [\#725](https://github.com/nlohmann/json/issues/725)
|
- Using json Object as value in a map [\#725](https://github.com/nlohmann/json/issues/725)
|
||||||
- std::regex and nlohmann::json value [\#724](https://github.com/nlohmann/json/issues/724)
|
- std::regex and nlohmann::json value [\#724](https://github.com/nlohmann/json/issues/724)
|
||||||
|
@ -1469,7 +1571,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- could this json lib work on windows? [\#664](https://github.com/nlohmann/json/issues/664)
|
- could this json lib work on windows? [\#664](https://github.com/nlohmann/json/issues/664)
|
||||||
- How does from\_json work? [\#662](https://github.com/nlohmann/json/issues/662)
|
- How does from\_json work? [\#662](https://github.com/nlohmann/json/issues/662)
|
||||||
- insert\(or merge\) object should replace same key , not ignore [\#661](https://github.com/nlohmann/json/issues/661)
|
- insert\(or merge\) object should replace same key , not ignore [\#661](https://github.com/nlohmann/json/issues/661)
|
||||||
- Why is an object ordering values by Alphabetical Order? [\#660](https://github.com/nlohmann/json/issues/660)
|
|
||||||
- Parse method doesn't handle newlines. [\#659](https://github.com/nlohmann/json/issues/659)
|
- Parse method doesn't handle newlines. [\#659](https://github.com/nlohmann/json/issues/659)
|
||||||
- Compilation "note" on GCC 6 ARM [\#658](https://github.com/nlohmann/json/issues/658)
|
- Compilation "note" on GCC 6 ARM [\#658](https://github.com/nlohmann/json/issues/658)
|
||||||
- Adding additional push\_back/operator+= rvalue overloads for JSON object [\#657](https://github.com/nlohmann/json/issues/657)
|
- Adding additional push\_back/operator+= rvalue overloads for JSON object [\#657](https://github.com/nlohmann/json/issues/657)
|
||||||
|
@ -1519,7 +1620,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Use of the binary type in CBOR and Message Pack [\#601](https://github.com/nlohmann/json/issues/601)
|
- Use of the binary type in CBOR and Message Pack [\#601](https://github.com/nlohmann/json/issues/601)
|
||||||
- Newbie issue: how does one convert a map in Json back to std::map? [\#600](https://github.com/nlohmann/json/issues/600)
|
- Newbie issue: how does one convert a map in Json back to std::map? [\#600](https://github.com/nlohmann/json/issues/600)
|
||||||
- Plugin system [\#599](https://github.com/nlohmann/json/issues/599)
|
- Plugin system [\#599](https://github.com/nlohmann/json/issues/599)
|
||||||
- Feature request: Comments [\#597](https://github.com/nlohmann/json/issues/597)
|
|
||||||
- Using custom types for scalars? [\#596](https://github.com/nlohmann/json/issues/596)
|
- Using custom types for scalars? [\#596](https://github.com/nlohmann/json/issues/596)
|
||||||
- Issues with the arithmetic in iterator and reverse iterator [\#593](https://github.com/nlohmann/json/issues/593)
|
- Issues with the arithmetic in iterator and reverse iterator [\#593](https://github.com/nlohmann/json/issues/593)
|
||||||
- not enough examples [\#592](https://github.com/nlohmann/json/issues/592)
|
- not enough examples [\#592](https://github.com/nlohmann/json/issues/592)
|
||||||
|
@ -1561,7 +1661,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Ambiguous compare operators with clang-5.0 [\#547](https://github.com/nlohmann/json/issues/547)
|
- Ambiguous compare operators with clang-5.0 [\#547](https://github.com/nlohmann/json/issues/547)
|
||||||
- Using tsl::ordered\_map [\#546](https://github.com/nlohmann/json/issues/546)
|
- Using tsl::ordered\_map [\#546](https://github.com/nlohmann/json/issues/546)
|
||||||
- Compiler support errors are inconvenient [\#544](https://github.com/nlohmann/json/issues/544)
|
- Compiler support errors are inconvenient [\#544](https://github.com/nlohmann/json/issues/544)
|
||||||
- Head Elements Sorting [\#543](https://github.com/nlohmann/json/issues/543)
|
|
||||||
- Duplicate symbols error happens while to\_json/from\_json method implemented inside entity definition header file [\#542](https://github.com/nlohmann/json/issues/542)
|
- Duplicate symbols error happens while to\_json/from\_json method implemented inside entity definition header file [\#542](https://github.com/nlohmann/json/issues/542)
|
||||||
- consider adding a bool json::is\_valid\(std::string const&\) non-member function [\#541](https://github.com/nlohmann/json/issues/541)
|
- consider adding a bool json::is\_valid\(std::string const&\) non-member function [\#541](https://github.com/nlohmann/json/issues/541)
|
||||||
- Help request [\#539](https://github.com/nlohmann/json/issues/539)
|
- Help request [\#539](https://github.com/nlohmann/json/issues/539)
|
||||||
|
@ -1730,7 +1829,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Getting std::invalid\_argument: stream error when following example [\#429](https://github.com/nlohmann/json/issues/429)
|
- Getting std::invalid\_argument: stream error when following example [\#429](https://github.com/nlohmann/json/issues/429)
|
||||||
- Forward declare-only header? [\#427](https://github.com/nlohmann/json/issues/427)
|
- Forward declare-only header? [\#427](https://github.com/nlohmann/json/issues/427)
|
||||||
- Implicit conversion from array to object [\#425](https://github.com/nlohmann/json/issues/425)
|
- Implicit conversion from array to object [\#425](https://github.com/nlohmann/json/issues/425)
|
||||||
- Automatic ordered JSON [\#424](https://github.com/nlohmann/json/issues/424)
|
|
||||||
- error C4996: 'strerror' when reading file [\#422](https://github.com/nlohmann/json/issues/422)
|
- error C4996: 'strerror' when reading file [\#422](https://github.com/nlohmann/json/issues/422)
|
||||||
- Get an error - JSON pointer must be empty or begin with '/' [\#421](https://github.com/nlohmann/json/issues/421)
|
- Get an error - JSON pointer must be empty or begin with '/' [\#421](https://github.com/nlohmann/json/issues/421)
|
||||||
- size parameter for parse\(\) [\#419](https://github.com/nlohmann/json/issues/419)
|
- size parameter for parse\(\) [\#419](https://github.com/nlohmann/json/issues/419)
|
||||||
|
@ -1739,7 +1837,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- comparing to 0 literal [\#414](https://github.com/nlohmann/json/issues/414)
|
- comparing to 0 literal [\#414](https://github.com/nlohmann/json/issues/414)
|
||||||
- Single char converted to ASCII code instead of string [\#413](https://github.com/nlohmann/json/issues/413)
|
- Single char converted to ASCII code instead of string [\#413](https://github.com/nlohmann/json/issues/413)
|
||||||
- How to know if a string was parsed as utf-8? [\#406](https://github.com/nlohmann/json/issues/406)
|
- How to know if a string was parsed as utf-8? [\#406](https://github.com/nlohmann/json/issues/406)
|
||||||
- Heap-buffer-overflow \(OSS-Fuzz issue 342\) [\#405](https://github.com/nlohmann/json/issues/405)
|
|
||||||
- Overloaded += to add objects to an array makes no sense? [\#404](https://github.com/nlohmann/json/issues/404)
|
- Overloaded += to add objects to an array makes no sense? [\#404](https://github.com/nlohmann/json/issues/404)
|
||||||
- Finding a value in an array [\#399](https://github.com/nlohmann/json/issues/399)
|
- Finding a value in an array [\#399](https://github.com/nlohmann/json/issues/399)
|
||||||
- add release information in static function [\#397](https://github.com/nlohmann/json/issues/397)
|
- add release information in static function [\#397](https://github.com/nlohmann/json/issues/397)
|
||||||
|
@ -1769,6 +1866,7 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Use-of-uninitialized-value \(OSS-Fuzz issue 347\) [\#409](https://github.com/nlohmann/json/issues/409)
|
- Use-of-uninitialized-value \(OSS-Fuzz issue 347\) [\#409](https://github.com/nlohmann/json/issues/409)
|
||||||
- Heap-buffer-overflow \(OSS-Fuzz issue 344\) [\#408](https://github.com/nlohmann/json/issues/408)
|
- Heap-buffer-overflow \(OSS-Fuzz issue 344\) [\#408](https://github.com/nlohmann/json/issues/408)
|
||||||
- Heap-buffer-overflow \(OSS-Fuzz issue 343\) [\#407](https://github.com/nlohmann/json/issues/407)
|
- Heap-buffer-overflow \(OSS-Fuzz issue 343\) [\#407](https://github.com/nlohmann/json/issues/407)
|
||||||
|
- Heap-buffer-overflow \(OSS-Fuzz issue 342\) [\#405](https://github.com/nlohmann/json/issues/405)
|
||||||
- strerror throwing error in compiler VS2015 [\#403](https://github.com/nlohmann/json/issues/403)
|
- strerror throwing error in compiler VS2015 [\#403](https://github.com/nlohmann/json/issues/403)
|
||||||
- json::parse of std::string being underlined by Visual Studio [\#402](https://github.com/nlohmann/json/issues/402)
|
- json::parse of std::string being underlined by Visual Studio [\#402](https://github.com/nlohmann/json/issues/402)
|
||||||
- Explicitly getting string without .dump\(\) [\#401](https://github.com/nlohmann/json/issues/401)
|
- Explicitly getting string without .dump\(\) [\#401](https://github.com/nlohmann/json/issues/401)
|
||||||
|
@ -1800,7 +1898,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381)
|
- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381)
|
||||||
- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380)
|
- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380)
|
||||||
- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377)
|
- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377)
|
||||||
- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376)
|
|
||||||
- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375)
|
- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375)
|
||||||
- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358)
|
- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358)
|
||||||
|
|
||||||
|
@ -1824,7 +1921,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366)
|
- json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366)
|
||||||
- Performance improvements [\#365](https://github.com/nlohmann/json/issues/365)
|
- Performance improvements [\#365](https://github.com/nlohmann/json/issues/365)
|
||||||
- 'to\_string' is not a member of 'std' [\#364](https://github.com/nlohmann/json/issues/364)
|
- 'to\_string' is not a member of 'std' [\#364](https://github.com/nlohmann/json/issues/364)
|
||||||
- Optional comment support. [\#363](https://github.com/nlohmann/json/issues/363)
|
|
||||||
- Crash in dump\(\) from a static object [\#359](https://github.com/nlohmann/json/issues/359)
|
- Crash in dump\(\) from a static object [\#359](https://github.com/nlohmann/json/issues/359)
|
||||||
- json::parse\(...\) vs json j; j.parse\(...\) [\#357](https://github.com/nlohmann/json/issues/357)
|
- json::parse\(...\) vs json j; j.parse\(...\) [\#357](https://github.com/nlohmann/json/issues/357)
|
||||||
- Hi, is there any method to dump json to string with the insert order rather than alphabets [\#356](https://github.com/nlohmann/json/issues/356)
|
- Hi, is there any method to dump json to string with the insert order rather than alphabets [\#356](https://github.com/nlohmann/json/issues/356)
|
||||||
|
@ -1902,7 +1998,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.2...v2.0.3)
|
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.2...v2.0.3)
|
||||||
|
|
||||||
- warning C4706: assignment within conditional expression [\#295](https://github.com/nlohmann/json/issues/295)
|
- warning C4706: assignment within conditional expression [\#295](https://github.com/nlohmann/json/issues/295)
|
||||||
- Strip comments / Minify [\#294](https://github.com/nlohmann/json/issues/294)
|
|
||||||
- Q: Is it possible to build json tree from already UTF8 encoded values? [\#293](https://github.com/nlohmann/json/issues/293)
|
- Q: Is it possible to build json tree from already UTF8 encoded values? [\#293](https://github.com/nlohmann/json/issues/293)
|
||||||
- Equality operator results in array when assigned object [\#292](https://github.com/nlohmann/json/issues/292)
|
- Equality operator results in array when assigned object [\#292](https://github.com/nlohmann/json/issues/292)
|
||||||
- Support for integers not from the range \[-\(2\*\*53\)+1, \(2\*\*53\)-1\] in parser [\#291](https://github.com/nlohmann/json/issues/291)
|
- Support for integers not from the range \[-\(2\*\*53\)+1, \(2\*\*53\)-1\] in parser [\#291](https://github.com/nlohmann/json/issues/291)
|
||||||
|
@ -2077,7 +2172,6 @@ All notable changes to this project will be documented in this file. This projec
|
||||||
- error: unterminated raw string [\#109](https://github.com/nlohmann/json/issues/109)
|
- error: unterminated raw string [\#109](https://github.com/nlohmann/json/issues/109)
|
||||||
- vector\<json\> copy constructor really weird [\#108](https://github.com/nlohmann/json/issues/108)
|
- vector\<json\> copy constructor really weird [\#108](https://github.com/nlohmann/json/issues/108)
|
||||||
- \[clang-3.6.2\] string/sstream with number to json issue [\#107](https://github.com/nlohmann/json/issues/107)
|
- \[clang-3.6.2\] string/sstream with number to json issue [\#107](https://github.com/nlohmann/json/issues/107)
|
||||||
- maintaining order of keys during iteration [\#106](https://github.com/nlohmann/json/issues/106)
|
|
||||||
- object field accessors [\#103](https://github.com/nlohmann/json/issues/103)
|
- object field accessors [\#103](https://github.com/nlohmann/json/issues/103)
|
||||||
- v8pp and json [\#95](https://github.com/nlohmann/json/issues/95)
|
- v8pp and json [\#95](https://github.com/nlohmann/json/issues/95)
|
||||||
- Wishlist [\#65](https://github.com/nlohmann/json/issues/65)
|
- Wishlist [\#65](https://github.com/nlohmann/json/issues/65)
|
||||||
|
|
120
Makefile
120
Makefile
|
@ -5,7 +5,7 @@
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# directory to recent compiler binaries
|
# directory to recent compiler binaries
|
||||||
COMPILER_DIR=/Users/niels/Documents/projects/compilers/local/bin
|
COMPILER_DIR=/usr/local/opt/llvm/bin
|
||||||
|
|
||||||
# find GNU sed to use `-i` parameter
|
# find GNU sed to use `-i` parameter
|
||||||
SED:=$(shell command -v gsed || which sed)
|
SED:=$(shell command -v gsed || which sed)
|
||||||
|
@ -30,7 +30,6 @@ AMALGAMATED_FILE=single_include/nlohmann/json.hpp
|
||||||
all:
|
all:
|
||||||
@echo "amalgamate - amalgamate file single_include/nlohmann/json.hpp from the include/nlohmann sources"
|
@echo "amalgamate - amalgamate file single_include/nlohmann/json.hpp from the include/nlohmann sources"
|
||||||
@echo "ChangeLog.md - generate ChangeLog file"
|
@echo "ChangeLog.md - generate ChangeLog file"
|
||||||
@echo "check - compile and execute test suite"
|
|
||||||
@echo "check-amalgamation - check whether sources have been amalgamated"
|
@echo "check-amalgamation - check whether sources have been amalgamated"
|
||||||
@echo "clean - remove built files"
|
@echo "clean - remove built files"
|
||||||
@echo "coverage - create coverage information with lcov"
|
@echo "coverage - create coverage information with lcov"
|
||||||
|
@ -44,38 +43,24 @@ all:
|
||||||
@echo "fuzz_testing_cbor - prepare fuzz testing of the CBOR parser"
|
@echo "fuzz_testing_cbor - prepare fuzz testing of the CBOR parser"
|
||||||
@echo "fuzz_testing_msgpack - prepare fuzz testing of the MessagePack parser"
|
@echo "fuzz_testing_msgpack - prepare fuzz testing of the MessagePack parser"
|
||||||
@echo "fuzz_testing_ubjson - prepare fuzz testing of the UBJSON parser"
|
@echo "fuzz_testing_ubjson - prepare fuzz testing of the UBJSON parser"
|
||||||
@echo "json_unit - create single-file test executable"
|
|
||||||
@echo "pedantic_clang - run Clang with maximal warning flags"
|
@echo "pedantic_clang - run Clang with maximal warning flags"
|
||||||
@echo "pedantic_gcc - run GCC with maximal warning flags"
|
@echo "pedantic_gcc - run GCC with maximal warning flags"
|
||||||
@echo "pretty - beautify code with Artistic Style"
|
@echo "pretty - beautify code with Artistic Style"
|
||||||
@echo "run_benchmarks - build and run benchmarks"
|
@echo "run_benchmarks - build and run benchmarks"
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# unit tests
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
# build unit tests
|
|
||||||
json_unit:
|
|
||||||
@$(MAKE) json_unit -C test
|
|
||||||
|
|
||||||
# run unit tests
|
|
||||||
check:
|
|
||||||
$(MAKE) check -C test
|
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# coverage
|
# coverage
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
rm -fr build_coverage
|
rm -fr cmake-build-coverage
|
||||||
mkdir build_coverage
|
mkdir cmake-build-coverage
|
||||||
cd build_coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
|
cd cmake-build-coverage ; cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
|
||||||
cd build_coverage ; ninja
|
cd cmake-build-coverage ; ninja
|
||||||
cd build_coverage ; ctest -j10
|
cd cmake-build-coverage ; ctest -j10
|
||||||
cd build_coverage ; ninja lcov_html
|
cd cmake-build-coverage ; ninja lcov_html
|
||||||
open build_coverage/test/html/index.html
|
open cmake-build-coverage/test/html/index.html
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# documentation tests
|
# documentation tests
|
||||||
|
@ -97,12 +82,13 @@ doctest:
|
||||||
# -Wno-exit-time-destructors: warning in json code triggered by NLOHMANN_JSON_SERIALIZE_ENUM
|
# -Wno-exit-time-destructors: warning in json code triggered by NLOHMANN_JSON_SERIALIZE_ENUM
|
||||||
# -Wno-float-equal: not all comparisons in the tests can be replaced by Approx
|
# -Wno-float-equal: not all comparisons in the tests can be replaced by Approx
|
||||||
# -Wno-keyword-macro: unit-tests use "#define private public"
|
# -Wno-keyword-macro: unit-tests use "#define private public"
|
||||||
|
# -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
|
||||||
# -Wno-padded: padding is nothing to warn about
|
# -Wno-padded: padding is nothing to warn about
|
||||||
# -Wno-range-loop-analysis: items tests "for(const auto i...)"
|
# -Wno-range-loop-analysis: items tests "for(const auto i...)"
|
||||||
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
|
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
|
||||||
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
|
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
|
||||||
pedantic_clang:
|
pedantic_clang:
|
||||||
rm -fr build_pedantic
|
rm -fr cmake-build-pedantic
|
||||||
CXXFLAGS=" \
|
CXXFLAGS=" \
|
||||||
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
|
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
|
||||||
-Werror \
|
-Werror \
|
||||||
|
@ -113,15 +99,16 @@ pedantic_clang:
|
||||||
-Wno-exit-time-destructors \
|
-Wno-exit-time-destructors \
|
||||||
-Wno-float-equal \
|
-Wno-float-equal \
|
||||||
-Wno-keyword-macro \
|
-Wno-keyword-macro \
|
||||||
|
-Wno-missing-prototypes \
|
||||||
-Wno-padded \
|
-Wno-padded \
|
||||||
-Wno-range-loop-analysis \
|
-Wno-range-loop-analysis \
|
||||||
-Wno-switch-enum -Wno-covered-switch-default \
|
-Wno-switch-enum -Wno-covered-switch-default \
|
||||||
-Wno-weak-vtables" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
|
-Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
|
||||||
cmake --build build_pedantic
|
cmake --build cmake-build-pedantic
|
||||||
|
|
||||||
# calling GCC with most warnings
|
# calling GCC with most warnings
|
||||||
pedantic_gcc:
|
pedantic_gcc:
|
||||||
rm -fr build_pedantic
|
rm -fr cmake-build-pedantic
|
||||||
CXXFLAGS=" \
|
CXXFLAGS=" \
|
||||||
-std=c++11 \
|
-std=c++11 \
|
||||||
-pedantic \
|
-pedantic \
|
||||||
|
@ -253,7 +240,7 @@ pedantic_gcc:
|
||||||
-Wmismatched-tags \
|
-Wmismatched-tags \
|
||||||
-Wmissing-attributes \
|
-Wmissing-attributes \
|
||||||
-Wmissing-braces \
|
-Wmissing-braces \
|
||||||
-Wmissing-declarations \
|
-Wno-missing-declarations \
|
||||||
-Wmissing-field-initializers \
|
-Wmissing-field-initializers \
|
||||||
-Wmissing-include-dirs \
|
-Wmissing-include-dirs \
|
||||||
-Wmissing-profile \
|
-Wmissing-profile \
|
||||||
|
@ -379,19 +366,19 @@ pedantic_gcc:
|
||||||
-Wwrite-strings \
|
-Wwrite-strings \
|
||||||
-Wzero-as-null-pointer-constant \
|
-Wzero-as-null-pointer-constant \
|
||||||
-Wzero-length-bounds \
|
-Wzero-length-bounds \
|
||||||
" cmake -S . -B build_pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
|
" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
|
||||||
cmake --build build_pedantic
|
cmake --build cmake-build-pedantic
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# benchmarks
|
# benchmarks
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
run_benchmarks:
|
run_benchmarks:
|
||||||
rm -fr build_benchmarks
|
rm -fr cmake-build-benchmarks
|
||||||
mkdir build_benchmarks
|
mkdir cmake-build-benchmarks
|
||||||
cd build_benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On
|
cd cmake-build-benchmarks ; cmake ../benchmarks -GNinja -DCMAKE_BUILD_TYPE=Release -DJSON_BuildTests=On
|
||||||
cd build_benchmarks ; ninja
|
cd cmake-build-benchmarks ; ninja
|
||||||
cd build_benchmarks ; ./json_benchmarks
|
cd cmake-build-benchmarks ; ./json_benchmarks
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# fuzzing
|
# fuzzing
|
||||||
|
@ -464,14 +451,14 @@ cppcheck:
|
||||||
|
|
||||||
# call Clang Static Analyzer <https://clang-analyzer.llvm.org>
|
# call Clang Static Analyzer <https://clang-analyzer.llvm.org>
|
||||||
clang_analyze:
|
clang_analyze:
|
||||||
rm -fr clang_analyze_build
|
rm -fr cmake-build-clang-analyze
|
||||||
mkdir clang_analyze_build
|
mkdir cmake-build-clang-analyze
|
||||||
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On
|
cd cmake-build-clang-analyze ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On
|
||||||
cd clang_analyze_build ; \
|
cd cmake-build-clang-analyze ; \
|
||||||
$(COMPILER_DIR)/scan-build \
|
$(COMPILER_DIR)/scan-build \
|
||||||
-enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull \
|
-enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull \
|
||||||
--use-c++=$(COMPILER_DIR)/clang++ -analyze-headers -o report ninja
|
--use-c++=$(COMPILER_DIR)/clang++ -analyze-headers -o report ninja
|
||||||
open clang_analyze_build/report/*/index.html
|
open cmake-build-clang-analyze/report/*/index.html
|
||||||
|
|
||||||
# call cpplint <https://github.com/cpplint/cpplint>
|
# call cpplint <https://github.com/cpplint/cpplint>
|
||||||
# Note: some errors expected due to false positives
|
# Note: some errors expected due to false positives
|
||||||
|
@ -482,22 +469,22 @@ cpplint:
|
||||||
|
|
||||||
# call Clang-Tidy <https://clang.llvm.org/extra/clang-tidy/>
|
# call Clang-Tidy <https://clang.llvm.org/extra/clang-tidy/>
|
||||||
clang_tidy:
|
clang_tidy:
|
||||||
$(COMPILER_DIR)/clang-tidy $(AMALGAMATED_FILE) -- -Iinclude -std=c++11
|
$(COMPILER_DIR)/clang-tidy $(SRCS) -- -Iinclude -std=c++11
|
||||||
|
|
||||||
# call PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>
|
# call PVS-Studio Analyzer <https://www.viva64.com/en/pvs-studio/>
|
||||||
pvs_studio:
|
pvs_studio:
|
||||||
rm -fr pvs_studio_build
|
rm -fr cmake-build-pvs-studio
|
||||||
mkdir pvs_studio_build
|
mkdir cmake-build-pvs-studio
|
||||||
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On
|
cd cmake-build-pvs-studio ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=ON
|
||||||
cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10
|
cd cmake-build-pvs-studio ; pvs-studio-analyzer analyze -j 10
|
||||||
cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
cd cmake-build-pvs-studio ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
||||||
open pvs_studio_build/pvs/index.html
|
open cmake-build-pvs-studio/pvs/index.html
|
||||||
|
|
||||||
# call Infer <https://fbinfer.com> static analyzer
|
# call Infer <https://fbinfer.com> static analyzer
|
||||||
infer:
|
infer:
|
||||||
rm -fr infer_build
|
rm -fr cmake-build-infer
|
||||||
mkdir infer_build
|
mkdir cmake-build-infer
|
||||||
cd infer_build ; infer compile -- cmake .. ; infer run -- make -j 4
|
cd cmake-build-infer ; infer compile -- cmake .. -DJSON_MultipleHeaders=ON ; infer run -- make -j 4
|
||||||
|
|
||||||
# call OCLint <http://oclint.org> static analyzer
|
# call OCLint <http://oclint.org> static analyzer
|
||||||
oclint:
|
oclint:
|
||||||
|
@ -506,11 +493,11 @@ oclint:
|
||||||
|
|
||||||
# execute the test suite with Clang sanitizers (address and undefined behavior)
|
# execute the test suite with Clang sanitizers (address and undefined behavior)
|
||||||
clang_sanitize:
|
clang_sanitize:
|
||||||
rm -fr clang_sanitize_build
|
rm -fr cmake-build-clang-sanitize
|
||||||
mkdir clang_sanitize_build
|
mkdir cmake-build-clang-sanitize
|
||||||
cd clang_sanitize_build ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja
|
cd cmake-build-clang-sanitize ; CXX=$(COMPILER_DIR)/clang++ cmake .. -DJSON_Sanitizer=On -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On -GNinja
|
||||||
cd clang_sanitize_build ; ninja
|
cd cmake-build-clang-sanitize ; ninja
|
||||||
cd clang_sanitize_build ; ctest -j10
|
cd cmake-build-clang-sanitize ; ctest -j10
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -538,7 +525,11 @@ pretty:
|
||||||
--preserve-date \
|
--preserve-date \
|
||||||
--suffix=none \
|
--suffix=none \
|
||||||
--formatted \
|
--formatted \
|
||||||
$(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp
|
$(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp
|
||||||
|
|
||||||
|
# call the Clang-Format on all source files
|
||||||
|
pretty_format:
|
||||||
|
for FILE in $(SRCS) $(AMALGAMATED_FILE) test/src/*.cpp test/src/*.hpp benchmarks/src/benchmarks.cpp doc/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
|
||||||
|
|
||||||
# create single header file
|
# create single header file
|
||||||
amalgamate: $(AMALGAMATED_FILE)
|
amalgamate: $(AMALGAMATED_FILE)
|
||||||
|
@ -560,7 +551,7 @@ check-amalgamation:
|
||||||
check-single-includes:
|
check-single-includes:
|
||||||
@for x in $(SRCS); do \
|
@for x in $(SRCS); do \
|
||||||
echo "Checking self-sufficiency of $$x..." ; \
|
echo "Checking self-sufficiency of $$x..." ; \
|
||||||
echo "#include <$$x>\nint main() {}\n" | sed 's|include/||' > single_include_test.cpp; \
|
echo "#include <$$x>\nint main() {}\n" | $(SED) 's|include/||' > single_include_test.cpp; \
|
||||||
$(CXX) $(CXXFLAGS) -Iinclude -std=c++11 single_include_test.cpp -o single_include_test; \
|
$(CXX) $(CXXFLAGS) -Iinclude -std=c++11 single_include_test.cpp -o single_include_test; \
|
||||||
rm -f single_include_test.cpp single_include_test; \
|
rm -f single_include_test.cpp single_include_test; \
|
||||||
done
|
done
|
||||||
|
@ -570,17 +561,17 @@ check-single-includes:
|
||||||
# CMake
|
# CMake
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# grep "^option" CMakeLists.txt test/CMakeLists.txt | sed 's/(/ /' | awk '{print $2}' | xargs
|
# grep "^option" CMakeLists.txt test/CMakeLists.txt | $(SED) 's/(/ /' | awk '{print $2}' | xargs
|
||||||
|
|
||||||
# check if all flags of our CMake files work
|
# check if all flags of our CMake files work
|
||||||
check_cmake_flags_do:
|
check_cmake_flags_do:
|
||||||
$(CMAKE_BINARY) --version
|
$(CMAKE_BINARY) --version
|
||||||
for flag in '' JSON_BuildTests JSON_Install JSON_MultipleHeaders JSON_Sanitizer JSON_Valgrind JSON_NoExceptions JSON_Coverage; do \
|
for flag in JSON_BuildTests JSON_Install JSON_MultipleHeaders JSON_Sanitizer JSON_Valgrind JSON_NoExceptions JSON_Coverage; do \
|
||||||
rm -fr cmake_build; \
|
rm -fr cmake_build; \
|
||||||
mkdir cmake_build; \
|
mkdir cmake_build; \
|
||||||
echo "$(CMAKE_BINARY) .. -D$$flag=On" ; \
|
echo "\n\n$(CMAKE_BINARY) .. -D$$flag=On\n" ; \
|
||||||
cd cmake_build ; \
|
cd cmake_build ; \
|
||||||
CXX=g++-8 $(CMAKE_BINARY) .. -D$$flag=On -DCMAKE_CXX_COMPILE_FEATURES="cxx_std_11;cxx_range_for" -DCMAKE_CXX_FLAGS="-std=gnu++11" ; \
|
$(CMAKE_BINARY) -Werror=dev .. -D$$flag=On -DCMAKE_CXX_COMPILE_FEATURES="cxx_std_11;cxx_range_for" -DCMAKE_CXX_FLAGS="-std=gnu++11" ; \
|
||||||
test -f Makefile || exit 1 ; \
|
test -f Makefile || exit 1 ; \
|
||||||
cd .. ; \
|
cd .. ; \
|
||||||
done;
|
done;
|
||||||
|
@ -638,9 +629,8 @@ clean:
|
||||||
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html
|
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM test/*.dSYM oclint_report.html
|
||||||
rm -fr benchmarks/files/numbers/*.json
|
rm -fr benchmarks/files/numbers/*.json
|
||||||
rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64
|
rm -fr cmake-3.1.0-Darwin64.tar.gz cmake-3.1.0-Darwin64
|
||||||
rm -fr build_coverage build_benchmarks fuzz-testing clang_analyze_build pvs_studio_build infer_build clang_sanitize_build cmake_build
|
rm -fr cmake-build-coverage cmake-build-benchmarks fuzz-testing cmake-build-clang-analyze cmake-build-pvs-studio cmake-build-infer cmake-build-clang-sanitize cmake_build
|
||||||
$(MAKE) clean -Cdoc
|
$(MAKE) clean -Cdoc
|
||||||
$(MAKE) clean -Ctest
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Thirdparty code
|
# Thirdparty code
|
||||||
|
@ -649,6 +639,6 @@ clean:
|
||||||
update_hedley:
|
update_hedley:
|
||||||
rm -f include/nlohmann/thirdparty/hedley/hedley.hpp include/nlohmann/thirdparty/hedley/hedley_undef.hpp
|
rm -f include/nlohmann/thirdparty/hedley/hedley.hpp include/nlohmann/thirdparty/hedley/hedley_undef.hpp
|
||||||
curl https://raw.githubusercontent.com/nemequ/hedley/master/hedley.h -o include/nlohmann/thirdparty/hedley/hedley.hpp
|
curl https://raw.githubusercontent.com/nemequ/hedley/master/hedley.h -o include/nlohmann/thirdparty/hedley/hedley.hpp
|
||||||
gsed -i 's/HEDLEY_/JSON_HEDLEY_/g' include/nlohmann/thirdparty/hedley/hedley.hpp
|
$(SED) -i 's/HEDLEY_/JSON_HEDLEY_/g' include/nlohmann/thirdparty/hedley/hedley.hpp
|
||||||
grep "[[:blank:]]*#[[:blank:]]*undef" include/nlohmann/thirdparty/hedley/hedley.hpp | grep -v "__" | sort | uniq | gsed 's/ //g' | gsed 's/undef/undef /g' > include/nlohmann/thirdparty/hedley/hedley_undef.hpp
|
grep "[[:blank:]]*#[[:blank:]]*undef" include/nlohmann/thirdparty/hedley/hedley.hpp | grep -v "__" | sort | uniq | $(SED) 's/ //g' | $(SED) 's/undef/undef /g' > include/nlohmann/thirdparty/hedley/hedley_undef.hpp
|
||||||
$(MAKE) amalgamate
|
$(MAKE) amalgamate
|
||||||
|
|
88
README.md
88
README.md
|
@ -27,6 +27,7 @@
|
||||||
- [Integration](#integration)
|
- [Integration](#integration)
|
||||||
- [CMake](#cmake)
|
- [CMake](#cmake)
|
||||||
- [Package Managers](#package-managers)
|
- [Package Managers](#package-managers)
|
||||||
|
- [Pkg-config](#pkg-config)
|
||||||
- [Examples](#examples)
|
- [Examples](#examples)
|
||||||
- [JSON as first-class data type](#json-as-first-class-data-type)
|
- [JSON as first-class data type](#json-as-first-class-data-type)
|
||||||
- [Serialization / Deserialization](#serialization--deserialization)
|
- [Serialization / Deserialization](#serialization--deserialization)
|
||||||
|
@ -230,6 +231,20 @@ Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if
|
||||||
|
|
||||||
If you are using [`wsjcpp`](https://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch.
|
If you are using [`wsjcpp`](https://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch.
|
||||||
|
|
||||||
|
### Pkg-config
|
||||||
|
|
||||||
|
If you are using bare Makefiles, you can use `pkg-config` to generate the include flags that point to where the library is installed:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pkg-config nlohmann_json --cflags
|
||||||
|
```
|
||||||
|
|
||||||
|
Users of the Meson build system will also be able to use a system wide library, which will be found by `pkg-config`:
|
||||||
|
|
||||||
|
```meson
|
||||||
|
json = dependency('nlohmann_json', required: true)
|
||||||
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
|
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
|
||||||
|
@ -497,6 +512,8 @@ bool number_float(number_float_t val, const string_t& s);
|
||||||
|
|
||||||
// called when a string is parsed; value is passed and can be safely moved away
|
// called when a string is parsed; value is passed and can be safely moved away
|
||||||
bool string(string_t& val);
|
bool string(string_t& val);
|
||||||
|
// called when a binary value is parsed; value is passed and can be safely moved away
|
||||||
|
bool binary(binary_t& val);
|
||||||
|
|
||||||
// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
|
// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
|
||||||
bool start_object(std::size_t elements);
|
bool start_object(std::size_t elements);
|
||||||
|
@ -747,6 +764,7 @@ Supported types can be implicitly converted to JSON values.
|
||||||
|
|
||||||
It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
|
It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
|
||||||
You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958).
|
You can find more details about this recommendation [here](https://www.github.com/nlohmann/json/issues/958).
|
||||||
|
You can switch off implicit conversions by defining `JSON_USE_IMPLICIT_CONVERSIONS` to `0` before including the `json.hpp` header. When using CMake, you can also achieve this by setting the option `JSON_ImplicitConversions` to `OFF`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// strings
|
// strings
|
||||||
|
@ -869,6 +887,42 @@ Some important things:
|
||||||
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
|
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
|
||||||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
||||||
|
|
||||||
|
#### Simplify your life with macros
|
||||||
|
|
||||||
|
If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.
|
||||||
|
|
||||||
|
There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
|
||||||
|
|
||||||
|
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
|
||||||
|
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.
|
||||||
|
|
||||||
|
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
|
||||||
|
|
||||||
|
##### Examples
|
||||||
|
|
||||||
|
The `to_json`/`from_json` functions for the `person` struct above can be created with:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ns {
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ns {
|
||||||
|
class address {
|
||||||
|
private:
|
||||||
|
std::string street;
|
||||||
|
int housenumber;
|
||||||
|
int postcode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### How do I convert third-party types?
|
#### How do I convert third-party types?
|
||||||
|
|
||||||
|
@ -1139,6 +1193,7 @@ Though it's 2020 already, the support for C++11 is still a bit sparse. Currently
|
||||||
|
|
||||||
- GCC 4.8 - 10.1 (and possibly later)
|
- GCC 4.8 - 10.1 (and possibly later)
|
||||||
- Clang 3.4 - 10.0 (and possibly later)
|
- Clang 3.4 - 10.0 (and possibly later)
|
||||||
|
- Apple Clang 9.1 - 12.0 (and possibly later)
|
||||||
- Intel C++ Compiler 17.0.2 (and possibly later)
|
- Intel C++ Compiler 17.0.2 (and possibly later)
|
||||||
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (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++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
|
||||||
|
@ -1174,6 +1229,7 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||||
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
|
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
|
||||||
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis |
|
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis |
|
||||||
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions |
|
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions |
|
||||||
|
| Apple Clang 12.0.0 (clang-1200.0.22.7); Xcode 11.4.1 | macOS 10.15.5 | Travis |
|
||||||
| Clang 3.5.0 (3.5.0-4ubuntu2~trusty2) | Ubuntu 14.04.5 LTS | Travis |
|
| Clang 3.5.0 (3.5.0-4ubuntu2~trusty2) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| Clang 3.6.2 (3.6.2-svn240577-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
|
| Clang 3.6.2 (3.6.2-svn240577-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| Clang 3.7.1 (3.7.1-svn253571-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
|
| Clang 3.7.1 (3.7.1-svn253571-1~exp1) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
|
@ -1184,6 +1240,8 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||||
| Clang 6.0.1 (6.0.1-svn334776-1~exp1~20190309042707.121) | Ubuntu 14.04.5 LTS | Travis |
|
| Clang 6.0.1 (6.0.1-svn334776-1~exp1~20190309042707.121) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| Clang 7.1.0 (7.1.0-svn353565-1~exp1~20190419134007.64) | Ubuntu 14.04.5 LTS | Travis |
|
| Clang 7.1.0 (7.1.0-svn353565-1~exp1~20190419134007.64) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| Clang 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) | Ubuntu 18.04.4 LTS | Travis |
|
| Clang 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) | Ubuntu 18.04.4 LTS | Travis |
|
||||||
|
| Clang 9.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
|
||||||
|
| Clang 10.0.0 (x86_64-pc-windows-msvc) | Windows-10.0.17763 | GitHub Actions |
|
||||||
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8~14.04.2) | Ubuntu 14.04.5 LTS | Travis |
|
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8~14.04.2) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| GCC 4.9.4 (Ubuntu 4.9.4-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
|
| GCC 4.9.4 (Ubuntu 4.9.4-2ubuntu1~14.04.1) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1~14.04) | Ubuntu 14.04.5 LTS | Travis |
|
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1~14.04) | Ubuntu 14.04.5 LTS | Travis |
|
||||||
|
@ -1199,6 +1257,7 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||||
| MSVC 19.16.27035.0 (15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor |
|
| MSVC 19.16.27035.0 (15.9.21+g9802d43bc3 for .NET Framework) | Windows-10.0.14393 | AppVeyor |
|
||||||
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | AppVeyor |
|
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | AppVeyor |
|
||||||
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | GitHub Actions |
|
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) | Windows-10.0.17763 | GitHub Actions |
|
||||||
|
| MSVC 19.25.28614.0 (Build Engine version 16.5.0+d4cbfca49 for .NET Framework) with ClangCL 10.0.0 | Windows-10.0.17763 | GitHub Actions |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -1452,6 +1511,17 @@ I deeply appreciate the help of the following people.
|
||||||
- [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
- [XyFreak](https://github.com/XyFreak) fixed a compiler warning.
|
||||||
- [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README.
|
- [TotalCaesar659](https://github.com/TotalCaesar659) fixed links in the README.
|
||||||
- [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
- [Tanuj Garg](https://github.com/tanuj208) improved the fuzzer coverage for UBSAN input.
|
||||||
|
- [AODQ](https://github.com/AODQ) fixed a compiler warning.
|
||||||
|
- [jwittbrodt](https://github.com/jwittbrodt) made `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` inline.
|
||||||
|
- [pfeatherstone](https://github.com/pfeatherstone) improved the upper bound of arguments of the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||||
|
- [Jan Procházka](https://github.com/jprochazk) fixed a bug in the CBOR parser for binary and string values.
|
||||||
|
- [T0b1-iOS](https://github.com/T0b1-iOS) fixed a bug in the new hash implementation.
|
||||||
|
- [Matthew Bauer](https://github.com/matthewbauer) adjusted the CBOR writer to create tags for binary subtypes.
|
||||||
|
- [gatopeich](https://github.com/gatopeich) implemented an ordered map container for `nlohmann::ordered_json`.
|
||||||
|
- [Érico Nogueira Rolim](https://github.com/ericonr) added support for pkg-config.
|
||||||
|
- [KonanM](https://github.com/KonanM) proposed an implementation for the `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`/`NLOHMANN_DEFINE_TYPE_INTRUSIVE` macros.
|
||||||
|
- [Guillaume Racicot](https://github.com/gracicot) implemented `string_view` support and allowed C++20 support.
|
||||||
|
- [Alex Reinking](https://github.com/alexreinking) improved CMake support for `FetchContent`.
|
||||||
|
|
||||||
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
|
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
|
||||||
|
|
||||||
|
@ -1508,7 +1578,7 @@ The library supports **Unicode input** as follows:
|
||||||
|
|
||||||
### Comments in JSON
|
### Comments in JSON
|
||||||
|
|
||||||
This library does not support comments. It does so for three reasons:
|
This library does not support comments by default. It does so for three reasons:
|
||||||
|
|
||||||
1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript.
|
1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript.
|
||||||
2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012:
|
2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012:
|
||||||
|
@ -1519,15 +1589,13 @@ This library does not support comments. It does so for three reasons:
|
||||||
|
|
||||||
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
|
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
|
||||||
|
|
||||||
This library will not support comments in the future. If you wish to use comments, I see three options:
|
However, you can pass set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
|
||||||
|
|
||||||
1. Strip comments before using this library.
|
|
||||||
2. Use a different JSON library with comment support.
|
|
||||||
3. Use a format that natively supports comments (e.g., YAML or JSON5).
|
|
||||||
|
|
||||||
### Order of object keys
|
### Order of object keys
|
||||||
|
|
||||||
By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs".
|
||||||
|
|
||||||
|
If you do want to preserve the insertion order, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179). Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
||||||
|
|
||||||
### Memory Release
|
### Memory Release
|
||||||
|
|
||||||
|
@ -1540,7 +1608,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924).
|
||||||
|
|
||||||
### Further notes
|
### Further notes
|
||||||
|
|
||||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a233b02b0839ef798942dd46157cc0fe6.html#a233b02b0839ef798942dd46157cc0fe6) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a73ae333487310e3302135189ce8ff5d8.html#a73ae333487310e3302135189ce8ff5d8).
|
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a233b02b0839ef798942dd46157cc0fe6.html#a233b02b0839ef798942dd46157cc0fe6) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a73ae333487310e3302135189ce8ff5d8.html#a73ae333487310e3302135189ce8ff5d8). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
|
||||||
- As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
|
- As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
|
||||||
- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag.
|
- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag.
|
||||||
- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER´` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER´` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
||||||
|
@ -1557,4 +1625,6 @@ $ cmake --build .
|
||||||
$ ctest --output-on-failure
|
$ ctest --output-on-failure
|
||||||
```
|
```
|
||||||
|
|
||||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
Note that during the `ctest` stage, several JSON test files are downloaded from an [external repository](https://github.com/nlohmann/json_test_data). If policies forbid downloading artifacts during testing, you can download the files yourself and pass the directory with the test files via `-DJSON_TestDataDirectory=path` to CMake. Then, no Internet connectivity is required. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
|
||||||
|
|
||||||
|
In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure`. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
|
||||||
|
|
23
appveyor.yml
23
appveyor.yml
|
@ -7,6 +7,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
@ -14,6 +15,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 15 2017
|
GENERATOR: Visual Studio 15 2017
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
@ -21,6 +23,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 16 2019
|
GENERATOR: Visual Studio 16 2019
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
@ -28,6 +31,7 @@ environment:
|
||||||
platform: x64
|
platform: x64
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 16 2019
|
GENERATOR: Visual Studio 16 2019
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
@ -36,6 +40,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Ninja
|
GENERATOR: Ninja
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
@ -44,6 +49,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Ninja
|
GENERATOR: Ninja
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
@ -51,6 +57,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
@ -59,6 +66,7 @@ environment:
|
||||||
name: with_win_header
|
name: with_win_header
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
@ -66,6 +74,7 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: "/permissive- /std:c++latest /utf-8"
|
CXX_FLAGS: "/permissive- /std:c++latest /utf-8"
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 15 2017
|
GENERATOR: Visual Studio 15 2017
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
@ -73,6 +82,15 @@ environment:
|
||||||
platform: x86
|
platform: x86
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: "-DJSON_ImplicitConversions=OFF"
|
||||||
|
GENERATOR: Visual Studio 16 2019
|
||||||
|
|
||||||
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
configuration: Release
|
||||||
|
platform: x64
|
||||||
|
CXX_FLAGS: ""
|
||||||
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 16 2019
|
GENERATOR: Visual Studio 16 2019
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
|
@ -80,6 +98,7 @@ environment:
|
||||||
platform: x64
|
platform: x64
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 14 2015
|
GENERATOR: Visual Studio 14 2015
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
@ -87,6 +106,7 @@ environment:
|
||||||
platform: x64
|
platform: x64
|
||||||
CXX_FLAGS: "/permissive- /std:c++latest /Zc:__cplusplus /utf-8 /F4000000"
|
CXX_FLAGS: "/permissive- /std:c++latest /Zc:__cplusplus /utf-8 /F4000000"
|
||||||
LINKER_FLAGS: "/STACK:4000000"
|
LINKER_FLAGS: "/STACK:4000000"
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 15 2017
|
GENERATOR: Visual Studio 15 2017
|
||||||
|
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
@ -94,6 +114,7 @@ environment:
|
||||||
platform: x64
|
platform: x64
|
||||||
CXX_FLAGS: ""
|
CXX_FLAGS: ""
|
||||||
LINKER_FLAGS: ""
|
LINKER_FLAGS: ""
|
||||||
|
CMAKE_OPTIONS: ""
|
||||||
GENERATOR: Visual Studio 16 2019
|
GENERATOR: Visual Studio 16 2019
|
||||||
|
|
||||||
init:
|
init:
|
||||||
|
@ -112,7 +133,7 @@ before_build:
|
||||||
# for with_win_header build, inject the inclusion of Windows.h to the single-header library
|
# for with_win_header build, inject the inclusion of Windows.h to the single-header library
|
||||||
- ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
|
- ps: if ($env:name -Eq "with_win_header") { $header_path = "single_include\nlohmann\json.hpp" }
|
||||||
- ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
|
- ps: if ($env:name -Eq "with_win_header") { "#include <Windows.h>`n" + (Get-Content $header_path | Out-String) | Set-Content $header_path }
|
||||||
- if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On) else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On)
|
- if "%GENERATOR%"=="Ninja" (cmake . -G "%GENERATOR%" -DCMAKE_BUILD_TYPE="%configuration%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%") else (cmake . -G "%GENERATOR%" -A "%GENERATOR_PLATFORM%" -DCMAKE_CXX_FLAGS="%CXX_FLAGS%" -DCMAKE_EXE_LINKER_FLAGS="%LINKER_FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin" -DJSON_BuildTests=On "%CMAKE_OPTIONS%")
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmake --build . --config "%configuration%"
|
- cmake --build . --config "%configuration%"
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
find_package(Git)
|
|
||||||
|
|
||||||
set(JSON_TEST_DATA_URL https://github.com/nlohmann/json_test_data)
|
set(JSON_TEST_DATA_URL https://github.com/nlohmann/json_test_data)
|
||||||
set(JSON_TEST_DATA_VERSION 2.0.0)
|
set(JSON_TEST_DATA_VERSION 3.0.0)
|
||||||
|
|
||||||
|
# if variable is set, use test data from given directory rather than downloading them
|
||||||
|
if(JSON_TestDataDirectory)
|
||||||
|
message(STATUS "Using test data in ${JSON_TestDataDirectory}.")
|
||||||
|
add_custom_target(download_test_data)
|
||||||
|
file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${JSON_TestDataDirectory}\"\n")
|
||||||
|
else()
|
||||||
|
find_package(Git)
|
||||||
# target to download test data
|
# target to download test data
|
||||||
add_custom_target(download_test_data
|
add_custom_target(download_test_data
|
||||||
COMMAND test -d json_test_data || ${GIT_EXECUTABLE} clone -c advice.detachedHead=false --branch v${JSON_TEST_DATA_VERSION} ${JSON_TEST_DATA_URL}.git --quiet --depth 1
|
COMMAND test -d json_test_data || ${GIT_EXECUTABLE} clone -c advice.detachedHead=false --branch v${JSON_TEST_DATA_VERSION} ${JSON_TEST_DATA_URL}.git --quiet --depth 1
|
||||||
COMMENT "Downloading test data from ${JSON_TEST_DATA_URL} (v${JSON_TEST_DATA_VERSION})"
|
COMMENT "Downloading test data from ${JSON_TEST_DATA_URL} (v${JSON_TEST_DATA_VERSION})"
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
# create a header with the path to the downloaded test data
|
# create a header with the path to the downloaded test data
|
||||||
file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${CMAKE_BINARY_DIR}/json_test_data\"\n")
|
file(WRITE ${CMAKE_BINARY_DIR}/include/test_data.hpp "#define TEST_DATA_DIRECTORY \"${CMAKE_BINARY_DIR}/json_test_data\"\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
# determine the operating system (for debug and support purposes)
|
# determine the operating system (for debug and support purposes)
|
||||||
find_program(UNAME_COMMAND uname)
|
find_program(UNAME_COMMAND uname)
|
||||||
|
|
4
cmake/pkg-config.pc.in
Normal file
4
cmake/pkg-config.pc.in
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Name: ${PROJECT_NAME}
|
||||||
|
Description: JSON for Modern C++
|
||||||
|
Version: ${PROJECT_VERSION}
|
||||||
|
Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}
|
|
@ -5,7 +5,7 @@
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
DOXYFILE_ENCODING = UTF-8
|
DOXYFILE_ENCODING = UTF-8
|
||||||
PROJECT_NAME = "JSON for Modern C++"
|
PROJECT_NAME = "JSON for Modern C++"
|
||||||
PROJECT_NUMBER = 3.8.0
|
PROJECT_NUMBER = 3.9.0
|
||||||
PROJECT_BRIEF =
|
PROJECT_BRIEF =
|
||||||
PROJECT_LOGO =
|
PROJECT_LOGO =
|
||||||
OUTPUT_DIRECTORY = .
|
OUTPUT_DIRECTORY = .
|
||||||
|
|
|
@ -43,7 +43,7 @@ check_output: $(EXAMPLES:.cpp=.test)
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr me.nlohmann.json.docset html $(EXAMPLES:.cpp=)
|
rm -fr me.nlohmann.json.docset html xml $(EXAMPLES:.cpp=)
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
BIN
doc/avatars.png
BIN
doc/avatars.png
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
@ -1 +1 @@
|
||||||
<a target="_blank" href="https://wandbox.org/permlink/EezQxM0Nzi8tTUEe"><b>online</b></a>
|
<a target="_blank" href="https://wandbox.org/permlink/shE8T6phAQiEzAad"><b>online</b></a>
|
|
@ -2,16 +2,16 @@
|
||||||
"compiler": {
|
"compiler": {
|
||||||
"c++": "201103",
|
"c++": "201103",
|
||||||
"family": "clang",
|
"family": "clang",
|
||||||
"version": "11.0.3 (clang-1103.0.32.62)"
|
"version": "12.0.0 (clang-1200.0.22.19)"
|
||||||
},
|
},
|
||||||
"copyright": "(C) 2013-2017 Niels Lohmann",
|
"copyright": "(C) 2013-2020 Niels Lohmann",
|
||||||
"name": "JSON for Modern C++",
|
"name": "JSON for Modern C++",
|
||||||
"platform": "apple",
|
"platform": "apple",
|
||||||
"url": "https://github.com/nlohmann/json",
|
"url": "https://github.com/nlohmann/json",
|
||||||
"version": {
|
"version": {
|
||||||
"major": 3,
|
"major": 3,
|
||||||
"minor": 8,
|
"minor": 9,
|
||||||
"patch": 0,
|
"patch": 0,
|
||||||
"string": "3.8.0"
|
"string": "3.9.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,4 +332,4 @@ Note that this table only lists those exceptions thrown due to the type. For ins
|
||||||
@author [Niels Lohmann](http://nlohmann.me)
|
@author [Niels Lohmann](http://nlohmann.me)
|
||||||
@see https://github.com/nlohmann/json to download the source code
|
@see https://github.com/nlohmann/json to download the source code
|
||||||
|
|
||||||
@version 3.8.0
|
@version 3.9.0
|
||||||
|
|
BIN
doc/json.gif
BIN
doc/json.gif
Binary file not shown.
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
74
doc/mkdocs/docs/api/basic_json/dump.md
Normal file
74
doc/mkdocs/docs/api/basic_json/dump.md
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# basic_json::dump
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
string_t dump(const int indent = -1,
|
||||||
|
const char indent_char = ' ',
|
||||||
|
const bool ensure_ascii = false,
|
||||||
|
const error_handler_t error_handler = error_handler_t::strict) const
|
||||||
|
```
|
||||||
|
|
||||||
|
Serialization function for JSON values. The function tries to mimic
|
||||||
|
Python's `json.dumps()` function, and currently supports its `indent`
|
||||||
|
and `ensure_ascii` parameters.
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
`indent` (in)
|
||||||
|
: If `indent` is nonnegative, then array elements and object
|
||||||
|
members will be pretty-printed with that indent level. An indent level of
|
||||||
|
`0` will only insert newlines. `-1` (the default) selects the most compact
|
||||||
|
representation.
|
||||||
|
|
||||||
|
`indent_char` (in)
|
||||||
|
: The character to use for indentation if `indent` is
|
||||||
|
greater than `0`. The default is ` ` (space).
|
||||||
|
|
||||||
|
`ensure_ascii` (in)
|
||||||
|
: If `ensure_ascii` is true, all non-ASCII characters
|
||||||
|
in the output are escaped with `\uXXXX` sequences, and the result consists
|
||||||
|
of ASCII characters only.
|
||||||
|
|
||||||
|
`error_handler` (in)
|
||||||
|
: how to react on decoding errors; there are three
|
||||||
|
possible values: `strict` (throws and exception in case a decoding error
|
||||||
|
occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
|
||||||
|
and `ignore` (ignore invalid UTF-8 sequences during serialization; all
|
||||||
|
bytes are copied to the output unchanged).
|
||||||
|
|
||||||
|
## Return value
|
||||||
|
|
||||||
|
string containing the serialization of the JSON value
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
Strong guarantee: if an exception is thrown, there are no
|
||||||
|
changes to any JSON value.
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
Linear.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Binary values are serialized as object containing two keys:
|
||||||
|
|
||||||
|
- "bytes": an array of bytes as integers
|
||||||
|
- "subtype": the subtype as integer or `#!json null` if the binary has no subtype
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The following example shows the effect of different `indent`,
|
||||||
|
`indent_char`, and `ensure_ascii` parameters to the result of the
|
||||||
|
serialization.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/dump.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/dump.output"
|
||||||
|
```
|
253
doc/mkdocs/docs/api/basic_json/index.md
Normal file
253
doc/mkdocs/docs/api/basic_json/index.md
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
# basic_json
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
This page is under construction.
|
||||||
|
|
||||||
|
Defined in header `<json.hpp>`
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<template<typename, typename, typename...> class ObjectType,
|
||||||
|
template<typename, typename...> class ArrayType,
|
||||||
|
class StringType, class BooleanType, class NumberIntegerType,
|
||||||
|
class NumberUnsignedType, class NumberFloatType,
|
||||||
|
template<typename> class AllocatorType,
|
||||||
|
template<typename, typename = void> class JSONSerializer,
|
||||||
|
class BinaryType>
|
||||||
|
class basic_json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Specializations
|
||||||
|
|
||||||
|
- json
|
||||||
|
- ordered_json
|
||||||
|
|
||||||
|
## Template parameters
|
||||||
|
|
||||||
|
- ObjectType
|
||||||
|
- ArrayType
|
||||||
|
- StringType
|
||||||
|
- BooleanType
|
||||||
|
- NumberIntegerType
|
||||||
|
- NumberUnsignedType
|
||||||
|
- NumberFloatType
|
||||||
|
- AllocatorType
|
||||||
|
- JSONSerializer
|
||||||
|
- BinaryType
|
||||||
|
|
||||||
|
## Iterator invalidation
|
||||||
|
|
||||||
|
## Member types
|
||||||
|
|
||||||
|
- value_t
|
||||||
|
- json_pointer
|
||||||
|
- json_serializer
|
||||||
|
- error_handler_t
|
||||||
|
- cbor_tag_handler_t
|
||||||
|
- initializer_list_t
|
||||||
|
- input_format_t
|
||||||
|
- json_sax_t
|
||||||
|
|
||||||
|
### Exceptions
|
||||||
|
|
||||||
|
- exception
|
||||||
|
- parse_error
|
||||||
|
- invalid_iterator
|
||||||
|
- type_error
|
||||||
|
- out_of_range
|
||||||
|
- other_error
|
||||||
|
|
||||||
|
### Container types
|
||||||
|
|
||||||
|
- value_type
|
||||||
|
- reference
|
||||||
|
- const_reference
|
||||||
|
- difference_type
|
||||||
|
- size_type
|
||||||
|
- allocator_type
|
||||||
|
- pointer
|
||||||
|
- const_pointer
|
||||||
|
- iterator
|
||||||
|
- const_iterator
|
||||||
|
- reverse_iterator
|
||||||
|
- const_reverse_iterator
|
||||||
|
|
||||||
|
### JSON value data types
|
||||||
|
|
||||||
|
- object_comparator_t
|
||||||
|
- object_t
|
||||||
|
- array_t
|
||||||
|
- string_t
|
||||||
|
- boolean_t
|
||||||
|
- number_integer_t
|
||||||
|
- number_unsigned_t
|
||||||
|
- number_float_t
|
||||||
|
- binary_t
|
||||||
|
|
||||||
|
### Parser callback
|
||||||
|
|
||||||
|
- parse_event_t
|
||||||
|
- parser_callback_t
|
||||||
|
|
||||||
|
## Member functions
|
||||||
|
|
||||||
|
- (constructor)
|
||||||
|
- (destructor)
|
||||||
|
- binary (static) - explicitly create a binary array
|
||||||
|
- array (static) - explicitly create an array
|
||||||
|
- object (static) - explicitly create an object
|
||||||
|
- operator= - copy assignment
|
||||||
|
|
||||||
|
### Object inspection
|
||||||
|
|
||||||
|
Functions to inspect the type of a JSON value.
|
||||||
|
|
||||||
|
- type - return the type of the JSON value
|
||||||
|
- is_primitive - return whether type is primitive
|
||||||
|
- is_structured - return whether type is structured
|
||||||
|
- is_null - return whether value is null
|
||||||
|
- is_boolean - return whether value is a boolean
|
||||||
|
- is_number - return whether value is a number
|
||||||
|
- is_number_integer - return whether value is an integer number
|
||||||
|
- is_number_unsigned - return whether value is an unsigned integer number
|
||||||
|
- is_number_float - return whether value is a floating-point number
|
||||||
|
- is_object - return whether value is an object
|
||||||
|
- is_array - return whether value is an array
|
||||||
|
- is_string - return whether value is a string
|
||||||
|
- is_binary - return whether value is a binary array
|
||||||
|
- is_discarded - return whether value is discarded
|
||||||
|
- operator value_t - return the type of the JSON value
|
||||||
|
|
||||||
|
### Value access
|
||||||
|
|
||||||
|
Direct access to the stored value of a JSON value.
|
||||||
|
|
||||||
|
- get - get a value
|
||||||
|
- get_to - get a value
|
||||||
|
- get_ptr - get a pointer value
|
||||||
|
- get_ref - get a reference value
|
||||||
|
- operator ValueType - get a value
|
||||||
|
- get_binary - get a binary value
|
||||||
|
|
||||||
|
### Element access
|
||||||
|
|
||||||
|
Access to the JSON value
|
||||||
|
|
||||||
|
- at - access specified array element with bounds checking
|
||||||
|
- at - access specified object element with bounds checking
|
||||||
|
- operator[] - access specified array element
|
||||||
|
- operator[] - access specified object element
|
||||||
|
- value - access specified object element with default value
|
||||||
|
- front - access the first element
|
||||||
|
- back - access the last element
|
||||||
|
- erase - remove elements
|
||||||
|
|
||||||
|
### Lookup
|
||||||
|
|
||||||
|
- find - find an element in a JSON object
|
||||||
|
- count - returns the number of occurrences of a key in a JSON object
|
||||||
|
- contains - check the existence of an element in a JSON object
|
||||||
|
|
||||||
|
### Iterators
|
||||||
|
|
||||||
|
- begin - returns an iterator to the first element
|
||||||
|
- cbegin - returns a const iterator to the first element
|
||||||
|
- end - returns an iterator to one past the last element
|
||||||
|
- cend - returns a const iterator to one past the last element
|
||||||
|
- rbegin - returns an iterator to the reverse-beginning
|
||||||
|
- rend - returns an iterator to the reverse-end
|
||||||
|
- crbegin - returns a const iterator to the reverse-beginning
|
||||||
|
- crend - returns a const iterator to the reverse-end
|
||||||
|
- items - wrapper to access iterator member functions in range-based for
|
||||||
|
|
||||||
|
### Capacity
|
||||||
|
|
||||||
|
- empty - checks whether the container is empty
|
||||||
|
- size - returns the number of elements
|
||||||
|
- max_size - returns the maximum possible number of elements
|
||||||
|
|
||||||
|
### Modifiers
|
||||||
|
|
||||||
|
- clear - clears the contents
|
||||||
|
- push_back - add an object to an array
|
||||||
|
- operator+= - add an object to an array
|
||||||
|
- push_back - add an object to an object
|
||||||
|
- operator+= - add an object to an object
|
||||||
|
- emplace_back - add an object to an array
|
||||||
|
- emplace - add an object to an object if key does not exist
|
||||||
|
- insert - inserts element
|
||||||
|
- update - updates a JSON object from another object, overwriting existing keys
|
||||||
|
- swap - exchanges the values
|
||||||
|
|
||||||
|
### Lexicographical comparison operators
|
||||||
|
|
||||||
|
- operator== - comparison: equal
|
||||||
|
- operator!= - comparison: not equal
|
||||||
|
- operator< - comparison: less than
|
||||||
|
- operator<= - comparison: less than or equal
|
||||||
|
- operator> - comparison: greater than
|
||||||
|
- operator>= - comparison: greater than or equal
|
||||||
|
|
||||||
|
### Serialization
|
||||||
|
|
||||||
|
- [**dump**](dump.md) - serialization
|
||||||
|
- to_string - user-defined to_string function for JSON values
|
||||||
|
|
||||||
|
### Deserialization
|
||||||
|
|
||||||
|
- [**parse**](parse.md) - deserialize from a compatible input
|
||||||
|
- accept - check if the input is valid JSON
|
||||||
|
- sax_parse - generate SAX events
|
||||||
|
|
||||||
|
### Convenience functions
|
||||||
|
|
||||||
|
- type_name - return the type as string
|
||||||
|
|
||||||
|
### JSON Pointer functions
|
||||||
|
|
||||||
|
- at - access specified object element with bounds checking via JSON Pointer
|
||||||
|
- operator[] - access specified element via JSON Pointer
|
||||||
|
- value - access specified object element with default value via JSON Pointer
|
||||||
|
- flatten - return flattened JSON value
|
||||||
|
- unflatten - unflatten a previously flattened JSON value
|
||||||
|
|
||||||
|
### JSON Patch functions
|
||||||
|
|
||||||
|
- patch - applies a JSON patch
|
||||||
|
- diff (static) - creates a diff as a JSON patch
|
||||||
|
|
||||||
|
### JSON Merge Patch functions
|
||||||
|
|
||||||
|
- merge_patch - applies a JSON Merge Patch
|
||||||
|
|
||||||
|
## Static functions
|
||||||
|
|
||||||
|
- [**meta**](meta.md) - returns version information on the library
|
||||||
|
- get_allocator - returns the allocator associated with the container
|
||||||
|
|
||||||
|
### Binary formats
|
||||||
|
|
||||||
|
- to_cbor - create a CBOR serialization of a given JSON value
|
||||||
|
- to_msgpack - create a MessagePack serialization of a given JSON value
|
||||||
|
- to_ubjson - create a UBJSON serialization of a given JSON value
|
||||||
|
- to_bson - create a BSON serialization of a given JSON value
|
||||||
|
- from_cbor - create a JSON value from an input in CBOR format
|
||||||
|
- from_msgpack - create a JSON value from an input in MessagePack format
|
||||||
|
- from_ubjson - create a JSON value from an input in UBJSON format
|
||||||
|
- from_bson - create a JSON value from an input in BSON format
|
||||||
|
|
||||||
|
## Non-member functions
|
||||||
|
|
||||||
|
- operator<<(std::ostream&) - serialize to stream
|
||||||
|
- operator>>(std::istream&) - deserialize from stream
|
||||||
|
|
||||||
|
## Literals
|
||||||
|
|
||||||
|
- operator""_json
|
||||||
|
- operator""_json_pointer
|
||||||
|
|
||||||
|
## Helper classes
|
||||||
|
|
||||||
|
- std::hash<nlohmann::json\>
|
||||||
|
- std::less<nlohmann::value_t\>
|
||||||
|
- std::swap<nlohmann::json\>
|
45
doc/mkdocs/docs/api/basic_json/meta.md
Normal file
45
doc/mkdocs/docs/api/basic_json/meta.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# basic_json::meta
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
static basic_json meta();
|
||||||
|
```
|
||||||
|
|
||||||
|
This function returns a JSON object with information about the library,
|
||||||
|
including the version number and information on the platform and compiler.
|
||||||
|
|
||||||
|
## Return value
|
||||||
|
|
||||||
|
JSON object holding version information
|
||||||
|
|
||||||
|
key | description
|
||||||
|
----------- | ---------------
|
||||||
|
`compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
|
||||||
|
`copyright` | The copyright line for the library as string.
|
||||||
|
`name` | The name of the library as string.
|
||||||
|
`platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
|
||||||
|
`url` | The URL of the project as string.
|
||||||
|
`version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
Strong guarantee: if an exception is thrown, there are no
|
||||||
|
changes to any JSON value.
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
Constant.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
The following code shows an example output of the `meta()`
|
||||||
|
function.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/meta.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/meta.output"
|
||||||
|
```
|
146
doc/mkdocs/docs/api/basic_json/parse.md
Normal file
146
doc/mkdocs/docs/api/basic_json/parse.md
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
# basic_json::parse
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// (1)
|
||||||
|
template<typename InputType>
|
||||||
|
static basic_json parse(InputType&& i,
|
||||||
|
const parser_callback_t cb = nullptr,
|
||||||
|
const bool allow_exceptions = true,
|
||||||
|
const bool ignore_comments = false)
|
||||||
|
|
||||||
|
// (2)
|
||||||
|
template<typename IteratorType>
|
||||||
|
static basic_json parse(IteratorType first,
|
||||||
|
IteratorType last,
|
||||||
|
const parser_callback_t cb = nullptr,
|
||||||
|
const bool allow_exceptions = true,
|
||||||
|
const bool ignore_comments = false)
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Deserialize from a compatible input.
|
||||||
|
2. Deserialize from a pair of character iterators
|
||||||
|
|
||||||
|
The value_type of the iterator must be a integral type with size of 1, 2 or
|
||||||
|
4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
|
||||||
|
|
||||||
|
## Template parameters
|
||||||
|
|
||||||
|
`InputType`
|
||||||
|
: A compatible input, for instance:
|
||||||
|
|
||||||
|
- an `std::istream` object
|
||||||
|
- a `FILE` pointer
|
||||||
|
- a C-style array of characters
|
||||||
|
- a pointer to a null-terminated string of single byte characters
|
||||||
|
- an object `obj` for which `begin(obj)` and `end(obj)` produces a valid pair of
|
||||||
|
iterators.
|
||||||
|
|
||||||
|
`IteratorType`
|
||||||
|
: Description
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
`i` (in)
|
||||||
|
: Input to parse from.
|
||||||
|
|
||||||
|
`cb` (in)
|
||||||
|
: a parser callback function of type `parser_callback_t`
|
||||||
|
which is used to control the deserialization by filtering unwanted values
|
||||||
|
(optional)
|
||||||
|
|
||||||
|
`allow_exceptions` (in)
|
||||||
|
: whether to throw exceptions in case of a parse error (optional, `#!cpp true` by default)
|
||||||
|
|
||||||
|
`ignore_comments` (in)
|
||||||
|
: whether comments should be ignored and treated
|
||||||
|
like whitespace (`#!cpp true`) or yield a parse error (`#!cpp false`); (optional, `#!cpp false` by
|
||||||
|
default)
|
||||||
|
|
||||||
|
`first` (in)
|
||||||
|
: iterator to start of character range
|
||||||
|
|
||||||
|
`last` (in)
|
||||||
|
: iterator to end of character range
|
||||||
|
|
||||||
|
## Return value
|
||||||
|
|
||||||
|
Deserialized JSON value; in case of a parse error and `allow_exceptions`
|
||||||
|
set to `#!cpp false`, the return value will be `value_t::discarded`.
|
||||||
|
|
||||||
|
## Exception safety
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
Linear in the length of the input. The parser is a predictive
|
||||||
|
LL(1) parser. The complexity can be higher if the parser callback function
|
||||||
|
`cb` or reading from (1) the input `i` or (2) the iterator range [`first`, `last`] has a super-linear complexity.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
(1) A UTF-8 byte order mark is silently ignored.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The example below demonstrates the `parse()` function reading
|
||||||
|
from an array.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/parse__array__parser_callback_t.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/parse__array__parser_callback_t.output"
|
||||||
|
```
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The example below demonstrates the `parse()` function with
|
||||||
|
and without callback function.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/parse__string__parser_callback_t.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/parse__string__parser_callback_t.output"
|
||||||
|
```
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The example below demonstrates the `parse()` function with
|
||||||
|
and without callback function.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/parse__istream__parser_callback_t.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/parse__istream__parser_callback_t.output"
|
||||||
|
```
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The example below demonstrates the `parse()` function reading
|
||||||
|
from a contiguous container.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
--8<-- "examples/parse__contiguouscontainer__parser_callback_t.cpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
--8<-- "examples/parse__contiguouscontainer__parser_callback_t.output"
|
||||||
|
```
|
||||||
|
|
||||||
|
## History
|
||||||
|
|
||||||
|
(1) version 2.0.3 (contiguous containers); version 3.9.0 allowed to ignore comments.
|
|
@ -81,6 +81,47 @@ Some important things:
|
||||||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
||||||
|
|
||||||
|
|
||||||
|
## Simplify your life with macros
|
||||||
|
|
||||||
|
If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.
|
||||||
|
|
||||||
|
There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
|
||||||
|
|
||||||
|
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
|
||||||
|
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.
|
||||||
|
|
||||||
|
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The `to_json`/`from_json` functions for the `person` struct above can be created with:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ns {
|
||||||
|
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace ns {
|
||||||
|
class address {
|
||||||
|
private:
|
||||||
|
std::string street;
|
||||||
|
int housenumber;
|
||||||
|
int postcode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## How do I convert third-party types?
|
## How do I convert third-party types?
|
||||||
|
|
||||||
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
|
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
|
||||||
|
|
|
@ -64,7 +64,6 @@ binary | *size*: 4294967296..18446744073709551615 | byte string (8 by
|
||||||
|
|
||||||
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
If NaN or Infinity are stored inside a JSON number, they are serialized properly. This behavior differs from the normal JSON serialization which serializes NaN or Infinity to `null`.
|
||||||
|
|
||||||
|
|
||||||
!!! info "Unused CBOR types"
|
!!! info "Unused CBOR types"
|
||||||
|
|
||||||
The following CBOR types are not used in the conversion:
|
The following CBOR types are not used in the conversion:
|
||||||
|
@ -77,13 +76,16 @@ binary | *size*: 4294967296..18446744073709551615 | byte string (8 by
|
||||||
- bignum (0xC2..0xC3)
|
- bignum (0xC2..0xC3)
|
||||||
- decimal fraction (0xC4)
|
- decimal fraction (0xC4)
|
||||||
- bigfloat (0xC5)
|
- bigfloat (0xC5)
|
||||||
- tagged items (0xC6..0xD4, 0xD8..0xDB)
|
|
||||||
- expected conversions (0xD5..0xD7)
|
- expected conversions (0xD5..0xD7)
|
||||||
- simple values (0xE0..0xF3, 0xF8)
|
- simple values (0xE0..0xF3, 0xF8)
|
||||||
- undefined (0xF7)
|
- undefined (0xF7)
|
||||||
- half-precision floats (0xF9)
|
- half-precision floats (0xF9)
|
||||||
- break (0xFF)
|
- break (0xFF)
|
||||||
|
|
||||||
|
!!! info "Tagged items"
|
||||||
|
|
||||||
|
Binary subtypes will be serialized as tagged items. See [binary values](../binary_values.md#cbor) for an example.
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
@ -150,7 +152,6 @@ Double-Precision Float | number_float | 0xFB
|
||||||
- bignum (0xC2..0xC3)
|
- bignum (0xC2..0xC3)
|
||||||
- decimal fraction (0xC4)
|
- decimal fraction (0xC4)
|
||||||
- bigfloat (0xC5)
|
- bigfloat (0xC5)
|
||||||
- tagged items (0xC6..0xD4, 0xD8..0xDB)
|
|
||||||
- expected conversions (0xD5..0xD7)
|
- expected conversions (0xD5..0xD7)
|
||||||
- simple values (0xE0..0xF3, 0xF8)
|
- simple values (0xE0..0xF3, 0xF8)
|
||||||
- undefined (0xF7)
|
- undefined (0xF7)
|
||||||
|
@ -159,6 +160,10 @@ Double-Precision Float | number_float | 0xFB
|
||||||
|
|
||||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
||||||
|
|
||||||
|
!!! warning "Tagged items"
|
||||||
|
|
||||||
|
Tagged items will throw a parse error by default. However, they can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`.
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
|
|
@ -31,7 +31,8 @@ number_unsigned | 128..255 | uint 8 | 0xCC
|
||||||
number_unsigned | 256..65535 | uint 16 | 0xCD
|
number_unsigned | 256..65535 | uint 16 | 0xCD
|
||||||
number_unsigned | 65536..4294967295 | uint 32 | 0xCE
|
number_unsigned | 65536..4294967295 | uint 32 | 0xCE
|
||||||
number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
|
number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
|
||||||
number_float | *any value* | float 64 | 0xCB
|
number_float | *any value representable by a float* | float 32 | 0xCA
|
||||||
|
number_float | *any value NOT representable by a float* | float 64 | 0xCB
|
||||||
string | *length*: 0..31 | fixstr | 0xA0..0xBF
|
string | *length*: 0..31 | fixstr | 0xA0..0xBF
|
||||||
string | *length*: 32..255 | str 8 | 0xD9
|
string | *length*: 32..255 | str 8 | 0xD9
|
||||||
string | *length*: 256..65535 | str 16 | 0xDA
|
string | *length*: 256..65535 | str 16 | 0xDA
|
||||||
|
@ -61,10 +62,6 @@ binary | *size*: 65536..4294967295 | bin 32 | 0xC6
|
||||||
- arrays with more than 4294967295 elements
|
- arrays with more than 4294967295 elements
|
||||||
- objects with more than 4294967295 elements
|
- objects with more than 4294967295 elements
|
||||||
|
|
||||||
!!! info "Unused MessagePack types"
|
|
||||||
|
|
||||||
The following MessagePack types are not used in the conversion: float 32 (0xCA)
|
|
||||||
|
|
||||||
!!! info "NaN/infinity handling"
|
!!! info "NaN/infinity handling"
|
||||||
|
|
||||||
If NaN or Infinity are stored inside a JSON number, they are serialized properly. function which serializes NaN or Infinity to `null`.
|
If NaN or Infinity are stored inside a JSON number, they are serialized properly. function which serializes NaN or Infinity to `null`.
|
||||||
|
|
|
@ -28,6 +28,7 @@ number_unsigned | 128..255 | uint8 | `U`
|
||||||
number_unsigned | 256..32767 | int16 | `I`
|
number_unsigned | 256..32767 | int16 | `I`
|
||||||
number_unsigned | 32768..2147483647 | int32 | `l`
|
number_unsigned | 32768..2147483647 | int32 | `l`
|
||||||
number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
|
number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
|
||||||
|
number_unsigned | 2147483649..18446744073709551615 | high-precision | `H`
|
||||||
number_float | *any value* | float64 | `D`
|
number_float | *any value* | float64 | `D`
|
||||||
string | *with shortest length indicator* | string | `S`
|
string | *with shortest length indicator* | string | `S`
|
||||||
array | *see notes on optimized format* | array | `[`
|
array | *see notes on optimized format* | array | `[`
|
||||||
|
@ -44,7 +45,6 @@ object | *see notes on optimized format* | map | `{`
|
||||||
The following values can **not** be converted to a UBJSON value:
|
The following values can **not** be converted to a UBJSON value:
|
||||||
|
|
||||||
- strings with more than 9223372036854775807 bytes (theoretical)
|
- strings with more than 9223372036854775807 bytes (theoretical)
|
||||||
- unsigned integer numbers above 9223372036854775807
|
|
||||||
|
|
||||||
!!! info "Unused UBJSON markers"
|
!!! info "Unused UBJSON markers"
|
||||||
|
|
||||||
|
|
|
@ -158,14 +158,14 @@ JSON does not have a binary type, and this library does not introduce a new type
|
||||||
|
|
||||||
### CBOR
|
### CBOR
|
||||||
|
|
||||||
[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Any binary value will be serialized as byte strings. The library will choose the smallest representation using the length of the byte array.
|
[CBOR](binary_formats/cbor.md) supports binary values, but no subtypes. Subtypes will be serialized as tags. Any binary value will be serialized as byte strings. The library will choose the smallest representation using the length of the byte array.
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
Code:
|
Code:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// create a binary value of subtype 42 (will be ignored by CBOR)
|
// create a binary value of subtype 42
|
||||||
json j;
|
json j;
|
||||||
j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42);
|
j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42);
|
||||||
|
|
||||||
|
@ -173,17 +173,18 @@ JSON does not have a binary type, and this library does not introduce a new type
|
||||||
auto v = json::to_cbor(j);
|
auto v = json::to_cbor(j);
|
||||||
```
|
```
|
||||||
|
|
||||||
`v` is a `std::vector<std::uint8t>` with the following 13 elements:
|
`v` is a `std::vector<std::uint8t>` with the following 15 elements:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
0xA1 // map(1)
|
0xA1 // map(1)
|
||||||
0x66 // text(6)
|
0x66 // text(6)
|
||||||
0x62 0x69 0x6E 0x61 0x72 0x79 // "binary"
|
0x62 0x69 0x6E 0x61 0x72 0x79 // "binary"
|
||||||
|
0xD8 0x2A // tag(42)
|
||||||
0x44 // bytes(4)
|
0x44 // bytes(4)
|
||||||
0xCA 0xFE 0xBA 0xBE // content
|
0xCA 0xFE 0xBA 0xBE // content
|
||||||
```
|
```
|
||||||
|
|
||||||
Note the subtype (42) is **not** serialized, and deserializing `v` would yield the following value:
|
Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless `json::cbor_tag_handler_t::ignore` is passed to `json::from_cbor`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
83
doc/mkdocs/docs/features/comments.md
Normal file
83
doc/mkdocs/docs/features/comments.md
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
# Comments
|
||||||
|
|
||||||
|
This library does not support comments *by default*. It does so for three reasons:
|
||||||
|
|
||||||
|
1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript.
|
||||||
|
2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012:
|
||||||
|
|
||||||
|
> I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't.
|
||||||
|
|
||||||
|
> Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser.
|
||||||
|
|
||||||
|
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
|
||||||
|
|
||||||
|
However, you can pass set parameter `ignore_comments` to `#!c true` in the parse function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
|
||||||
|
|
||||||
|
!!! example
|
||||||
|
|
||||||
|
Consider the following JSON with comments.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
// update in 2006: removed Pluto
|
||||||
|
"planets": ["Mercury", "Venus", "Earth", "Mars",
|
||||||
|
"Jupiter", "Uranus", "Neptune" /*, "Pluto" */]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When calling `parse` without additional argument, a parse error exception is thrown. If `skip_comments` is set to `#! true`, the comments are skipped during parsing:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <iostream>
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::string s = R"(
|
||||||
|
{
|
||||||
|
// update in 2006: removed Pluto
|
||||||
|
"planets": ["Mercury", "Venus", "Earth", "Mars",
|
||||||
|
"Jupiter", "Uranus", "Neptune" /*, "Pluto" */]
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json j = json::parse(s);
|
||||||
|
}
|
||||||
|
catch (json::exception &e)
|
||||||
|
{
|
||||||
|
std::cout << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
json j = json::parse(s,
|
||||||
|
/* callback */ nullptr,
|
||||||
|
/* allow exceptions */ true,
|
||||||
|
/* skip_comments */ true);
|
||||||
|
std::cout << j.dump(2) << '\n';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
[json.exception.parse_error.101] parse error at line 3, column 9:
|
||||||
|
syntax error while parsing object key - invalid literal;
|
||||||
|
last read: '<U+000A> {<U+000A> /'; expected string literal
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"planets": [
|
||||||
|
"Mercury",
|
||||||
|
"Venus",
|
||||||
|
"Earth",
|
||||||
|
"Mars",
|
||||||
|
"Jupiter",
|
||||||
|
"Uranus",
|
||||||
|
"Neptune"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
77
doc/mkdocs/docs/features/element_access/checked_access.md
Normal file
77
doc/mkdocs/docs/features/element_access/checked_access.md
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# Checked access: at
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `#!cpp at()` member function performs checked access; that is, it returns a reference to the desired value if it exists and throws a [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) otherwise.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
Consider the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Mary Smith",
|
||||||
|
"age": 42,
|
||||||
|
"hobbies": ["hiking", "reading"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Assume the value is parsed to a `json` variable `j`.
|
||||||
|
|
||||||
|
| expression | value |
|
||||||
|
| ---------- | ----- |
|
||||||
|
| `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` |
|
||||||
|
| `#!cpp j.at("name")` | `#!json "Mary Smith"` |
|
||||||
|
| `#!cpp j.at("age")` | `#!json 42` |
|
||||||
|
| `#!cpp j.at("hobbies")` | `#!json ["hiking", "reading"]` |
|
||||||
|
| `#!cpp j.at("hobbies").at(0)` | `#!json "hiking"` |
|
||||||
|
| `#!cpp j.at("hobbies").at(1)` | `#!json "reading"` |
|
||||||
|
|
||||||
|
The return value is a reference, so it can be modify the original value.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
j.at("name") = "John Smith";
|
||||||
|
```
|
||||||
|
|
||||||
|
This code produces the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "John Smith",
|
||||||
|
"age": 42,
|
||||||
|
"hobbies": ["hiking", "reading"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When accessing an invalid index (i.e., and index greater than or equal to the array size) or the passed object key is non-existing, an exception is thrown.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
j.at("hobbies").at(3) = "cooking";
|
||||||
|
```
|
||||||
|
|
||||||
|
This code produces the following exception:
|
||||||
|
|
||||||
|
```
|
||||||
|
[json.exception.out_of_range.401] array index 3 is out of range
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
|
||||||
|
!!! failure "Exceptions"
|
||||||
|
|
||||||
|
- `at` can only be used with objects (with a string argument) or with arrays (with a numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error304) is thrown.
|
||||||
|
- [`basic_json::out_of_range` exception](../../home/exceptions.md#out-of-range) exceptions are thrown if the provided key is not found in an object or the provided index is invalid.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| scenario | non-const value | const value |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| access to existing object key | reference to existing value is returned | const reference to existing value is returned |
|
||||||
|
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
|
||||||
|
| access to non-existing object key | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown |
|
||||||
|
| access to invalid array index | `basic_json::out_of_range` exception is thrown | `basic_json::out_of_range` exception is thrown |
|
32
doc/mkdocs/docs/features/element_access/default_value.md
Normal file
32
doc/mkdocs/docs/features/element_access/default_value.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Access with default value: value
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
In many situations such as configuration files, missing values are not exceptional, but may be treated as if a default value was present.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
Consider the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"logOutput": "result.log",
|
||||||
|
"append": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Assume the value is parsed to a `json` variable `j`.
|
||||||
|
|
||||||
|
| expression | value |
|
||||||
|
| ---------- | ----- |
|
||||||
|
| `#!cpp j` | `#!json {"logOutput": "result.log", "append": true}` |
|
||||||
|
| `#!cpp j.value("logOutput", "logfile.log")` | `#!json "result.log"` |
|
||||||
|
| `#!cpp j.value("append", true)` | `#!json true` |
|
||||||
|
| `#!cpp j.value("append", false)` | `#!json true` |
|
||||||
|
| `#!cpp j.value("logLevel", "verbose")` | `#!json "verbose"` |
|
||||||
|
|
||||||
|
## Note
|
||||||
|
|
||||||
|
!!! failure "Exceptions"
|
||||||
|
|
||||||
|
- `value` can only be used with objects. For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error306) is thrown.
|
9
doc/mkdocs/docs/features/element_access/index.md
Normal file
9
doc/mkdocs/docs/features/element_access/index.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
There are many ways elements in a JSON value can be accessed:
|
||||||
|
|
||||||
|
- unchecked access via [`operator[]`](unchecked_access.md)
|
||||||
|
- checked access via [`at`](checked_access.md)
|
||||||
|
- access with default value via [`value`](default_value.md)
|
||||||
|
- iterators
|
||||||
|
- JSON pointers
|
102
doc/mkdocs/docs/features/element_access/unchecked_access.md
Normal file
102
doc/mkdocs/docs/features/element_access/unchecked_access.md
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
# Unchecked access: operator[]
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Elements in a JSON object and a JSON array can be accessed via `#!cpp operator[]` similar to a `#!cpp std::map` and a `#!cpp std::vector`, respectively.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
Consider the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "Mary Smith",
|
||||||
|
"age": 42,
|
||||||
|
"hobbies": ["hiking", "reading"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Assume the value is parsed to a `json` variable `j`.
|
||||||
|
|
||||||
|
| expression | value |
|
||||||
|
| ---------- | ----- |
|
||||||
|
| `#!cpp j` | `#!json {"name": "Mary Smith", "age": 42, "hobbies": ["hiking", "reading"]}` |
|
||||||
|
| `#!cpp j["name"]` | `#!json "Mary Smith"` |
|
||||||
|
| `#!cpp j["age"]` | `#!json 42` |
|
||||||
|
| `#!cpp j["hobbies"]` | `#!json ["hiking", "reading"]` |
|
||||||
|
| `#!cpp j["hobbies"][0]` | `#!json "hiking"` |
|
||||||
|
| `#!cpp j["hobbies"][1]` | `#!json "reading"` |
|
||||||
|
|
||||||
|
The return value is a reference, so it can be modify the original value. In case the passed object key is non-existing, a `#!json null` value is inserted which can be immediately be overwritten.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
j["name"] = "John Smith";
|
||||||
|
j["maidenName"] = "Jones";
|
||||||
|
```
|
||||||
|
|
||||||
|
This code produces the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "John Smith",
|
||||||
|
"maidenName": "Jones",
|
||||||
|
"age": 42,
|
||||||
|
"hobbies": ["hiking", "reading"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When accessing an invalid index (i.e., and index greater than or equal to the array size), the JSON array is resized such that the passed index is the new maximal index. Intermediate values are filled with `#!json null`.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
j["hobbies"][0] = "running";
|
||||||
|
j["hobbies"][3] = "cooking";
|
||||||
|
```
|
||||||
|
|
||||||
|
This code produces the following JSON value:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "John Smith",
|
||||||
|
"maidenName": "Jones",
|
||||||
|
"age": 42,
|
||||||
|
"hobbies": ["running", "reading", null, "cooking"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
!!! info "Design rationale"
|
||||||
|
|
||||||
|
The library behaves differently to `#!cpp std::vector` and `#!cpp std::map`:
|
||||||
|
|
||||||
|
- `#!cpp std::vector::operator[]` never inserts a new element.
|
||||||
|
- `#!cpp std::map::operator[]` is not available for const values.
|
||||||
|
|
||||||
|
The type `#!cpp json` wraps all JSON value types. It would be impossible to remove `operator[]` for const objects. At the same time, inserting elements for non-const objects is really convenient as it avoids awkward `insert` calls. To this end, we decided to have an inserting non-const behavior for both arrays and objects.
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
|
||||||
|
The access is unchecked. In case the passed object key does not exist or the passed array index is invalid, no exception is thrown.
|
||||||
|
|
||||||
|
!!! danger
|
||||||
|
|
||||||
|
- It is **undefined behavior** to access a const object with a non-existing key.
|
||||||
|
- It is **undefined behavior** to access a const array with an invalid index.
|
||||||
|
- In debug mode, an **assertion** will fire in both cases. You can disable assertions by defining the preprocessor symbol `#!cpp NDEBUG` or redefine the macro [`JSON_ASSERT(x)`](../macros.md#json_assertx).
|
||||||
|
|
||||||
|
!!! failure "Exceptions"
|
||||||
|
|
||||||
|
`operator[]` can only be used with objects (with a string argument) or with arrays (with a numeric argument). For other types, a [`basic_json::type_error`](../../home/exceptions.md#jsonexceptiontype_error305) is thrown.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
| scenario | non-const value | const value |
|
||||||
|
| -------- | ------------- | ----------- |
|
||||||
|
| access to existing object key | reference to existing value is returned | const reference to existing value is returned |
|
||||||
|
| access to valid array index | reference to existing value is returned | const reference to existing value is returned |
|
||||||
|
| access to non-existing object key | reference to newly inserted `#!json null` value is returned | **undefined behavior**; assertion in debug mode |
|
||||||
|
| access to invalid array index | reference to newly inserted `#!json null` value is returned; any index between previous maximal index and passed index are filled with `#!json null` | **undefined behavior**; assertion in debug mode |
|
79
doc/mkdocs/docs/features/macros.md
Normal file
79
doc/mkdocs/docs/features/macros.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Supported Macros
|
||||||
|
|
||||||
|
Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header.
|
||||||
|
|
||||||
|
## `JSON_ASSERT(x)`
|
||||||
|
|
||||||
|
The default value is `#!cpp assert(x)`.
|
||||||
|
|
||||||
|
## `JSON_CATCH_USER(exception)`
|
||||||
|
|
||||||
|
This macro overrides `#!cpp catch` calls inside the library. The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range` exceptions internally to rethrow them as [`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The macro is always followed by a scope.
|
||||||
|
|
||||||
|
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
|
||||||
|
|
||||||
|
## `JSON_NOEXCEPTION`
|
||||||
|
|
||||||
|
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
|
||||||
|
When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`,
|
||||||
|
`#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by `#!cpp std::abort()`.
|
||||||
|
|
||||||
|
The same effect is achieved by setting the compiler flag `-fno-exceptions`.
|
||||||
|
|
||||||
|
## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
|
||||||
|
|
||||||
|
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
|
||||||
|
|
||||||
|
## `JSON_THROW_USER(exception)`
|
||||||
|
|
||||||
|
This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
||||||
|
|
||||||
|
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
|
||||||
|
|
||||||
|
## `JSON_TRY_USER`
|
||||||
|
|
||||||
|
This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
|
||||||
|
|
||||||
|
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
|
||||||
|
|
||||||
|
## `JSON_USE_IMPLICIT_CONVERSIONS`
|
||||||
|
|
||||||
|
When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
This is an example for an implicit conversion:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
json j = "Hello, world!";
|
||||||
|
std::string s = j;
|
||||||
|
```
|
||||||
|
|
||||||
|
When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be written like this:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
json j = "Hello, world!";
|
||||||
|
auto s = j.get<std::string>();
|
||||||
|
```
|
||||||
|
|
||||||
|
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
|
||||||
|
|
||||||
|
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.
|
||||||
|
|
||||||
|
The macro is to be defined inside of the class/struct to create code for. Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members.
|
||||||
|
The first parameter is the name of the class/struct, and all remaining parameters name the members.
|
||||||
|
|
||||||
|
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
|
||||||
|
|
||||||
|
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
|
||||||
|
|
||||||
|
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.
|
||||||
|
|
||||||
|
The macro is to be defined inside of the namespace of the class/struct to create code for. Private members cannot be accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios.
|
||||||
|
The first parameter is the name of the class/struct, and all remaining parameters name the members.
|
||||||
|
|
||||||
|
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
|
||||||
|
|
||||||
|
## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
|
||||||
|
|
||||||
|
This macro simplifies the serialization/deserialization of enum types. See [Specializing enum conversion](enum_conversion.md) for more information.
|
67
doc/mkdocs/docs/features/object_order.md
Normal file
67
doc/mkdocs/docs/features/object_order.md
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Object Order
|
||||||
|
|
||||||
|
The [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs". As such, an implementation does not need to preserve any specific order of object keys.
|
||||||
|
|
||||||
|
The default type `nlohmann::json` uses a `std::map` to store JSON objects, and thus stores object keys **sorted alphabetically**.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <iostream>
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["one"] = 1;
|
||||||
|
j["two"] = 2;
|
||||||
|
j["three"] = 3;
|
||||||
|
|
||||||
|
std::cout << j.dump(2) << '\n';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"one": 1,
|
||||||
|
"three": 3,
|
||||||
|
"two": 2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do want to preserve the **insertion order**, you can try the type [`nlohmann::ordered_json`](https://github.com/nlohmann/json/issues/2179).
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <iostream>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
using ordered_json = nlohmann::ordered_json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ordered_json j;
|
||||||
|
j["one"] = 1;
|
||||||
|
j["two"] = 2;
|
||||||
|
j["three"] = 3;
|
||||||
|
|
||||||
|
std::cout << j.dump(2) << '\n';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"one": 1,
|
||||||
|
"two": 2,
|
||||||
|
"three": 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can use a more sophisticated ordered map like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
|
@ -14,6 +14,7 @@ interface json::sax_t {
|
||||||
+ {abstract} bool number_float(number_float_t val, const string_t& s)
|
+ {abstract} bool number_float(number_float_t val, const string_t& s)
|
||||||
|
|
||||||
+ {abstract} bool string(string_t& val)
|
+ {abstract} bool string(string_t& val)
|
||||||
|
+ {abstract} bool binary(binary_t& val)
|
||||||
|
|
||||||
+ {abstract} bool start_object(std::size_t elements)
|
+ {abstract} bool start_object(std::size_t elements)
|
||||||
+ {abstract} bool end_object()
|
+ {abstract} bool end_object()
|
||||||
|
@ -41,6 +42,8 @@ bool number_float(number_float_t val, const string_t& s);
|
||||||
|
|
||||||
// called when a string is parsed; value is passed and can be safely moved away
|
// called when a string is parsed; value is passed and can be safely moved away
|
||||||
bool string(string_t& val);
|
bool string(string_t& val);
|
||||||
|
// called when a binary value is parsed; value is passed and can be safely moved away
|
||||||
|
bool binary(binary& val);
|
||||||
|
|
||||||
// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
|
// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
|
||||||
bool start_object(std::size_t elements);
|
bool start_object(std::size_t elements);
|
||||||
|
|
|
@ -32,6 +32,24 @@ Exceptions are used widely within the library. They can, however, be switched of
|
||||||
|
|
||||||
Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The code below switches off exceptions and creates a log entry with a detailed error message in case of errors.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define JSON_TRY_USER if(true)
|
||||||
|
#define JSON_CATCH_USER(exception) if(false)
|
||||||
|
#define JSON_THROW_USER(exception) \
|
||||||
|
{std::clog << "Error in " << __FILE__ << ":" << __LINE__ \
|
||||||
|
<< " (function " << __FUNCTION__ << ") - " \
|
||||||
|
<< (exception).what() << std::endl; \
|
||||||
|
std::abort();}
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
```
|
||||||
|
|
||||||
## Parse errors
|
## Parse errors
|
||||||
|
|
||||||
This exception is thrown by the library when a parse error occurs. Parse errors
|
This exception is thrown by the library when a parse error occurs. Parse errors
|
||||||
|
@ -261,6 +279,16 @@ The parsing of the corresponding BSON record type is not implemented (yet).
|
||||||
[json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF
|
[json.exception.parse_error.114] parse error at byte 5: Unsupported BSON record type 0xFF
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### json.exception.parse_error.115
|
||||||
|
|
||||||
|
A UBJSON high-precision number could not be parsed.
|
||||||
|
|
||||||
|
!!! failure "Example message"
|
||||||
|
|
||||||
|
```
|
||||||
|
[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A
|
||||||
|
```
|
||||||
|
|
||||||
## Iterator errors
|
## Iterator errors
|
||||||
|
|
||||||
This exception is thrown if iterators passed to a library function do not match
|
This exception is thrown if iterators passed to a library function do not match
|
||||||
|
@ -747,6 +775,10 @@ UBJSON and BSON only support integer numbers up to 9223372036854775807.
|
||||||
number overflow serializing '9223372036854775808'
|
number overflow serializing '9223372036854775808'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
Since version 3.9.0, integer numbers beyond int64 are serialized as high-precision UBJSON numbers, and this exception does not further occur.
|
||||||
|
|
||||||
### json.exception.out_of_range.408
|
### json.exception.out_of_range.408
|
||||||
|
|
||||||
The size (following `#`) of an UBJSON array or object exceeds the maximal capacity.
|
The size (following `#`) of an UBJSON array or object exceeds the maximal capacity.
|
||||||
|
|
|
@ -2,31 +2,6 @@
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
### Comments
|
|
||||||
|
|
||||||
!!! question "Questions"
|
|
||||||
|
|
||||||
- Why does the library not support comments?
|
|
||||||
- Can you add support for JSON5/JSONC/HOCON so that comments are supported?
|
|
||||||
|
|
||||||
This library does not support comments. It does so for three reasons:
|
|
||||||
|
|
||||||
1. Comments are not part of the [JSON specification](https://tools.ietf.org/html/rfc8259). You may argue that `//` or `/* */` are allowed in JavaScript, but JSON is not JavaScript.
|
|
||||||
2. This was not an oversight: Douglas Crockford [wrote on this](https://plus.google.com/118095276221607585885/posts/RK8qyGVaGSr) in May 2012:
|
|
||||||
|
|
||||||
> I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't.
|
|
||||||
|
|
||||||
> Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser.
|
|
||||||
|
|
||||||
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
|
|
||||||
|
|
||||||
This library will not support comments in the future. If you wish to use comments, I see three options:
|
|
||||||
|
|
||||||
1. Strip comments before using this library.
|
|
||||||
2. Use a different JSON library with comment support.
|
|
||||||
3. Use a format that natively supports comments (e.g., YAML or JSON5).
|
|
||||||
|
|
||||||
|
|
||||||
### Relaxed parsing
|
### Relaxed parsing
|
||||||
|
|
||||||
!!! question
|
!!! question
|
||||||
|
@ -69,18 +44,6 @@ No, this is not possible. See <https://github.com/nlohmann/json/issues/932> for
|
||||||
## Serialization issues
|
## Serialization issues
|
||||||
|
|
||||||
|
|
||||||
### Order of object keys
|
|
||||||
|
|
||||||
!!! question "Questions"
|
|
||||||
|
|
||||||
- Why are object keys sorted?
|
|
||||||
- Why is the insertion order of object keys not preserved?
|
|
||||||
|
|
||||||
By default, the library does not preserve the **insertion order of object elements**. This is standards-compliant, as the [JSON standard](https://tools.ietf.org/html/rfc8259.html) defines objects as "an unordered collection of zero or more name/value pairs".
|
|
||||||
|
|
||||||
If you do want to preserve the insertion order, you can specialize the object type with containers like [`tsl::ordered_map`](https://github.com/Tessil/ordered-map) ([integration](https://github.com/nlohmann/json/issues/546#issuecomment-304447518)) or [`nlohmann::fifo_map`](https://github.com/nlohmann/fifo_map) ([integration](https://github.com/nlohmann/json/issues/485#issuecomment-333652309)).
|
|
||||||
|
|
||||||
|
|
||||||
### Number precision
|
### Number precision
|
||||||
|
|
||||||
!!! question
|
!!! question
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
|
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
|
||||||
|
|
||||||
Copyright © 2013-2019 [Niels Lohmann](http://nlohmann.me)
|
Copyright © 2013-2020 [Niels Lohmann](http://nlohmann.me)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,8 @@ import os.path
|
||||||
|
|
||||||
|
|
||||||
def copy_doxygen(*args, **kwargs):
|
def copy_doxygen(*args, **kwargs):
|
||||||
shutil.copytree('../html', os.path.join(kwargs['config']['site_dir'], 'doxygen'))
|
doxygen_dir = os.path.join(kwargs['config']['site_dir'], 'doxygen')
|
||||||
|
if not os.path.isdir(doxygen_dir) or not os.listdir(doxygen_dir):
|
||||||
|
print('Copy Doxygen files...')
|
||||||
|
shutil.copytree('../html', doxygen_dir)
|
||||||
print('Copy Doxygen complete')
|
print('Copy Doxygen complete')
|
||||||
|
|
|
@ -44,16 +44,24 @@ nav:
|
||||||
- features/binary_formats/messagepack.md
|
- features/binary_formats/messagepack.md
|
||||||
- features/binary_formats/ubjson.md
|
- features/binary_formats/ubjson.md
|
||||||
- features/binary_values.md
|
- features/binary_values.md
|
||||||
|
- features/comments.md
|
||||||
|
- Element Access:
|
||||||
|
- features/element_access/index.md
|
||||||
|
- features/element_access/unchecked_access.md
|
||||||
|
- features/element_access/checked_access.md
|
||||||
|
- features/element_access/default_value.md
|
||||||
- features/iterators.md
|
- features/iterators.md
|
||||||
- features/json_pointer.md
|
- features/json_pointer.md
|
||||||
- features/json_patch.md
|
- features/json_patch.md
|
||||||
- features/merge_patch.md
|
- features/merge_patch.md
|
||||||
- features/enum_conversion.md
|
- features/object_order.md
|
||||||
- Parsing:
|
- Parsing:
|
||||||
- features/parsing/index.md
|
- features/parsing/index.md
|
||||||
- features/parsing/parse_exceptions.md
|
- features/parsing/parse_exceptions.md
|
||||||
- features/parsing/parser_callbacks.md
|
- features/parsing/parser_callbacks.md
|
||||||
- features/parsing/sax_interface.md
|
- features/parsing/sax_interface.md
|
||||||
|
- features/enum_conversion.md
|
||||||
|
- features/macros.md
|
||||||
- features/types.md
|
- features/types.md
|
||||||
- Integration:
|
- Integration:
|
||||||
- integration/index.md
|
- integration/index.md
|
||||||
|
@ -61,6 +69,12 @@ nav:
|
||||||
- integration/package_managers.md
|
- integration/package_managers.md
|
||||||
- Doxygen:
|
- Doxygen:
|
||||||
- doxygen/index.html
|
- doxygen/index.html
|
||||||
|
- API:
|
||||||
|
- basic_json:
|
||||||
|
- api/basic_json/index.md
|
||||||
|
- api/basic_json/dump.md
|
||||||
|
- api/basic_json/meta.md
|
||||||
|
- api/basic_json/parse.md
|
||||||
|
|
||||||
# Extras
|
# Extras
|
||||||
extra:
|
extra:
|
||||||
|
@ -79,6 +93,7 @@ extra:
|
||||||
# Extensions
|
# Extensions
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- admonition
|
- admonition
|
||||||
|
- def_list
|
||||||
- codehilite:
|
- codehilite:
|
||||||
guess_lang: false
|
guess_lang: false
|
||||||
- toc:
|
- toc:
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Header <ciso646> is removed in C++20.
|
|
||||||
// See <https://github.com/nlohmann/json/issues/2089> for more information.
|
|
||||||
|
|
||||||
#if __cplusplus <= 201703L
|
|
||||||
#include <ciso646> // and, not, or
|
|
||||||
#endif
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <utility> // pair, declval
|
#include <utility> // pair, declval
|
||||||
#include <valarray> // valarray
|
#include <valarray> // valarray
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
|
@ -26,7 +25,7 @@ namespace detail
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_null()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -35,8 +34,8 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
|
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||||
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +65,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_boolean()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -86,13 +85,13 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
||||||
template <
|
template <
|
||||||
typename BasicJsonType, typename ConstructibleStringType,
|
typename BasicJsonType, typename ConstructibleStringType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
|
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
|
||||||
not std::is_same<typename BasicJsonType::string_t,
|
!std::is_same<typename BasicJsonType::string_t,
|
||||||
ConstructibleStringType>::value,
|
ConstructibleStringType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
|
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -129,10 +128,10 @@ void from_json(const BasicJsonType& j, EnumType& e)
|
||||||
|
|
||||||
// forward_list doesn't have an insert method
|
// forward_list doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T, typename Allocator,
|
template<typename BasicJsonType, typename T, typename Allocator,
|
||||||
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||||
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -146,15 +145,19 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||||
|
|
||||||
// valarray doesn't have an insert method
|
// valarray doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T,
|
||||||
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
|
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||||
void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
l.resize(j.size());
|
l.resize(j.size());
|
||||||
std::copy(j.begin(), j.end(), std::begin(l));
|
std::transform(j.begin(), j.end(), std::begin(l),
|
||||||
|
[](const BasicJsonType & elem)
|
||||||
|
{
|
||||||
|
return elem.template get<T>();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
|
@ -225,18 +228,18 @@ void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
|
||||||
|
|
||||||
template < typename BasicJsonType, typename ConstructibleArrayType,
|
template < typename BasicJsonType, typename ConstructibleArrayType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
|
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||||
not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
|
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||||
not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
|
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||||
not std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value and
|
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
|
||||||
not is_basic_json<ConstructibleArrayType>::value,
|
!is_basic_json<ConstructibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
||||||
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
|
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
|
||||||
j.template get<typename ConstructibleArrayType::value_type>(),
|
j.template get<typename ConstructibleArrayType::value_type>(),
|
||||||
void())
|
void())
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " +
|
JSON_THROW(type_error::create(302, "type must be array, but is " +
|
||||||
std::string(j.type_name())));
|
std::string(j.type_name())));
|
||||||
|
@ -248,7 +251,7 @@ void())
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
|
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_binary()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -260,7 +263,7 @@ template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||||
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
||||||
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -284,11 +287,11 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||||
// an arithmetic type?
|
// an arithmetic type?
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template < typename BasicJsonType, typename ArithmeticType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_arithmetic<ArithmeticType>::value and
|
std::is_arithmetic<ArithmeticType>::value&&
|
||||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
|
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
|
||||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
|
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
|
||||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
|
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
|
||||||
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void from_json(const BasicJsonType& j, ArithmeticType& val)
|
void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
|
@ -339,18 +342,18 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||||
typename = enable_if_t<not std::is_constructible<
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename BasicJsonType::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
m.clear();
|
m.clear();
|
||||||
for (const auto& p : j)
|
for (const auto& p : j)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
||||||
}
|
}
|
||||||
|
@ -359,18 +362,18 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
||||||
typename = enable_if_t<not std::is_constructible<
|
typename = enable_if_t < !std::is_constructible <
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename BasicJsonType::string_t, Key >::value >>
|
||||||
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||||
}
|
}
|
||||||
m.clear();
|
m.clear();
|
||||||
for (const auto& p : j)
|
for (const auto& p : j)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cmath> // signbit, isfinite
|
#include <cmath> // signbit, isfinite
|
||||||
#include <cstdint> // intN_t, uintN_t
|
#include <cstdint> // intN_t, uintN_t
|
||||||
#include <cstring> // memcpy, memmove
|
#include <cstring> // memcpy, memmove
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <type_traits> // conditional
|
#include <type_traits> // conditional
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
|
@ -63,8 +61,8 @@ struct diyfp // f * 2^e
|
||||||
*/
|
*/
|
||||||
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
|
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
|
||||||
{
|
{
|
||||||
assert(x.e == y.e);
|
JSON_ASSERT(x.e == y.e);
|
||||||
assert(x.f >= y.f);
|
JSON_ASSERT(x.f >= y.f);
|
||||||
|
|
||||||
return {x.f - y.f, x.e};
|
return {x.f - y.f, x.e};
|
||||||
}
|
}
|
||||||
|
@ -140,7 +138,7 @@ struct diyfp // f * 2^e
|
||||||
*/
|
*/
|
||||||
static diyfp normalize(diyfp x) noexcept
|
static diyfp normalize(diyfp x) noexcept
|
||||||
{
|
{
|
||||||
assert(x.f != 0);
|
JSON_ASSERT(x.f != 0);
|
||||||
|
|
||||||
while ((x.f >> 63u) == 0)
|
while ((x.f >> 63u) == 0)
|
||||||
{
|
{
|
||||||
|
@ -159,8 +157,8 @@ struct diyfp // f * 2^e
|
||||||
{
|
{
|
||||||
const int delta = x.e - target_exponent;
|
const int delta = x.e - target_exponent;
|
||||||
|
|
||||||
assert(delta >= 0);
|
JSON_ASSERT(delta >= 0);
|
||||||
assert(((x.f << delta) >> delta) == x.f);
|
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
|
||||||
|
|
||||||
return {x.f << delta, target_exponent};
|
return {x.f << delta, target_exponent};
|
||||||
}
|
}
|
||||||
|
@ -182,8 +180,8 @@ boundaries.
|
||||||
template<typename FloatType>
|
template<typename FloatType>
|
||||||
boundaries compute_boundaries(FloatType value)
|
boundaries compute_boundaries(FloatType value)
|
||||||
{
|
{
|
||||||
assert(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
assert(value > 0);
|
JSON_ASSERT(value > 0);
|
||||||
|
|
||||||
// Convert the IEEE representation into a diyfp.
|
// Convert the IEEE representation into a diyfp.
|
||||||
//
|
//
|
||||||
|
@ -232,7 +230,7 @@ boundaries compute_boundaries(FloatType value)
|
||||||
// -----------------+------+------+-------------+-------------+--- (B)
|
// -----------------+------+------+-------------+-------------+--- (B)
|
||||||
// v- m- v m+ v+
|
// v- m- v m+ v+
|
||||||
|
|
||||||
const bool lower_boundary_is_closer = F == 0 and E > 1;
|
const bool lower_boundary_is_closer = F == 0 && E > 1;
|
||||||
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
||||||
const diyfp m_minus = lower_boundary_is_closer
|
const diyfp m_minus = lower_boundary_is_closer
|
||||||
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
||||||
|
@ -463,18 +461,18 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
||||||
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
|
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
|
||||||
// for |e| <= 1500, but doesn't require floating-point operations.
|
// for |e| <= 1500, but doesn't require floating-point operations.
|
||||||
// NB: log_10(2) ~= 78913 / 2^18
|
// NB: log_10(2) ~= 78913 / 2^18
|
||||||
assert(e >= -1500);
|
JSON_ASSERT(e >= -1500);
|
||||||
assert(e <= 1500);
|
JSON_ASSERT(e <= 1500);
|
||||||
const int f = kAlpha - e - 1;
|
const int f = kAlpha - e - 1;
|
||||||
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
|
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
|
||||||
|
|
||||||
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
|
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
|
||||||
assert(index >= 0);
|
JSON_ASSERT(index >= 0);
|
||||||
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
|
JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
|
||||||
|
|
||||||
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
|
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
|
||||||
assert(kAlpha <= cached.e + e + 64);
|
JSON_ASSERT(kAlpha <= cached.e + e + 64);
|
||||||
assert(kGamma >= cached.e + e + 64);
|
JSON_ASSERT(kGamma >= cached.e + e + 64);
|
||||||
|
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
@ -542,10 +540,10 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
|
||||||
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
||||||
std::uint64_t rest, std::uint64_t ten_k)
|
std::uint64_t rest, std::uint64_t ten_k)
|
||||||
{
|
{
|
||||||
assert(len >= 1);
|
JSON_ASSERT(len >= 1);
|
||||||
assert(dist <= delta);
|
JSON_ASSERT(dist <= delta);
|
||||||
assert(rest <= delta);
|
JSON_ASSERT(rest <= delta);
|
||||||
assert(ten_k > 0);
|
JSON_ASSERT(ten_k > 0);
|
||||||
|
|
||||||
// <--------------------------- delta ---->
|
// <--------------------------- delta ---->
|
||||||
// <---- dist --------->
|
// <---- dist --------->
|
||||||
|
@ -567,10 +565,10 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
|
||||||
// integer arithmetic.
|
// integer arithmetic.
|
||||||
|
|
||||||
while (rest < dist
|
while (rest < dist
|
||||||
and delta - rest >= ten_k
|
&& delta - rest >= ten_k
|
||||||
and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
|
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
|
||||||
{
|
{
|
||||||
assert(buf[len - 1] != '0');
|
JSON_ASSERT(buf[len - 1] != '0');
|
||||||
buf[len - 1]--;
|
buf[len - 1]--;
|
||||||
rest += ten_k;
|
rest += ten_k;
|
||||||
}
|
}
|
||||||
|
@ -598,8 +596,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
// Grisu2 generates the digits of M+ from left to right and stops as soon as
|
// Grisu2 generates the digits of M+ from left to right and stops as soon as
|
||||||
// V is in [M-,M+].
|
// V is in [M-,M+].
|
||||||
|
|
||||||
assert(M_plus.e >= kAlpha);
|
JSON_ASSERT(M_plus.e >= kAlpha);
|
||||||
assert(M_plus.e <= kGamma);
|
JSON_ASSERT(M_plus.e <= kGamma);
|
||||||
|
|
||||||
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
||||||
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
||||||
|
@ -620,7 +618,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
//
|
//
|
||||||
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
|
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
|
||||||
|
|
||||||
assert(p1 > 0);
|
JSON_ASSERT(p1 > 0);
|
||||||
|
|
||||||
std::uint32_t pow10;
|
std::uint32_t pow10;
|
||||||
const int k = find_largest_pow10(p1, pow10);
|
const int k = find_largest_pow10(p1, pow10);
|
||||||
|
@ -656,7 +654,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
||||||
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
||||||
//
|
//
|
||||||
assert(d <= 9);
|
JSON_ASSERT(d <= 9);
|
||||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
|
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
|
||||||
|
@ -743,7 +741,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
//
|
//
|
||||||
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
|
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
|
||||||
|
|
||||||
assert(p2 > delta);
|
JSON_ASSERT(p2 > delta);
|
||||||
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -754,7 +752,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
|
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
|
||||||
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
|
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
|
||||||
//
|
//
|
||||||
assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
||||||
p2 *= 10;
|
p2 *= 10;
|
||||||
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
||||||
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
||||||
|
@ -763,7 +761,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
||||||
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||||
//
|
//
|
||||||
assert(d <= 9);
|
JSON_ASSERT(d <= 9);
|
||||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||||
|
@ -824,8 +822,8 @@ JSON_HEDLEY_NON_NULL(1)
|
||||||
inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
||||||
diyfp m_minus, diyfp v, diyfp m_plus)
|
diyfp m_minus, diyfp v, diyfp m_plus)
|
||||||
{
|
{
|
||||||
assert(m_plus.e == m_minus.e);
|
JSON_ASSERT(m_plus.e == m_minus.e);
|
||||||
assert(m_plus.e == v.e);
|
JSON_ASSERT(m_plus.e == v.e);
|
||||||
|
|
||||||
// --------(-----------------------+-----------------------)-------- (A)
|
// --------(-----------------------+-----------------------)-------- (A)
|
||||||
// m- v m+
|
// m- v m+
|
||||||
|
@ -886,8 +884,8 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
|
||||||
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
|
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
|
||||||
"internal error: not enough precision");
|
"internal error: not enough precision");
|
||||||
|
|
||||||
assert(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
assert(value > 0);
|
JSON_ASSERT(value > 0);
|
||||||
|
|
||||||
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
|
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
|
||||||
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
|
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
|
||||||
|
@ -923,8 +921,8 @@ JSON_HEDLEY_NON_NULL(1)
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
inline char* append_exponent(char* buf, int e)
|
inline char* append_exponent(char* buf, int e)
|
||||||
{
|
{
|
||||||
assert(e > -1000);
|
JSON_ASSERT(e > -1000);
|
||||||
assert(e < 1000);
|
JSON_ASSERT(e < 1000);
|
||||||
|
|
||||||
if (e < 0)
|
if (e < 0)
|
||||||
{
|
{
|
||||||
|
@ -976,8 +974,8 @@ JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||||
int min_exp, int max_exp)
|
int min_exp, int max_exp)
|
||||||
{
|
{
|
||||||
assert(min_exp < 0);
|
JSON_ASSERT(min_exp < 0);
|
||||||
assert(max_exp > 0);
|
JSON_ASSERT(max_exp > 0);
|
||||||
|
|
||||||
const int k = len;
|
const int k = len;
|
||||||
const int n = len + decimal_exponent;
|
const int n = len + decimal_exponent;
|
||||||
|
@ -986,7 +984,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||||
// k is the length of the buffer (number of decimal digits)
|
// k is the length of the buffer (number of decimal digits)
|
||||||
// n is the position of the decimal point relative to the start of the buffer.
|
// n is the position of the decimal point relative to the start of the buffer.
|
||||||
|
|
||||||
if (k <= n and n <= max_exp)
|
if (k <= n && n <= max_exp)
|
||||||
{
|
{
|
||||||
// digits[000]
|
// digits[000]
|
||||||
// len <= max_exp + 2
|
// len <= max_exp + 2
|
||||||
|
@ -998,19 +996,19 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||||
return buf + (static_cast<size_t>(n) + 2);
|
return buf + (static_cast<size_t>(n) + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 < n and n <= max_exp)
|
if (0 < n && n <= max_exp)
|
||||||
{
|
{
|
||||||
// dig.its
|
// dig.its
|
||||||
// len <= max_digits10 + 1
|
// len <= max_digits10 + 1
|
||||||
|
|
||||||
assert(k > n);
|
JSON_ASSERT(k > n);
|
||||||
|
|
||||||
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
|
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
|
||||||
buf[n] = '.';
|
buf[n] = '.';
|
||||||
return buf + (static_cast<size_t>(k) + 1U);
|
return buf + (static_cast<size_t>(k) + 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (min_exp < n and n <= 0)
|
if (min_exp < n && n <= 0)
|
||||||
{
|
{
|
||||||
// 0.[000]digits
|
// 0.[000]digits
|
||||||
// len <= 2 + (-min_exp - 1) + max_digits10
|
// len <= 2 + (-min_exp - 1) + max_digits10
|
||||||
|
@ -1061,7 +1059,7 @@ JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
char* to_chars(char* first, const char* last, FloatType value)
|
char* to_chars(char* first, const char* last, FloatType value)
|
||||||
{
|
{
|
||||||
static_cast<void>(last); // maybe unused - fix warning
|
static_cast<void>(last); // maybe unused - fix warning
|
||||||
assert(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
|
|
||||||
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
||||||
if (std::signbit(value))
|
if (std::signbit(value))
|
||||||
|
@ -1079,7 +1077,7 @@ char* to_chars(char* first, const char* last, FloatType value)
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
|
||||||
// Compute v = buffer * 10^decimal_exponent.
|
// Compute v = buffer * 10^decimal_exponent.
|
||||||
// The decimal digits are stored in the buffer, which needs to be interpreted
|
// The decimal digits are stored in the buffer, which needs to be interpreted
|
||||||
|
@ -1089,16 +1087,16 @@ char* to_chars(char* first, const char* last, FloatType value)
|
||||||
int decimal_exponent = 0;
|
int decimal_exponent = 0;
|
||||||
dtoa_impl::grisu2(first, len, decimal_exponent, value);
|
dtoa_impl::grisu2(first, len, decimal_exponent, value);
|
||||||
|
|
||||||
assert(len <= std::numeric_limits<FloatType>::max_digits10);
|
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
|
||||||
// Format the buffer like printf("%.*g", prec, value)
|
// Format the buffer like printf("%.*g", prec, value)
|
||||||
constexpr int kMinExp = -4;
|
constexpr int kMinExp = -4;
|
||||||
// Use digits10 here to increase compatibility with version 2.
|
// Use digits10 here to increase compatibility with version 2.
|
||||||
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
|
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
|
||||||
|
|
||||||
assert(last - first >= kMaxExp + 2);
|
JSON_ASSERT(last - first >= kMaxExp + 2);
|
||||||
assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
||||||
assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
||||||
|
|
||||||
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
|
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <valarray> // valarray
|
#include <valarray> // valarray
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
@ -57,7 +56,7 @@ struct external_constructor<value_t::string>
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleStringType,
|
template < typename BasicJsonType, typename CompatibleStringType,
|
||||||
enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
|
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
||||||
{
|
{
|
||||||
|
@ -145,7 +144,7 @@ struct external_constructor<value_t::array>
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||||
enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
|
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
|
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||||
{
|
{
|
||||||
|
@ -204,7 +203,7 @@ struct external_constructor<value_t::object>
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
template < typename BasicJsonType, typename CompatibleObjectType,
|
||||||
enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
|
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
|
||||||
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
|
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||||
{
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
|
@ -277,11 +276,11 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e)
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||||
enable_if_t < is_compatible_array_type<BasicJsonType,
|
enable_if_t < is_compatible_array_type<BasicJsonType,
|
||||||
CompatibleArrayType>::value and
|
CompatibleArrayType>::value&&
|
||||||
not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
|
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
|
||||||
not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
|
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
|
||||||
not std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value and
|
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
|
||||||
not is_basic_json<CompatibleArrayType>::value,
|
!is_basic_json<CompatibleArrayType>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||||
{
|
{
|
||||||
|
@ -308,7 +307,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
template < typename BasicJsonType, typename CompatibleObjectType,
|
||||||
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
|
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
|
||||||
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::object>::construct(j, obj);
|
external_constructor<value_t::object>::construct(j, obj);
|
||||||
|
@ -322,7 +321,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename BasicJsonType, typename T, std::size_t N,
|
typename BasicJsonType, typename T, std::size_t N,
|
||||||
enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
|
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
|
||||||
const T(&)[N]>::value,
|
const T(&)[N]>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void to_json(BasicJsonType& j, const T(&arr)[N])
|
void to_json(BasicJsonType& j, const T(&arr)[N])
|
||||||
|
|
|
@ -97,6 +97,7 @@ json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vect
|
||||||
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
|
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
|
||||||
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
|
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
|
||||||
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
|
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
|
||||||
|
json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
|
||||||
|
|
||||||
@note For an input with n bytes, 1 is the index of the first character and n+1
|
@note For an input with n bytes, 1 is the index of the first character and n+1
|
||||||
is the index of the terminating null byte or the end of file. This also
|
is the index of the terminating null byte or the end of file. This also
|
||||||
|
@ -285,7 +286,7 @@ json.exception.out_of_range.403 | key 'foo' not found | The provided key was not
|
||||||
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
|
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
|
||||||
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
|
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
|
||||||
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
|
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
|
||||||
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
|
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
|
||||||
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
|
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
|
||||||
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
|
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
|
||||||
|
|
||||||
|
|
117
include/nlohmann/detail/hash.hpp
Normal file
117
include/nlohmann/detail/hash.hpp
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef> // size_t, uint8_t
|
||||||
|
#include <functional> // hash
|
||||||
|
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
// boost::hash_combine
|
||||||
|
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
||||||
|
{
|
||||||
|
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@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.
|
||||||
|
|
||||||
|
@tparam BasicJsonType basic_json specialization
|
||||||
|
@param j JSON value to hash
|
||||||
|
@return hash value of j
|
||||||
|
*/
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
std::size_t hash(const BasicJsonType& j)
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
switch (j.type())
|
||||||
|
{
|
||||||
|
case BasicJsonType::value_t::null:
|
||||||
|
case BasicJsonType::value_t::discarded:
|
||||||
|
{
|
||||||
|
return combine(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
case BasicJsonType::value_t::object:
|
||||||
|
{
|
||||||
|
auto seed = combine(type, j.size());
|
||||||
|
for (const auto& element : j.items())
|
||||||
|
{
|
||||||
|
const auto h = std::hash<string_t> {}(element.key());
|
||||||
|
seed = combine(seed, h);
|
||||||
|
seed = combine(seed, hash(element.value()));
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BasicJsonType::value_t::array:
|
||||||
|
{
|
||||||
|
auto seed = combine(type, j.size());
|
||||||
|
for (const auto& element : j)
|
||||||
|
{
|
||||||
|
seed = combine(seed, hash(element));
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BasicJsonType::value_t::string:
|
||||||
|
{
|
||||||
|
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
||||||
|
return combine(type, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
case BasicJsonType::value_t::boolean:
|
||||||
|
{
|
||||||
|
const auto h = std::hash<bool> {}(j.template get<bool>());
|
||||||
|
return combine(type, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nlohmann::detail::value_t::number_unsigned:
|
||||||
|
{
|
||||||
|
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
||||||
|
return combine(type, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
case nlohmann::detail::value_t::number_float:
|
||||||
|
{
|
||||||
|
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
||||||
|
return combine(type, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
case nlohmann::detail::value_t::binary:
|
||||||
|
{
|
||||||
|
auto seed = combine(type, j.get_binary().size());
|
||||||
|
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||||
|
seed = combine(seed, h);
|
||||||
|
seed = combine(seed, j.get_binary().subtype());
|
||||||
|
for (const auto byte : j.get_binary())
|
||||||
|
{
|
||||||
|
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: // LCOV_EXCL_LINE
|
||||||
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace nlohmann
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdio> //FILE *
|
#include <cstdio> //FILE *
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
|
@ -76,7 +75,7 @@ class input_stream_adapter
|
||||||
{
|
{
|
||||||
// clear stream flags; we use underlying streambuf I/O, do not
|
// clear stream flags; we use underlying streambuf I/O, do not
|
||||||
// maintain ifstream flags, except eof
|
// maintain ifstream flags, except eof
|
||||||
if (is)
|
if (is != nullptr)
|
||||||
{
|
{
|
||||||
is->clear(is->rdstate() & std::ios::eofbit);
|
is->clear(is->rdstate() & std::ios::eofbit);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +90,7 @@ class input_stream_adapter
|
||||||
input_stream_adapter& operator=(input_stream_adapter&) = delete;
|
input_stream_adapter& operator=(input_stream_adapter&) = delete;
|
||||||
input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
|
input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
|
||||||
|
|
||||||
input_stream_adapter(input_stream_adapter&& rhs) : is(rhs.is), sb(rhs.sb)
|
input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb)
|
||||||
{
|
{
|
||||||
rhs.is = nullptr;
|
rhs.is = nullptr;
|
||||||
rhs.sb = nullptr;
|
rhs.sb = nullptr;
|
||||||
|
@ -251,7 +250,7 @@ struct wide_string_input_helper<BaseInputAdapter, 2>
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||||
utf8_bytes_filled = 2;
|
utf8_bytes_filled = 2;
|
||||||
}
|
}
|
||||||
else if (0xD800 > wc or wc >= 0xE000)
|
else if (0xD800 > wc || wc >= 0xE000)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
|
||||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
||||||
|
@ -260,7 +259,7 @@ struct wide_string_input_helper<BaseInputAdapter, 2>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not input.empty()))
|
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
|
||||||
{
|
{
|
||||||
const auto wc2 = static_cast<unsigned int>(input.get_character());
|
const auto wc2 = static_cast<unsigned int>(input.get_character());
|
||||||
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||||
|
@ -297,13 +296,13 @@ class wide_string_input_adapter
|
||||||
{
|
{
|
||||||
fill_buffer<sizeof(WideCharType)>();
|
fill_buffer<sizeof(WideCharType)>();
|
||||||
|
|
||||||
assert(utf8_bytes_filled > 0);
|
JSON_ASSERT(utf8_bytes_filled > 0);
|
||||||
assert(utf8_bytes_index == 0);
|
JSON_ASSERT(utf8_bytes_index == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// use buffer
|
// use buffer
|
||||||
assert(utf8_bytes_filled > 0);
|
JSON_ASSERT(utf8_bytes_filled > 0);
|
||||||
assert(utf8_bytes_index < utf8_bytes_filled);
|
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
|
||||||
return utf8_bytes[utf8_bytes_index++];
|
return utf8_bytes[utf8_bytes_index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,15 +402,15 @@ using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const
|
||||||
// Null-delimited strings, and the like.
|
// Null-delimited strings, and the like.
|
||||||
template < typename CharT,
|
template < typename CharT,
|
||||||
typename std::enable_if <
|
typename std::enable_if <
|
||||||
std::is_pointer<CharT>::value and
|
std::is_pointer<CharT>::value&&
|
||||||
not std::is_array<CharT>::value and
|
!std::is_array<CharT>::value&&
|
||||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
||||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||||
int >::type = 0 >
|
int >::type = 0 >
|
||||||
contiguous_bytes_input_adapter input_adapter(CharT b)
|
contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||||
{
|
{
|
||||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||||
auto ptr = reinterpret_cast<const char*>(b);
|
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||||
return input_adapter(ptr, ptr + length);
|
return input_adapter(ptr, ptr + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,8 +428,8 @@ class span_input_adapter
|
||||||
public:
|
public:
|
||||||
template < typename CharT,
|
template < typename CharT,
|
||||||
typename std::enable_if <
|
typename std::enable_if <
|
||||||
std::is_pointer<CharT>::value and
|
std::is_pointer<CharT>::value&&
|
||||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
||||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||||
int >::type = 0 >
|
int >::type = 0 >
|
||||||
span_input_adapter(CharT b, std::size_t l)
|
span_input_adapter(CharT b, std::size_t l)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
@ -218,7 +217,7 @@ class json_sax_dom_parser
|
||||||
{
|
{
|
||||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408,
|
JSON_THROW(out_of_range::create(408,
|
||||||
"excessive object size: " + std::to_string(len)));
|
"excessive object size: " + std::to_string(len)));
|
||||||
|
@ -244,7 +243,7 @@ class json_sax_dom_parser
|
||||||
{
|
{
|
||||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408,
|
JSON_THROW(out_of_range::create(408,
|
||||||
"excessive array size: " + std::to_string(len)));
|
"excessive array size: " + std::to_string(len)));
|
||||||
|
@ -259,30 +258,15 @@ class json_sax_dom_parser
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Exception>
|
||||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||||
const detail::exception& ex)
|
const Exception& ex)
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
|
static_cast<void>(ex);
|
||||||
if (allow_exceptions)
|
if (allow_exceptions)
|
||||||
{
|
{
|
||||||
// determine the proper exception type from the id
|
JSON_THROW(ex);
|
||||||
switch ((ex.id / 100) % 100)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
|
||||||
case 4:
|
|
||||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
case 2:
|
|
||||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
|
||||||
case 3:
|
|
||||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
|
||||||
case 5:
|
|
||||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +293,7 @@ class json_sax_dom_parser
|
||||||
return &root;
|
return &root;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
|
||||||
|
|
||||||
if (ref_stack.back()->is_array())
|
if (ref_stack.back()->is_array())
|
||||||
{
|
{
|
||||||
|
@ -317,8 +301,8 @@ class json_sax_dom_parser
|
||||||
return &(ref_stack.back()->m_value.array->back());
|
return &(ref_stack.back()->m_value.array->back());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ref_stack.back()->is_object());
|
JSON_ASSERT(ref_stack.back()->is_object());
|
||||||
assert(object_element);
|
JSON_ASSERT(object_element);
|
||||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||||
return object_element;
|
return object_element;
|
||||||
}
|
}
|
||||||
|
@ -414,7 +398,7 @@ class json_sax_dom_callback_parser
|
||||||
ref_stack.push_back(val.second);
|
ref_stack.push_back(val.second);
|
||||||
|
|
||||||
// check object limit
|
// check object limit
|
||||||
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
|
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
|
||||||
}
|
}
|
||||||
|
@ -431,7 +415,7 @@ class json_sax_dom_callback_parser
|
||||||
key_keep_stack.push_back(keep);
|
key_keep_stack.push_back(keep);
|
||||||
|
|
||||||
// add discarded value at given key and store the reference for later
|
// add discarded value at given key and store the reference for later
|
||||||
if (keep and ref_stack.back())
|
if (keep && ref_stack.back())
|
||||||
{
|
{
|
||||||
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
|
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
|
||||||
}
|
}
|
||||||
|
@ -441,18 +425,18 @@ class json_sax_dom_callback_parser
|
||||||
|
|
||||||
bool end_object()
|
bool end_object()
|
||||||
{
|
{
|
||||||
if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
if (ref_stack.back() && !callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
||||||
{
|
{
|
||||||
// discard object
|
// discard object
|
||||||
*ref_stack.back() = discarded;
|
*ref_stack.back() = discarded;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(not ref_stack.empty());
|
JSON_ASSERT(!ref_stack.empty());
|
||||||
assert(not keep_stack.empty());
|
JSON_ASSERT(!keep_stack.empty());
|
||||||
ref_stack.pop_back();
|
ref_stack.pop_back();
|
||||||
keep_stack.pop_back();
|
keep_stack.pop_back();
|
||||||
|
|
||||||
if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_structured())
|
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||||
{
|
{
|
||||||
// remove discarded value
|
// remove discarded value
|
||||||
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
|
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
|
||||||
|
@ -477,7 +461,7 @@ class json_sax_dom_callback_parser
|
||||||
ref_stack.push_back(val.second);
|
ref_stack.push_back(val.second);
|
||||||
|
|
||||||
// check array limit
|
// check array limit
|
||||||
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
|
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
|
||||||
}
|
}
|
||||||
|
@ -492,20 +476,20 @@ class json_sax_dom_callback_parser
|
||||||
if (ref_stack.back())
|
if (ref_stack.back())
|
||||||
{
|
{
|
||||||
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
|
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
|
||||||
if (not keep)
|
if (!keep)
|
||||||
{
|
{
|
||||||
// discard array
|
// discard array
|
||||||
*ref_stack.back() = discarded;
|
*ref_stack.back() = discarded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(not ref_stack.empty());
|
JSON_ASSERT(!ref_stack.empty());
|
||||||
assert(not keep_stack.empty());
|
JSON_ASSERT(!keep_stack.empty());
|
||||||
ref_stack.pop_back();
|
ref_stack.pop_back();
|
||||||
keep_stack.pop_back();
|
keep_stack.pop_back();
|
||||||
|
|
||||||
// remove discarded value
|
// remove discarded value
|
||||||
if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
|
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
|
||||||
{
|
{
|
||||||
ref_stack.back()->m_value.array->pop_back();
|
ref_stack.back()->m_value.array->pop_back();
|
||||||
}
|
}
|
||||||
|
@ -513,30 +497,15 @@ class json_sax_dom_callback_parser
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Exception>
|
||||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||||
const detail::exception& ex)
|
const Exception& ex)
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
|
static_cast<void>(ex);
|
||||||
if (allow_exceptions)
|
if (allow_exceptions)
|
||||||
{
|
{
|
||||||
// determine the proper exception type from the id
|
JSON_THROW(ex);
|
||||||
switch ((ex.id / 100) % 100)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
|
||||||
case 4:
|
|
||||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
case 2:
|
|
||||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
|
||||||
case 3:
|
|
||||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
|
||||||
case 5:
|
|
||||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -565,11 +534,11 @@ class json_sax_dom_callback_parser
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
|
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
|
||||||
{
|
{
|
||||||
assert(not keep_stack.empty());
|
JSON_ASSERT(!keep_stack.empty());
|
||||||
|
|
||||||
// do not handle this value if we know it would be added to a discarded
|
// do not handle this value if we know it would be added to a discarded
|
||||||
// container
|
// container
|
||||||
if (not keep_stack.back())
|
if (!keep_stack.back())
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return {false, nullptr};
|
||||||
}
|
}
|
||||||
|
@ -578,10 +547,10 @@ class json_sax_dom_callback_parser
|
||||||
auto value = BasicJsonType(std::forward<Value>(v));
|
auto value = BasicJsonType(std::forward<Value>(v));
|
||||||
|
|
||||||
// check callback
|
// check callback
|
||||||
const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
|
const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
|
||||||
|
|
||||||
// do not handle this value if we just learnt it shall be discarded
|
// do not handle this value if we just learnt it shall be discarded
|
||||||
if (not keep)
|
if (!keep)
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return {false, nullptr};
|
||||||
}
|
}
|
||||||
|
@ -594,13 +563,13 @@ class json_sax_dom_callback_parser
|
||||||
|
|
||||||
// skip this value if we already decided to skip the parent
|
// skip this value if we already decided to skip the parent
|
||||||
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
|
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
|
||||||
if (not ref_stack.back())
|
if (!ref_stack.back())
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return {false, nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
// we now only expect arrays and objects
|
// we now only expect arrays and objects
|
||||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
|
||||||
|
|
||||||
// array
|
// array
|
||||||
if (ref_stack.back()->is_array())
|
if (ref_stack.back()->is_array())
|
||||||
|
@ -610,18 +579,18 @@ class json_sax_dom_callback_parser
|
||||||
}
|
}
|
||||||
|
|
||||||
// object
|
// object
|
||||||
assert(ref_stack.back()->is_object());
|
JSON_ASSERT(ref_stack.back()->is_object());
|
||||||
// check if we should store an element for the current key
|
// check if we should store an element for the current key
|
||||||
assert(not key_keep_stack.empty());
|
JSON_ASSERT(!key_keep_stack.empty());
|
||||||
const bool store_element = key_keep_stack.back();
|
const bool store_element = key_keep_stack.back();
|
||||||
key_keep_stack.pop_back();
|
key_keep_stack.pop_back();
|
||||||
|
|
||||||
if (not store_element)
|
if (!store_element)
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return {false, nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(object_element);
|
JSON_ASSERT(object_element);
|
||||||
*object_element = std::move(value);
|
*object_element = std::move(value);
|
||||||
return {true, object_element};
|
return {true, object_element};
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,11 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
public:
|
public:
|
||||||
using token_type = typename lexer_base<BasicJsonType>::token_type;
|
using token_type = typename lexer_base<BasicJsonType>::token_type;
|
||||||
|
|
||||||
explicit lexer(InputAdapterType&& adapter)
|
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
|
||||||
: ia(std::move(adapter)), decimal_point_char(static_cast<char_int_type>(get_decimal_point())) {}
|
: ia(std::move(adapter))
|
||||||
|
, ignore_comments(ignore_comments_)
|
||||||
|
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
|
||||||
|
{}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
lexer(const lexer&) = delete;
|
lexer(const lexer&) = delete;
|
||||||
|
@ -131,8 +134,8 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
JSON_HEDLEY_PURE
|
JSON_HEDLEY_PURE
|
||||||
static char get_decimal_point() noexcept
|
static char get_decimal_point() noexcept
|
||||||
{
|
{
|
||||||
const auto loc = localeconv();
|
const auto* loc = localeconv();
|
||||||
assert(loc != nullptr);
|
JSON_ASSERT(loc != nullptr);
|
||||||
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
|
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +161,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
int get_codepoint()
|
int get_codepoint()
|
||||||
{
|
{
|
||||||
// this function only makes sense after reading `\u`
|
// this function only makes sense after reading `\u`
|
||||||
assert(current == 'u');
|
JSON_ASSERT(current == 'u');
|
||||||
int codepoint = 0;
|
int codepoint = 0;
|
||||||
|
|
||||||
const auto factors = { 12u, 8u, 4u, 0u };
|
const auto factors = { 12u, 8u, 4u, 0u };
|
||||||
|
@ -166,15 +169,15 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
|
|
||||||
if (current >= '0' and current <= '9')
|
if (current >= '0' && current <= '9')
|
||||||
{
|
{
|
||||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
|
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
|
||||||
}
|
}
|
||||||
else if (current >= 'A' and current <= 'F')
|
else if (current >= 'A' && current <= 'F')
|
||||||
{
|
{
|
||||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
|
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
|
||||||
}
|
}
|
||||||
else if (current >= 'a' and current <= 'f')
|
else if (current >= 'a' && current <= 'f')
|
||||||
{
|
{
|
||||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
|
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +187,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
|
JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
|
||||||
return codepoint;
|
return codepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,13 +208,13 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
*/
|
*/
|
||||||
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
|
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
|
||||||
{
|
{
|
||||||
assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
|
JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
|
||||||
add(current);
|
add(current);
|
||||||
|
|
||||||
for (auto range = ranges.begin(); range != ranges.end(); ++range)
|
for (auto range = ranges.begin(); range != ranges.end(); ++range)
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
|
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
|
||||||
{
|
{
|
||||||
add(current);
|
add(current);
|
||||||
}
|
}
|
||||||
|
@ -246,7 +249,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
// we entered the function by reading an open quote
|
// we entered the function by reading an open quote
|
||||||
assert(current == '\"');
|
JSON_ASSERT(current == '\"');
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -317,10 +320,10 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if code point is a high surrogate
|
// check if code point is a high surrogate
|
||||||
if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
|
if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
|
||||||
{
|
{
|
||||||
// expect next \uxxxx entry
|
// expect next \uxxxx entry
|
||||||
if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
|
if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
|
||||||
{
|
{
|
||||||
const int codepoint2 = get_codepoint();
|
const int codepoint2 = get_codepoint();
|
||||||
|
|
||||||
|
@ -331,7 +334,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if codepoint2 is a low surrogate
|
// check if codepoint2 is a low surrogate
|
||||||
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
|
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
|
||||||
{
|
{
|
||||||
// overwrite codepoint
|
// overwrite codepoint
|
||||||
codepoint = static_cast<int>(
|
codepoint = static_cast<int>(
|
||||||
|
@ -358,7 +361,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
|
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
|
||||||
{
|
{
|
||||||
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
|
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
|
@ -366,7 +369,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
|
|
||||||
// result of the above calculation yields a proper codepoint
|
// result of the above calculation yields a proper codepoint
|
||||||
assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
|
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
|
||||||
|
|
||||||
// translate codepoint into bytes
|
// translate codepoint into bytes
|
||||||
if (codepoint < 0x80)
|
if (codepoint < 0x80)
|
||||||
|
@ -733,7 +736,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
case 0xDE:
|
case 0xDE:
|
||||||
case 0xDF:
|
case 0xDF:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
|
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -743,7 +746,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
|
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
|
||||||
case 0xE0:
|
case 0xE0:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -767,7 +770,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
case 0xEE:
|
case 0xEE:
|
||||||
case 0xEF:
|
case 0xEF:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -777,7 +780,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
|
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
|
||||||
case 0xED:
|
case 0xED:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -787,7 +790,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -799,7 +802,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
case 0xF2:
|
case 0xF2:
|
||||||
case 0xF3:
|
case 0xF3:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -809,7 +812,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
|
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
|
||||||
case 0xF4:
|
case 0xF4:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
@ -826,6 +829,77 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief scan a comment
|
||||||
|
* @return whether comment could be scanned successfully
|
||||||
|
*/
|
||||||
|
bool scan_comment()
|
||||||
|
{
|
||||||
|
switch (get())
|
||||||
|
{
|
||||||
|
// single-line comments skip input until a newline or EOF is read
|
||||||
|
case '/':
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
switch (get())
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
case std::char_traits<char_type>::eof():
|
||||||
|
case '\0':
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi-line comments skip input until */ is read
|
||||||
|
case '*':
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
switch (get())
|
||||||
|
{
|
||||||
|
case std::char_traits<char_type>::eof():
|
||||||
|
case '\0':
|
||||||
|
{
|
||||||
|
error_message = "invalid comment; missing closing '*/'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
{
|
||||||
|
switch (get())
|
||||||
|
{
|
||||||
|
case '/':
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
unget();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unexpected character after reading '/'
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
error_message = "invalid comment; expecting '/' or '*' after '/'";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
static void strtof(float& f, const char* str, char** endptr) noexcept
|
static void strtof(float& f, const char* str, char** endptr) noexcept
|
||||||
{
|
{
|
||||||
|
@ -924,7 +998,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||||
|
|
||||||
// all other characters are rejected outside scan_number()
|
// all other characters are rejected outside scan_number()
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
assert(false); // LCOV_EXCL_LINE
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_number_minus:
|
scan_number_minus:
|
||||||
|
@ -1171,7 +1245,7 @@ scan_number_done:
|
||||||
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
|
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
|
||||||
|
|
||||||
// we checked the number format before
|
// we checked the number format before
|
||||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||||
|
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
{
|
{
|
||||||
|
@ -1187,7 +1261,7 @@ scan_number_done:
|
||||||
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
|
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
|
||||||
|
|
||||||
// we checked the number format before
|
// we checked the number format before
|
||||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||||
|
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
{
|
{
|
||||||
|
@ -1204,7 +1278,7 @@ scan_number_done:
|
||||||
strtof(value_float, token_buffer.data(), &endptr);
|
strtof(value_float, token_buffer.data(), &endptr);
|
||||||
|
|
||||||
// we checked the number format before
|
// we checked the number format before
|
||||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||||
|
|
||||||
return token_type::value_float;
|
return token_type::value_float;
|
||||||
}
|
}
|
||||||
|
@ -1218,7 +1292,7 @@ scan_number_done:
|
||||||
token_type scan_literal(const char_type* literal_text, const std::size_t length,
|
token_type scan_literal(const char_type* literal_text, const std::size_t length,
|
||||||
token_type return_type)
|
token_type return_type)
|
||||||
{
|
{
|
||||||
assert(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
|
JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
|
||||||
for (std::size_t i = 1; i < length; ++i)
|
for (std::size_t i = 1; i < length; ++i)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
|
if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
|
||||||
|
@ -1310,7 +1384,7 @@ scan_number_done:
|
||||||
|
|
||||||
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
|
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
|
||||||
{
|
{
|
||||||
assert(not token_string.empty());
|
JSON_ASSERT(!token_string.empty());
|
||||||
token_string.pop_back();
|
token_string.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1406,7 +1480,7 @@ scan_number_done:
|
||||||
if (get() == 0xEF)
|
if (get() == 0xEF)
|
||||||
{
|
{
|
||||||
// check if we completely parse the BOM
|
// check if we completely parse the BOM
|
||||||
return get() == 0xBB and get() == 0xBF;
|
return get() == 0xBB && get() == 0xBF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the first character is not the beginning of the BOM; unget it to
|
// the first character is not the beginning of the BOM; unget it to
|
||||||
|
@ -1415,21 +1489,38 @@ scan_number_done:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void skip_whitespace()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
get();
|
||||||
|
}
|
||||||
|
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
|
||||||
|
}
|
||||||
|
|
||||||
token_type scan()
|
token_type scan()
|
||||||
{
|
{
|
||||||
// initially, skip the BOM
|
// initially, skip the BOM
|
||||||
if (position.chars_read_total == 0 and not skip_bom())
|
if (position.chars_read_total == 0 && !skip_bom())
|
||||||
{
|
{
|
||||||
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
|
error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read next character and ignore whitespace
|
// read next character and ignore whitespace
|
||||||
do
|
skip_whitespace();
|
||||||
|
|
||||||
|
// ignore comments
|
||||||
|
if (ignore_comments && current == '/')
|
||||||
{
|
{
|
||||||
get();
|
if (!scan_comment())
|
||||||
|
{
|
||||||
|
return token_type::parse_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip following whitespace
|
||||||
|
skip_whitespace();
|
||||||
}
|
}
|
||||||
while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
|
|
||||||
|
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
|
@ -1499,6 +1590,9 @@ scan_number_done:
|
||||||
/// input adapter
|
/// input adapter
|
||||||
InputAdapterType ia;
|
InputAdapterType ia;
|
||||||
|
|
||||||
|
/// whether comments should be ignored (true) or signaled as errors (false)
|
||||||
|
const bool ignore_comments = false;
|
||||||
|
|
||||||
/// the current character
|
/// the current character
|
||||||
char_int_type current = std::char_traits<char_type>::eof();
|
char_int_type current = std::char_traits<char_type>::eof();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cmath> // isfinite
|
#include <cmath> // isfinite
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <functional> // function
|
#include <functional> // function
|
||||||
|
@ -63,8 +62,11 @@ class parser
|
||||||
/// a parser reading from an input adapter
|
/// a parser reading from an input adapter
|
||||||
explicit parser(InputAdapterType&& adapter,
|
explicit parser(InputAdapterType&& adapter,
|
||||||
const parser_callback_t<BasicJsonType> cb = nullptr,
|
const parser_callback_t<BasicJsonType> cb = nullptr,
|
||||||
const bool allow_exceptions_ = true)
|
const bool allow_exceptions_ = true,
|
||||||
: callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
|
const bool skip_comments = false)
|
||||||
|
: callback(cb)
|
||||||
|
, m_lexer(std::move(adapter), skip_comments)
|
||||||
|
, allow_exceptions(allow_exceptions_)
|
||||||
{
|
{
|
||||||
// read first token
|
// read first token
|
||||||
get_token();
|
get_token();
|
||||||
|
@ -89,7 +91,7 @@ class parser
|
||||||
result.assert_invariant();
|
result.assert_invariant();
|
||||||
|
|
||||||
// in strict mode, input must be completely read
|
// in strict mode, input must be completely read
|
||||||
if (strict and (get_token() != token_type::end_of_input))
|
if (strict && (get_token() != token_type::end_of_input))
|
||||||
{
|
{
|
||||||
sdp.parse_error(m_lexer.get_position(),
|
sdp.parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_token_string(),
|
||||||
|
@ -118,7 +120,7 @@ class parser
|
||||||
result.assert_invariant();
|
result.assert_invariant();
|
||||||
|
|
||||||
// in strict mode, input must be completely read
|
// in strict mode, input must be completely read
|
||||||
if (strict and (get_token() != token_type::end_of_input))
|
if (strict && (get_token() != token_type::end_of_input))
|
||||||
{
|
{
|
||||||
sdp.parse_error(m_lexer.get_position(),
|
sdp.parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_token_string(),
|
||||||
|
@ -155,7 +157,7 @@ class parser
|
||||||
const bool result = sax_parse_internal(sax);
|
const bool result = sax_parse_internal(sax);
|
||||||
|
|
||||||
// strict mode: next byte must be EOF
|
// strict mode: next byte must be EOF
|
||||||
if (result and strict and (get_token() != token_type::end_of_input))
|
if (result && strict && (get_token() != token_type::end_of_input))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_token_string(),
|
||||||
|
@ -179,14 +181,14 @@ class parser
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (not skip_to_state_evaluation)
|
if (!skip_to_state_evaluation)
|
||||||
{
|
{
|
||||||
// invariant: get_token() was called before each iteration
|
// invariant: get_token() was called before each iteration
|
||||||
switch (last_token)
|
switch (last_token)
|
||||||
{
|
{
|
||||||
case token_type::begin_object:
|
case token_type::begin_object:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
|
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +196,7 @@ class parser
|
||||||
// closing } -> we are done
|
// closing } -> we are done
|
||||||
if (get_token() == token_type::end_object)
|
if (get_token() == token_type::end_object)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
|
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +211,7 @@ class parser
|
||||||
parse_error::create(101, m_lexer.get_position(),
|
parse_error::create(101, m_lexer.get_position(),
|
||||||
exception_message(token_type::value_string, "object key")));
|
exception_message(token_type::value_string, "object key")));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +235,7 @@ class parser
|
||||||
|
|
||||||
case token_type::begin_array:
|
case token_type::begin_array:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
|
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +243,7 @@ class parser
|
||||||
// closing ] -> we are done
|
// closing ] -> we are done
|
||||||
if (get_token() == token_type::end_array)
|
if (get_token() == token_type::end_array)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
|
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -259,14 +261,14 @@ class parser
|
||||||
{
|
{
|
||||||
const auto res = m_lexer.get_number_float();
|
const auto res = m_lexer.get_number_float();
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res)))
|
if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_token_string(),
|
||||||
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
|
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +278,7 @@ class parser
|
||||||
|
|
||||||
case token_type::literal_false:
|
case token_type::literal_false:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false)))
|
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -285,7 +287,7 @@ class parser
|
||||||
|
|
||||||
case token_type::literal_null:
|
case token_type::literal_null:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->null()))
|
if (JSON_HEDLEY_UNLIKELY(!sax->null()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +296,7 @@ class parser
|
||||||
|
|
||||||
case token_type::literal_true:
|
case token_type::literal_true:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true)))
|
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +305,7 @@ class parser
|
||||||
|
|
||||||
case token_type::value_integer:
|
case token_type::value_integer:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +314,7 @@ class parser
|
||||||
|
|
||||||
case token_type::value_string:
|
case token_type::value_string:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -321,7 +323,7 @@ class parser
|
||||||
|
|
||||||
case token_type::value_unsigned:
|
case token_type::value_unsigned:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +373,7 @@ class parser
|
||||||
// closing ]
|
// closing ]
|
||||||
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
|
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
|
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +382,7 @@ class parser
|
||||||
// new value, we need to evaluate the new state first.
|
// new value, we need to evaluate the new state first.
|
||||||
// By setting skip_to_state_evaluation to false, we
|
// By setting skip_to_state_evaluation to false, we
|
||||||
// are effectively jumping to the beginning of this if.
|
// are effectively jumping to the beginning of this if.
|
||||||
assert(not states.empty());
|
JSON_ASSERT(!states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_state_evaluation = true;
|
skip_to_state_evaluation = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -405,7 +407,7 @@ class parser
|
||||||
exception_message(token_type::value_string, "object key")));
|
exception_message(token_type::value_string, "object key")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -427,7 +429,7 @@ class parser
|
||||||
// closing }
|
// closing }
|
||||||
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
|
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
|
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -436,7 +438,7 @@ class parser
|
||||||
// new value, we need to evaluate the new state first.
|
// new value, we need to evaluate the new state first.
|
||||||
// By setting skip_to_state_evaluation to false, we
|
// By setting skip_to_state_evaluation to false, we
|
||||||
// are effectively jumping to the beginning of this if.
|
// are effectively jumping to the beginning of this if.
|
||||||
assert(not states.empty());
|
JSON_ASSERT(!states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_state_evaluation = true;
|
skip_to_state_evaluation = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -460,7 +462,7 @@ class parser
|
||||||
{
|
{
|
||||||
std::string error_msg = "syntax error ";
|
std::string error_msg = "syntax error ";
|
||||||
|
|
||||||
if (not context.empty())
|
if (!context.empty())
|
||||||
{
|
{
|
||||||
error_msg += "while parsing " + context + " ";
|
error_msg += "while parsing " + context + " ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,6 @@ template<typename BasicJsonType> struct internal_iterator
|
||||||
typename BasicJsonType::object_t::iterator object_iterator {};
|
typename BasicJsonType::object_t::iterator object_iterator {};
|
||||||
/// iterator for JSON arrays
|
/// iterator for JSON arrays
|
||||||
typename BasicJsonType::array_t::iterator array_iterator {};
|
typename BasicJsonType::array_t::iterator array_iterator {};
|
||||||
/// iterator for JSON binary arrays
|
|
||||||
typename BasicJsonType::binary_t::container_type::iterator binary_iterator {};
|
|
||||||
/// generic iterator for all other types
|
/// generic iterator for all other types
|
||||||
primitive_iterator_t primitive_iterator {};
|
primitive_iterator_t primitive_iterator {};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
|
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
|
||||||
#include <type_traits> // conditional, is_const, remove_const
|
#include <type_traits> // conditional, is_const, remove_const
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
||||||
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
|
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
|
||||||
|
@ -85,7 +84,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
explicit iter_impl(pointer object) noexcept : m_object(object)
|
explicit iter_impl(pointer object) noexcept : m_object(object)
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -171,7 +170,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
void set_begin() noexcept
|
void set_begin() noexcept
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -208,7 +207,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
void set_end() noexcept
|
void set_end() noexcept
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -239,19 +238,19 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
reference operator*() const
|
reference operator*() const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
{
|
{
|
||||||
assert(m_it.object_iterator != m_object->m_value.object->end());
|
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
|
||||||
return m_it.object_iterator->second;
|
return m_it.object_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
assert(m_it.array_iterator != m_object->m_value.array->end());
|
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
|
||||||
return *m_it.array_iterator;
|
return *m_it.array_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,19 +275,19 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
pointer operator->() const
|
pointer operator->() const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
{
|
{
|
||||||
assert(m_it.object_iterator != m_object->m_value.object->end());
|
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
|
||||||
return &(m_it.object_iterator->second);
|
return &(m_it.object_iterator->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
assert(m_it.array_iterator != m_object->m_value.array->end());
|
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
|
||||||
return &*m_it.array_iterator;
|
return &*m_it.array_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +320,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
iter_impl& operator++()
|
iter_impl& operator++()
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +363,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
iter_impl& operator--()
|
iter_impl& operator--()
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -402,7 +401,7 @@ class iter_impl
|
||||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -423,7 +422,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
bool operator!=(const iter_impl& other) const
|
bool operator!=(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
return not operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -438,7 +437,7 @@ class iter_impl
|
||||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -459,7 +458,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
bool operator<=(const iter_impl& other) const
|
bool operator<=(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
return not other.operator < (*this);
|
return !other.operator < (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -468,7 +467,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
bool operator>(const iter_impl& other) const
|
bool operator>(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
return not operator<=(other);
|
return !operator<=(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -477,7 +476,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
bool operator>=(const iter_impl& other) const
|
bool operator>=(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
return not operator<(other);
|
return !operator<(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -486,7 +485,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
iter_impl& operator+=(difference_type i)
|
iter_impl& operator+=(difference_type i)
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -557,7 +556,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
difference_type operator-(const iter_impl& other) const
|
difference_type operator-(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -578,7 +577,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
reference operator[](difference_type n) const
|
reference operator[](difference_type n) const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
switch (m_object->m_type)
|
switch (m_object->m_type)
|
||||||
{
|
{
|
||||||
|
@ -609,7 +608,7 @@ class iter_impl
|
||||||
*/
|
*/
|
||||||
const typename object_t::key_type& key() const
|
const typename object_t::key_type& key() const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
|
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,9 @@ namespace detail
|
||||||
template<typename string_type>
|
template<typename string_type>
|
||||||
void int_to_string( string_type& target, std::size_t value )
|
void int_to_string( string_type& target, std::size_t value )
|
||||||
{
|
{
|
||||||
target = std::to_string(value);
|
// For ADL
|
||||||
|
using std::to_string;
|
||||||
|
target = to_string(value);
|
||||||
}
|
}
|
||||||
template<typename IteratorType> class iteration_proxy_value
|
template<typename IteratorType> class iteration_proxy_value
|
||||||
{
|
{
|
||||||
|
@ -72,7 +74,7 @@ template <typename IteratorType> class iteration_proxy_value
|
||||||
/// return key of the iterator
|
/// return key of the iterator
|
||||||
const string_type& key() const
|
const string_type& key() const
|
||||||
{
|
{
|
||||||
assert(anchor.m_object != nullptr);
|
JSON_ASSERT(anchor.m_object != nullptr);
|
||||||
|
|
||||||
switch (anchor.m_object->type())
|
switch (anchor.m_object->type())
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // all_of
|
#include <algorithm> // all_of
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cctype> // isdigit
|
#include <cctype> // isdigit
|
||||||
|
#include <limits> // max
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
@ -325,12 +325,17 @@ class json_pointer
|
||||||
|
|
||||||
@return integer representation of @a s
|
@return integer representation of @a s
|
||||||
|
|
||||||
|
@throw parse_error.106 if an array index begins with '0'
|
||||||
|
@throw parse_error.109 if an array index begins not with a digit
|
||||||
@throw out_of_range.404 if string @a s could not be converted to an integer
|
@throw out_of_range.404 if string @a s could not be converted to an integer
|
||||||
|
@throw out_of_range.410 if an array index exceeds size_type
|
||||||
*/
|
*/
|
||||||
static int array_index(const std::string& s)
|
static typename BasicJsonType::size_type array_index(const std::string& s)
|
||||||
{
|
{
|
||||||
|
using size_type = typename BasicJsonType::size_type;
|
||||||
|
|
||||||
// error condition (cf. RFC 6901, Sect. 4)
|
// error condition (cf. RFC 6901, Sect. 4)
|
||||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
|
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::parse_error::create(106, 0,
|
JSON_THROW(detail::parse_error::create(106, 0,
|
||||||
"array index '" + s +
|
"array index '" + s +
|
||||||
|
@ -338,16 +343,16 @@ class json_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// error condition (cf. RFC 6901, Sect. 4)
|
// error condition (cf. RFC 6901, Sect. 4)
|
||||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and not (s[0] >= '1' and s[0] <= '9')))
|
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
|
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t processed_chars = 0;
|
std::size_t processed_chars = 0;
|
||||||
int res = 0;
|
unsigned long long res = 0;
|
||||||
JSON_TRY
|
JSON_TRY
|
||||||
{
|
{
|
||||||
res = std::stoi(s, &processed_chars);
|
res = std::stoull(s, &processed_chars);
|
||||||
}
|
}
|
||||||
JSON_CATCH(std::out_of_range&)
|
JSON_CATCH(std::out_of_range&)
|
||||||
{
|
{
|
||||||
|
@ -360,7 +365,14 @@ class json_pointer
|
||||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
// only triggered on special platforms (like 32bit), see also
|
||||||
|
// https://github.com/nlohmann/json/pull/2203
|
||||||
|
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
|
||||||
|
{
|
||||||
|
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<size_type>(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
json_pointer top() const
|
json_pointer top() const
|
||||||
|
@ -385,7 +397,6 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
BasicJsonType& get_and_create(BasicJsonType& j) const
|
BasicJsonType& get_and_create(BasicJsonType& j) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
auto result = &j;
|
auto result = &j;
|
||||||
|
|
||||||
// in case no reference tokens exist, return a reference to the JSON value
|
// in case no reference tokens exist, return a reference to the JSON value
|
||||||
|
@ -419,7 +430,7 @@ class json_pointer
|
||||||
case detail::value_t::array:
|
case detail::value_t::array:
|
||||||
{
|
{
|
||||||
// create an entry in the array
|
// create an entry in the array
|
||||||
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
|
result = &result->operator[](array_index(reference_token));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +469,6 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
|
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
// convert null values to arrays or objects before continuing
|
// convert null values to arrays or objects before continuing
|
||||||
|
@ -473,7 +483,7 @@ class json_pointer
|
||||||
});
|
});
|
||||||
|
|
||||||
// change value to array for numbers or "-" or to object otherwise
|
// change value to array for numbers or "-" or to object otherwise
|
||||||
*ptr = (nums or reference_token == "-")
|
*ptr = (nums || reference_token == "-")
|
||||||
? detail::value_t::array
|
? detail::value_t::array
|
||||||
: detail::value_t::object;
|
: detail::value_t::object;
|
||||||
}
|
}
|
||||||
|
@ -497,8 +507,7 @@ class json_pointer
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// convert array index to number; unchecked access
|
// convert array index to number; unchecked access
|
||||||
ptr = &ptr->operator[](
|
ptr = &ptr->operator[](array_index(reference_token));
|
||||||
static_cast<size_type>(array_index(reference_token)));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -519,7 +528,6 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
BasicJsonType& get_checked(BasicJsonType* ptr) const
|
BasicJsonType& get_checked(BasicJsonType* ptr) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
switch (ptr->type())
|
switch (ptr->type())
|
||||||
|
@ -542,7 +550,7 @@ class json_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: at performs range check
|
// note: at performs range check
|
||||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
ptr = &ptr->at(array_index(reference_token));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +577,6 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
|
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
switch (ptr->type())
|
switch (ptr->type())
|
||||||
|
@ -592,8 +599,7 @@ class json_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// use unchecked array access
|
// use unchecked array access
|
||||||
ptr = &ptr->operator[](
|
ptr = &ptr->operator[](array_index(reference_token));
|
||||||
static_cast<size_type>(array_index(reference_token)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +619,6 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
|
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
switch (ptr->type())
|
switch (ptr->type())
|
||||||
|
@ -636,7 +641,7 @@ class json_pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: at performs range check
|
// note: at performs range check
|
||||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
ptr = &ptr->at(array_index(reference_token));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,14 +659,13 @@ class json_pointer
|
||||||
*/
|
*/
|
||||||
bool contains(const BasicJsonType* ptr) const
|
bool contains(const BasicJsonType* ptr) const
|
||||||
{
|
{
|
||||||
using size_type = typename BasicJsonType::size_type;
|
|
||||||
for (const auto& reference_token : reference_tokens)
|
for (const auto& reference_token : reference_tokens)
|
||||||
{
|
{
|
||||||
switch (ptr->type())
|
switch (ptr->type())
|
||||||
{
|
{
|
||||||
case detail::value_t::object:
|
case detail::value_t::object:
|
||||||
{
|
{
|
||||||
if (not ptr->contains(reference_token))
|
if (!ptr->contains(reference_token))
|
||||||
{
|
{
|
||||||
// we did not find the key in the object
|
// we did not find the key in the object
|
||||||
return false;
|
return false;
|
||||||
|
@ -678,21 +682,21 @@ class json_pointer
|
||||||
// "-" always fails the range check
|
// "-" always fails the range check
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not ("0" <= reference_token and reference_token <= "9")))
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
||||||
{
|
{
|
||||||
// invalid char
|
// invalid char
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
|
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not ('1' <= reference_token[0] and reference_token[0] <= '9')))
|
if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
|
||||||
{
|
{
|
||||||
// first char should be between '1' and '9'
|
// first char should be between '1' and '9'
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (std::size_t i = 1; i < reference_token.size(); i++)
|
for (std::size_t i = 1; i < reference_token.size(); i++)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not ('0' <= reference_token[i] and reference_token[i] <= '9')))
|
if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
|
||||||
{
|
{
|
||||||
// other char should be between '0' and '9'
|
// other char should be between '0' and '9'
|
||||||
return false;
|
return false;
|
||||||
|
@ -700,7 +704,7 @@ class json_pointer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto idx = static_cast<size_type>(array_index(reference_token));
|
const auto idx = array_index(reference_token);
|
||||||
if (idx >= ptr->size())
|
if (idx >= ptr->size())
|
||||||
{
|
{
|
||||||
// index out of range
|
// index out of range
|
||||||
|
@ -776,11 +780,11 @@ class json_pointer
|
||||||
pos != std::string::npos;
|
pos != std::string::npos;
|
||||||
pos = reference_token.find_first_of('~', pos + 1))
|
pos = reference_token.find_first_of('~', pos + 1))
|
||||||
{
|
{
|
||||||
assert(reference_token[pos] == '~');
|
JSON_ASSERT(reference_token[pos] == '~');
|
||||||
|
|
||||||
// ~ must be followed by 0 or 1
|
// ~ must be followed by 0 or 1
|
||||||
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or
|
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
|
||||||
(reference_token[pos + 1] != '0' and
|
(reference_token[pos + 1] != '0' &&
|
||||||
reference_token[pos + 1] != '1')))
|
reference_token[pos + 1] != '1')))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
|
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
|
||||||
|
@ -811,7 +815,7 @@ class json_pointer
|
||||||
static void replace_substring(std::string& s, const std::string& f,
|
static void replace_substring(std::string& s, const std::string& f,
|
||||||
const std::string& t)
|
const std::string& t)
|
||||||
{
|
{
|
||||||
assert(not f.empty());
|
JSON_ASSERT(!f.empty());
|
||||||
for (auto pos = s.find(f); // find first occurrence of f
|
for (auto pos = s.find(f); // find first occurrence of f
|
||||||
pos != std::string::npos; // make sure f was found
|
pos != std::string::npos; // make sure f was found
|
||||||
s.replace(pos, f.size(), t), // replace with t, and
|
s.replace(pos, f.size(), t), // replace with t, and
|
||||||
|
@ -906,7 +910,7 @@ class json_pointer
|
||||||
static BasicJsonType
|
static BasicJsonType
|
||||||
unflatten(const BasicJsonType& value)
|
unflatten(const BasicJsonType& value)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not value.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
|
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
|
||||||
}
|
}
|
||||||
|
@ -916,7 +920,7 @@ class json_pointer
|
||||||
// iterate the JSON object values
|
// iterate the JSON object values
|
||||||
for (const auto& element : *value.m_value.object)
|
for (const auto& element : *value.m_value.object)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive()))
|
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
|
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
|
||||||
}
|
}
|
||||||
|
@ -962,7 +966,7 @@ class json_pointer
|
||||||
friend bool operator!=(json_pointer const& lhs,
|
friend bool operator!=(json_pointer const& lhs,
|
||||||
json_pointer const& rhs) noexcept
|
json_pointer const& rhs) noexcept
|
||||||
{
|
{
|
||||||
return not (lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// the reference tokens
|
/// the reference tokens
|
||||||
|
|
|
@ -16,23 +16,30 @@ class json_ref
|
||||||
using value_type = BasicJsonType;
|
using value_type = BasicJsonType;
|
||||||
|
|
||||||
json_ref(value_type&& value)
|
json_ref(value_type&& value)
|
||||||
: owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
|
: owned_value(std::move(value))
|
||||||
|
, value_ref(&owned_value)
|
||||||
|
, is_rvalue(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json_ref(const value_type& value)
|
json_ref(const value_type& value)
|
||||||
: value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
|
: value_ref(const_cast<value_type*>(&value))
|
||||||
|
, is_rvalue(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json_ref(std::initializer_list<json_ref> init)
|
json_ref(std::initializer_list<json_ref> init)
|
||||||
: owned_value(init), value_ref(&owned_value), is_rvalue(true)
|
: owned_value(init)
|
||||||
|
, value_ref(&owned_value)
|
||||||
|
, is_rvalue(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
class... Args,
|
class... Args,
|
||||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
||||||
json_ref(Args && ... args)
|
json_ref(Args && ... args)
|
||||||
: owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
|
: owned_value(std::forward<Args>(args)...)
|
||||||
is_rvalue(true) {}
|
, value_ref(&owned_value)
|
||||||
|
, is_rvalue(true)
|
||||||
|
{}
|
||||||
|
|
||||||
// class should be movable only
|
// class should be movable only
|
||||||
json_ref(json_ref&&) = default;
|
json_ref(json_ref&&) = default;
|
||||||
|
@ -63,7 +70,7 @@ class json_ref
|
||||||
private:
|
private:
|
||||||
mutable value_type owned_value = nullptr;
|
mutable value_type owned_value = nullptr;
|
||||||
value_type* value_ref = nullptr;
|
value_type* value_ref = nullptr;
|
||||||
const bool is_rvalue;
|
const bool is_rvalue = true;
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
|
@ -20,7 +20,11 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C++ language standard detection
|
// C++ language standard detection
|
||||||
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
|
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||||
|
#define JSON_HAS_CPP_20
|
||||||
|
#define JSON_HAS_CPP_17
|
||||||
|
#define JSON_HAS_CPP_14
|
||||||
|
#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
|
||||||
#define JSON_HAS_CPP_17
|
#define JSON_HAS_CPP_17
|
||||||
#define JSON_HAS_CPP_14
|
#define JSON_HAS_CPP_14
|
||||||
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
|
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
|
||||||
|
@ -73,6 +77,12 @@
|
||||||
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
|
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// allow to override assert
|
||||||
|
#if !defined(JSON_ASSERT)
|
||||||
|
#include <cassert> // assert
|
||||||
|
#define JSON_ASSERT(x) assert(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief macro to briefly define a mapping between an enum and JSON
|
@brief macro to briefly define a mapping between an enum and JSON
|
||||||
@def NLOHMANN_JSON_SERIALIZE_ENUM
|
@def NLOHMANN_JSON_SERIALIZE_ENUM
|
||||||
|
@ -120,3 +130,167 @@
|
||||||
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
|
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
|
||||||
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
|
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
|
||||||
AllocatorType, JSONSerializer, BinaryType>
|
AllocatorType, JSONSerializer, BinaryType>
|
||||||
|
|
||||||
|
// Macros to simplify conversion from/to types
|
||||||
|
|
||||||
|
#define NLOHMANN_JSON_EXPAND( x ) x
|
||||||
|
#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
|
||||||
|
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
||||||
|
NLOHMANN_JSON_PASTE64, \
|
||||||
|
NLOHMANN_JSON_PASTE63, \
|
||||||
|
NLOHMANN_JSON_PASTE62, \
|
||||||
|
NLOHMANN_JSON_PASTE61, \
|
||||||
|
NLOHMANN_JSON_PASTE60, \
|
||||||
|
NLOHMANN_JSON_PASTE59, \
|
||||||
|
NLOHMANN_JSON_PASTE58, \
|
||||||
|
NLOHMANN_JSON_PASTE57, \
|
||||||
|
NLOHMANN_JSON_PASTE56, \
|
||||||
|
NLOHMANN_JSON_PASTE55, \
|
||||||
|
NLOHMANN_JSON_PASTE54, \
|
||||||
|
NLOHMANN_JSON_PASTE53, \
|
||||||
|
NLOHMANN_JSON_PASTE52, \
|
||||||
|
NLOHMANN_JSON_PASTE51, \
|
||||||
|
NLOHMANN_JSON_PASTE50, \
|
||||||
|
NLOHMANN_JSON_PASTE49, \
|
||||||
|
NLOHMANN_JSON_PASTE48, \
|
||||||
|
NLOHMANN_JSON_PASTE47, \
|
||||||
|
NLOHMANN_JSON_PASTE46, \
|
||||||
|
NLOHMANN_JSON_PASTE45, \
|
||||||
|
NLOHMANN_JSON_PASTE44, \
|
||||||
|
NLOHMANN_JSON_PASTE43, \
|
||||||
|
NLOHMANN_JSON_PASTE42, \
|
||||||
|
NLOHMANN_JSON_PASTE41, \
|
||||||
|
NLOHMANN_JSON_PASTE40, \
|
||||||
|
NLOHMANN_JSON_PASTE39, \
|
||||||
|
NLOHMANN_JSON_PASTE38, \
|
||||||
|
NLOHMANN_JSON_PASTE37, \
|
||||||
|
NLOHMANN_JSON_PASTE36, \
|
||||||
|
NLOHMANN_JSON_PASTE35, \
|
||||||
|
NLOHMANN_JSON_PASTE34, \
|
||||||
|
NLOHMANN_JSON_PASTE33, \
|
||||||
|
NLOHMANN_JSON_PASTE32, \
|
||||||
|
NLOHMANN_JSON_PASTE31, \
|
||||||
|
NLOHMANN_JSON_PASTE30, \
|
||||||
|
NLOHMANN_JSON_PASTE29, \
|
||||||
|
NLOHMANN_JSON_PASTE28, \
|
||||||
|
NLOHMANN_JSON_PASTE27, \
|
||||||
|
NLOHMANN_JSON_PASTE26, \
|
||||||
|
NLOHMANN_JSON_PASTE25, \
|
||||||
|
NLOHMANN_JSON_PASTE24, \
|
||||||
|
NLOHMANN_JSON_PASTE23, \
|
||||||
|
NLOHMANN_JSON_PASTE22, \
|
||||||
|
NLOHMANN_JSON_PASTE21, \
|
||||||
|
NLOHMANN_JSON_PASTE20, \
|
||||||
|
NLOHMANN_JSON_PASTE19, \
|
||||||
|
NLOHMANN_JSON_PASTE18, \
|
||||||
|
NLOHMANN_JSON_PASTE17, \
|
||||||
|
NLOHMANN_JSON_PASTE16, \
|
||||||
|
NLOHMANN_JSON_PASTE15, \
|
||||||
|
NLOHMANN_JSON_PASTE14, \
|
||||||
|
NLOHMANN_JSON_PASTE13, \
|
||||||
|
NLOHMANN_JSON_PASTE12, \
|
||||||
|
NLOHMANN_JSON_PASTE11, \
|
||||||
|
NLOHMANN_JSON_PASTE10, \
|
||||||
|
NLOHMANN_JSON_PASTE9, \
|
||||||
|
NLOHMANN_JSON_PASTE8, \
|
||||||
|
NLOHMANN_JSON_PASTE7, \
|
||||||
|
NLOHMANN_JSON_PASTE6, \
|
||||||
|
NLOHMANN_JSON_PASTE5, \
|
||||||
|
NLOHMANN_JSON_PASTE4, \
|
||||||
|
NLOHMANN_JSON_PASTE3, \
|
||||||
|
NLOHMANN_JSON_PASTE2, \
|
||||||
|
NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
|
||||||
|
#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
|
||||||
|
#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
|
||||||
|
#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
|
||||||
|
#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
|
||||||
|
#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
|
||||||
|
#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
|
||||||
|
#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
|
||||||
|
#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
|
||||||
|
#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
|
||||||
|
#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
|
||||||
|
#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
|
||||||
|
#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
|
||||||
|
#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
|
||||||
|
#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
|
||||||
|
#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
|
||||||
|
#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
|
||||||
|
#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
|
||||||
|
#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
|
||||||
|
#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
|
||||||
|
#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
|
||||||
|
#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
|
||||||
|
#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
|
||||||
|
#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
|
||||||
|
#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
|
||||||
|
#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
|
||||||
|
#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
|
||||||
|
#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
|
||||||
|
#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
|
||||||
|
#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
|
||||||
|
#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
|
||||||
|
#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
|
||||||
|
#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
|
||||||
|
#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
|
||||||
|
#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
|
||||||
|
#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
|
||||||
|
#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
|
||||||
|
#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
|
||||||
|
#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
|
||||||
|
#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
|
||||||
|
#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
|
||||||
|
#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
|
||||||
|
#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
|
||||||
|
#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
|
||||||
|
#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
|
||||||
|
#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
|
||||||
|
#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
|
||||||
|
#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
|
||||||
|
#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
|
||||||
|
#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
|
||||||
|
#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
|
||||||
|
#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
|
||||||
|
#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
|
||||||
|
#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
|
||||||
|
#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
|
||||||
|
#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
|
||||||
|
#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
|
||||||
|
#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
|
||||||
|
#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
|
||||||
|
#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
|
||||||
|
#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
|
||||||
|
#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
|
||||||
|
#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
|
||||||
|
#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
|
||||||
|
|
||||||
|
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
|
||||||
|
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief macro
|
||||||
|
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
|
||||||
|
@since version 3.9.0
|
||||||
|
*/
|
||||||
|
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
|
||||||
|
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
|
||||||
|
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief macro
|
||||||
|
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
|
||||||
|
@since version 3.9.0
|
||||||
|
*/
|
||||||
|
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
|
||||||
|
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
|
||||||
|
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
|
||||||
|
|
||||||
|
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
|
||||||
|
#define JSON_USE_IMPLICIT_CONVERSIONS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if JSON_USE_IMPLICIT_CONVERSIONS
|
||||||
|
#define JSON_EXPLICIT
|
||||||
|
#else
|
||||||
|
#define JSON_EXPLICIT explicit
|
||||||
|
#endif
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
|
#undef JSON_ASSERT
|
||||||
#undef JSON_INTERNAL_CATCH
|
#undef JSON_INTERNAL_CATCH
|
||||||
#undef JSON_CATCH
|
#undef JSON_CATCH
|
||||||
#undef JSON_THROW
|
#undef JSON_THROW
|
||||||
|
@ -17,5 +18,6 @@
|
||||||
#undef JSON_HAS_CPP_17
|
#undef JSON_HAS_CPP_17
|
||||||
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||||
#undef NLOHMANN_BASIC_JSON_TPL
|
#undef NLOHMANN_BASIC_JSON_TPL
|
||||||
|
#undef JSON_EXPLICIT
|
||||||
|
|
||||||
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
|
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|
|
@ -34,6 +34,10 @@ template <typename T, typename String>
|
||||||
using string_function_t =
|
using string_function_t =
|
||||||
decltype(std::declval<T&>().string(std::declval<String&>()));
|
decltype(std::declval<T&>().string(std::declval<String&>()));
|
||||||
|
|
||||||
|
template<typename T, typename Binary>
|
||||||
|
using binary_function_t =
|
||||||
|
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using start_object_function_t =
|
using start_object_function_t =
|
||||||
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
||||||
|
@ -68,19 +72,18 @@ struct is_sax
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
using number_float_t = typename BasicJsonType::number_float_t;
|
using number_float_t = typename BasicJsonType::number_float_t;
|
||||||
using string_t = typename BasicJsonType::string_t;
|
using string_t = typename BasicJsonType::string_t;
|
||||||
|
using binary_t = typename BasicJsonType::binary_t;
|
||||||
using exception_t = typename BasicJsonType::exception;
|
using exception_t = typename BasicJsonType::exception;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
is_detected_exact<bool, null_function_t, SAX>::value &&
|
is_detected_exact<bool, null_function_t, SAX>::value &&
|
||||||
is_detected_exact<bool, boolean_function_t, SAX>::value &&
|
is_detected_exact<bool, boolean_function_t, SAX>::value &&
|
||||||
is_detected_exact<bool, number_integer_function_t, SAX,
|
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
|
||||||
number_integer_t>::value &&
|
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
|
||||||
is_detected_exact<bool, number_unsigned_function_t, SAX,
|
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
|
||||||
number_unsigned_t>::value &&
|
|
||||||
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
|
|
||||||
string_t>::value &&
|
|
||||||
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
|
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
|
||||||
|
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
|
||||||
is_detected_exact<bool, start_object_function_t, SAX>::value &&
|
is_detected_exact<bool, start_object_function_t, SAX>::value &&
|
||||||
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
|
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
|
||||||
is_detected_exact<bool, end_object_function_t, SAX>::value &&
|
is_detected_exact<bool, end_object_function_t, SAX>::value &&
|
||||||
|
@ -100,6 +103,7 @@ struct is_sax_static_asserts
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
using number_float_t = typename BasicJsonType::number_float_t;
|
using number_float_t = typename BasicJsonType::number_float_t;
|
||||||
using string_t = typename BasicJsonType::string_t;
|
using string_t = typename BasicJsonType::string_t;
|
||||||
|
using binary_t = typename BasicJsonType::binary_t;
|
||||||
using exception_t = typename BasicJsonType::exception;
|
using exception_t = typename BasicJsonType::exception;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -123,6 +127,9 @@ struct is_sax_static_asserts
|
||||||
static_assert(
|
static_assert(
|
||||||
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
|
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
|
||||||
"Missing/invalid function: bool string(string_t&)");
|
"Missing/invalid function: bool string(string_t&)");
|
||||||
|
static_assert(
|
||||||
|
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
|
||||||
|
"Missing/invalid function: bool binary(binary_t&)");
|
||||||
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
|
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
|
||||||
"Missing/invalid function: bool start_object(std::size_t)");
|
"Missing/invalid function: bool start_object(std::size_t)");
|
||||||
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
|
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||||
#include <utility> // declval
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
|
@ -95,9 +94,19 @@ using get_template_function = decltype(std::declval<T>().template get<U>());
|
||||||
template<typename BasicJsonType, typename T, typename = void>
|
template<typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_from_json : std::false_type {};
|
struct has_from_json : std::false_type {};
|
||||||
|
|
||||||
|
// trait checking if j.get<T> is valid
|
||||||
|
// use this trait instead of std::is_constructible or std::is_convertible,
|
||||||
|
// both rely on, or make use of implicit conversions, and thus fail when T
|
||||||
|
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
|
||||||
|
template <typename BasicJsonType, typename T>
|
||||||
|
struct is_getable
|
||||||
|
{
|
||||||
|
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_from_json < BasicJsonType, T,
|
struct has_from_json < BasicJsonType, T,
|
||||||
enable_if_t<not is_basic_json<T>::value>>
|
enable_if_t < !is_basic_json<T>::value >>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -112,7 +121,7 @@ template <typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_non_default_from_json : std::false_type {};
|
struct has_non_default_from_json : std::false_type {};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
|
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -127,7 +136,7 @@ template <typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_to_json : std::false_type {};
|
struct has_to_json : std::false_type {};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
|
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -174,7 +183,7 @@ struct is_compatible_object_type_impl : std::false_type {};
|
||||||
template<typename BasicJsonType, typename CompatibleObjectType>
|
template<typename BasicJsonType, typename CompatibleObjectType>
|
||||||
struct is_compatible_object_type_impl <
|
struct is_compatible_object_type_impl <
|
||||||
BasicJsonType, CompatibleObjectType,
|
BasicJsonType, CompatibleObjectType,
|
||||||
enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
|
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
|
||||||
is_detected<key_type_t, CompatibleObjectType>::value >>
|
is_detected<key_type_t, CompatibleObjectType>::value >>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -183,7 +192,7 @@ struct is_compatible_object_type_impl <
|
||||||
// macOS's is_constructible does not play well with nonesuch...
|
// macOS's is_constructible does not play well with nonesuch...
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
std::is_constructible<typename object_t::key_type,
|
std::is_constructible<typename object_t::key_type,
|
||||||
typename CompatibleObjectType::key_type>::value and
|
typename CompatibleObjectType::key_type>::value &&
|
||||||
std::is_constructible<typename object_t::mapped_type,
|
std::is_constructible<typename object_t::mapped_type,
|
||||||
typename CompatibleObjectType::mapped_type>::value;
|
typename CompatibleObjectType::mapped_type>::value;
|
||||||
};
|
};
|
||||||
|
@ -199,22 +208,22 @@ struct is_constructible_object_type_impl : std::false_type {};
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType>
|
template<typename BasicJsonType, typename ConstructibleObjectType>
|
||||||
struct is_constructible_object_type_impl <
|
struct is_constructible_object_type_impl <
|
||||||
BasicJsonType, ConstructibleObjectType,
|
BasicJsonType, ConstructibleObjectType,
|
||||||
enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
|
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
|
||||||
is_detected<key_type_t, ConstructibleObjectType>::value >>
|
is_detected<key_type_t, ConstructibleObjectType>::value >>
|
||||||
{
|
{
|
||||||
using object_t = typename BasicJsonType::object_t;
|
using object_t = typename BasicJsonType::object_t;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
(std::is_default_constructible<ConstructibleObjectType>::value and
|
(std::is_default_constructible<ConstructibleObjectType>::value &&
|
||||||
(std::is_move_assignable<ConstructibleObjectType>::value or
|
(std::is_move_assignable<ConstructibleObjectType>::value ||
|
||||||
std::is_copy_assignable<ConstructibleObjectType>::value) and
|
std::is_copy_assignable<ConstructibleObjectType>::value) &&
|
||||||
(std::is_constructible<typename ConstructibleObjectType::key_type,
|
(std::is_constructible<typename ConstructibleObjectType::key_type,
|
||||||
typename object_t::key_type>::value and
|
typename object_t::key_type>::value &&
|
||||||
std::is_same <
|
std::is_same <
|
||||||
typename object_t::mapped_type,
|
typename object_t::mapped_type,
|
||||||
typename ConstructibleObjectType::mapped_type >::value)) or
|
typename ConstructibleObjectType::mapped_type >::value)) ||
|
||||||
(has_from_json<BasicJsonType,
|
(has_from_json<BasicJsonType,
|
||||||
typename ConstructibleObjectType::mapped_type>::value or
|
typename ConstructibleObjectType::mapped_type>::value ||
|
||||||
has_non_default_from_json <
|
has_non_default_from_json <
|
||||||
BasicJsonType,
|
BasicJsonType,
|
||||||
typename ConstructibleObjectType::mapped_type >::value);
|
typename ConstructibleObjectType::mapped_type >::value);
|
||||||
|
@ -268,12 +277,12 @@ struct is_compatible_array_type_impl : std::false_type {};
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||||
struct is_compatible_array_type_impl <
|
struct is_compatible_array_type_impl <
|
||||||
BasicJsonType, CompatibleArrayType,
|
BasicJsonType, CompatibleArrayType,
|
||||||
enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
|
enable_if_t < is_detected<value_type_t, CompatibleArrayType>::value&&
|
||||||
is_detected<iterator_t, CompatibleArrayType>::value and
|
is_detected<iterator_t, CompatibleArrayType>::value&&
|
||||||
// This is needed because json_reverse_iterator has a ::iterator type...
|
// This is needed because json_reverse_iterator has a ::iterator type...
|
||||||
// Therefore it is detected as a CompatibleArrayType.
|
// Therefore it is detected as a CompatibleArrayType.
|
||||||
// The real fix would be to have an Iterable concept.
|
// The real fix would be to have an Iterable concept.
|
||||||
not is_iterator_traits<
|
!is_iterator_traits <
|
||||||
iterator_traits<CompatibleArrayType >>::value >>
|
iterator_traits<CompatibleArrayType >>::value >>
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
|
@ -298,13 +307,13 @@ struct is_constructible_array_type_impl <
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||||
struct is_constructible_array_type_impl <
|
struct is_constructible_array_type_impl <
|
||||||
BasicJsonType, ConstructibleArrayType,
|
BasicJsonType, ConstructibleArrayType,
|
||||||
enable_if_t<not std::is_same<ConstructibleArrayType,
|
enable_if_t < !std::is_same<ConstructibleArrayType,
|
||||||
typename BasicJsonType::value_type>::value and
|
typename BasicJsonType::value_type>::value&&
|
||||||
std::is_default_constructible<ConstructibleArrayType>::value and
|
std::is_default_constructible<ConstructibleArrayType>::value&&
|
||||||
(std::is_move_assignable<ConstructibleArrayType>::value or
|
(std::is_move_assignable<ConstructibleArrayType>::value ||
|
||||||
std::is_copy_assignable<ConstructibleArrayType>::value) and
|
std::is_copy_assignable<ConstructibleArrayType>::value)&&
|
||||||
is_detected<value_type_t, ConstructibleArrayType>::value and
|
is_detected<value_type_t, ConstructibleArrayType>::value&&
|
||||||
is_detected<iterator_t, ConstructibleArrayType>::value and
|
is_detected<iterator_t, ConstructibleArrayType>::value&&
|
||||||
is_complete_type <
|
is_complete_type <
|
||||||
detected_t<value_type_t, ConstructibleArrayType >>::value >>
|
detected_t<value_type_t, ConstructibleArrayType >>::value >>
|
||||||
{
|
{
|
||||||
|
@ -314,12 +323,12 @@ detected_t<value_type_t, ConstructibleArrayType>>::value >>
|
||||||
// base class `iterator`... Therefore it is detected as a
|
// base class `iterator`... Therefore it is detected as a
|
||||||
// ConstructibleArrayType. The real fix would be to have an Iterable
|
// ConstructibleArrayType. The real fix would be to have an Iterable
|
||||||
// concept.
|
// concept.
|
||||||
not is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value and
|
!is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value &&
|
||||||
|
|
||||||
(std::is_same<typename ConstructibleArrayType::value_type,
|
(std::is_same<typename ConstructibleArrayType::value_type,
|
||||||
typename BasicJsonType::array_t::value_type>::value or
|
typename BasicJsonType::array_t::value_type>::value ||
|
||||||
has_from_json<BasicJsonType,
|
has_from_json<BasicJsonType,
|
||||||
typename ConstructibleArrayType::value_type>::value or
|
typename ConstructibleArrayType::value_type>::value ||
|
||||||
has_non_default_from_json <
|
has_non_default_from_json <
|
||||||
BasicJsonType, typename ConstructibleArrayType::value_type >::value);
|
BasicJsonType, typename ConstructibleArrayType::value_type >::value);
|
||||||
};
|
};
|
||||||
|
@ -335,9 +344,9 @@ struct is_compatible_integer_type_impl : std::false_type {};
|
||||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||||
struct is_compatible_integer_type_impl <
|
struct is_compatible_integer_type_impl <
|
||||||
RealIntegerType, CompatibleNumberIntegerType,
|
RealIntegerType, CompatibleNumberIntegerType,
|
||||||
enable_if_t<std::is_integral<RealIntegerType>::value and
|
enable_if_t < std::is_integral<RealIntegerType>::value&&
|
||||||
std::is_integral<CompatibleNumberIntegerType>::value and
|
std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||||
not std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
||||||
{
|
{
|
||||||
// is there an assert somewhere on overflows?
|
// is there an assert somewhere on overflows?
|
||||||
using RealLimits = std::numeric_limits<RealIntegerType>;
|
using RealLimits = std::numeric_limits<RealIntegerType>;
|
||||||
|
@ -345,8 +354,8 @@ struct is_compatible_integer_type_impl <
|
||||||
|
|
||||||
static constexpr auto value =
|
static constexpr auto value =
|
||||||
std::is_constructible<RealIntegerType,
|
std::is_constructible<RealIntegerType,
|
||||||
CompatibleNumberIntegerType>::value and
|
CompatibleNumberIntegerType>::value &&
|
||||||
CompatibleLimits::is_integer and
|
CompatibleLimits::is_integer &&
|
||||||
RealLimits::is_signed == CompatibleLimits::is_signed;
|
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ class binary_writer
|
||||||
{
|
{
|
||||||
using string_t = typename BasicJsonType::string_t;
|
using string_t = typename BasicJsonType::string_t;
|
||||||
using binary_t = typename BasicJsonType::binary_t;
|
using binary_t = typename BasicJsonType::binary_t;
|
||||||
|
using number_float_t = typename BasicJsonType::number_float_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@ -37,7 +38,7 @@ class binary_writer
|
||||||
*/
|
*/
|
||||||
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
|
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
|
||||||
{
|
{
|
||||||
assert(oa);
|
JSON_ASSERT(oa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -194,18 +195,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (static_cast<double>(j.m_value.number_float) >= static_cast<double>(std::numeric_limits<float>::lowest()) and
|
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
|
||||||
static_cast<double>(j.m_value.number_float) <= static_cast<double>((std::numeric_limits<float>::max)()) and
|
|
||||||
static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
|
|
||||||
{
|
|
||||||
oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
|
|
||||||
write_number(static_cast<float>(j.m_value.number_float));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
|
|
||||||
write_number(j.m_value.number_float);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -289,6 +279,12 @@ class binary_writer
|
||||||
|
|
||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
{
|
{
|
||||||
|
if (j.m_value.binary->has_subtype())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xd8));
|
||||||
|
write_number(j.m_value.binary->subtype());
|
||||||
|
}
|
||||||
|
|
||||||
// step 1: write control byte and the binary array size
|
// step 1: write control byte and the binary array size
|
||||||
const auto N = j.m_value.binary->size();
|
const auto N = j.m_value.binary->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
|
@ -436,28 +432,28 @@ class binary_writer
|
||||||
// negative fixnum
|
// negative fixnum
|
||||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
|
||||||
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
// int 8
|
// int 8
|
||||||
oa->write_character(to_char_type(0xD0));
|
oa->write_character(to_char_type(0xD0));
|
||||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
|
||||||
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||||
{
|
{
|
||||||
// int 16
|
// int 16
|
||||||
oa->write_character(to_char_type(0xD1));
|
oa->write_character(to_char_type(0xD1));
|
||||||
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
|
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
|
||||||
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
// int 32
|
// int 32
|
||||||
oa->write_character(to_char_type(0xD2));
|
oa->write_character(to_char_type(0xD2));
|
||||||
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
|
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
|
||||||
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
{
|
{
|
||||||
// int 64
|
// int 64
|
||||||
|
@ -504,8 +500,7 @@ class binary_writer
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
{
|
{
|
||||||
oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
|
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
|
||||||
write_number(j.m_value.number_float);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +579,7 @@ class binary_writer
|
||||||
const auto N = j.m_value.binary->size();
|
const auto N = j.m_value.binary->size();
|
||||||
if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
{
|
{
|
||||||
std::uint8_t output_type;
|
std::uint8_t output_type{};
|
||||||
bool fixed = true;
|
bool fixed = true;
|
||||||
if (use_ext)
|
if (use_ext)
|
||||||
{
|
{
|
||||||
|
@ -619,37 +614,25 @@ class binary_writer
|
||||||
}
|
}
|
||||||
|
|
||||||
oa->write_character(to_char_type(output_type));
|
oa->write_character(to_char_type(output_type));
|
||||||
if (not fixed)
|
if (!fixed)
|
||||||
{
|
{
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
write_number(static_cast<std::uint8_t>(N));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
{
|
{
|
||||||
std::uint8_t output_type;
|
std::uint8_t output_type = use_ext
|
||||||
if (use_ext)
|
? 0xC8 // ext 16
|
||||||
{
|
: 0xC5; // bin 16
|
||||||
output_type = 0xC8; // ext 16
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
output_type = 0xC5; // bin 16
|
|
||||||
}
|
|
||||||
|
|
||||||
oa->write_character(to_char_type(output_type));
|
oa->write_character(to_char_type(output_type));
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
write_number(static_cast<std::uint16_t>(N));
|
||||||
}
|
}
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
{
|
{
|
||||||
std::uint8_t output_type;
|
std::uint8_t output_type = use_ext
|
||||||
if (use_ext)
|
? 0xC9 // ext 32
|
||||||
{
|
: 0xC6; // bin 32
|
||||||
output_type = 0xC9; // ext 32
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
output_type = 0xC6; // bin 32
|
|
||||||
}
|
|
||||||
|
|
||||||
oa->write_character(to_char_type(output_type));
|
oa->write_character(to_char_type(output_type));
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
write_number(static_cast<std::uint32_t>(N));
|
||||||
|
@ -775,9 +758,9 @@ class binary_writer
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prefix_required = true;
|
bool prefix_required = true;
|
||||||
if (use_type and not j.m_value.array->empty())
|
if (use_type && !j.m_value.array->empty())
|
||||||
{
|
{
|
||||||
assert(use_count);
|
JSON_ASSERT(use_count);
|
||||||
const CharType first_prefix = ubjson_prefix(j.front());
|
const CharType first_prefix = ubjson_prefix(j.front());
|
||||||
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
|
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
|
||||||
[this, first_prefix](const BasicJsonType & v)
|
[this, first_prefix](const BasicJsonType & v)
|
||||||
|
@ -804,7 +787,7 @@ class binary_writer
|
||||||
write_ubjson(el, use_count, use_type, prefix_required);
|
write_ubjson(el, use_count, use_type, prefix_required);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not use_count)
|
if (!use_count)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(']'));
|
oa->write_character(to_char_type(']'));
|
||||||
}
|
}
|
||||||
|
@ -819,9 +802,9 @@ class binary_writer
|
||||||
oa->write_character(to_char_type('['));
|
oa->write_character(to_char_type('['));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_type and not j.m_value.binary->empty())
|
if (use_type && !j.m_value.binary->empty())
|
||||||
{
|
{
|
||||||
assert(use_count);
|
JSON_ASSERT(use_count);
|
||||||
oa->write_character(to_char_type('$'));
|
oa->write_character(to_char_type('$'));
|
||||||
oa->write_character('U');
|
oa->write_character('U');
|
||||||
}
|
}
|
||||||
|
@ -847,7 +830,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not use_count)
|
if (!use_count)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(']'));
|
oa->write_character(to_char_type(']'));
|
||||||
}
|
}
|
||||||
|
@ -863,9 +846,9 @@ class binary_writer
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prefix_required = true;
|
bool prefix_required = true;
|
||||||
if (use_type and not j.m_value.object->empty())
|
if (use_type && !j.m_value.object->empty())
|
||||||
{
|
{
|
||||||
assert(use_count);
|
JSON_ASSERT(use_count);
|
||||||
const CharType first_prefix = ubjson_prefix(j.front());
|
const CharType first_prefix = ubjson_prefix(j.front());
|
||||||
const bool same_prefix = std::all_of(j.begin(), j.end(),
|
const bool same_prefix = std::all_of(j.begin(), j.end(),
|
||||||
[this, first_prefix](const BasicJsonType & v)
|
[this, first_prefix](const BasicJsonType & v)
|
||||||
|
@ -896,7 +879,7 @@ class binary_writer
|
||||||
write_ubjson(el.second, use_count, use_type, prefix_required);
|
write_ubjson(el.second, use_count, use_type, prefix_required);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not use_count)
|
if (!use_count)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('}'));
|
oa->write_character(to_char_type('}'));
|
||||||
}
|
}
|
||||||
|
@ -997,7 +980,7 @@ class binary_writer
|
||||||
*/
|
*/
|
||||||
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
||||||
{
|
{
|
||||||
return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
|
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
|
||||||
? sizeof(std::int32_t)
|
? sizeof(std::int32_t)
|
||||||
: sizeof(std::int64_t);
|
: sizeof(std::int64_t);
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +991,7 @@ class binary_writer
|
||||||
void write_bson_integer(const string_t& name,
|
void write_bson_integer(const string_t& name,
|
||||||
const std::int64_t value)
|
const std::int64_t value)
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
|
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x10); // int32
|
write_bson_entry_header(name, 0x10); // int32
|
||||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
|
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
|
||||||
|
@ -1157,7 +1140,7 @@ class binary_writer
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
default:
|
default:
|
||||||
assert(false);
|
JSON_ASSERT(false);
|
||||||
return 0ul;
|
return 0ul;
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
@ -1204,7 +1187,7 @@ class binary_writer
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
default:
|
default:
|
||||||
assert(false);
|
JSON_ASSERT(false);
|
||||||
return;
|
return;
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
@ -1336,18 +1319,28 @@ class binary_writer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa->write_character(to_char_type('H')); // high-precision number
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto number = BasicJsonType(n).dump();
|
||||||
|
write_number_with_ubjson_prefix(number.size(), true);
|
||||||
|
for (std::size_t i = 0; i < number.size(); ++i)
|
||||||
|
{
|
||||||
|
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UBJSON: write number (signed integer)
|
// UBJSON: write number (signed integer)
|
||||||
template < typename NumberType, typename std::enable_if <
|
template < typename NumberType, typename std::enable_if <
|
||||||
std::is_signed<NumberType>::value and
|
std::is_signed<NumberType>::value&&
|
||||||
not std::is_floating_point<NumberType>::value, int>::type = 0>
|
!std::is_floating_point<NumberType>::value, int >::type = 0 >
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
void write_number_with_ubjson_prefix(const NumberType n,
|
||||||
const bool add_prefix)
|
const bool add_prefix)
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
|
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
|
@ -1355,7 +1348,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
write_number(static_cast<std::int8_t>(n));
|
write_number(static_cast<std::int8_t>(n));
|
||||||
}
|
}
|
||||||
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
|
@ -1363,7 +1356,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
write_number(static_cast<std::uint8_t>(n));
|
write_number(static_cast<std::uint8_t>(n));
|
||||||
}
|
}
|
||||||
else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
|
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
|
@ -1371,7 +1364,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
write_number(static_cast<std::int16_t>(n));
|
write_number(static_cast<std::int16_t>(n));
|
||||||
}
|
}
|
||||||
else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
|
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
|
@ -1379,7 +1372,7 @@ class binary_writer
|
||||||
}
|
}
|
||||||
write_number(static_cast<std::int32_t>(n));
|
write_number(static_cast<std::int32_t>(n));
|
||||||
}
|
}
|
||||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
|
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
|
@ -1390,19 +1383,23 @@ class binary_writer
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa->write_character(to_char_type('H')); // high-precision number
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto number = BasicJsonType(n).dump();
|
||||||
|
write_number_with_ubjson_prefix(number.size(), true);
|
||||||
|
for (std::size_t i = 0; i < number.size(); ++i)
|
||||||
|
{
|
||||||
|
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief determine the type prefix of container values
|
@brief determine the type prefix of container values
|
||||||
|
|
||||||
@note This function does not need to be 100% accurate when it comes to
|
|
||||||
integer limits. In case a number exceeds the limits of int64_t,
|
|
||||||
this will be detected by a later call to function
|
|
||||||
write_number_with_ubjson_prefix. Therefore, we return 'L' for any
|
|
||||||
value that does not fit the previous limits.
|
|
||||||
*/
|
*/
|
||||||
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
|
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
|
||||||
{
|
{
|
||||||
|
@ -1416,25 +1413,29 @@ class binary_writer
|
||||||
|
|
||||||
case value_t::number_integer:
|
case value_t::number_integer:
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
return 'i';
|
return 'i';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
{
|
{
|
||||||
return 'U';
|
return 'U';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||||
{
|
{
|
||||||
return 'I';
|
return 'I';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
return 'l';
|
return 'l';
|
||||||
}
|
}
|
||||||
// no check and assume int64_t (see note above)
|
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
|
{
|
||||||
return 'L';
|
return 'L';
|
||||||
}
|
}
|
||||||
|
// anything else is treated as high-precision number
|
||||||
|
return 'H'; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
|
@ -1454,9 +1455,13 @@ class binary_writer
|
||||||
{
|
{
|
||||||
return 'l';
|
return 'l';
|
||||||
}
|
}
|
||||||
// no check and assume int64_t (see note above)
|
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
|
||||||
|
{
|
||||||
return 'L';
|
return 'L';
|
||||||
}
|
}
|
||||||
|
// anything else is treated as high-precision number
|
||||||
|
return 'H'; // LCOV_EXCL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
return get_ubjson_float_prefix(j.m_value.number_float);
|
return get_ubjson_float_prefix(j.m_value.number_float);
|
||||||
|
@ -1518,20 +1523,40 @@ class binary_writer
|
||||||
oa->write_characters(vec.data(), sizeof(NumberType));
|
oa->write_characters(vec.data(), sizeof(NumberType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_compact_float(const number_float_t n, detail::input_format_t format)
|
||||||
|
{
|
||||||
|
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
||||||
|
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
||||||
|
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
|
||||||
|
{
|
||||||
|
oa->write_character(format == detail::input_format_t::cbor
|
||||||
|
? get_cbor_float_prefix(static_cast<float>(n))
|
||||||
|
: get_msgpack_float_prefix(static_cast<float>(n)));
|
||||||
|
write_number(static_cast<float>(n));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oa->write_character(format == detail::input_format_t::cbor
|
||||||
|
? get_cbor_float_prefix(n)
|
||||||
|
: get_msgpack_float_prefix(n));
|
||||||
|
write_number(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// The following to_char_type functions are implement the conversion
|
// The following to_char_type functions are implement the conversion
|
||||||
// between uint8_t and CharType. In case CharType is not unsigned,
|
// between uint8_t and CharType. In case CharType is not unsigned,
|
||||||
// such a conversion is required to allow values greater than 128.
|
// such a conversion is required to allow values greater than 128.
|
||||||
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
|
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
|
||||||
template < typename C = CharType,
|
template < typename C = CharType,
|
||||||
enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
|
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
|
||||||
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<char*>(&x);
|
return *reinterpret_cast<char*>(&x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename C = CharType,
|
template < typename C = CharType,
|
||||||
enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
|
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
|
||||||
static CharType to_char_type(std::uint8_t x) noexcept
|
static CharType to_char_type(std::uint8_t x) noexcept
|
||||||
{
|
{
|
||||||
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
|
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
|
||||||
|
@ -1550,8 +1575,8 @@ class binary_writer
|
||||||
|
|
||||||
template < typename InputCharType, typename C = CharType,
|
template < typename InputCharType, typename C = CharType,
|
||||||
enable_if_t <
|
enable_if_t <
|
||||||
std::is_signed<C>::value and
|
std::is_signed<C>::value &&
|
||||||
std::is_signed<char>::value and
|
std::is_signed<char>::value &&
|
||||||
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
|
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
|
||||||
> * = nullptr >
|
> * = nullptr >
|
||||||
static constexpr CharType to_char_type(InputCharType x) noexcept
|
static constexpr CharType to_char_type(InputCharType x) noexcept
|
||||||
|
|
|
@ -2,18 +2,16 @@
|
||||||
|
|
||||||
#include <algorithm> // reverse, remove, fill, find, none_of
|
#include <algorithm> // reverse, remove, fill, find, none_of
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cassert> // assert
|
|
||||||
#include <clocale> // localeconv, lconv
|
#include <clocale> // localeconv, lconv
|
||||||
#include <cmath> // labs, isfinite, isnan, signbit
|
#include <cmath> // labs, isfinite, isnan, signbit
|
||||||
#include <cstddef> // size_t, ptrdiff_t
|
#include <cstddef> // size_t, ptrdiff_t
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <string> // string
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // is_same
|
#include <type_traits> // is_same
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
@ -59,8 +57,8 @@ class serializer
|
||||||
error_handler_t error_handler_ = error_handler_t::strict)
|
error_handler_t error_handler_ = error_handler_t::strict)
|
||||||
: o(std::move(s))
|
: o(std::move(s))
|
||||||
, loc(std::localeconv())
|
, loc(std::localeconv())
|
||||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
|
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
|
||||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
|
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
|
||||||
, indent_char(ichar)
|
, indent_char(ichar)
|
||||||
, indent_string(512, indent_char)
|
, indent_string(512, indent_char)
|
||||||
, error_handler(error_handler_)
|
, error_handler(error_handler_)
|
||||||
|
@ -135,8 +133,8 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(i != val.m_value.object->cend());
|
JSON_ASSERT(i != val.m_value.object->cend());
|
||||||
assert(std::next(i) == val.m_value.object->cend());
|
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
|
||||||
o->write_characters(indent_string.c_str(), new_indent);
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
o->write_character('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first, ensure_ascii);
|
dump_escaped(i->first, ensure_ascii);
|
||||||
|
@ -163,8 +161,8 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(i != val.m_value.object->cend());
|
JSON_ASSERT(i != val.m_value.object->cend());
|
||||||
assert(std::next(i) == val.m_value.object->cend());
|
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
|
||||||
o->write_character('\"');
|
o->write_character('\"');
|
||||||
dump_escaped(i->first, ensure_ascii);
|
dump_escaped(i->first, ensure_ascii);
|
||||||
o->write_characters("\":", 2);
|
o->write_characters("\":", 2);
|
||||||
|
@ -205,7 +203,7 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(not val.m_value.array->empty());
|
JSON_ASSERT(!val.m_value.array->empty());
|
||||||
o->write_characters(indent_string.c_str(), new_indent);
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
|
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
|
||||||
|
|
||||||
|
@ -226,7 +224,7 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// last element
|
// last element
|
||||||
assert(not val.m_value.array->empty());
|
JSON_ASSERT(!val.m_value.array->empty());
|
||||||
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
|
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
|
||||||
|
|
||||||
o->write_character(']');
|
o->write_character(']');
|
||||||
|
@ -260,7 +258,7 @@ class serializer
|
||||||
|
|
||||||
o->write_characters("\"bytes\": [", 10);
|
o->write_characters("\"bytes\": [", 10);
|
||||||
|
|
||||||
if (not val.m_value.binary->empty())
|
if (!val.m_value.binary->empty())
|
||||||
{
|
{
|
||||||
for (auto i = val.m_value.binary->cbegin();
|
for (auto i = val.m_value.binary->cbegin();
|
||||||
i != val.m_value.binary->cend() - 1; ++i)
|
i != val.m_value.binary->cend() - 1; ++i)
|
||||||
|
@ -291,7 +289,7 @@ class serializer
|
||||||
{
|
{
|
||||||
o->write_characters("{\"bytes\":[", 10);
|
o->write_characters("{\"bytes\":[", 10);
|
||||||
|
|
||||||
if (not val.m_value.binary->empty())
|
if (!val.m_value.binary->empty())
|
||||||
{
|
{
|
||||||
for (auto i = val.m_value.binary->cbegin();
|
for (auto i = val.m_value.binary->cbegin();
|
||||||
i != val.m_value.binary->cend() - 1; ++i)
|
i != val.m_value.binary->cend() - 1; ++i)
|
||||||
|
@ -360,7 +358,7 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
assert(false); // LCOV_EXCL_LINE
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +450,7 @@ class serializer
|
||||||
{
|
{
|
||||||
// escape control characters (0x00..0x1F) or, if
|
// escape control characters (0x00..0x1F) or, if
|
||||||
// ensure_ascii parameter is used, non-ASCII characters
|
// ensure_ascii parameter is used, non-ASCII characters
|
||||||
if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
|
if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
|
||||||
{
|
{
|
||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
|
@ -559,14 +557,14 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
assert(false); // LCOV_EXCL_LINE
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // decode found yet incomplete multi-byte code point
|
default: // decode found yet incomplete multi-byte code point
|
||||||
{
|
{
|
||||||
if (not ensure_ascii)
|
if (!ensure_ascii)
|
||||||
{
|
{
|
||||||
// code point will not be escaped - copy byte to buffer
|
// code point will not be escaped - copy byte to buffer
|
||||||
string_buffer[bytes++] = s[i];
|
string_buffer[bytes++] = s[i];
|
||||||
|
@ -622,7 +620,7 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
assert(false); // LCOV_EXCL_LINE
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -671,8 +669,8 @@ class serializer
|
||||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||||
*/
|
*/
|
||||||
template < typename NumberType, detail::enable_if_t <
|
template < typename NumberType, detail::enable_if_t <
|
||||||
std::is_same<NumberType, number_unsigned_t>::value or
|
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||||
std::is_same<NumberType, number_integer_t>::value or
|
std::is_same<NumberType, number_integer_t>::value ||
|
||||||
std::is_same<NumberType, binary_char_t>::value,
|
std::is_same<NumberType, binary_char_t>::value,
|
||||||
int > = 0 >
|
int > = 0 >
|
||||||
void dump_integer(NumberType x)
|
void dump_integer(NumberType x)
|
||||||
|
@ -703,7 +701,7 @@ class serializer
|
||||||
// use a pointer to fill the buffer
|
// use a pointer to fill the buffer
|
||||||
auto buffer_ptr = number_buffer.begin();
|
auto buffer_ptr = number_buffer.begin();
|
||||||
|
|
||||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
|
const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
|
||||||
unsigned int n_chars;
|
unsigned int n_chars;
|
||||||
|
@ -723,7 +721,7 @@ class serializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// spare 1 byte for '\0'
|
// spare 1 byte for '\0'
|
||||||
assert(n_chars < number_buffer.size() - 1);
|
JSON_ASSERT(n_chars < number_buffer.size() - 1);
|
||||||
|
|
||||||
// jump to the end to generate the string from backward
|
// jump to the end to generate the string from backward
|
||||||
// so we later avoid reversing the result
|
// so we later avoid reversing the result
|
||||||
|
@ -764,7 +762,7 @@ class serializer
|
||||||
void dump_float(number_float_t x)
|
void dump_float(number_float_t x)
|
||||||
{
|
{
|
||||||
// NaN / inf
|
// NaN / inf
|
||||||
if (not std::isfinite(x))
|
if (!std::isfinite(x))
|
||||||
{
|
{
|
||||||
o->write_characters("null", 4);
|
o->write_characters("null", 4);
|
||||||
return;
|
return;
|
||||||
|
@ -776,8 +774,8 @@ class serializer
|
||||||
//
|
//
|
||||||
// NB: The test below works if <long double> == <double>.
|
// NB: The test below works if <long double> == <double>.
|
||||||
static constexpr bool is_ieee_single_or_double
|
static constexpr bool is_ieee_single_or_double
|
||||||
= (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
|
= (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
|
||||||
(std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
|
(std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
|
||||||
|
|
||||||
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
||||||
}
|
}
|
||||||
|
@ -799,9 +797,9 @@ class serializer
|
||||||
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
|
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
|
||||||
|
|
||||||
// negative value indicates an error
|
// negative value indicates an error
|
||||||
assert(len > 0);
|
JSON_ASSERT(len > 0);
|
||||||
// check if buffer was large enough
|
// check if buffer was large enough
|
||||||
assert(static_cast<std::size_t>(len) < number_buffer.size());
|
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
|
||||||
|
|
||||||
// erase thousands separator
|
// erase thousands separator
|
||||||
if (thousands_sep != '\0')
|
if (thousands_sep != '\0')
|
||||||
|
@ -809,12 +807,12 @@ class serializer
|
||||||
const auto end = std::remove(number_buffer.begin(),
|
const auto end = std::remove(number_buffer.begin(),
|
||||||
number_buffer.begin() + len, thousands_sep);
|
number_buffer.begin() + len, thousands_sep);
|
||||||
std::fill(end, number_buffer.end(), '\0');
|
std::fill(end, number_buffer.end(), '\0');
|
||||||
assert((end - number_buffer.begin()) <= len);
|
JSON_ASSERT((end - number_buffer.begin()) <= len);
|
||||||
len = (end - number_buffer.begin());
|
len = (end - number_buffer.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert decimal point to '.'
|
// convert decimal point to '.'
|
||||||
if (decimal_point != '\0' and decimal_point != '.')
|
if (decimal_point != '\0' && decimal_point != '.')
|
||||||
{
|
{
|
||||||
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
|
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
|
||||||
if (dec_pos != number_buffer.end())
|
if (dec_pos != number_buffer.end())
|
||||||
|
@ -830,7 +828,7 @@ class serializer
|
||||||
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
||||||
[](char c)
|
[](char c)
|
||||||
{
|
{
|
||||||
return c == '.' or c == 'e';
|
return c == '.' || c == 'e';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (value_is_int_like)
|
if (value_is_int_like)
|
||||||
|
@ -889,7 +887,7 @@ class serializer
|
||||||
: (0xFFu >> type) & (byte);
|
: (0xFFu >> type) & (byte);
|
||||||
|
|
||||||
std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
|
std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
|
||||||
assert(index < 400);
|
JSON_ASSERT(index < 400);
|
||||||
state = utf8d[index];
|
state = utf8d[index];
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -901,7 +899,7 @@ class serializer
|
||||||
*/
|
*/
|
||||||
number_unsigned_t remove_sign(number_unsigned_t x)
|
number_unsigned_t remove_sign(number_unsigned_t x)
|
||||||
{
|
{
|
||||||
assert(false); // LCOV_EXCL_LINE
|
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||||
return x; // LCOV_EXCL_LINE
|
return x; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,7 +914,7 @@ class serializer
|
||||||
*/
|
*/
|
||||||
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||||
{
|
{
|
||||||
assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
|
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
|
||||||
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
|
|
||||||
#include <nlohmann/detail/boolean_operators.hpp>
|
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
|
@ -77,7 +75,7 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
||||||
|
|
||||||
const auto l_index = static_cast<std::size_t>(lhs);
|
const auto l_index = static_cast<std::size_t>(lhs);
|
||||||
const auto r_index = static_cast<std::size_t>(rhs);
|
const auto r_index = static_cast<std::size_t>(rhs);
|
||||||
return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
|
return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
|
||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -60,6 +60,19 @@ uses the standard template types.
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
using json = basic_json<>;
|
using json = basic_json<>;
|
||||||
|
|
||||||
|
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||||
|
struct ordered_map;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief ordered JSON class
|
||||||
|
|
||||||
|
This type preserves the insertion order of object keys.
|
||||||
|
|
||||||
|
@since version 3.9.0
|
||||||
|
*/
|
||||||
|
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||||
|
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
||||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
|
|
71
include/nlohmann/ordered_map.hpp
Normal file
71
include/nlohmann/ordered_map.hpp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional> // less
|
||||||
|
#include <memory> // allocator
|
||||||
|
#include <utility> // pair
|
||||||
|
#include <vector> // vector
|
||||||
|
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
|
||||||
|
/// ordered_map: a minimal map-like container that preserves insertion order
|
||||||
|
/// for use within nlohmann::basic_json<ordered_map>
|
||||||
|
template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||||
|
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||||
|
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
|
||||||
|
{
|
||||||
|
using key_type = Key;
|
||||||
|
using mapped_type = T;
|
||||||
|
using Container = std::vector<std::pair<const Key, T>, Allocator>;
|
||||||
|
using typename Container::iterator;
|
||||||
|
using typename Container::size_type;
|
||||||
|
using typename Container::value_type;
|
||||||
|
|
||||||
|
// Explicit constructors instead of `using Container::Container`
|
||||||
|
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
||||||
|
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
|
||||||
|
template <class It>
|
||||||
|
ordered_map(It first, It last, const Allocator& alloc = Allocator())
|
||||||
|
: Container{first, last, alloc} {}
|
||||||
|
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
|
||||||
|
: Container{init, alloc} {}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> emplace(key_type&& key, T&& t)
|
||||||
|
{
|
||||||
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == key)
|
||||||
|
{
|
||||||
|
return {it, false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Container::emplace_back(key, t);
|
||||||
|
return {--this->end(), true};
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](Key&& key)
|
||||||
|
{
|
||||||
|
return emplace(std::move(key), T{}).first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type erase(const Key& key)
|
||||||
|
{
|
||||||
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first == key)
|
||||||
|
{
|
||||||
|
// Since we cannot move const Keys, re-construct them in place
|
||||||
|
for (auto next = it; ++next != this->end(); ++it)
|
||||||
|
{
|
||||||
|
it->~value_type(); // Destroy but keep allocation
|
||||||
|
new (&*it) value_type{std::move(*next)};
|
||||||
|
}
|
||||||
|
Container::pop_back();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nlohmann
|
|
@ -1,6 +1,6 @@
|
||||||
project('nlohmann_json',
|
project('nlohmann_json',
|
||||||
'cpp',
|
'cpp',
|
||||||
version : '3.8.0',
|
version : '3.9.0',
|
||||||
license : 'MIT',
|
license : 'MIT',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -95,6 +95,7 @@ set(files
|
||||||
src/unit-algorithms.cpp
|
src/unit-algorithms.cpp
|
||||||
src/unit-allocator.cpp
|
src/unit-allocator.cpp
|
||||||
src/unit-alt-string.cpp
|
src/unit-alt-string.cpp
|
||||||
|
src/unit-assert_macro.cpp
|
||||||
src/unit-bson.cpp
|
src/unit-bson.cpp
|
||||||
src/unit-capacity.cpp
|
src/unit-capacity.cpp
|
||||||
src/unit-cbor.cpp
|
src/unit-cbor.cpp
|
||||||
|
@ -111,6 +112,7 @@ set(files
|
||||||
src/unit-deserialization.cpp
|
src/unit-deserialization.cpp
|
||||||
src/unit-element_access1.cpp
|
src/unit-element_access1.cpp
|
||||||
src/unit-element_access2.cpp
|
src/unit-element_access2.cpp
|
||||||
|
src/unit-hash.cpp
|
||||||
src/unit-inspection.cpp
|
src/unit-inspection.cpp
|
||||||
src/unit-items.cpp
|
src/unit-items.cpp
|
||||||
src/unit-iterators1.cpp
|
src/unit-iterators1.cpp
|
||||||
|
@ -123,6 +125,7 @@ set(files
|
||||||
src/unit-modifiers.cpp
|
src/unit-modifiers.cpp
|
||||||
src/unit-msgpack.cpp
|
src/unit-msgpack.cpp
|
||||||
src/unit-noexcept.cpp
|
src/unit-noexcept.cpp
|
||||||
|
src/unit-ordered_json.cpp
|
||||||
src/unit-pointer_access.cpp
|
src/unit-pointer_access.cpp
|
||||||
src/unit-readme.cpp
|
src/unit-readme.cpp
|
||||||
src/unit-reference_access.cpp
|
src/unit-reference_access.cpp
|
||||||
|
@ -132,6 +135,7 @@ set(files
|
||||||
src/unit-to_chars.cpp
|
src/unit-to_chars.cpp
|
||||||
src/unit-ubjson.cpp
|
src/unit-ubjson.cpp
|
||||||
src/unit-udt.cpp
|
src/unit-udt.cpp
|
||||||
|
src/unit-udt_macro.cpp
|
||||||
src/unit-unicode.cpp
|
src/unit-unicode.cpp
|
||||||
src/unit-user_defined_input.cpp
|
src/unit-user_defined_input.cpp
|
||||||
src/unit-wstring.cpp)
|
src/unit-wstring.cpp)
|
||||||
|
@ -189,3 +193,4 @@ add_subdirectory(cmake_import)
|
||||||
add_subdirectory(cmake_import_minver)
|
add_subdirectory(cmake_import_minver)
|
||||||
add_subdirectory(cmake_add_subdirectory)
|
add_subdirectory(cmake_add_subdirectory)
|
||||||
add_subdirectory(cmake_fetch_content)
|
add_subdirectory(cmake_fetch_content)
|
||||||
|
add_subdirectory(cmake_target_include_directories)
|
||||||
|
|
101
test/Makefile
101
test/Makefile
|
@ -1,98 +1,13 @@
|
||||||
##########################################################################
|
##############################################################################
|
||||||
# unit tests
|
# OSS-Fuzz
|
||||||
##########################################################################
|
##############################################################################
|
||||||
|
|
||||||
|
# The following targets realize the integration to OSS-Fuzz.
|
||||||
|
# See <https://github.com/google/oss-fuzz/blob/master/projects/json/build.sh> for more information.
|
||||||
|
|
||||||
# additional flags
|
# additional flags
|
||||||
CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wno-ctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wno-float-equal
|
CXXFLAGS += -std=c++11
|
||||||
CPPFLAGS += -I ../single_include -I . -I thirdparty/doctest -I thirdparty/fifo_map -DDOCTEST_CONFIG_SUPER_FAST_ASSERTS
|
CPPFLAGS += -I ../single_include
|
||||||
|
|
||||||
SOURCES = src/unit.cpp \
|
|
||||||
src/unit-algorithms.cpp \
|
|
||||||
src/unit-allocator.cpp \
|
|
||||||
src/unit-alt-string.cpp \
|
|
||||||
src/unit-bson.cpp \
|
|
||||||
src/unit-capacity.cpp \
|
|
||||||
src/unit-cbor.cpp \
|
|
||||||
src/unit-class_const_iterator.cpp \
|
|
||||||
src/unit-class_iterator.cpp \
|
|
||||||
src/unit-class_lexer.cpp \
|
|
||||||
src/unit-class_parser.cpp \
|
|
||||||
src/unit-comparison.cpp \
|
|
||||||
src/unit-concepts.cpp \
|
|
||||||
src/unit-constructor1.cpp \
|
|
||||||
src/unit-constructor2.cpp \
|
|
||||||
src/unit-convenience.cpp \
|
|
||||||
src/unit-conversions.cpp \
|
|
||||||
src/unit-deserialization.cpp \
|
|
||||||
src/unit-element_access1.cpp \
|
|
||||||
src/unit-element_access2.cpp \
|
|
||||||
src/unit-inspection.cpp \
|
|
||||||
src/unit-items.cpp \
|
|
||||||
src/unit-iterators1.cpp \
|
|
||||||
src/unit-iterators2.cpp \
|
|
||||||
src/unit-merge_patch.cpp \
|
|
||||||
src/unit-json_patch.cpp \
|
|
||||||
src/unit-json_pointer.cpp \
|
|
||||||
src/unit-meta.cpp \
|
|
||||||
src/unit-modifiers.cpp \
|
|
||||||
src/unit-msgpack.cpp \
|
|
||||||
src/unit-pointer_access.cpp \
|
|
||||||
src/unit-readme.cpp \
|
|
||||||
src/unit-reference_access.cpp \
|
|
||||||
src/unit-regression.cpp \
|
|
||||||
src/unit-serialization.cpp \
|
|
||||||
src/unit-testsuites.cpp \
|
|
||||||
src/unit-ubjson.cpp \
|
|
||||||
src/unit-unicode.cpp \
|
|
||||||
src/unit-user_defined_input.cpp \
|
|
||||||
src/unit-wstring.cpp
|
|
||||||
|
|
||||||
OBJECTS = $(SOURCES:.cpp=.o)
|
|
||||||
|
|
||||||
TESTCASES = $(patsubst src/unit-%.cpp,test-%,$(wildcard src/unit-*.cpp))
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# main rules
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
all: $(TESTCASES)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda) $(TESTCASES) $(FUZZERS) test_data.hpp
|
|
||||||
|
|
||||||
test_data.hpp:
|
|
||||||
@echo "#define TEST_DATA_DIRECTORY" > $@
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# single test file
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
json_unit: $(OBJECTS) ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h
|
|
||||||
@echo "[CXXLD] $@"
|
|
||||||
@$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) -o $@
|
|
||||||
|
|
||||||
%.o: %.cpp ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h test_data.hpp
|
|
||||||
@echo "[CXX] $@"
|
|
||||||
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# individual test cases
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
test-%: src/unit-%.o src/unit.o ../single_include/nlohmann/json.hpp thirdparty/doctest/doctest.h test_data.hpp
|
|
||||||
@echo "[CXXLD] $@"
|
|
||||||
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $< src/unit.o -o $@
|
|
||||||
|
|
||||||
TEST_PATTERN ?= "*"
|
|
||||||
TEST_PREFIX = ""
|
|
||||||
check: $(OBJECTS) $(TESTCASES)
|
|
||||||
@cd .. ; for testcase in $(TESTCASES); do echo "Executing $$testcase..."; $(TEST_PREFIX)test/$$testcase $(TEST_PATTERN) || exit 1; done
|
|
||||||
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# fuzzer
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
FUZZER_ENGINE = src/fuzzer-driver_afl.cpp
|
FUZZER_ENGINE = src/fuzzer-driver_afl.cpp
|
||||||
FUZZERS = parse_afl_fuzzer parse_bson_fuzzer parse_cbor_fuzzer parse_msgpack_fuzzer parse_ubjson_fuzzer
|
FUZZERS = parse_afl_fuzzer parse_bson_fuzzer parse_cbor_fuzzer parse_msgpack_fuzzer parse_ubjson_fuzzer
|
||||||
|
|
|
@ -11,8 +11,10 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.11.0")
|
||||||
)
|
)
|
||||||
set_tests_properties(cmake_fetch_content_configure PROPERTIES
|
set_tests_properties(cmake_fetch_content_configure PROPERTIES
|
||||||
FIXTURES_SETUP cmake_fetch_content
|
FIXTURES_SETUP cmake_fetch_content
|
||||||
|
LABELS git_required
|
||||||
)
|
)
|
||||||
set_tests_properties(cmake_fetch_content_build PROPERTIES
|
set_tests_properties(cmake_fetch_content_build PROPERTIES
|
||||||
FIXTURES_REQUIRED cmake_fetch_content
|
FIXTURES_REQUIRED cmake_fetch_content
|
||||||
|
LABELS git_required
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -4,9 +4,8 @@ project(DummyImport CXX)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(json
|
get_filename_component(GIT_REPOSITORY_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../.. ABSOLUTE)
|
||||||
GIT_REPOSITORY ${CMAKE_CURRENT_SOURCE_DIR}/../../..
|
FetchContent_Declare(json GIT_REPOSITORY ${GIT_REPOSITORY_DIRECTORY} GIT_TAG HEAD)
|
||||||
GIT_TAG HEAD)
|
|
||||||
|
|
||||||
FetchContent_GetProperties(json)
|
FetchContent_GetProperties(json)
|
||||||
if(NOT json_POPULATED)
|
if(NOT json_POPULATED)
|
||||||
|
|
16
test/cmake_target_include_directories/CMakeLists.txt
Normal file
16
test/cmake_target_include_directories/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
add_test(NAME cmake_target_include_directories_configure
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-G "${CMAKE_GENERATOR}"
|
||||||
|
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||||
|
-Dnlohmann_json_source=${PROJECT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/project
|
||||||
|
)
|
||||||
|
add_test(NAME cmake_target_include_directories_build
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build .
|
||||||
|
)
|
||||||
|
set_tests_properties(cmake_target_include_directories_configure PROPERTIES
|
||||||
|
FIXTURES_SETUP cmake_target_include_directories
|
||||||
|
)
|
||||||
|
set_tests_properties(cmake_target_include_directories_build PROPERTIES
|
||||||
|
FIXTURES_REQUIRED cmake_target_include_directories
|
||||||
|
)
|
3
test/cmake_target_include_directories/project/Bar.cpp
Normal file
3
test/cmake_target_include_directories/project/Bar.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include "Bar.hpp"
|
||||||
|
|
||||||
|
class Bar;
|
4
test/cmake_target_include_directories/project/Bar.hpp
Normal file
4
test/cmake_target_include_directories/project/Bar.hpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include "Foo.hpp"
|
||||||
|
|
||||||
|
class Bar : public Foo{};
|
21
test/cmake_target_include_directories/project/CMakeLists.txt
Normal file
21
test/cmake_target_include_directories/project/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
|
project(DummyImport CXX)
|
||||||
|
|
||||||
|
add_executable(with_private_target main.cpp)
|
||||||
|
target_include_directories(with_private_target PRIVATE ${nlohmann_json_source}/include)
|
||||||
|
set_target_properties(with_private_target PROPERTIES CXX_STANDARD 11)
|
||||||
|
|
||||||
|
add_executable(with_private_system_target main.cpp)
|
||||||
|
target_include_directories(with_private_system_target PRIVATE SYSTEM ${nlohmann_json_source}/include)
|
||||||
|
set_target_properties(with_private_system_target PROPERTIES CXX_STANDARD 11)
|
||||||
|
|
||||||
|
# regression from https://github.com/nlohmann/json/discussions/2281
|
||||||
|
add_library(Foo STATIC Foo.cpp Bar.cpp)
|
||||||
|
target_include_directories(Foo PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
|
||||||
|
set_target_properties(Foo PROPERTIES CXX_STANDARD 11)
|
||||||
|
|
||||||
|
add_library(Bar STATIC Bar.cpp)
|
||||||
|
target_link_libraries(Bar PRIVATE Foo)
|
||||||
|
target_include_directories(Bar PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${nlohmann_json_source}/include)
|
||||||
|
set_target_properties(Bar PROPERTIES CXX_STANDARD 11)
|
3
test/cmake_target_include_directories/project/Foo.cpp
Normal file
3
test/cmake_target_include_directories/project/Foo.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#include "Foo.hpp"
|
||||||
|
|
||||||
|
class Foo;
|
4
test/cmake_target_include_directories/project/Foo.hpp
Normal file
4
test/cmake_target_include_directories/project/Foo.hpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
class Foo{};
|
8
test/cmake_target_include_directories/project/main.cpp
Normal file
8
test/cmake_target_include_directories/project/main.cpp
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
nlohmann::json j;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
|
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a parser test suitable for fuzz testing. Given a byte
|
This file implements a parser test suitable for fuzz testing. Given a byte
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a parser test suitable for fuzz testing. Given a byte
|
This file implements a parser test suitable for fuzz testing. Given a byte
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a parser test suitable for fuzz testing. Given a byte
|
This file implements a parser test suitable for fuzz testing. Given a byte
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a parser test suitable for fuzz testing. Given a byte
|
This file implements a parser test suitable for fuzz testing. Given a byte
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
This file implements a parser test suitable for fuzz testing. Given a byte
|
This file implements a parser test suitable for fuzz testing. Given a byte
|
||||||
|
|
25
test/src/test_utils.hpp
Normal file
25
test/src/test_utils.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
|
#include <fstream> // ifstream, istreambuf_iterator, ios
|
||||||
|
#include <vector> // vector
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
|
||||||
|
inline std::vector<std::uint8_t> read_binary_file(const std::string& filename)
|
||||||
|
{
|
||||||
|
std::ifstream file(filename, std::ios::binary);
|
||||||
|
file.unsetf(std::ios::skipws);
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
const auto size = file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
|
std::vector<std::uint8_t> byte_vector;
|
||||||
|
byte_vector.reserve(static_cast<std::size_t>(size));
|
||||||
|
byte_vector.insert(byte_vector.begin(), std::istream_iterator<std::uint8_t>(file), std::istream_iterator<std::uint8_t>());
|
||||||
|
return byte_vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace utils
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
@ -55,7 +55,7 @@ TEST_CASE("algorithms")
|
||||||
{
|
{
|
||||||
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
|
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
|
||||||
{
|
{
|
||||||
return value.is_string() and value.get<std::string>() == "foo";
|
return value.is_string() && value.get<std::string>() == "foo";
|
||||||
}));
|
}));
|
||||||
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
|
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
|
||||||
{
|
{
|
||||||
|
@ -139,14 +139,14 @@ TEST_CASE("algorithms")
|
||||||
{
|
{
|
||||||
CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
|
CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
|
||||||
CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
|
CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
|
||||||
CHECK(not std::equal(j_array.begin(), j_array.end(), j_object.begin()));
|
CHECK(!std::equal(j_array.begin(), j_array.end(), j_object.begin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("using user-defined comparison")
|
SECTION("using user-defined comparison")
|
||||||
{
|
{
|
||||||
// compare objects only by size of its elements
|
// compare objects only by size of its elements
|
||||||
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
|
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
|
||||||
CHECK(not std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
|
CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
|
||||||
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
|
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
|
||||||
[](const json & a, const json & b)
|
[](const json & a, const json & b)
|
||||||
{
|
{
|
||||||
|
@ -213,7 +213,7 @@ TEST_CASE("algorithms")
|
||||||
return v.is_string();
|
return v.is_string();
|
||||||
});
|
});
|
||||||
CHECK(std::distance(j_array.begin(), it) == 2);
|
CHECK(std::distance(j_array.begin(), it) == 2);
|
||||||
CHECK(not it[2].is_string());
|
CHECK(!it[2].is_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
|
65
test/src/unit-assert_macro.cpp
Normal file
65
test/src/unit-assert_macro.cpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
__ _____ _____ _____
|
||||||
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
|
| | |__ | | | | | | version 3.9.0
|
||||||
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid warning when assert does not abort
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic ignored "-Wstrict-overflow"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
/// global variable to record side effect of assert calls
|
||||||
|
static int assert_counter;
|
||||||
|
|
||||||
|
/// set failure variable to true instead of calling assert(x)
|
||||||
|
#define JSON_ASSERT(x) {if (!(x)) ++assert_counter; }
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
// the test assumes exceptions to work
|
||||||
|
#if !defined(JSON_NOEXCEPTION)
|
||||||
|
TEST_CASE("JSON_ASSERT(x)")
|
||||||
|
{
|
||||||
|
SECTION("basic_json(first, second)")
|
||||||
|
{
|
||||||
|
assert_counter = 0;
|
||||||
|
CHECK(assert_counter == 0);
|
||||||
|
|
||||||
|
json::iterator it;
|
||||||
|
json j;
|
||||||
|
|
||||||
|
// in case assertions do not abort execution, an exception is thrown
|
||||||
|
CHECK_THROWS_WITH_AS(json(it, j.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator);
|
||||||
|
|
||||||
|
// check that assertion actually happened
|
||||||
|
CHECK(assert_counter == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
@ -35,6 +35,7 @@ using nlohmann::json;
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <test_data.hpp>
|
#include <test_data.hpp>
|
||||||
|
#include "test_utils.hpp"
|
||||||
|
|
||||||
TEST_CASE("BSON")
|
TEST_CASE("BSON")
|
||||||
{
|
{
|
||||||
|
@ -766,7 +767,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
||||||
|
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Incomplete BSON Input 2")
|
SECTION("Incomplete BSON Input 2")
|
||||||
|
@ -784,7 +785,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
||||||
|
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Incomplete BSON Input 3")
|
SECTION("Incomplete BSON Input 3")
|
||||||
|
@ -808,7 +809,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
||||||
|
|
||||||
SaxCountdown scp(1);
|
SaxCountdown scp(1);
|
||||||
CHECK(not json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Incomplete BSON Input 4")
|
SECTION("Incomplete BSON Input 4")
|
||||||
|
@ -825,7 +826,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
CHECK(json::from_bson(incomplete_bson, true, false).is_discarded());
|
||||||
|
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(incomplete_bson, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Improve coverage")
|
SECTION("Improve coverage")
|
||||||
|
@ -835,7 +836,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
json j = {{"key", "value"}};
|
json j = {{"key", "value"}};
|
||||||
auto bson_vec = json::to_bson(j);
|
auto bson_vec = json::to_bson(j);
|
||||||
SaxCountdown scp(2);
|
SaxCountdown scp(2);
|
||||||
CHECK(not json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
|
@ -846,7 +847,7 @@ TEST_CASE("Incomplete BSON Input")
|
||||||
};
|
};
|
||||||
auto bson_vec = json::to_bson(j);
|
auto bson_vec = json::to_bson(j);
|
||||||
SaxCountdown scp(2);
|
SaxCountdown scp(2);
|
||||||
CHECK(not json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(bson_vec, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -887,7 +888,7 @@ TEST_CASE("Unsupported BSON input")
|
||||||
CHECK(json::from_bson(bson, true, false).is_discarded());
|
CHECK(json::from_bson(bson, true, false).is_discarded());
|
||||||
|
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(bson, &scp, json::input_format_t::bson));
|
CHECK(!json::sax_parse(bson, &scp, json::input_format_t::bson));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("BSON numerical data")
|
TEST_CASE("BSON numerical data")
|
||||||
|
@ -1263,10 +1264,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse BSON file
|
// parse BSON file
|
||||||
std::ifstream f_bson(filename + ".bson", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".bson");
|
||||||
std::vector<std::uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_bson)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j2;
|
json j2;
|
||||||
CHECK_NOTHROW(j2 = json::from_bson(packed));
|
CHECK_NOTHROW(j2 = json::from_bson(packed));
|
||||||
|
|
||||||
|
@ -1296,10 +1294,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse BSON file
|
// parse BSON file
|
||||||
std::ifstream f_bson(filename + ".bson", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".bson");
|
||||||
std::vector<std::uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_bson)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j2;
|
json j2;
|
||||||
CHECK_NOTHROW(j2 = json::from_bson({packed.data(), packed.size()}));
|
CHECK_NOTHROW(j2 = json::from_bson({packed.data(), packed.size()}));
|
||||||
|
|
||||||
|
@ -1314,10 +1309,7 @@ TEST_CASE("BSON roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse BSON file
|
// parse BSON file
|
||||||
std::ifstream f_bson(filename + ".bson", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".bson");
|
||||||
std::vector<std::uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_bson)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
INFO_WITH_TEMP(filename + ": output adapters: std::vector<std::uint8_t>");
|
INFO_WITH_TEMP(filename + ": output adapters: std::vector<std::uint8_t>");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 3.8.0
|
| | |__ | | | | | | version 3.9.0
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
@ -39,6 +39,7 @@ using nlohmann::json;
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <test_data.hpp>
|
#include <test_data.hpp>
|
||||||
|
#include "test_utils.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -1011,21 +1012,21 @@ TEST_CASE("CBOR")
|
||||||
SECTION("0 (0 00000 0000000000)")
|
SECTION("0 (0 00000 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == 0.0);
|
CHECK(d == 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("-0 (1 00000 0000000000)")
|
SECTION("-0 (1 00000 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == -0.0);
|
CHECK(d == -0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("2**-24 (0 00000 0000000001)")
|
SECTION("2**-24 (0 00000 0000000001)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x01}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == std::pow(2.0, -24.0));
|
CHECK(d == std::pow(2.0, -24.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1035,7 +1036,7 @@ TEST_CASE("CBOR")
|
||||||
SECTION("infinity (0 11111 0000000000)")
|
SECTION("infinity (0 11111 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
|
CHECK(d == std::numeric_limits<json::number_float_t>::infinity());
|
||||||
CHECK(j.dump() == "null");
|
CHECK(j.dump() == "null");
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1044,7 @@ TEST_CASE("CBOR")
|
||||||
SECTION("-infinity (1 11111 0000000000)")
|
SECTION("-infinity (1 11111 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xfc, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
|
CHECK(d == -std::numeric_limits<json::number_float_t>::infinity());
|
||||||
CHECK(j.dump() == "null");
|
CHECK(j.dump() == "null");
|
||||||
}
|
}
|
||||||
|
@ -1054,21 +1055,21 @@ TEST_CASE("CBOR")
|
||||||
SECTION("1 (0 01111 0000000000)")
|
SECTION("1 (0 01111 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == 1);
|
CHECK(d == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("-2 (1 10000 0000000000)")
|
SECTION("-2 (1 10000 0000000000)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0xc0, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == -2);
|
CHECK(d == -2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("65504 (0 11110 1111111111)")
|
SECTION("65504 (0 11110 1111111111)")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(d == 65504);
|
CHECK(d == 65504);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1076,15 +1077,15 @@ TEST_CASE("CBOR")
|
||||||
SECTION("infinity")
|
SECTION("infinity")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(not std::isfinite(d));
|
CHECK(!std::isfinite(d));
|
||||||
CHECK(j.dump() == "null");
|
CHECK(j.dump() == "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("NaN")
|
SECTION("NaN")
|
||||||
{
|
{
|
||||||
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7e, 0x00}));
|
json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7e, 0x00}));
|
||||||
json::number_float_t d = j;
|
json::number_float_t d{j};
|
||||||
CHECK(std::isnan(d));
|
CHECK(std::isnan(d));
|
||||||
CHECK(j.dump() == "null");
|
CHECK(j.dump() == "null");
|
||||||
}
|
}
|
||||||
|
@ -1869,7 +1870,7 @@ TEST_CASE("CBOR")
|
||||||
{
|
{
|
||||||
const auto result = json::from_cbor(vec, false);
|
const auto result = json::from_cbor(vec, false);
|
||||||
CHECK(result == json());
|
CHECK(result == json());
|
||||||
CHECK(not json::from_cbor(vec, false, false).is_discarded());
|
CHECK(!json::from_cbor(vec, false, false).is_discarded());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("strict mode")
|
SECTION("strict mode")
|
||||||
|
@ -1889,21 +1890,21 @@ TEST_CASE("CBOR")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v = {0x83, 0x01, 0x02, 0x03};
|
std::vector<uint8_t> v = {0x83, 0x01, 0x02, 0x03};
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("start_object(len)")
|
SECTION("start_object(len)")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
||||||
SaxCountdown scp(0);
|
SaxCountdown scp(0);
|
||||||
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("key()")
|
SECTION("key()")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
||||||
SaxCountdown scp(1);
|
SaxCountdown scp(1);
|
||||||
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
CHECK(!json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1920,9 +1921,7 @@ TEST_CASE("single CBOR roundtrip")
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse CBOR file
|
// parse CBOR file
|
||||||
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".cbor");
|
||||||
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j2;
|
json j2;
|
||||||
CHECK_NOTHROW(j2 = json::from_cbor(packed));
|
CHECK_NOTHROW(j2 = json::from_cbor(packed));
|
||||||
|
|
||||||
|
@ -1954,7 +1953,7 @@ TEST_CASE("single CBOR roundtrip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if not defined(JSON_NOEXCEPTION)
|
#if !defined(JSON_NOEXCEPTION)
|
||||||
TEST_CASE("CBOR regressions")
|
TEST_CASE("CBOR regressions")
|
||||||
{
|
{
|
||||||
SECTION("fuzz test results")
|
SECTION("fuzz test results")
|
||||||
|
@ -1994,10 +1993,7 @@ TEST_CASE("CBOR regressions")
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// parse CBOR file
|
// parse CBOR file
|
||||||
std::ifstream f_cbor(filename, std::ios::binary);
|
auto vec1 = utils::read_binary_file(filename);
|
||||||
std::vector<uint8_t> vec1(
|
|
||||||
(std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j1 = json::from_cbor(vec1);
|
json j1 = json::from_cbor(vec1);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -2204,10 +2200,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse CBOR file
|
// parse CBOR file
|
||||||
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".cbor");
|
||||||
std::vector<uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j2;
|
json j2;
|
||||||
CHECK_NOTHROW(j2 = json::from_cbor(packed));
|
CHECK_NOTHROW(j2 = json::from_cbor(packed));
|
||||||
|
|
||||||
|
@ -2237,10 +2230,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse CBOR file
|
// parse CBOR file
|
||||||
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".cbor");
|
||||||
std::vector<uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j2;
|
json j2;
|
||||||
CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
|
CHECK_NOTHROW(j2 = json::from_cbor({packed.data(), packed.size()}));
|
||||||
|
|
||||||
|
@ -2255,10 +2245,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
json j1 = json::parse(f_json);
|
json j1 = json::parse(f_json);
|
||||||
|
|
||||||
// parse CBOR file
|
// parse CBOR file
|
||||||
std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
|
auto packed = utils::read_binary_file(filename + ".cbor");
|
||||||
std::vector<uint8_t> packed(
|
|
||||||
(std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
if (!exclude_packed.count(filename))
|
if (!exclude_packed.count(filename))
|
||||||
{
|
{
|
||||||
|
@ -2274,7 +2261,7 @@ TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if not defined(JSON_NOEXCEPTION)
|
#if !defined(JSON_NOEXCEPTION)
|
||||||
TEST_CASE("all CBOR first bytes")
|
TEST_CASE("all CBOR first bytes")
|
||||||
{
|
{
|
||||||
// these bytes will fail immediately with exception parse_error.112
|
// these bytes will fail immediately with exception parse_error.112
|
||||||
|
@ -2493,16 +2480,14 @@ TEST_CASE("examples from RFC 7049 Appendix A")
|
||||||
|
|
||||||
SECTION("byte arrays")
|
SECTION("byte arrays")
|
||||||
{
|
{
|
||||||
std::ifstream f_cbor(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor", std::ios::binary);
|
auto packed = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.cbor");
|
||||||
std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
json j;
|
json j;
|
||||||
CHECK_NOTHROW(j = json::from_cbor(packed));
|
CHECK_NOTHROW(j = json::from_cbor(packed));
|
||||||
|
|
||||||
std::ifstream f_bin(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out", std::ios::binary);
|
auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out");
|
||||||
std::vector<uint8_t> expected((std::istreambuf_iterator<char>(f_bin)),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
CHECK(j == json::binary(expected));
|
CHECK(j == json::binary(expected));
|
||||||
|
|
||||||
|
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)) == std::vector<uint8_t> {0xd8, 0x42, 0x40});
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("arrays")
|
SECTION("arrays")
|
||||||
|
@ -2548,3 +2533,197 @@ TEST_CASE("examples from RFC 7049 Appendix A")
|
||||||
CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
|
CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Tagged values")
|
||||||
|
{
|
||||||
|
json j = "s";
|
||||||
|
auto v = json::to_cbor(j);
|
||||||
|
|
||||||
|
SECTION("0xC6..0xD4")
|
||||||
|
{
|
||||||
|
for (auto b : std::vector<std::uint8_t>
|
||||||
|
{
|
||||||
|
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
|
||||||
|
})
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), b);
|
||||||
|
|
||||||
|
// check that parsing fails in error mode
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
|
||||||
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(j_tagged == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("0xD8 - 1 byte follows")
|
||||||
|
{
|
||||||
|
SECTION("success")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in error mode
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
|
||||||
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(j_tagged == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("missing byte after tag")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in all modes
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("0xD9 - 2 byte follow")
|
||||||
|
{
|
||||||
|
SECTION("success")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in error mode
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
|
||||||
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(j_tagged == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("missing byte after tag")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in all modes
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("0xDA - 4 bytes follow")
|
||||||
|
{
|
||||||
|
SECTION("success")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in error mode
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
|
||||||
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(j_tagged == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("missing bytes after tag")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in all modes
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("0xDB - 8 bytes follow")
|
||||||
|
{
|
||||||
|
SECTION("success")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in error mode
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
|
||||||
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(j_tagged == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("missing byte after tag")
|
||||||
|
{
|
||||||
|
// add tag to value
|
||||||
|
auto v_tagged = v;
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
|
||||||
|
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
|
||||||
|
|
||||||
|
// check that parsing fails in all modes
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("tagged binary")
|
||||||
|
{
|
||||||
|
// create a binary value of subtype 42
|
||||||
|
json j_binary;
|
||||||
|
j_binary["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42);
|
||||||
|
|
||||||
|
// convert to CBOR
|
||||||
|
const auto vec = json::to_cbor(j_binary);
|
||||||
|
CHECK(vec == std::vector<std::uint8_t> {0xA1, 0x66, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, 0xD8, 0x2A, 0x44, 0xCA, 0xFE, 0xBA, 0xBE});
|
||||||
|
|
||||||
|
// parse error when parsing tagged value
|
||||||
|
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
|
||||||
|
CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8");
|
||||||
|
|
||||||
|
// binary without subtype when tags are ignored
|
||||||
|
json jb = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
|
CHECK(jb.is_object());
|
||||||
|
CHECK(jb["binary"].is_binary());
|
||||||
|
CHECK(!jb["binary"].get_binary().has_subtype());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue