Compare commits

..

46 Commits

Author SHA1 Message Date
Niels Lohmann 2e928c39ae 🔀 merge develop 2024-11-17 07:45:45 +01:00
Niels Lohmann a65d65c724 🔀 merge develop 2024-11-16 23:25:05 +01:00
Niels Lohmann 5e9bf559b1 # Conflicts:
#	.github/workflows/macos.yml
#	include/nlohmann/detail/input/parser.hpp
#	include/nlohmann/detail/meta/std_fs.hpp
#	include/nlohmann/json.hpp
#	single_include/nlohmann/json.hpp
2024-11-16 23:23:05 +01:00
Niels Lohmann 9561a122a3 🚨 fix warning 2024-11-08 23:47:11 +01:00
Niels Lohmann ad552c41be 🚨 fix warning 2024-11-08 23:41:46 +01:00
Niels Lohmann 078d25ed68 🚨 fix warning 2024-11-08 23:19:04 +01:00
Niels Lohmann ddecb704e3 🚨 fix warning 2024-11-08 23:13:25 +01:00
Niels Lohmann 9240ba4911 Merge remote-tracking branch 'origin/clang-tidy' into clang-tidy 2024-11-08 23:07:51 +01:00
Niels Lohmann b48e05be7c 💚 update actions 2024-11-08 23:07:44 +01:00
Niels Lohmann c4ec5e0bc5 Merge branch 'develop' into clang-tidy 2024-11-08 22:49:30 +01:00
Niels Lohmann 83dc915ac2 🚑 fix warning 2024-11-08 22:48:11 +01:00
Niels Lohmann 88318f9a77 🔀 merge develop 2024-11-08 22:40:55 +01:00
Borislav Stanimirov 18ff442e63 Allow overriding the CMake target name (#4483) 2024-11-08 21:42:36 +01:00
Niccolò Iardella aff5a31d35 Add NLOHMANN_DEFINE_DERIVED_TYPE_* macros (#4033)
* Add NLOHMANN_DEFINE_DERIVED_TYPE_* macros

* Fix with amalgamate

* Add documentation

* Fix with amalgamate

* Fix with amalgamate

---------

Co-authored-by: Niccolò Iardella <niccolo.iardella@doriansrl.it>
2024-11-08 21:41:19 +01:00
Balazs Erseki ac8b22180d Update CONTRIBUTING.md (#4486)
Typo in the filename.
2024-11-04 17:45:58 +01:00
thetimr 6325839776 Update is_structured.md (#4472) 2024-10-08 06:53:32 +02:00
Griffin Myers b36f4c477c Update natvis to reflect 3.11.3 and the current structure of basic_json (#4451)
* Update natvis Jinja template to reflect the current structure of basic_json.

In 5a1a57510a the underlying structure of
basic_json was altered to move m_type and m_value under an m_data field.
This updates the nativ template to be consistent with this change.

* Generate nlohmann_json.natvis for 3.11.3 and latest basic_json structure.
2024-09-05 20:28:24 +02:00
Nikhil Idiculla 960b763ecd Docs: fix typos of 'whether' in operator_{gt,le,lt}.md (#4412) 2024-07-07 10:22:17 +02:00
Niels Lohmann fd968125e8 🚨 fix warning 2024-04-15 22:50:47 +02:00
Niels Lohmann 3c282210d6 🚨 fix warning 2024-04-15 21:44:44 +02:00
Niels Lohmann 751b93652f 🚨 fix warning 2024-04-15 21:44:33 +02:00
Niels Lohmann bb2468a52c 🚨 fix warning 2024-04-15 21:16:40 +02:00
Niels Lohmann 4b7721c392 🚨 fix warning 2024-04-14 13:56:22 +02:00
Niels Lohmann e8cfe1f712 🚨 fix warning 2024-04-14 12:38:17 +02:00
Niels Lohmann 760f54f993 🚨 fix warning 2024-04-14 12:01:20 +02:00
Niels Lohmann 414345eef9 🚨 fix warning 2024-04-13 14:59:13 +02:00
Fallen_Breath 8c391e04fe Docs: Fix wrong code usage in the Value access section of json_pointer.md (#4255) 2024-04-13 14:15:00 +02:00
Yuanhao Jia 01da82eae2 Fix gdb pretty printer (#4343) 2024-04-13 14:11:49 +02:00
laterlaugh 97f0bdaf9a chore: fix some typos in comments (#4345)
chore: fix some typos in comments

Signed-off-by: laterlaugh <manziwenzhai@sina.cn>
2024-04-12 15:20:18 +02:00
Alex Prabhat Bara c883fb0f17 Fix for incorrect function name in documentation example (#4342) 2024-04-10 18:17:47 +02:00
Leila Shcheglova 377c767aa1 Updated exception handling to catch const reference in out_of_range (#4331)
Co-authored-by: LeilaSh <leilanagieva81@gmail.com>
2024-04-08 21:12:32 +02:00
Philip Müller 16b3d841d5 Fixed an error in the Custom data source example. (#4335) 2024-04-08 21:11:25 +02:00
Niels Lohmann 8ef27594d1 🚨 fix warning 2024-03-26 17:25:26 +01:00
Niels Lohmann 91be9e0175 🚨 fix warning 2024-03-15 19:24:59 +01:00
Niels Lohmann 22d3ee930e 🚨 fix warning 2024-03-15 18:57:27 +01:00
Niels Lohmann cc4d7f1697 🚨 fix warning 2024-03-15 18:33:24 +01:00
Niels Lohmann 7b89d3ab29 🚨 fix warning 2024-03-15 17:32:27 +01:00
Niels Lohmann b131d285ed 🚨 fix warning 2024-03-15 17:27:37 +01:00
AniketDhemare 199dea11b1 #4307 Updated docx to 3.10.5 from 3.10.4 (#4310) 2024-03-15 13:12:21 +01:00
Niels Lohmann 57e22b996e 🚨 suppress warning 2024-03-15 13:08:10 +01:00
ss 0457de21cf Align astyle flags in Makefile with CI (#4277)
Remove unsupported `--squeeze-lines=2` parameter

Fixes #4275
2024-01-28 20:25:22 +01:00
Niels Lohmann c35d260c2f Suppress Clang-Tidy warnings (#4276) 2024-01-28 14:04:07 +01:00
ss 6a064e026a Remove broken link from CONTRIBUTING.md (#4274)
http://issuestats.com domain does not exist anymore
2024-01-28 08:55:49 +01:00
alferov 7efe875495 Update json_has_static_rtti.md (#4269) 2024-01-18 19:21:53 +01:00
Juan Carlos Arevalo Baeza a259ecc51e Fix to_json for enums when the enum has an unsigned underlying type. (#4237)
* Enhance the UDT unit test to expose the issue

Add a new enum type with uint64_t as the underlying type.
Use it in the overall UDT. Not strictly needed, but it helps exercise its expected usage.
Create an object of this enum type with a large value (negative if cast to int64_t).
Perform several checks on this object as converted to `json`, which fail without the fix.

* Fix the issue in the relevant `to_json` overload.

Select the correct json type depending on the signedness of the enum's underlying type.
This fixes the new checks in the unit test.

* Add the fix to the single_include

I ran `make pretty` but that modified 20 files, performing a significant amount of indentation changes, none of them related to my change.
I ran `make amalgamate`, but that did nothing. Apparently, the make rule won't run if the single_include files have already been updated by `make pretty`.
I forced `make amalgamate` to do the work by touching the file with the fix.
I then decided to keep just the minimal needed change: the addition of the fix to the single_include file.

I just am not conversant enough in Linux to know whether I installed astyle correctly (had to clone the source from a beta branch and build, in order to get support for `--squeeze-lines`).

* Resolve CI errors and use qualified `std::uint64_t`

The fix was relying on implicit conversions in the non-taken branch.
- Ordinarily (work on a C++20 codebase) I would have used `if constexpr` here, sidestepping the issue, but that's not available on C++11 so I didn't bother.
- So instead of an `if` statement, I used a compile-time constant to select the correct overload.
- This is arguably better in this case, anyway.

I was using function-style casts for typed constants, which I consider superior for constants, but the CI checks disagree, so changed all to `static_cast`.
- For some reason, the CI checks didn't point at all of them, so I hope I caught them all myself.

Built with clang14 and all unit tests pass.

---------

Co-authored-by: Juan Carlos Arevalo Baeza (JCAB) <jcab@ntdev.microsoft.com>
2023-12-14 09:26:10 +01:00
Niels Lohmann 3780b41dd0 💰 update sponsors 2023-12-06 20:51:04 +01:00
146 changed files with 20503 additions and 26298 deletions
+10 -23
View File
@@ -1,3 +1,4 @@
#AccessModifierOffset: 2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
#AlignConsecutiveBitFields: false
@@ -11,7 +12,7 @@ AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
#AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Empty
@@ -29,26 +30,27 @@ BraceWrapping:
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
#BeforeLambdaBody: false
#BeforeWhile: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakStringLiterals: false
ColumnLimit: 160
ColumnLimit: 0
CompactNamespaces: false
ConstructorInitializerIndentWidth: 2
Cpp11BracedListStyle: false
Cpp11BracedListStyle: true
PointerAlignment: Left
FixNamespaceComments: true
IncludeBlocks: Preserve
#IndentCaseBlocks: false
IndentCaseLabels: true
IndentGotoLabels: false
@@ -58,6 +60,7 @@ KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ReflowComments: false
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
@@ -76,22 +79,6 @@ SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
Standard: c++11
TabWidth: 4
UseTab: Never
# what to do with include blocks
SortIncludes: true
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^".*"'
Priority: 1
- Regex: '<[^\/]+>'
Priority: 2
- Regex: '^<(nlohmann)\/-*'
Priority: 3
- Regex: '.*'
Priority: 4
Macros:
- JSON_PRIVATE_UNLESS_TESTED=private
+11
View File
@@ -1,8 +1,16 @@
# TODO: The first three checks are only removed to get the CI going. They have to be addressed at some point.
Checks: '*,
-portability-template-virtual-member-function,
-bugprone-use-after-move,
-hicpp-invalid-access-moved,
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
-android-cloexec-fopen,
-boost-use-ranges,
-bugprone-easily-swappable-parameters,
-cert-err58-cpp,
-concurrency-mt-unsafe,
@@ -44,7 +52,10 @@ Checks: '*,
-modernize-concat-nested-namespaces,
-modernize-type-traits,
-modernize-use-constraints,
-modernize-use-designated-initializers,
-modernize-use-nodiscard,
-modernize-use-ranges,
-modernize-use-std-numbers,
-modernize-use-trailing-return-type,
-performance-enum-size,
-readability-function-cognitive-complexity,
+2 -4
View File
@@ -1,5 +1,3 @@
[![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/pr?style=flat)](http://issuestats.com/github/nlohmann/json) [![Issue Stats](http://issuestats.com/github/nlohmann/json/badge/issue?style=flat)](http://issuestats.com/github/nlohmann/json)
# How to contribute
This project started as a little excuse to exercise some of the cool new C++11 features. Over time, people actually started to use the JSON library (yey!) and started to help improve it by proposing features, finding bugs, or even fixing my mistakes. I am really [thankful](https://github.com/nlohmann/json/blob/master/README.md#thanks) for this and try to keep track of all the helpers.
@@ -22,7 +20,7 @@ Clearly describe the issue:
- If you propose a change or addition, try to give an **example** how the improved code could look like or how to use it.
- If you found a compilation error, please tell us which **compiler** (version and operating system) you used and paste the (relevant part of) the error messages to the ticket.
Please stick to the provided issue template ([bug report](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE/bug.yml) if possible. For questions, feature or support requests, please [open a discussion](https://github.com/nlohmann/json/discussions/new).
Please stick to the provided issue template ([bug report](https://github.com/nlohmann/json/blob/develop/.github/ISSUE_TEMPLATE/bug.yaml) if possible. For questions, feature or support requests, please [open a discussion](https://github.com/nlohmann/json/discussions/new).
## Files to change
@@ -50,7 +48,7 @@ To make changes, you need to edit the following files:
## Note
- If you open a pull request, the code will be automatically tested with [Valgrind](http://valgrind.org)'s Memcheck tool to detect memory leaks. Please be aware that the execution with Valgrind _may_ in rare cases yield different behavior than running the code directly. This can result in failing unit tests which run successfully without Valgrind.
- There is a Makefile target `make pretty` which runs [Clang-Format](https://clang.llvm.org/docs/ClangFormat.html) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
- There is a Makefile target `make pretty` which runs [Artistic Style](http://astyle.sourceforge.net) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
## Please don't
+31 -5
View File
@@ -14,31 +14,57 @@ jobs:
mkdir -p ./pr
echo ${{ github.event.number }} > ./pr/number
echo ${{ github.event.pull_request.user.login }} > ./pr/author
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v4
with:
name: pr
path: pr/
check:
runs-on: ubuntu-latest
container: silkeh/clang:dev
env:
MAIN_DIR: ${{ github.workspace }}/main
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
ASTYLE_FLAGS: >
--style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block
--indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type
--align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date
--formatted
steps:
- name: Checkout pull request
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: main
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout tools
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: tools
ref: develop
- name: Install astyle
run: |
sudo apt-get update
sudo apt-get install astyle
- name: Check amalgamation
run: |
cd $MAIN_DIR
make check-amalgamation
rm -fr $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json_fwd.hpp~
cp $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json.hpp~
cp $INCLUDE_DIR/json_fwd.hpp $INCLUDE_DIR/json_fwd.hpp~
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
echo "Format (1)"
astyle $ASTYLE_FLAGS --suffix=none --quiet $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp
diff $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json.hpp
diff $INCLUDE_DIR/json_fwd.hpp~ $INCLUDE_DIR/json_fwd.hpp
astyle $ASTYLE_FLAGS $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
echo Check
find $MAIN_DIR -name '*.orig' -exec false {} \+
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
dry-run: false
language: c++
- name: Upload Crash
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
+2 -2
View File
@@ -27,11 +27,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: c-cpp
+72 -20
View File
@@ -17,25 +17,26 @@ concurrency:
cancel-in-progress: true
jobs:
xcode_1:
runs-on: macos-11
strategy:
matrix:
xcode: ['11.7', '12.4', '12.5.1', '13.0']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
# macos-11 is deprecated
# macos-11:
# runs-on: macos-11
# strategy:
# matrix:
# xcode: ['11.7', '12.4', '12.5.1', '13.0']
# env:
# DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
#
# steps:
# - uses: actions/checkout@v4
# - name: Run CMake
# run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
# - name: Build
# run: cmake --build build --parallel 10
# - name: Test
# run: cd build ; ctest -j 10 --output-on-failure
steps:
- uses: actions/checkout@v3
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: Build
run: cmake --build build --parallel 10
- name: Test
run: cd build ; ctest -j 10 --output-on-failure
xcode_2:
runs-on: macos-12
macos-12:
runs-on: macos-12 # https://github.com/actions/runner-images/blob/main/images/macos/macos-12-Readme.md
strategy:
matrix:
xcode: ['13.1', '13.2.1', '13.3.1', '13.4.1', '14.0', '14.0.1', '14.1']
@@ -43,7 +44,58 @@ jobs:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: Build
run: cmake --build build --parallel 10
- name: Test
run: cd build ; ctest -j 10 --output-on-failure
macos-13:
runs-on: macos-13 # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md
strategy:
matrix:
xcode: [ '14.2', '14.3', '14.3.1', '15.0.1', '15.1', '15.2']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps:
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: Build
run: cmake --build build --parallel 10
- name: Test
run: cd build ; ctest -j 10 --output-on-failure
macos-14:
runs-on: macos-14 # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md
strategy:
matrix:
xcode: ['15.3', '15.4']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps:
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: Build
run: cmake --build build --parallel 10
- name: Test
run: cd build ; ctest -j 10 --output-on-failure
macos-15:
runs-on: macos-15 # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
strategy:
matrix:
xcode: ['16.0', '16.1']
env:
DEVELOPER_DIR: /Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer
steps:
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_FastTests=ON
- name: Build
@@ -58,7 +110,7 @@ jobs:
standard: [11, 14, 17, 20, 23]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DJSON_TestStandards=${{ matrix.standard }}
- name: Build
+2 -2
View File
@@ -23,7 +23,7 @@ jobs:
if: github.repository == 'nlohmann/json'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install and update PlantUML
run: sudo apt-get update ; sudo apt-get install -y plantuml
@@ -35,7 +35,7 @@ jobs:
run: make build -C docs/mkdocs
- name: Deploy documentation
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/mkdocs/site
+49 -40
View File
@@ -23,9 +23,9 @@ jobs:
steps:
- name: Install git and unzip
run: apt-get update ; apt-get install -y git unzip
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
container: ghcr.io/nlohmann/json-ci:v2.4.0
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -46,35 +46,23 @@ jobs:
container: ghcr.io/nlohmann/json-ci:v2.4.0
strategy:
matrix:
target: [ci_cppcheck, ci_test_valgrind, ci_test_single_header, ci_single_binaries, ci_infer]
target: [ci_cppcheck, ci_test_valgrind, ci_test_amalgamation, ci_test_single_header, ci_single_binaries, ci_infer]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ${{ matrix.target }}
ci_test_amalgamation:
runs-on: ubuntu-latest
container: silkeh/clang:dev
steps:
- uses: actions/checkout@v3
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_amalgamation
ci_static_analysis_ubuntu:
runs-on: ubuntu-latest
strategy:
matrix:
target: [ci_cpplint, ci_reproducible_tests, ci_non_git_tests, ci_offline_testdata]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -89,9 +77,9 @@ jobs:
steps:
- name: Install git, clang-tools, and unzip
run: apt-get update ; apt-get install -y git clang-tools unzip
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -106,9 +94,9 @@ jobs:
steps:
- name: Install build-essential
run: apt-get update ; apt-get install -y build-essential unzip wget git
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -121,7 +109,7 @@ jobs:
contents: read
checks: write
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -137,16 +125,30 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ${{ github.workspace }}/build/json.info.filtered.noexcept
ci_test_compilers_gcc_old:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['4.8', '4.9', '5', '6']
container: ghcr.io/nlohmann/json-ci:v2.4.0
steps:
- uses: actions/checkout@v4
- name: Run CMake
run: CXX=g++-${{ matrix.compiler }} cmake -S . -B build -DJSON_CI=On
- name: Build
run: cmake --build build --target ci_test_compiler_g++-${{ matrix.compiler }}
ci_test_compilers_gcc:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['4', '5', '6', '7', '8', '9', '10', '11', '12', 'latest']
# older GCC docker images (4, 5, 6) fail to check out code
compiler: ['7', '8', '9', '10', '11', '12', '13', '14', 'latest']
container: gcc:${{ matrix.compiler }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -156,14 +158,14 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
compiler: ['3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', 'latest']
compiler: ['3.5', '3.6', '3.7', '3.8', '3.9', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15-bullseye', '16', '17', '18', '19', 'latest']
container: silkeh/clang:${{ matrix.compiler }}
steps:
- name: Install unzip and git
run: apt-get update ; apt-get install -y unzip git
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Set env FORCE_STDCPPFS_FLAG for clang 7 / 8 / 9 / 10
run: echo "JSON_FORCED_GLOBAL_COMPILE_OPTIONS=-DJSON_HAS_FILESYSTEM=0;-DJSON_HAS_EXPERIMENTAL_FILESYSTEM=0" >> "$GITHUB_ENV"
if: ${{ matrix.compiler == '7' || matrix.compiler == '8' || matrix.compiler == '9' || matrix.compiler == '10' }}
@@ -179,7 +181,7 @@ jobs:
matrix:
compiler: [g++-4.8]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -192,7 +194,7 @@ jobs:
matrix:
standard: [11, 14, 17, 20, 23]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -204,22 +206,27 @@ jobs:
strategy:
matrix:
standard: [11, 14, 17, 20, 23]
stdlib: [libcxx, libstdcxx]
steps:
- name: Install git and unzip
run: apt-get update ; apt-get install -y git unzip
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Get latest CMake and ninja
uses: lukka/get-cmake@v3.27.7
uses: lukka/get-cmake@v3.31.0
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
- name: Build with libc++
run: cmake --build build --target ci_test_clang_libcxx_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libcxx' }}
- name: Build with libstdc++
run: cmake --build build --target ci_test_clang_cxx${{ matrix.standard }}
if: ${{ matrix.stdlib == 'libstdcxx' }}
ci_cuda_example:
runs-on: ubuntu-latest
container: ghcr.io/nlohmann/json-ci:v2.4.0
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -229,7 +236,7 @@ jobs:
runs-on: ubuntu-latest
container: ghcr.io/nlohmann/json-ci:v2.2.0
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
@@ -240,8 +247,10 @@ jobs:
ci_reuse_compliance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install REUSE tool
run: python -m pip install reuse
- name: Run REUSE lint
@@ -253,7 +262,7 @@ jobs:
matrix:
target: [ci_test_examples, ci_test_api_documentation]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -DJSON_CI=On
- name: Build
+7 -7
View File
@@ -24,7 +24,7 @@ jobs:
architecture: [x64, x86]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up MinGW
uses: egor-tensin/setup-mingw@v2
with:
@@ -45,7 +45,7 @@ jobs:
architecture: [Win32, x64]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Release'
@@ -61,7 +61,7 @@ jobs:
runs-on: windows-2019
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
- name: Build
@@ -77,7 +77,7 @@ jobs:
architecture: [Win32, x64]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
if: matrix.build_type == 'Release'
@@ -93,7 +93,7 @@ jobs:
runs-on: windows-2022
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 17 2022" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
- name: Build
@@ -108,7 +108,7 @@ jobs:
version: [11, 12, 13, 14, 15]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install Clang
run: curl -fsSL -o LLVM${{ matrix.version }}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.version }}.0.0/LLVM-${{ matrix.version }}.0.0-win64.exe ; 7z x LLVM${{ matrix.version }}.exe -y -o"C:/Program Files/LLVM"
- name: Run CMake
@@ -125,7 +125,7 @@ jobs:
architecture: [Win32, x64]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Run CMake
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -T ClangCL -DJSON_BuildTests=On
- name: Build
-1
View File
@@ -49,5 +49,4 @@ cc_library(
],
includes = ["include"],
visibility = ["//visibility:public"],
alwayslink = True,
)
+6 -1
View File
@@ -57,7 +57,11 @@ endif ()
##
include(GNUInstallDirs)
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
if (NOT DEFINED NLOHMANN_JSON_TARGET_NAME)
# Allow overriding the target name when using FetchContent / add_subdirectory.
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
endif()
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
@@ -206,4 +210,5 @@ if(JSON_Install)
FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
DESTINATION ${NLOHMANN_JSON_PKGCONFIG_INSTALL_DIR}
)
include(CPack)
endif()
+25 -2
View File
@@ -142,9 +142,32 @@ pvs_studio:
# Code format and source amalgamation
##########################################################################
# call the Clang-Format on all source files
# call the Artistic Style pretty printer on all source files
pretty:
clang-format --Werror --verbose -i $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
astyle \
--style=allman \
--indent=spaces=4 \
--indent-modifiers \
--indent-switches \
--indent-preproc-block \
--indent-preproc-define \
--indent-col1-comments \
--pad-oper \
--pad-header \
--align-pointer=type \
--align-reference=type \
--add-braces \
--convert-tabs \
--close-templates \
--lineend=linux \
--preserve-date \
--suffix=none \
--formatted \
$(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/examples/*.cpp
# call the Clang-Format on all source files
pretty_format:
for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
# create single header files and pretty print
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
+57 -43
View File
@@ -75,9 +75,9 @@ See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.
You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nlohmann).
### :office: Corporate Sponsor
### :raising_hand: Priority Sponsor
[![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Codacy-logo-black.svg/320px-Codacy-logo-black.svg.png)](https://github.com/codacy/About)
- [Martti Laine](https://github.com/codeclown)
### :label: Named Sponsors
@@ -385,7 +385,7 @@ struct MyIterator {
using iterator_category = std::input_iterator_tag;
MyIterator& operator++() {
MyContainer.advance();
target->advance();
return *this;
}
@@ -394,7 +394,7 @@ struct MyIterator {
}
reference operator*() const {
return target.get_current();
return target->get_current();
}
MyContainer* target = nullptr;
@@ -1111,11 +1111,11 @@ auto cbor = json::to_msgpack(j); // 0xD5 (fixext2), 0x10, 0xCA, 0xFE
## Supported compilers
Though it's 2023 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
Though it's 2024 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
- GCC 4.8 - 12.0 (and possibly later)
- Clang 3.4 - 15.0 (and possibly later)
- Apple Clang 9.1 - 13.1 (and possibly later)
- GCC 4.8 - 14.2 (and possibly later)
- Clang 3.4 - 20.0 (and possibly later)
- Apple Clang 9.1 - 16.0 (and possibly later)
- Intel C++ Compiler 17.0.2 (and possibly later)
- Nvidia CUDA Compiler 11.0.221 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
@@ -1146,29 +1146,35 @@ The following compilers are currently used in continuous integration at [AppVeyo
| Compiler | Operating System | CI Provider |
|--------------------------------------------------------------------------------------------------------|--------------------|----------------|
| Apple Clang 11.0.3 (clang-1103.0.32.62); Xcode 11.7 | macOS 11.7.1 | GitHub Actions |
| Apple Clang 12.0.0 (clang-1200.0.32.29); Xcode 12.4 | macOS 11.7.1 | GitHub Actions |
| Apple Clang 12.0.5 (clang-1205.0.22.11); Xcode 12.5.1 | macOS 11.7.1 | GitHub Actions |
| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.0 | macOS 11.7.1 | GitHub Actions |
| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.1 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2.1 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 13.1.6 (clang-1316.0.21.2.3); Xcode 13.3.1 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 13.1.6 (clang-1316.0.21.2.5); Xcode 13.4.1 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0.1 | macOS 12.6.1 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.1 | macOS 12.6.1 | GitHub Actions |
| Clang 3.5.2 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 3.6.2 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 3.7.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 3.8.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 3.9.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 4.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 5.0.2 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 6.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 7.0.1 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 8.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 9.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 10.0.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Apple Clang 13.0.0 (clang-1300.0.29.3); Xcode 13.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 13.0.0 (clang-1300.0.29.30); Xcode 13.2.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 13.1.6 (clang-1316.0.21.2.3); Xcode 13.3.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 13.1.6 (clang-1316.0.21.2.5); Xcode 13.4.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.102); Xcode 14.0.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.1 | macOS 12.7.6 | GitHub Actions |
| Apple Clang 14.0.0 (clang-1400.0.29.202); Xcode 14.2 | macOS 13.7 | GitHub Actions |
| Apple Clang 14.0.3 (clang-1403.0.22.14.1); Xcode 14.3 | macOS 13.7 | GitHub Actions |
| Apple Clang 14.0.3 (clang-1403.0.22.14.1); Xcode 14.3.1 | macOS 13.7.1 | GitHub Actions |
| Apple Clang 15.0.0 (clang-1500.0.40.1); Xcode 15.0.1 | macOS 13.7 | GitHub Actions |
| Apple Clang 15.0.0 (clang-1500.1.0.2.5); Xcode 15.1 | macOS 13.7 | GitHub Actions |
| Apple Clang 15.0.0 (clang-1500.1.0.2.5); Xcode 15.2 | macOS 13.7 | GitHub Actions |
| Apple Clang 15.0.0 (clang-1500.3.9.4); Xcode 15.3 | macOS 14.7 | GitHub Actions |
| Apple Clang 15.0.0 (clang-1500.3.9.4); Xcode 15.4 | macOS 14.7 | GitHub Actions |
| Apple Clang 16.0.0 (clang-1600.0.26.3); Xcode 16.0 | macOS 15.0.1 | GitHub Actions |
| Apple Clang 16.0.0 (clang-1600.0.26.4); Xcode 16.1 | macOS 15.0.1 | GitHub Actions |
| Clang 3.5.2 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 3.6.2 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 3.7.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 3.8.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 3.9.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 4.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 5.0.2 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 6.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 7.0.1 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 8.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 9.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 10.0.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Clang 10.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 11.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 11.0.0 with MSVC-like command-line | Windows-10.0.17763 | GitHub Actions |
@@ -1182,20 +1188,28 @@ The following compilers are currently used in continuous integration at [AppVeyo
| Clang 15.0.0 with GNU-like command-line | Windows-10.0.17763 | GitHub Actions |
| Clang 15.0.4 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 16.0.0 (16.0.0-++20221031071727+500876226c60-1~exp1~20221031071831.439) | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 4.9.4 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 5.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 6.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 7.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Clang 16.0.6 (++20231112084702+7cbf1a259152-1~exp1~20231112084757.16) | Ubuntu 20.04.1 LTS | GitHub Actions |
| Clang 17.0.6 (++20231208085813+6009708b4367-1~exp1~20231208085906.81) | Ubuntu 20.04.1 LTS | GitHub Actions |
| Clang 18.1.8 (++20240731024826+3b5b5c1ec4a3-1~exp1~20240731144843.145) | Ubuntu 20.04.1 LTS | GitHub Actions |
| Clang 19.1.2 (++20241016063422+7ba7d8e2f7b6-1~exp1~20241016063541.55) | Ubuntu 20.04.1 LTS | GitHub Actions |
| Clang 20.0.0 (++20241022113049+f1ade1f874db-1~exp1~20241022113104.1036) | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu8) | Ubuntu 20.04.4 LTS | GitHub Actions |
| GCC 4.9.3 (Ubuntu 4.9.3-13ubuntu2) | Ubuntu 20.04.4 LTS | GitHub Actions |
| GCC 4.8.5 (Ubuntu 4.8.5-4ubuntu2) | Ubuntu 20.04.4 LTS | GitHub Actions |
| GCC 5.5.0 (Ubuntu 5.5.0-12ubuntu1) | Ubuntu 20.04.4 LTS | GitHub Actions |
| GCC 6.4.0 (Ubuntu 6.4.0-17ubuntu1) | Ubuntu 20.04.4 LTS | GitHub Actions |
| GCC 7.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions |
| GCC 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project) | Windows-10.0.17763 | GitHub Actions |
| GCC 8.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 9.5.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 10.4.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 8.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 9.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 10.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 11.1.0 | Ubuntu (aarch64) | Cirrus CI |
| GCC 11.3.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 12.2.0 | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 11.5.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 12.4.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 13.0.0 20220605 (experimental) | Ubuntu 20.04.3 LTS | GitHub Actions |
| GCC 13.3.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| GCC 14.2.0 | Ubuntu 22.04.1 LTS | GitHub Actions |
| Intel C++ Compiler 2021.5.0.20211109 | Ubuntu 20.04.3 LTS | GitHub Actions |
| NVCC 11.0.221 | Ubuntu 20.04.3 LTS | GitHub Actions |
| Visual Studio 14 2015 MSVC 19.0.24241.7 (Build Engine version 14.0.25420.1) | Windows-6.3.9600 | AppVeyor |
@@ -1774,8 +1788,8 @@ The library itself consists of a single header file licensed under the MIT licen
- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file
- [**American fuzzy lop**](https://lcamtuf.coredump.cx/afl/) for fuzz testing
- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code indentation
- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers
- [**Clang-Format**](https://clang.llvm.org/docs/ClangFormat.html) for automatic source code indentation
- [**CMake**](https://cmake.org) for build automation
- [**Codacy**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json)
- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
@@ -1884,7 +1898,7 @@ json/tests/src/make_test_data_available.hpp:23: FATAL ERROR: REQUIRE( utils::che
In case you have downloaded the library rather than checked out the code via Git, test `cmake_fetch_content_configure` will fail. Please execute `ctest -LE git_required` to skip these tests. See [issue #2189](https://github.com/nlohmann/json/issues/2189) for more information.
Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information.
Some tests change the installed files and hence make the whole process not reproducible. Please execute `ctest -LE not_reproducible` to skip these tests. See [issue #2324](https://github.com/nlohmann/json/issues/2324) for more information. Furthermore, assertions must be switched off to ensure reproducible builds (see [discussion 4494](https://github.com/nlohmann/json/discussions/4494)).
Note you need to call `cmake -LE "not_reproducible|git_required"` to exclude both labels. See [issue #2596](https://github.com/nlohmann/json/issues/2596) for more information.
+46 -8
View File
@@ -8,16 +8,16 @@ set(N 10)
include(FindPython3)
find_package(Python3 COMPONENTS Interpreter)
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
find_program(ASTYLE_TOOL NAMES astyle)
execute_process(COMMAND ${ASTYLE_TOOL} --version OUTPUT_VARIABLE ASTYLE_TOOL_VERSION ERROR_VARIABLE ASTYLE_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" ASTYLE_TOOL_VERSION "${ASTYLE_TOOL_VERSION}")
message(STATUS "🔖 Artistic Style ${ASTYLE_TOOL_VERSION} (${ASTYLE_TOOL})")
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-20 clang++-19 clang++-18 clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
find_program(CLANG_FORMAT_TOOL NAMES clang-format)
execute_process(COMMAND ${CLANG_FORMAT_TOOL} --version OUTPUT_VARIABLE CLANG_FORMAT_TOOL_VERSION ERROR_VARIABLE CLANG_FORMAT_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_FORMAT_TOOL_VERSION "${CLANG_FORMAT_TOOL_VERSION}")
message(STATUS "🔖 Clang-Format ${CLANG_FORMAT_TOOL_VERSION} (${CLANG_FORMAT_TOOL})")
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
@@ -461,6 +461,19 @@ foreach(CXX_STANDARD 11 14 17 20 23)
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMENT "Compile and test with Clang for C++${CXX_STANDARD}"
)
add_custom_target(ci_test_clang_libcxx_cxx${CXX_STANDARD}
COMMAND CXX=${CLANG_TOOL} CXXFLAGS="${CLANG_CXXFLAGS}" ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE=Debug -GNinja
-DJSON_BuildTests=ON -DJSON_FastTests=ON
-DJSON_TestStandards=${CXX_STANDARD}
-DCMAKE_CXX_FLAGS="-stdlib=libc++"
-DCMAKE_EXE_LINKER_FLAGS="-lc++abi"
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD}
COMMAND cd ${PROJECT_BINARY_DIR}/build_clang_cxx${CXX_STANDARD} && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
COMMENT "Compile and test with Clang for C++${CXX_STANDARD} (libc++)"
)
endforeach()
###############################################################################
@@ -581,8 +594,33 @@ add_custom_target(ci_test_clang_sanitizer
# Check if header is amalgamated and sources are properly indented.
###############################################################################
set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type --align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date --formatted)
file(GLOB_RECURSE INDENT_FILES
${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
${PROJECT_SOURCE_DIR}/tests/src/*.cpp
${PROJECT_SOURCE_DIR}/tests/src/*.hpp
${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
${PROJECT_SOURCE_DIR}/docs/examples/*.cpp
)
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
add_custom_target(ci_test_amalgamation
COMMAND make check-amalgamation
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} ${INDENT_FILES}
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Check amalgamation and indentation"
)
@@ -875,7 +913,7 @@ add_custom_target(ci_cmake_flags
# Use more installed compilers.
###############################################################################
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17)
foreach(COMPILER g++-4.8 g++-4.9 g++-5 g++-6 g++-7 g++-8 g++-9 g++-10 g++-11 clang++-3.5 clang++-3.6 clang++-3.7 clang++-3.8 clang++-3.9 clang++-4.0 clang++-5.0 clang++-6.0 clang++-7 clang++-8 clang++-9 clang++-10 clang++-11 clang++-12 clang++-13 clang++-14 clang++-15 clang++-16 clang++-17 clang++-18 clang++-19 clang++-20)
find_program(COMPILER_TOOL NAMES ${COMPILER})
if (COMPILER_TOOL)
unset(ADDITIONAL_FLAGS)
+1 -1
View File
@@ -36,7 +36,7 @@ int main()
// try to read from a nonexisting key using string_view
std::cout << object.at("the fast"sv) << '\n';
}
catch (const json::out_of_range)
catch (const json::out_of_range& e)
{
std::cout << "out of range" << '\n';
}
@@ -21,7 +21,7 @@ Constant.
## Possible implementation
```cpp
constexpr bool is_primitive() const noexcept
constexpr bool is_structured() const noexcept
{
return is_array() || is_object();
}
@@ -17,7 +17,7 @@ bool operator>(ScalarType lhs, const const_reference rhs) noexcept; // (2)
operand is `NaN` and the other operand is either `NaN` or any other number.
- Otherwise, returns the result of `#!cpp !(lhs <= rhs)` (see [**operator<=**](operator_le.md)).
2. Compares wether a JSON value is greater than a scalar or a scalar is greater than a JSON value by
2. Compares whether a JSON value is greater than a scalar or a scalar is greater than a JSON value by
converting the scalar to a JSON value and comparing both JSON values according to 1.
## Template parameters
@@ -17,7 +17,7 @@ bool operator<=(ScalarType lhs, const const_reference rhs) noexcept; // (2)
operand is `NaN` and the other operand is either `NaN` or any other number.
- Otherwise, returns the result of `#!cpp !(rhs < lhs)` (see [**operator<**](operator_lt.md)).
1. Compares wether a JSON value is less than or equal to a scalar or a scalar is less than or equal
1. Compares whether a JSON value is less than or equal to a scalar or a scalar is less than or equal
to a JSON value by converting the scalar to a JSON value and comparing both JSON values according
to 1.
@@ -27,7 +27,7 @@ bool operator<(ScalarType lhs, const const_reference rhs) noexcept; // (2)
7. binary
For instance, any boolean value is considered less than any string.
2. Compares wether a JSON value is less than a scalar or a scalar is less than a JSON value by converting
2. Compares whether a JSON value is less than a scalar or a scalar is less than a JSON value by converting
the scalar to a JSON value and comparing both JSON values according to 1.
## Template parameters
+1 -1
View File
@@ -139,4 +139,4 @@ function.
## Version history
- Added in version 3.0.0.
- Added `merge_objects` parameter in 3.10.4.
- Added `merge_objects` parameter in 3.10.5.
@@ -28,4 +28,4 @@ When the macro is not defined, the library will define it to its default value.
## Version history
- Added in version ?.
- Added in version 3.11.3.
@@ -0,0 +1,118 @@
# NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
# NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
```cpp
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(type, base_type, member...) // (1)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(type, base_type, member...) // (2)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(type, base_type, member...) // (3)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, base_type, member...) // (4)
```
These macros can be used to simplify the serialization/deserialization of derived types if you want to use a JSON
object as serialization and want to use the member variable names as object keys in that object.
- Macros 1 and 2 are to be defined **inside** the class/struct to create code for.
Like [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), they can access private members.
- Macros 3 and 4 are to be defined **outside** the class/struct to create code for, but **inside** its namespace.
Like [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md),
they **cannot** access private members.
The first parameter is the name of the derived class/struct,
the second parameter is the name of the base class/struct and all remaining parameters name the members.
The base type **must** be already serializable/deserializable.
- Macros 1 and 3 will use [`at`](../basic_json/at.md) during deserialization and will throw
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object.
- Macros 2 and 4 will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
default constructs an object and uses its values as the defaults when calling the `value` function.
## Parameters
`type` (in)
: name of the type (class, struct) to serialize/deserialize
`base_type` (in)
: name of the base type (class, struct) `type` is derived from
`member` (in)
: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list
## Default definition
Macros 1 and 2 add two friend functions to the class which take care of the serialization and deserialization:
```cpp
friend void to_json(nlohmann::json&, const type&);
friend void from_json(const nlohmann::json&, type&);
```
Macros 3 and 4 add two functions to the namespace which take care of the serialization and deserialization:
```cpp
void to_json(nlohmann::json&, const type&);
void from_json(const nlohmann::json&, type&);
```
In both cases they call the `to_json`/`from_json` functions of the base type
before serializing/deserializing the members of the derived type:
```cpp
class A { /* ... */ };
class B : public A { /* ... */ };
void to_json(nlohmann::json& j, const B& b) {
nlohmann::to_json(j, static_cast<const A&>(b));
// ...
}
void from_json(const nlohmann::json& j, B& b) {
nlohmann::from_json(j, static_cast<A&>(b));
// ...
}
```
## Notes
!!! info "Prerequisites"
- Macros 1 and 2 have the same prerequisites of NLOHMANN_DEFINE_TYPE_INTRUSIVE.
- Macros 3 and 3 have the same prerequisites of NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE.
- Serialization/deserialization of base types must be defined.
!!! warning "Implementation limits"
- See Implementation limits for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE.
## Examples
Example of `NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE` usage:
```cpp
class A {
double Aa;
double Ab;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(A, Aa, Ab)
};
class B : public A {
int Ba;
int Bb;
NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(B, A, Ba, Bb)
};
```
## See also
- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md)
for similar macros that can be defined _inside_ a non-derived type.
- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md)
for a similar macros that can be defined _outside_ a non-derived type.
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview.
## Version history
1. Added in version 3.11.x.
+1 -1
View File
@@ -265,7 +265,7 @@ struct bad_serializer
}
template <typename BasicJsonType>
static void to_json(const BasicJsonType& j, T& value) {
static void from_json(const BasicJsonType& j, T& value) {
// this calls BasicJsonType::json_serializer<T>::from_json(j, value);
// if BasicJsonType::json_serializer == bad_serializer ... oops!
value = j.template template get<T>(); // oops!
+3 -3
View File
@@ -71,10 +71,10 @@ auto j = json::parse(R"({
})");
// access values
auto val = j["/"_json_pointer]; // {"array":["A","B","C"],...}
auto val = j[""_json_pointer]; // {"array":["A","B","C"],...}
auto val1 = j["/nested/one"_json_pointer]; // 1
auto val2 = j.at[json::json_pointer("/nested/three/1")]; // false
auto val3 = j.value[json::json_pointer("/nested/four", 0)]; // 0
auto val2 = j.at(json::json_pointer("/nested/three/1")); // false
auto val3 = j.value(json::json_pointer("/nested/four"), 0); // 0
```
## Flatten / unflatten
+10 -7
View File
@@ -24,8 +24,9 @@ struct adl_serializer
/// @brief convert a JSON value to any value type
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto from_json(BasicJsonType&& j, TargetType& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
{
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
}
@@ -33,17 +34,19 @@ struct adl_serializer
/// @brief convert a JSON value to any value type
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto from_json(BasicJsonType&& j) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{})))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{}))
static auto from_json(BasicJsonType && j) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
{
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{});
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
}
/// @brief convert any value type to a JSON value
/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
template<typename BasicJsonType, typename TargetType = ValueType>
static auto to_json(BasicJsonType& j, TargetType&& val) noexcept(noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
{
::nlohmann::to_json(j, std::forward<TargetType>(val));
}
@@ -8,9 +8,9 @@
#pragma once
#include <cstdint> // uint8_t, uint64_t
#include <tuple> // tie
#include <utility> // move
#include <cstdint> // uint8_t, uint64_t
#include <tuple> // tie
#include <utility> // move
#include <nlohmann/detail/abi_macros.hpp>
@@ -27,31 +27,31 @@ class byte_container_with_subtype : public BinaryType
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype() noexcept(noexcept(container_type()))
: container_type()
: container_type()
{}
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
: container_type(b)
: container_type(b)
{}
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
: container_type(std::move(b))
: container_type(std::move(b))
{}
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
: container_type(b)
, m_subtype(subtype_)
, m_has_subtype(true)
: container_type(b)
, m_subtype(subtype_)
, m_has_subtype(true)
{}
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
: container_type(std::move(b))
, m_subtype(subtype_)
, m_has_subtype(true)
: container_type(std::move(b))
, m_subtype(subtype_)
, m_has_subtype(true)
{}
bool operator==(const byte_container_with_subtype& rhs) const
+33 -19
View File
@@ -47,40 +47,54 @@
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH)
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION)
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
+152 -87
View File
@@ -8,17 +8,21 @@
#pragma once
#include <algorithm> // transform
#include <array> // array
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
#include <algorithm> // transform
#include <array> // array
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
#include <map> // map
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -43,10 +47,29 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
n = nullptr;
}
#ifdef JSON_HAS_CPP_17
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
template<typename BasicJsonType, typename T>
void from_json(const BasicJsonType& j, std::optional<T>& opt)
{
if (j.is_null())
{
opt = std::nullopt;
}
else
{
opt.emplace(j.template get<T>());
}
}
#endif // JSON_USE_IMPLICIT_CONVERSIONS
#endif // JSON_HAS_CPP_17
// overloads for basic_json template parameters
template<typename BasicJsonType,
typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value && !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int> = 0>
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
@@ -99,12 +122,13 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t&
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
template<typename BasicJsonType,
typename StringType,
enable_if_t<std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value &&
is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value &&
!std::is_same<typename BasicJsonType::string_t, StringType>::value && !is_json_ref<StringType>::value,
int> = 0>
template <
typename BasicJsonType, typename StringType,
enable_if_t <
std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
&& is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
&& !std::is_same<typename BasicJsonType::string_t, StringType>::value
&& !is_json_ref<StringType>::value, int > = 0 >
inline void from_json(const BasicJsonType& j, StringType& s)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
@@ -134,7 +158,8 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_int
}
#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void from_json(const BasicJsonType& j, EnumType& e)
{
typename std::underlying_type<EnumType>::type val;
@@ -144,7 +169,8 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
#endif // JSON_DISABLE_ENUM_SERIALIZATION
// forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@@ -152,13 +178,16 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.clear();
std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType& i) {
std::transform(j.rbegin(), j.rend(),
std::front_inserter(l), [](const BasicJsonType & i)
{
return i.template get<T>();
});
}
// valarray doesn't have an insert method
template<typename BasicJsonType, typename T, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
template<typename BasicJsonType, typename T,
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@@ -166,14 +195,16 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
l.resize(j.size());
std::transform(j.begin(), j.end(), std::begin(l), [](const BasicJsonType& elem) {
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>
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
-> decltype(j.template get<T>(), void())
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
@@ -188,7 +219,9 @@ inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType:
}
template<typename BasicJsonType, typename T, std::size_t N>
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) -> decltype(j.template get<T>(), void())
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
@@ -196,17 +229,23 @@ auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priorit
}
}
template<typename BasicJsonType,
typename ConstructibleArrayType,
enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
template<typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t<
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
int> = 0>
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
-> decltype(arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), j.template get<typename ConstructibleArrayType::value_type>(), void())
-> decltype(
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
j.template get<typename ConstructibleArrayType::value_type>(),
void())
{
using std::end;
ConstructibleArrayType ret;
ret.reserve(j.size());
std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
std::transform(j.begin(), j.end(),
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
@@ -214,15 +253,20 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
arr = std::move(ret);
}
template<typename BasicJsonType,
typename ConstructibleArrayType,
enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/)
template<typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t<
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
int> = 0>
inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
priority_tag<0> /*unused*/)
{
using std::end;
ConstructibleArrayType ret;
std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
std::transform(
j.begin(), j.end(), std::inserter(ret, end(ret)),
[](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
@@ -230,41 +274,51 @@ inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType&
arr = std::move(ret);
}
template<typename BasicJsonType,
typename ConstructibleArrayType,
enable_if_t<is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value &&
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value &&
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value &&
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value && !is_basic_json<ConstructibleArrayType>::value,
int> = 0>
template < typename BasicJsonType, typename ConstructibleArrayType,
enable_if_t <
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
!is_basic_json<ConstructibleArrayType>::value,
int > = 0 >
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
-> decltype(from_json_array_impl(j, arr, priority_tag<3>{}), j.template get<typename ConstructibleArrayType::value_type>(), void())
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
j.template get<typename ConstructibleArrayType::value_type>(),
void())
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
from_json_array_impl(j, arr, priority_tag<3>{});
from_json_array_impl(j, arr, priority_tag<3> {});
}
template<typename BasicJsonType, typename T, std::size_t... Idx>
std::array<T, sizeof...(Idx)>
from_json_inplace_array_impl(BasicJsonType&& j, identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
template < typename BasicJsonType, typename T, std::size_t... Idx >
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
{
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
return { { std::forward<BasicJsonType>(j).at(Idx).template get < T&& > ()... } };
}
template<typename BasicJsonType, typename T, std::size_t N>
template < typename BasicJsonType, typename T, std::size_t... Idx >
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(const BasicJsonType& j,
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
{
return { { j.at(Idx).template get<T>()... } };
}
template < typename BasicJsonType, typename T, std::size_t N >
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{}))
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{});
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
}
template<typename BasicJsonType>
@@ -278,8 +332,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
}
template<typename BasicJsonType,
typename ConstructibleObjectType,
template<typename BasicJsonType, typename ConstructibleObjectType,
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
{
@@ -291,7 +344,11 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type;
std::transform(inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()), [](typename BasicJsonType::object_t::value_type const& p) {
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
{
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
});
obj = std::move(ret);
@@ -301,13 +358,14 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
// (BooleanType, etc..); note: Is it really necessary to provide explicit
// overloads for boolean_t etc. in case of a custom BooleanType which is not
// an arithmetic type?
template<typename BasicJsonType,
typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value && !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value &&
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value &&
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value &&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int> = 0>
template < typename BasicJsonType, typename ArithmeticType,
enable_if_t <
std::is_arithmetic<ArithmeticType>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
int > = 0 >
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
{
switch (static_cast<value_t>(j))
@@ -344,54 +402,64 @@ inline void from_json(const BasicJsonType& j, ArithmeticType& val)
}
}
template<typename BasicJsonType, typename... Args, std::size_t... Idx>
std::tuple<Args...> from_json_tuple_impl_base(const BasicJsonType& j, index_sequence<Idx...> /*unused*/)
{
return std::make_tuple(j.at(Idx).template get<Args>()...);
}
template<typename BasicJsonType, typename... Args, std::size_t... Idx>
std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
{
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
}
template<typename BasicJsonType, class A1, class A2>
template < typename BasicJsonType, class A1, class A2 >
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
{
return { std::forward<BasicJsonType>(j).at(0).template get<A1>(), std::forward<BasicJsonType>(j).at(1).template get<A2>() };
return {std::forward<BasicJsonType>(j).at(0).template get < A1&& > (),
std::forward<BasicJsonType>(j).at(1).template get < A2&& > ()};
}
template < typename BasicJsonType, class A1, class A2 >
std::pair<A1, A2> from_json_tuple_impl(const BasicJsonType& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
{
return {j.at(0).template get<A1>(), j.at(1).template get<A2>()};
}
template<typename BasicJsonType, typename A1, typename A2>
inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
{
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>>{}, priority_tag<0>{});
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
}
template<typename BasicJsonType, typename... Args>
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
{
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...>{});
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
template<typename BasicJsonType, typename... Args>
inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
{
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...>{});
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
}
template<typename BasicJsonType, typename TupleRelated>
auto from_json(BasicJsonType&& j, TupleRelated&& t)
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{}))
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
{
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
}
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{});
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
}
template<typename BasicJsonType,
typename Key,
typename Value,
typename Compare,
typename Allocator,
typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@@ -409,13 +477,9 @@ inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allo
}
}
template<typename BasicJsonType,
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator,
typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
typename = enable_if_t < !std::is_constructible <
typename BasicJsonType::string_t, Key >::value >>
inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@@ -448,8 +512,9 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
struct from_json_fn
{
template<typename BasicJsonType, typename T>
auto operator()(const BasicJsonType& j, T&& val) const noexcept(noexcept(from_json(j, std::forward<T>(val))))
-> decltype(from_json(j, std::forward<T>(val)))
auto operator()(const BasicJsonType& j, T&& val) const
noexcept(noexcept(from_json(j, std::forward<T>(val))))
-> decltype(from_json(j, std::forward<T>(val)))
{
return from_json(j, std::forward<T>(val));
}
@@ -461,10 +526,10 @@ struct from_json_fn
/// namespace to hold default `from_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
#endif
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
detail::static_const<detail::from_json_fn>::value;
#ifndef JSON_HAS_CPP_17
} // namespace
+165 -94
View File
@@ -9,12 +9,12 @@
#pragma once
#include <array> // array
#include <cmath> // signbit, isfinite
#include <cstdint> // intN_t, uintN_t
#include <cstring> // memcpy, memmove
#include <limits> // numeric_limits
#include <type_traits> // conditional
#include <array> // array
#include <cmath> // signbit, isfinite
#include <cstdint> // intN_t, uintN_t
#include <cstring> // memcpy, memmove
#include <limits> // numeric_limits
#include <type_traits> // conditional
#include <nlohmann/detail/macro_scope.hpp>
@@ -54,17 +54,14 @@ Target reinterpret_bits(const Source source)
return target;
}
struct diyfp // f * 2^e
struct diyfp // f * 2^e
{
static constexpr int kPrecision = 64; // = q
static constexpr int kPrecision = 64; // = q
std::uint64_t f = 0;
int e = 0;
constexpr diyfp(std::uint64_t f_, int e_) noexcept
: f(f_)
, e(e_)
{}
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
/*!
@brief returns x - y
@@ -75,7 +72,7 @@ struct diyfp // f * 2^e
JSON_ASSERT(x.e == y.e);
JSON_ASSERT(x.f >= y.f);
return { x.f - y.f, x.e };
return {x.f - y.f, x.e};
}
/*!
@@ -136,11 +133,11 @@ struct diyfp // f * 2^e
// Effectively we only need to add the highest bit in p_lo to p_hi (and
// Q_hi + 1 does not overflow).
Q += std::uint64_t{ 1 } << (64u - 32u - 1u); // round, ties up
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
return { h, x.e + y.e + 64 };
return {h, x.e + y.e + 64};
}
/*!
@@ -171,7 +168,7 @@ struct diyfp // f * 2^e
JSON_ASSERT(delta >= 0);
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
return { x.f << delta, target_exponent };
return {x.f << delta, target_exponent};
}
};
@@ -201,21 +198,24 @@ boundaries compute_boundaries(FloatType value)
// If v is normalized:
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
static_assert(std::numeric_limits<FloatType>::is_iec559, "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
static_assert(std::numeric_limits<FloatType>::is_iec559,
"internal error: dtoa_short requires an IEEE-754 floating-point implementation");
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
constexpr int kMinExp = 1 - kBias;
constexpr std::uint64_t kHiddenBit = std::uint64_t{ 1 } << (kPrecision - 1); // = 2^(p-1)
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
constexpr int kMinExp = 1 - kBias;
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t>::type;
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
const std::uint64_t E = bits >> (kPrecision - 1);
const std::uint64_t F = bits & (kHiddenBit - 1);
const bool is_denormal = E == 0;
const diyfp v = is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
const diyfp v = is_denormal
? diyfp(F, kMinExp)
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
// Compute the boundaries m- and m+ of the floating-point value
// v = f * 2^e.
@@ -239,9 +239,10 @@ boundaries compute_boundaries(FloatType value)
// v- m- v m+ v+
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_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B)
: diyfp(2 * v.f - 1, v.e - 1); // (A)
const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
const diyfp m_minus = lower_boundary_is_closer
? diyfp((4 * v.f) - 1, v.e - 2) // (B)
: diyfp((2 * v.f) - 1, v.e - 1); // (A)
// Determine the normalized w+ = m+.
const diyfp w_plus = diyfp::normalize(m_plus);
@@ -249,7 +250,7 @@ boundaries compute_boundaries(FloatType value)
// Determine w- = m- such that e_(w-) = e_(w+).
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
return { diyfp::normalize(v), w_minus, w_plus };
return {diyfp::normalize(v), w_minus, w_plus};
}
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
@@ -310,7 +311,7 @@ boundaries compute_boundaries(FloatType value)
constexpr int kAlpha = -60;
constexpr int kGamma = -32;
struct cached_power // c = f * 2^e ~= 10^k
struct cached_power // c = f * 2^e ~= 10^k
{
std::uint64_t f;
int e;
@@ -379,37 +380,99 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
constexpr int kCachedPowersMinDecExp = -300;
constexpr int kCachedPowersDecStep = 8;
static constexpr std::array<cached_power, 79> kCachedPowers = { {
{ 0xAB70FE17C79AC6CA, -1060, -300 }, { 0xFF77B1FCBEBCDC4F, -1034, -292 }, { 0xBE5691EF416BD60C, -1007, -284 }, { 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 }, { 0x9D71AC8FADA6C9B5, -927, -260 }, { 0xEA9C227723EE8BCB, -901, -252 }, { 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 }, { 0xC21094364DFB5637, -821, -228 }, { 0x9096EA6F3848984F, -794, -220 }, { 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 }, { 0xEF340A98172AACE5, -715, -196 }, { 0xB23867FB2A35B28E, -688, -188 }, { 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 }, { 0x936B9FCEBB25C996, -608, -164 }, { 0xDBAC6C247D62A584, -582, -156 }, { 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 }, { 0xB5B5ADA8AAFF80B8, -502, -132 }, { 0x87625F056C7C4A8B, -475, -124 }, { 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 }, { 0xDFF9772470297EBD, -396, -100 }, { 0xA6DFBD9FB8E5B88F, -369, -92 }, { 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 }, { 0x8A08F0F8BF0F156B, -289, -68 }, { 0xCDB02555653131B6, -263, -60 }, { 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 }, { 0xAA242499697392D3, -183, -36 }, { 0xFD87B5F28300CA0E, -157, -28 }, { 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 }, { 0xD1B71758E219652C, -77, -4 }, { 0x9C40000000000000, -50, 4 }, { 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 }, { 0x813F3978F8940984, 30, 28 }, { 0xC097CE7BC90715B3, 56, 36 }, { 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 }, { 0x9F4F2726179A2245, 136, 60 }, { 0xED63A231D4C4FB27, 162, 68 }, { 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 }, { 0xC45D1DF942711D9A, 242, 92 }, { 0x924D692CA61BE758, 269, 100 }, { 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 }, { 0xF209787BB47D6B85, 348, 124 }, { 0xB454E4A179DD1877, 375, 132 }, { 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 }, { 0x952AB45CFA97A0B3, 455, 156 }, { 0xDE469FBD99A05FE3, 481, 164 }, { 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 }, { 0xB7DCBF5354E9BECE, 561, 188 }, { 0x88FCF317F22241E2, 588, 196 }, { 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 }, { 0xE2A0B5DC971F303A, 667, 220 }, { 0xA8D9D1535CE3B396, 694, 228 }, { 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 }, { 0x8BAB8EEFB6409C1A, 774, 252 }, { 0xD01FEF10A657842C, 800, 260 }, { 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 }, { 0xAC2820D9623BF429, 880, 284 }, { 0x80444B5E7AA7CF85, 907, 292 }, { 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 }, { 0xD433179D9C8CB841, 986, 316 }, { 0x9E19DB92B4E31BA9, 1013, 324 },
} };
static constexpr std::array<cached_power, 79> kCachedPowers =
{
{
{ 0xAB70FE17C79AC6CA, -1060, -300 },
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
{ 0xBE5691EF416BD60C, -1007, -284 },
{ 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 },
{ 0x9D71AC8FADA6C9B5, -927, -260 },
{ 0xEA9C227723EE8BCB, -901, -252 },
{ 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 },
{ 0xC21094364DFB5637, -821, -228 },
{ 0x9096EA6F3848984F, -794, -220 },
{ 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 },
{ 0xEF340A98172AACE5, -715, -196 },
{ 0xB23867FB2A35B28E, -688, -188 },
{ 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 },
{ 0x936B9FCEBB25C996, -608, -164 },
{ 0xDBAC6C247D62A584, -582, -156 },
{ 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 },
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
{ 0x87625F056C7C4A8B, -475, -124 },
{ 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 },
{ 0xDFF9772470297EBD, -396, -100 },
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
{ 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 },
{ 0x8A08F0F8BF0F156B, -289, -68 },
{ 0xCDB02555653131B6, -263, -60 },
{ 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 },
{ 0xAA242499697392D3, -183, -36 },
{ 0xFD87B5F28300CA0E, -157, -28 },
{ 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 },
{ 0xD1B71758E219652C, -77, -4 },
{ 0x9C40000000000000, -50, 4 },
{ 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 },
{ 0x813F3978F8940984, 30, 28 },
{ 0xC097CE7BC90715B3, 56, 36 },
{ 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 },
{ 0x9F4F2726179A2245, 136, 60 },
{ 0xED63A231D4C4FB27, 162, 68 },
{ 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 },
{ 0xC45D1DF942711D9A, 242, 92 },
{ 0x924D692CA61BE758, 269, 100 },
{ 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 },
{ 0xF209787BB47D6B85, 348, 124 },
{ 0xB454E4A179DD1877, 375, 132 },
{ 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 },
{ 0x952AB45CFA97A0B3, 455, 156 },
{ 0xDE469FBD99A05FE3, 481, 164 },
{ 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 },
{ 0xB7DCBF5354E9BECE, 561, 188 },
{ 0x88FCF317F22241E2, 588, 196 },
{ 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 },
{ 0xE2A0B5DC971F303A, 667, 220 },
{ 0xA8D9D1535CE3B396, 694, 228 },
{ 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 },
{ 0x8BAB8EEFB6409C1A, 774, 252 },
{ 0xD01FEF10A657842C, 800, 260 },
{ 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 },
{ 0xAC2820D9623BF429, 880, 284 },
{ 0x80444B5E7AA7CF85, 907, 292 },
{ 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 },
{ 0xD433179D9C8CB841, 986, 316 },
{ 0x9E19DB92B4E31BA9, 1013, 324 },
}
};
// This computation gives exactly the same results for k as
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
// for |e| <= 1500, but doesn't require floating-point operations.
// NB: log_10(2) ~= 78913 / 2^18
JSON_ASSERT(e >= -1500);
JSON_ASSERT(e <= 1500);
JSON_ASSERT(e <= 1500);
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;
JSON_ASSERT(index >= 0);
@@ -438,49 +501,50 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
if (n >= 100000000)
{
pow10 = 100000000;
return 9;
return 9;
}
if (n >= 10000000)
{
pow10 = 10000000;
return 8;
return 8;
}
if (n >= 1000000)
{
pow10 = 1000000;
return 7;
return 7;
}
if (n >= 100000)
{
pow10 = 100000;
return 6;
return 6;
}
if (n >= 10000)
{
pow10 = 10000;
return 5;
return 5;
}
if (n >= 1000)
{
pow10 = 1000;
return 4;
return 4;
}
if (n >= 100)
{
pow10 = 100;
return 3;
return 3;
}
if (n >= 10)
{
pow10 = 10;
return 2;
return 2;
}
pow10 = 1;
return 1;
}
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)
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)
{
JSON_ASSERT(len >= 1);
JSON_ASSERT(dist <= delta);
@@ -506,7 +570,9 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
// The tests are written in this order to avoid overflow in unsigned
// integer arithmetic.
while (rest < dist && delta - rest >= ten_k && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
while (rest < dist
&& delta - rest >= ten_k
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
{
JSON_ASSERT(buf[len - 1] != '0');
buf[len - 1]--;
@@ -518,7 +584,8 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
*/
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
diyfp M_minus, diyfp w, diyfp M_plus)
{
static_assert(kAlpha >= -60, "internal error");
static_assert(kGamma <= -32, "internal error");
@@ -538,8 +605,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
JSON_ASSERT(M_plus.e >= kAlpha);
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 dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), 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)
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
//
@@ -548,10 +615,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
// = ((p1 ) * 2^-e + (p2 )) * 2^e
// = p1 + p2 * 2^e
const diyfp one(std::uint64_t{ 1 } << -M_plus.e, M_plus.e);
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
// 1)
//
@@ -594,7 +661,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
//
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)
//
@@ -613,7 +680,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
// Note:
// Since rest and delta share the same exponent e, it suffices to
// compare the significands.
const std::uint64_t rest = (std::uint64_t{ p1 } << -one.e) + p2;
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
if (rest <= delta)
{
// V = buffer * 10^n, with M- <= V <= M+.
@@ -629,7 +696,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
//
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
//
const std::uint64_t ten_n = std::uint64_t{ pow10 } << -one.e;
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
grisu2_round(buffer, length, dist, delta, rest, ten_n);
return;
@@ -693,15 +760,15 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
//
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
p2 *= 10;
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 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
//
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + 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
//
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
//
@@ -717,7 +784,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, d
// p2 * 2^e <= 10^m * delta * 2^e
// p2 <= 10^m * delta
delta *= 10;
dist *= 10;
dist *= 10;
if (p2 <= delta)
{
break;
@@ -758,7 +825,8 @@ len is the length of the buffer (number of decimal digits)
The buffer must be large enough, i.e. >= max_digits10.
*/
JSON_HEDLEY_NON_NULL(1)
inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
inline void grisu2(char* buf, int& len, int& decimal_exponent,
diyfp m_minus, diyfp v, diyfp m_plus)
{
JSON_ASSERT(m_plus.e == m_minus.e);
JSON_ASSERT(m_plus.e == v.e);
@@ -774,12 +842,12 @@ inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, di
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
const diyfp w = diyfp::mul(v, c_minus_k);
const diyfp w = diyfp::mul(v, c_minus_k);
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
// ----(---+---)---------------(---+---)---------------(---+---)----
// w- w w+
@@ -803,9 +871,9 @@ inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, di
// Note that this does not mean that Grisu2 always generates the shortest
// possible number in the interval (m-, m+).
const diyfp M_minus(w_minus.f + 1, w_minus.e);
const diyfp M_plus(w_plus.f - 1, w_plus.e);
const diyfp M_plus (w_plus.f - 1, w_plus.e );
decimal_exponent = -cached.k; // = -(-k) = k
decimal_exponent = -cached.k; // = -(-k) = k
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
}
@@ -819,7 +887,8 @@ template<typename FloatType>
JSON_HEDLEY_NON_NULL(1)
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
{
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, "internal error: not enough precision");
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
"internal error: not enough precision");
JSON_ASSERT(std::isfinite(value));
JSON_ASSERT(value > 0);
@@ -840,7 +909,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
// NB: If the neighbors are computed for single-precision numbers, there is a single float
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
// value is off by 1 ulp.
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
const boundaries w = compute_boundaries(static_cast<double>(value));
#else
const boundaries w = compute_boundaries(value);
@@ -859,7 +928,7 @@ JSON_HEDLEY_RETURNS_NON_NULL
inline char* append_exponent(char* buf, int e)
{
JSON_ASSERT(e > -1000);
JSON_ASSERT(e < 1000);
JSON_ASSERT(e < 1000);
if (e < 0)
{
@@ -881,15 +950,15 @@ inline char* append_exponent(char* buf, int e)
}
else if (k < 100)
{
*buf++ = static_cast<char>('0' + k / 10);
*buf++ = static_cast<char>('0' + (k / 10));
k %= 10;
*buf++ = static_cast<char>('0' + k);
}
else
{
*buf++ = static_cast<char>('0' + k / 100);
*buf++ = static_cast<char>('0' + (k / 100));
k %= 100;
*buf++ = static_cast<char>('0' + k / 10);
*buf++ = static_cast<char>('0' + (k / 10));
k %= 10;
*buf++ = static_cast<char>('0' + k);
}
@@ -908,7 +977,8 @@ notation. Otherwise it will be printed in exponential notation.
*/
JSON_HEDLEY_NON_NULL(1)
JSON_HEDLEY_RETURNS_NON_NULL
inline char* format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp)
inline char* format_buffer(char* buf, int len, int decimal_exponent,
int min_exp, int max_exp)
{
JSON_ASSERT(min_exp < 0);
JSON_ASSERT(max_exp > 0);
@@ -991,9 +1061,10 @@ format. Returns an iterator pointing past-the-end of the decimal representation.
*/
template<typename FloatType>
JSON_HEDLEY_NON_NULL(1, 2)
JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, FloatType value)
JSON_HEDLEY_RETURNS_NON_NULL
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
JSON_ASSERT(std::isfinite(value));
// Use signbit(value) instead of (value < 0) since signbit works for -0.
@@ -1004,10 +1075,10 @@ JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, Float
}
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
if (value == 0) // +-0
if (value == 0) // +-0
{
*first++ = '0';
// Make it look like a floating-point number (#362, #378)
@@ -1016,7 +1087,7 @@ JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, Float
return first;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
+85 -67
View File
@@ -8,14 +8,17 @@
#pragma once
#include <algorithm> // copy
#include <iterator> // begin, end
#include <string> // string
#include <tuple> // tuple, get
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <algorithm> // copy
#include <iterator> // begin, end
#ifdef JSON_HAS_CPP_17
#include <optional> // optional
#endif
#include <string> // string
#include <tuple> // tuple, get
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -39,8 +42,7 @@ namespace detail
* https://github.com/nlohmann/json/issues/2865 for more information.
*/
template<value_t>
struct external_constructor;
template<value_t> struct external_constructor;
template<>
struct external_constructor<value_t::boolean>
@@ -76,9 +78,9 @@ struct external_constructor<value_t::string>
j.assert_invariant();
}
template<typename BasicJsonType,
typename CompatibleStringType,
enable_if_t<!std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, int> = 0>
template < typename BasicJsonType, typename CompatibleStringType,
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
int > = 0 >
static void construct(BasicJsonType& j, const CompatibleStringType& str)
{
j.m_data.m_value.destroy(j.m_data.m_type);
@@ -172,9 +174,9 @@ struct external_constructor<value_t::array>
j.assert_invariant();
}
template<typename BasicJsonType,
typename CompatibleArrayType,
enable_if_t<!std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, int> = 0>
template < typename BasicJsonType, typename CompatibleArrayType,
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
int > = 0 >
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
{
using std::begin;
@@ -202,7 +204,8 @@ struct external_constructor<value_t::array>
j.assert_invariant();
}
template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
{
j.m_data.m_value.destroy(j.m_data.m_type);
@@ -241,9 +244,8 @@ struct external_constructor<value_t::object>
j.assert_invariant();
}
template<typename BasicJsonType,
typename CompatibleObjectType,
enable_if_t<!std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
{
using std::begin;
@@ -261,27 +263,43 @@ struct external_constructor<value_t::object>
// to_json //
/////////////
template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
#ifdef JSON_HAS_CPP_17
template<typename BasicJsonType, typename T,
enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
void to_json(BasicJsonType& j, const std::optional<T>& opt)
{
if (opt.has_value())
{
j = *opt;
}
else
{
j = nullptr;
}
}
#endif
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
inline void to_json(BasicJsonType& j, T b) noexcept
{
external_constructor<value_t::boolean>::construct(j, b);
}
template<typename BasicJsonType,
typename BoolRef,
enable_if_t<((std::is_same<std::vector<bool>::reference, BoolRef>::value &&
!std::is_same<std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) ||
(std::is_same<std::vector<bool>::const_reference, BoolRef>::value &&
!std::is_same<detail::uncvref_t<std::vector<bool>::const_reference>, typename BasicJsonType::boolean_t>::value)) &&
std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value,
int> = 0>
template < typename BasicJsonType, typename BoolRef,
enable_if_t <
((std::is_same<std::vector<bool>::reference, BoolRef>::value
&& !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
|| (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
&& !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
typename BasicJsonType::boolean_t >::value))
&& std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
{
external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
}
template<typename BasicJsonType,
typename CompatibleString,
template<typename BasicJsonType, typename CompatibleString,
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
inline void to_json(BasicJsonType& j, const CompatibleString& s)
{
@@ -294,22 +312,21 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
external_constructor<value_t::string>::construct(j, std::move(s));
}
template<typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
template<typename BasicJsonType, typename FloatType,
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
inline void to_json(BasicJsonType& j, FloatType val) noexcept
{
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
}
template<typename BasicJsonType,
typename CompatibleNumberUnsignedType,
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
{
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
}
template<typename BasicJsonType,
typename CompatibleNumberIntegerType,
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
{
@@ -317,11 +334,13 @@ inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
}
#if !JSON_DISABLE_ENUM_SERIALIZATION
template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
template<typename BasicJsonType, typename EnumType,
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
inline void to_json(BasicJsonType& j, EnumType e) noexcept
{
using underlying_type = typename std::underlying_type<EnumType>::type;
external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
}
#endif // JSON_DISABLE_ENUM_SERIALIZATION
@@ -331,13 +350,14 @@ inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
external_constructor<value_t::array>::construct(j, e);
}
template<
typename BasicJsonType,
typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value && !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value &&
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value &&
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value && !is_basic_json<CompatibleArrayType>::value,
int> = 0>
template < typename BasicJsonType, typename CompatibleArrayType,
enable_if_t < is_compatible_array_type<BasicJsonType,
CompatibleArrayType>::value&&
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
!is_basic_json<CompatibleArrayType>::value,
int > = 0 >
inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
{
external_constructor<value_t::array>::construct(j, arr);
@@ -349,7 +369,8 @@ inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bi
external_constructor<value_t::binary>::construct(j, bin);
}
template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
@@ -361,9 +382,8 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
external_constructor<value_t::array>::construct(j, std::move(arr));
}
template<typename BasicJsonType,
typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value && !is_basic_json<CompatibleObjectType>::value, int> = 0>
template < typename BasicJsonType, typename CompatibleObjectType,
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{
external_constructor<value_t::object>::construct(j, obj);
@@ -375,31 +395,28 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
external_constructor<value_t::object>::construct(j, std::move(obj));
}
template<typename BasicJsonType,
typename T,
std::size_t N,
enable_if_t<!std::is_constructible<typename BasicJsonType::string_t,
const T (&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
int> = 0>
inline void to_json(BasicJsonType& j, const T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
template <
typename BasicJsonType, typename T, std::size_t N,
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
int > = 0 >
inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{
external_constructor<value_t::array>::construct(j, arr);
}
template<typename BasicJsonType,
typename T1,
typename T2,
enable_if_t<std::is_constructible<BasicJsonType, T1>::value && std::is_constructible<BasicJsonType, T2>::value, int> = 0>
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
{
j = { p.first, p.second };
}
// for https://github.com/nlohmann/json/pull/1134
template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
template<typename BasicJsonType, typename T,
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
inline void to_json(BasicJsonType& j, const T& b)
{
j = { { b.key(), b.value() } };
j = { {b.key(), b.value()} };
}
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
@@ -408,10 +425,10 @@ inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<
j = { std::get<Idx>(t)... };
}
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int> = 0>
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
inline void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value>{});
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
@@ -425,7 +442,8 @@ inline void to_json(BasicJsonType& j, const std_fs::path& p)
struct to_json_fn
{
template<typename BasicJsonType, typename T>
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) -> decltype(to_json(j, std::forward<T>(val)), void())
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
-> decltype(to_json(j, std::forward<T>(val)), void())
{
return to_json(j, std::forward<T>(val));
}
@@ -436,10 +454,10 @@ struct to_json_fn
/// namespace to hold default `to_json` function
/// to see why this is required:
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
{
#endif
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
detail::static_const<detail::to_json_fn>::value;
#ifndef JSON_HAS_CPP_17
} // namespace
+40 -51
View File
@@ -8,22 +8,22 @@
#pragma once
#include <cstddef> // nullptr_t
#include <exception> // exception
#include <cstddef> // nullptr_t
#include <exception> // exception
#if JSON_DIAGNOSTICS
#include <numeric> // accumulate
#include <numeric> // accumulate
#endif
#include <stdexcept> // runtime_error
#include <string> // to_string
#include <vector> // vector
#include <stdexcept> // runtime_error
#include <string> // to_string
#include <vector> // vector
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/string_escape.hpp>
#include <nlohmann/detail/input/position_t.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/string_concat.hpp>
#include <nlohmann/detail/string_escape.hpp>
#include <nlohmann/detail/value_t.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
@@ -45,14 +45,11 @@ class exception : public std::exception
}
/// the id of the exception
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
protected:
JSON_HEDLEY_NON_NULL(3)
exception(int id_, const char* what_arg)
: id(id_)
, m(what_arg) // NOLINT(bugprone-throw-keyword-missing)
{}
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
static std::string name(const std::string& ename, int id_)
{
@@ -99,16 +96,16 @@ class exception : public std::exception
break;
}
case value_t::null: // LCOV_EXCL_LINE
case value_t::string: // LCOV_EXCL_LINE
case value_t::boolean: // LCOV_EXCL_LINE
case value_t::number_integer: // LCOV_EXCL_LINE
case value_t::number_unsigned: // LCOV_EXCL_LINE
case value_t::number_float: // LCOV_EXCL_LINE
case value_t::binary: // LCOV_EXCL_LINE
case value_t::discarded: // LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
break; // LCOV_EXCL_LINE
case value_t::null: // LCOV_EXCL_LINE
case value_t::string: // LCOV_EXCL_LINE
case value_t::boolean: // LCOV_EXCL_LINE
case value_t::number_integer: // LCOV_EXCL_LINE
case value_t::number_unsigned: // LCOV_EXCL_LINE
case value_t::number_float: // LCOV_EXCL_LINE
case value_t::binary: // LCOV_EXCL_LINE
case value_t::discarded: // LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
break; // LCOV_EXCL_LINE
}
}
@@ -117,7 +114,9 @@ class exception : public std::exception
return "";
}
auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, [](const std::string& a, const std::string& b) {
auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
[](const std::string & a, const std::string & b)
{
return concat(a, '/', detail::escape(b));
});
return concat('(', str, ") ");
@@ -149,20 +148,18 @@ class parse_error : public exception
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("parse_error", id_), "parse error", position_string(pos), ": ", exception::diagnostics(context), what_arg);
return { id_, pos.chars_read_total, w.c_str() };
const std::string w = concat(exception::name("parse_error", id_), "parse error",
position_string(pos), ": ", exception::diagnostics(context), what_arg);
return {id_, pos.chars_read_total, w.c_str()};
}
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("parse_error", id_),
"parse error",
const std::string w = concat(exception::name("parse_error", id_), "parse error",
(byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
": ",
exception::diagnostics(context),
what_arg);
return { id_, byte_, w.c_str() };
": ", exception::diagnostics(context), what_arg);
return {id_, byte_, w.c_str()};
}
/*!
@@ -178,13 +175,12 @@ class parse_error : public exception
private:
parse_error(int id_, std::size_t byte_, const char* what_arg)
: exception(id_, what_arg)
, byte(byte_)
{}
: exception(id_, what_arg), byte(byte_) {}
static std::string position_string(const position_t& pos)
{
return concat(" at line ", std::to_string(pos.lines_read + 1), ", column ", std::to_string(pos.chars_read_current_line));
return concat(" at line ", std::to_string(pos.lines_read + 1),
", column ", std::to_string(pos.chars_read_current_line));
}
};
@@ -197,14 +193,13 @@ class invalid_iterator : public exception
static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
return { id_, w.c_str() };
return {id_, w.c_str()};
}
private:
JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_, const char* what_arg)
: exception(id_, what_arg)
{}
: exception(id_, what_arg) {}
};
/// @brief exception indicating executing a member function with a wrong type
@@ -216,14 +211,12 @@ class type_error : public exception
static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
return { id_, w.c_str() };
return {id_, w.c_str()};
}
private:
JSON_HEDLEY_NON_NULL(3)
type_error(int id_, const char* what_arg)
: exception(id_, what_arg)
{}
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
/// @brief exception indicating access out of the defined range
@@ -235,14 +228,12 @@ class out_of_range : public exception
static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
return { id_, w.c_str() };
return {id_, w.c_str()};
}
private:
JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_, const char* what_arg)
: exception(id_, what_arg)
{}
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
/// @brief exception indicating other library errors
@@ -254,14 +245,12 @@ class other_error : public exception
static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
{
const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
return { id_, w.c_str() };
return {id_, w.c_str()};
}
private:
JSON_HEDLEY_NON_NULL(3)
other_error(int id_, const char* what_arg)
: exception(id_, what_arg)
{}
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
} // namespace detail
+14 -14
View File
@@ -8,9 +8,9 @@
#pragma once
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <functional> // hash
#include <cstdint> // uint8_t
#include <cstddef> // size_t
#include <functional> // hash
#include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -59,7 +59,7 @@ std::size_t hash(const BasicJsonType& j)
auto seed = combine(type, j.size());
for (const auto& element : j.items())
{
const auto h = std::hash<string_t>{}(element.key());
const auto h = std::hash<string_t> {}(element.key());
seed = combine(seed, h);
seed = combine(seed, hash(element.value()));
}
@@ -78,50 +78,50 @@ std::size_t hash(const BasicJsonType& j)
case BasicJsonType::value_t::string:
{
const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
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>());
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>());
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
return combine(type, h);
}
case BasicJsonType::value_t::number_unsigned:
{
const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
return combine(type, h);
}
case BasicJsonType::value_t::number_float:
{
const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
return combine(type, h);
}
case BasicJsonType::value_t::binary:
{
auto seed = combine(type, j.get_binary().size());
const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
seed = combine(seed, h);
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
for (const auto byte : j.get_binary())
{
seed = combine(seed, std::hash<std::uint8_t>{}(byte));
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
}
return seed;
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return 0; // LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return 0; // LCOV_EXCL_LINE
}
}
File diff suppressed because it is too large Load Diff
@@ -8,15 +8,15 @@
#pragma once
#include <array> // array
#include <cstddef> // size_t
#include <cstring> // strlen
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
#include <numeric> // accumulate
#include <string> // string, char_traits
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
#include <utility> // pair, declval
#include <array> // array
#include <cstddef> // size_t
#include <cstring> // strlen
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
#include <numeric> // accumulate
#include <string> // string, char_traits
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
#include <utility> // pair, declval
#ifndef JSON_NO_IO
#include <cstdio> // FILE *
@@ -32,15 +32,7 @@ namespace detail
{
/// the supported input formats
enum class input_format_t
{
json,
cbor,
msgpack,
ubjson,
bson,
bjdata
};
enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
////////////////////
// input adapters //
@@ -58,7 +50,7 @@ class file_input_adapter
JSON_HEDLEY_NON_NULL(2)
explicit file_input_adapter(std::FILE* f) noexcept
: m_file(f)
: m_file(f)
{
JSON_ASSERT(m_file != nullptr);
}
@@ -105,8 +97,7 @@ class input_stream_adapter
}
explicit input_stream_adapter(std::istream& i)
: is(&i)
, sb(i.rdbuf())
: is(&i), sb(i.rdbuf())
{}
// delete because of pointer members
@@ -115,8 +106,7 @@ class input_stream_adapter
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
input_stream_adapter(input_stream_adapter&& rhs) noexcept
: is(rhs.is)
, sb(rhs.sb)
: is(rhs.is), sb(rhs.sb)
{
rhs.is = nullptr;
rhs.sb = nullptr;
@@ -152,8 +142,7 @@ class iterator_input_adapter
using char_type = typename std::iterator_traits<IteratorType>::value_type;
iterator_input_adapter(IteratorType first, IteratorType last)
: current(std::move(first))
, end(std::move(last))
: current(std::move(first)), end(std::move(last))
{}
typename char_traits<char_type>::int_type get_character()
@@ -188,8 +177,10 @@ template<typename BaseInputAdapter>
struct wide_string_input_helper<BaseInputAdapter, 4>
{
// UTF-32
static void
fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(BaseInputAdapter& input,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
@@ -244,8 +235,10 @@ template<typename BaseInputAdapter>
struct wide_string_input_helper<BaseInputAdapter, 2>
{
// UTF-16
static void
fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(BaseInputAdapter& input,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
@@ -308,8 +301,7 @@ class wide_string_input_adapter
using char_type = char;
wide_string_input_adapter(BaseInputAdapter base)
: base_adapter(base)
{}
: base_adapter(base) {}
typename std::char_traits<char>::int_type get_character() noexcept
{
@@ -338,7 +330,7 @@ class wide_string_input_adapter
}
/// a buffer for UTF-8 bytes
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = { { 0, 0, 0, 0 } };
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
/// index to the utf8_codes array for the next valid byte
std::size_t utf8_bytes_index = 0;
@@ -402,19 +394,19 @@ using std::begin;
using std::end;
template<typename ContainerType, typename Enable = void>
struct container_input_adapter_factory
{};
struct container_input_adapter_factory {};
template<typename ContainerType>
struct container_input_adapter_factory<ContainerType, void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
{
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
struct container_input_adapter_factory< ContainerType,
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
{
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
static adapter_type create(const ContainerType& container)
{
return input_adapter(begin(container), end(container));
}
};
static adapter_type create(const ContainerType& container)
{
return input_adapter(begin(container), end(container));
}
};
} // namespace container_input_adapter_factory_impl
@@ -445,11 +437,13 @@ inline input_stream_adapter input_adapter(std::istream&& stream)
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
// Null-delimited strings, and the like.
template<
typename CharT,
typename std::enable_if<std::is_pointer<CharT>::value && !std::is_array<CharT>::value &&
std::is_integral<typename std::remove_pointer<CharT>::type>::value && sizeof(typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
template < typename CharT,
typename std::enable_if <
std::is_pointer<CharT>::value&&
!std::is_array<CharT>::value&&
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
sizeof(typename std::remove_pointer<CharT>::type) == 1,
int >::type = 0 >
contiguous_bytes_input_adapter input_adapter(CharT b)
{
auto length = std::strlen(reinterpret_cast<const char*>(b));
@@ -458,8 +452,7 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
}
template<typename T, std::size_t N>
auto input_adapter(T (&array)[N])
-> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
{
return input_adapter(array, array + N);
}
@@ -470,24 +463,25 @@ auto input_adapter(T (&array)[N])
class span_input_adapter
{
public:
template<typename CharT,
typename std::enable_if<std::is_pointer<CharT>::value && std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
sizeof(typename std::remove_pointer<CharT>::type) == 1,
int>::type = 0>
template < typename CharT,
typename std::enable_if <
std::is_pointer<CharT>::value&&
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
sizeof(typename std::remove_pointer<CharT>::type) == 1,
int >::type = 0 >
span_input_adapter(CharT b, std::size_t l)
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l)
{}
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
template<
class IteratorType,
typename std::enable_if<std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0>
template<class IteratorType,
typename std::enable_if<
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
int>::type = 0>
span_input_adapter(IteratorType first, IteratorType last)
: ia(input_adapter(first, last))
{}
: ia(input_adapter(first, last)) {}
contiguous_bytes_input_adapter&& get()
{
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
}
private:
+32 -28
View File
@@ -9,9 +9,9 @@
#pragma once
#include <cstddef>
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -130,7 +130,9 @@ struct json_sax
@param[in] ex an exception object describing the error
@return whether parsing should proceed (must return false)
*/
virtual bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex) = 0;
virtual bool parse_error(std::size_t position,
const std::string& last_token,
const detail::exception& ex) = 0;
json_sax() = default;
json_sax(const json_sax&) = default;
@@ -171,15 +173,14 @@ class json_sax_dom_parser
@param[in] allow_exceptions_ whether parse errors yield exceptions
*/
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
: root(r)
, allow_exceptions(allow_exceptions_)
: root(r), allow_exceptions(allow_exceptions_)
{}
// make class move-only
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
~json_sax_dom_parser() = default;
bool null()
@@ -279,7 +280,8 @@ class json_sax_dom_parser
}
template<class Exception>
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
const Exception& ex)
{
errored = true;
static_cast<void>(ex);
@@ -303,7 +305,8 @@ class json_sax_dom_parser
object to which we can add elements
*/
template<typename Value>
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType* handle_value(Value&& v)
JSON_HEDLEY_RETURNS_NON_NULL
BasicJsonType* handle_value(Value&& v)
{
if (ref_stack.empty())
{
@@ -328,7 +331,7 @@ class json_sax_dom_parser
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack{};
std::vector<BasicJsonType*> ref_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
@@ -349,19 +352,19 @@ class json_sax_dom_callback_parser
using parser_callback_t = typename BasicJsonType::parser_callback_t;
using parse_event_t = typename BasicJsonType::parse_event_t;
json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb, const bool allow_exceptions_ = true)
: root(r)
, callback(cb)
, allow_exceptions(allow_exceptions_)
json_sax_dom_callback_parser(BasicJsonType& r,
parser_callback_t cb,
const bool allow_exceptions_ = true)
: root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_)
{
keep_stack.push_back(true);
}
// make class move-only
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
~json_sax_dom_callback_parser() = default;
bool null()
@@ -527,7 +530,8 @@ class json_sax_dom_callback_parser
}
template<class Exception>
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
const Exception& ex)
{
errored = true;
static_cast<void>(ex);
@@ -568,7 +572,7 @@ class json_sax_dom_callback_parser
// container
if (!keep_stack.back())
{
return { false, nullptr };
return {false, nullptr};
}
// create value
@@ -580,20 +584,20 @@ class json_sax_dom_callback_parser
// do not handle this value if we just learnt it shall be discarded
if (!keep)
{
return { false, nullptr };
return {false, nullptr};
}
if (ref_stack.empty())
{
root = std::move(value);
return { true, &root };
return {true, & root};
}
// skip this value if we already decided to skip the parent
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
if (!ref_stack.back())
{
return { false, nullptr };
return {false, nullptr};
}
// we now only expect arrays and objects
@@ -603,7 +607,7 @@ class json_sax_dom_callback_parser
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
return { true, &(ref_stack.back()->m_data.m_value.array->back()) };
return {true, & (ref_stack.back()->m_data.m_value.array->back())};
}
// object
@@ -615,22 +619,22 @@ class json_sax_dom_callback_parser
if (!store_element)
{
return { false, nullptr };
return {false, nullptr};
}
JSON_ASSERT(object_element);
*object_element = std::move(value);
return { true, object_element };
return {true, object_element};
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack{};
std::vector<BasicJsonType*> ref_stack {};
/// stack to manage which values to keep
std::vector<bool> keep_stack{};
std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
/// stack to manage which object keys to keep
std::vector<bool> key_keep_stack{};
std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
+50 -56
View File
@@ -8,15 +8,15 @@
#pragma once
#include <array> // array
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdio> // snprintf
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <initializer_list> // initializer_list
#include <string> // char_traits, string
#include <utility> // move
#include <vector> // vector
#include <array> // array
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdio> // snprintf
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <initializer_list> // initializer_list
#include <string> // char_traits, string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/position_t.hpp>
@@ -97,7 +97,7 @@ class lexer_base
case token_type::literal_or_value:
return "'[', '{', or a literal";
// LCOV_EXCL_START
default: // catch non-enum values
default: // catch non-enum values
return "unknown token";
// LCOV_EXCL_STOP
}
@@ -122,16 +122,16 @@ class lexer : public lexer_base<BasicJsonType>
using token_type = typename lexer_base<BasicJsonType>::token_type;
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
: ia(std::move(adapter))
, ignore_comments(ignore_comments_)
, 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
lexer(const lexer&) = delete;
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
lexer& operator=(lexer&) = delete;
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
~lexer() = default;
private:
@@ -223,7 +223,7 @@ class lexer : public lexer_base<BasicJsonType>
for (auto range = ranges.begin(); range != ranges.end(); ++range)
{
get();
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
{
add(current);
}
@@ -320,7 +320,7 @@ class lexer : public lexer_base<BasicJsonType>
case 'u':
{
const int codepoint1 = get_codepoint();
int codepoint = codepoint1; // start with codepoint1
int codepoint = codepoint1; // start with codepoint1
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
{
@@ -347,14 +347,14 @@ class lexer : public lexer_base<BasicJsonType>
{
// overwrite codepoint
codepoint = static_cast<int>(
// high surrogate occupies the most significant 22 bits
(static_cast<unsigned int>(codepoint1) << 10u)
// low surrogate occupies the least significant 15 bits
+ static_cast<unsigned int>(codepoint2)
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result, so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00u);
// high surrogate occupies the most significant 22 bits
(static_cast<unsigned int>(codepoint1) << 10u)
// low surrogate occupies the least significant 15 bits
+ static_cast<unsigned int>(codepoint2)
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result, so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00u);
}
else
{
@@ -745,7 +745,7 @@ class lexer : public lexer_base<BasicJsonType>
case 0xDE:
case 0xDF:
{
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({ 0x80, 0xBF })))
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
{
return token_type::parse_error;
}
@@ -755,7 +755,7 @@ class lexer : public lexer_base<BasicJsonType>
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
case 0xE0:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -779,7 +779,7 @@ class lexer : public lexer_base<BasicJsonType>
case 0xEE:
case 0xEF:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -789,7 +789,7 @@ class lexer : public lexer_base<BasicJsonType>
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
case 0xED:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -799,7 +799,7 @@ class lexer : public lexer_base<BasicJsonType>
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
case 0xF0:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -811,7 +811,7 @@ class lexer : public lexer_base<BasicJsonType>
case 0xF2:
case 0xF3:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -821,7 +821,7 @@ class lexer : public lexer_base<BasicJsonType>
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
case 0xF4:
{
if (JSON_HEDLEY_UNLIKELY(!(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;
}
@@ -967,7 +967,7 @@ class lexer : public lexer_base<BasicJsonType>
locale's decimal point is used instead of `.` to work with the
locale-dependent converters.
*/
token_type scan_number() // lgtm [cpp/use-of-goto]
token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
{
// reset token_buffer to store the number's bytes
reset();
@@ -1006,8 +1006,8 @@ class lexer : public lexer_base<BasicJsonType>
}
// all other characters are rejected outside scan_number()
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
scan_number_minus:
@@ -1185,7 +1185,8 @@ scan_number_exponent:
default:
{
error_message = "invalid number; expected '+', '-', or digit after exponent";
error_message =
"invalid number; expected '+', '-', or digit after exponent";
return token_type::parse_error;
}
}
@@ -1244,7 +1245,7 @@ scan_number_done:
// we are done scanning a number)
unget();
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
errno = 0;
// try to parse integers first and fall back to floats
@@ -1297,7 +1298,8 @@ scan_number_done:
@param[in] return_type the token type to return on success
*/
JSON_HEDLEY_NON_NULL(2)
token_type scan_literal(const char_type* literal_text, const std::size_t length, token_type return_type)
token_type scan_literal(const char_type* literal_text, const std::size_t length,
token_type return_type)
{
JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
for (std::size_t i = 1; i < length; ++i)
@@ -1453,9 +1455,8 @@ scan_number_done:
if (static_cast<unsigned char>(c) <= '\x1F')
{
// escape control characters
std::array<char, 9> cs{ {} };
static_cast<void>(( // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c)));
std::array<char, 9> cs{{}};
static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
result += cs.data();
}
else
@@ -1502,7 +1503,8 @@ scan_number_done:
do
{
get();
} while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
}
token_type scan()
@@ -1548,25 +1550,17 @@ scan_number_done:
// literals
case 't':
{
std::array<char_type, 4> true_literal = {
{ static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e') }
};
std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
}
case 'f':
{
std::array<char_type, 5> false_literal = { { static_cast<char_type>('f'),
static_cast<char_type>('a'),
static_cast<char_type>('l'),
static_cast<char_type>('s'),
static_cast<char_type>('e') } };
std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
}
case 'n':
{
std::array<char_type, 4> null_literal = {
{ static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l') }
};
std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
}
@@ -1615,13 +1609,13 @@ scan_number_done:
bool next_unget = false;
/// the start position of the current token
position_t position{};
position_t position {};
/// raw input token string (for error messages)
std::vector<char_type> token_string{};
std::vector<char_type> token_string {};
/// buffer for variable-length tokens (numbers, strings)
string_t token_buffer{};
string_t token_buffer {};
/// a description of occurred lexer errors
const char* error_message = "";
+43 -50
View File
@@ -8,12 +8,12 @@
#pragma once
#include <cmath> // isfinite
#include <cstdint> // uint8_t
#include <functional> // function
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <cmath> // isfinite
#include <cstdint> // uint8_t
#include <functional> // function
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
@@ -48,7 +48,8 @@ enum class parse_event_t : std::uint8_t
};
template<typename BasicJsonType>
using parser_callback_t = std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
using parser_callback_t =
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
/*!
@brief syntax analysis
@@ -68,12 +69,12 @@ class parser
public:
/// a parser reading from an input adapter
explicit parser(InputAdapterType&& adapter,
const parser_callback_t<BasicJsonType> cb = nullptr,
parser_callback_t<BasicJsonType> cb = nullptr,
const bool allow_exceptions_ = true,
const bool skip_comments = false)
: callback(cb)
, m_lexer(std::move(adapter), skip_comments)
, allow_exceptions(allow_exceptions_)
: callback(std::move(cb))
, m_lexer(std::move(adapter), skip_comments)
, allow_exceptions(allow_exceptions_)
{
// read first token
get_token();
@@ -101,7 +102,8 @@ class parser
{
sdp.parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_of_input, "value"), nullptr));
}
// in case of an error, return discarded value
@@ -158,7 +160,7 @@ class parser
JSON_HEDLEY_NON_NULL(2)
bool sax_parse(SAX* sax, const bool strict = true)
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType>{};
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
const bool result = sax_parse_internal(sax);
// strict mode: next byte must be EOF
@@ -210,10 +212,9 @@ class parser
// parse key
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
{
@@ -223,10 +224,9 @@ class parser
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// remember we are now inside an object
@@ -337,28 +337,23 @@ class parser
case token_type::parse_error:
{
// using "uninitialized" to avoid "expected" message
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
}
case token_type::end_of_input:
{
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101,
m_lexer.get_position(),
"attempting to parse an empty input; check that your input string or stream contains the expected JSON",
nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
}
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
}
case token_type::uninitialized:
case token_type::end_array:
@@ -366,12 +361,11 @@ class parser
case token_type::name_separator:
case token_type::value_separator:
case token_type::literal_or_value:
default: // the last token was unexpected
default: // the last token was unexpected
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
}
}
}
@@ -428,10 +422,9 @@ class parser
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
}
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
@@ -442,10 +435,9 @@ class parser
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(
m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
}
// parse values
@@ -496,7 +488,8 @@ class parser
if (last_token == token_type::parse_error)
{
error_msg += concat(m_lexer.get_error_message(), "; last read: '", m_lexer.get_token_string(), '\'');
error_msg += concat(m_lexer.get_error_message(), "; last read: '",
m_lexer.get_token_string(), '\'');
}
else
{
+1 -1
View File
@@ -8,7 +8,7 @@
#pragma once
#include <cstddef> // size_t
#include <cstddef> // size_t
#include <nlohmann/detail/abi_macros.hpp>
@@ -21,15 +21,14 @@ namespace detail
@note This structure could easily be a union, but MSVC currently does not allow
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
*/
template<typename BasicJsonType>
struct internal_iterator
template<typename BasicJsonType> struct internal_iterator
{
/// iterator for JSON objects
typename BasicJsonType::object_t::iterator object_iterator{};
typename BasicJsonType::object_t::iterator object_iterator {};
/// iterator for JSON arrays
typename BasicJsonType::array_t::iterator array_iterator{};
typename BasicJsonType::array_t::iterator array_iterator {};
/// generic iterator for all other types
primitive_iterator_t primitive_iterator{};
primitive_iterator_t primitive_iterator {};
};
} // namespace detail
+28 -32
View File
@@ -8,8 +8,8 @@
#pragma once
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
#include <type_traits> // conditional, is_const, remove_const
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
#include <type_traits> // conditional, is_const, remove_const
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/iterators/internal_iterator.hpp>
@@ -24,10 +24,8 @@ namespace detail
{
// forward declare, to be able to friend it later on
template<typename IteratorType>
class iteration_proxy;
template<typename IteratorType>
class iteration_proxy_value;
template<typename IteratorType> class iteration_proxy;
template<typename IteratorType> class iteration_proxy_value;
/*!
@brief a template for a bidirectional iterator for the @ref basic_json class
@@ -46,11 +44,10 @@ This class implements a both iterators (iterator and const_iterator) for the
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
*/
template<typename BasicJsonType>
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
{
/// the iterator with BasicJsonType of different const-ness
using other_iter_impl =
iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
/// allow basic_json to access private members
friend other_iter_impl;
friend BasicJsonType;
@@ -60,10 +57,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
using object_t = typename BasicJsonType::object_t;
using array_t = typename BasicJsonType::array_t;
// make sure BasicJsonType is basic_json or const basic_json
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, "iter_impl only accepts (const) basic_json");
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
"iter_impl only accepts (const) basic_json");
// superficial check for the LegacyBidirectionalIterator named requirement
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value &&
std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
&& std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
public:
@@ -79,11 +77,14 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// a type to represent differences between iterators
using difference_type = typename BasicJsonType::difference_type;
/// defines a pointer to the type iterated over (value_type)
using pointer =
typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer>::type;
using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
typename BasicJsonType::const_pointer,
typename BasicJsonType::pointer>::type;
/// defines a reference to the type iterated over (value_type)
using reference =
typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type;
typename std::conditional<std::is_const<BasicJsonType>::value,
typename BasicJsonType::const_reference,
typename BasicJsonType::reference>::type;
iter_impl() = default;
~iter_impl() = default;
@@ -96,8 +97,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@pre object != nullptr
@post The iterator is initialized; i.e. `m_object != nullptr`.
*/
explicit iter_impl(pointer object) noexcept
: m_object(object)
explicit iter_impl(pointer object) noexcept : m_object(object)
{
JSON_ASSERT(m_object != nullptr);
@@ -148,8 +148,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
information refer to: https://github.com/nlohmann/json/issues/1608
*/
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
: m_object(other.m_object)
, m_it(other.m_it)
: m_object(other.m_object), m_it(other.m_it)
{}
/*!
@@ -174,8 +173,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@note It is not checked whether @a other is initialized.
*/
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
: m_object(other.m_object)
, m_it(other.m_it)
: m_object(other.m_object), m_it(other.m_it)
{}
/*!
@@ -184,14 +182,14 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@return const/non-const iterator
@note It is not checked whether @a other is initialized.
*/
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
{
m_object = other.m_object;
m_it = other.m_it;
return *this;
}
JSON_PRIVATE_UNLESS_TESTED :
JSON_PRIVATE_UNLESS_TESTED:
/*!
@brief set the iterator to the first value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
@@ -365,7 +363,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl operator++(int) & // NOLINT(cert-dcl21-cpp)
iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
++(*this);
@@ -416,7 +414,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
iter_impl operator--(int) & // NOLINT(cert-dcl21-cpp)
iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
--(*this);
@@ -467,8 +465,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
template<typename IterImpl,
detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t> = nullptr>
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator==(const IterImpl& other) const
{
// if objects are not the same, the comparison is undefined
@@ -504,8 +501,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
@brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
template<typename IterImpl,
detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t> = nullptr>
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
bool operator!=(const IterImpl& other) const
{
return !operator==(other);
@@ -552,7 +548,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
*/
bool operator<=(const iter_impl& other) const
{
return !other.operator<(*this);
return !other.operator < (*this);
}
/*!
@@ -744,11 +740,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
return operator*();
}
JSON_PRIVATE_UNLESS_TESTED :
JSON_PRIVATE_UNLESS_TESTED:
/// associated JSON instance
pointer m_object = nullptr;
/// the actual iterator of the associated instance
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it{};
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
};
} // namespace detail
@@ -8,14 +8,14 @@
#pragma once
#include <cstddef> // size_t
#include <iterator> // input_iterator_tag
#include <string> // string, to_string
#include <tuple> // tuple_size, get, tuple_element
#include <utility> // move
#include <cstddef> // size_t
#include <iterator> // forward_iterator_tag
#include <string> // string, to_string
#include <tuple> // tuple_size, get, tuple_element
#include <utility> // move
#if JSON_HAS_RANGES
#include <ranges> // enable_borrowed_range
#include <ranges> // enable_borrowed_range
#endif
#include <nlohmann/detail/abi_macros.hpp>
@@ -27,22 +27,21 @@ namespace detail
{
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 )
{
// For ADL
using std::to_string;
target = to_string(value);
}
template<typename IteratorType>
class iteration_proxy_value
template<typename IteratorType> class iteration_proxy_value
{
public:
using difference_type = std::ptrdiff_t;
using value_type = iteration_proxy_value;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::input_iterator_tag;
using string_type = typename std::remove_cv<typename std::remove_reference<decltype(std::declval<IteratorType>().key())>::type>::type;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
private:
/// the iterator
@@ -58,21 +57,22 @@ class iteration_proxy_value
public:
explicit iteration_proxy_value() = default;
explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) noexcept(std::is_nothrow_move_constructible<IteratorType>::value &&
std::is_nothrow_default_constructible<string_type>::value)
: anchor(std::move(it))
, array_index(array_index_)
explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
&& std::is_nothrow_default_constructible<string_type>::value)
: anchor(std::move(it))
, array_index(array_index_)
{}
iteration_proxy_value(iteration_proxy_value const&) = default;
iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
// older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible<IteratorType>::value &&
std::is_nothrow_move_constructible<string_type>::value) =
default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable<IteratorType>::value &&
std::is_nothrow_move_assignable<string_type>::value) =
default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
iteration_proxy_value(iteration_proxy_value&&)
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
&& std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
iteration_proxy_value& operator=(iteration_proxy_value&&)
noexcept(std::is_nothrow_move_assignable<IteratorType>::value
&& std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
~iteration_proxy_value() = default;
/// dereference operator (needed for range-based for)
@@ -90,7 +90,7 @@ class iteration_proxy_value
return *this;
}
iteration_proxy_value operator++(int) & // NOLINT(cert-dcl21-cpp)
iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
{
auto tmp = iteration_proxy_value(anchor, array_index);
++anchor;
@@ -122,7 +122,7 @@ class iteration_proxy_value
{
if (array_index != array_index_last)
{
int_to_string(array_index_str, array_index);
int_to_string( array_index_str, array_index );
array_index_last = array_index;
}
return array_index_str;
@@ -154,8 +154,7 @@ class iteration_proxy_value
};
/// proxy class for the items() function
template<typename IteratorType>
class iteration_proxy
template<typename IteratorType> class iteration_proxy
{
private:
/// the container to iterate
@@ -166,8 +165,7 @@ class iteration_proxy
/// construct iteration proxy from a container
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
: container(&cont)
{}
: container(&cont) {}
iteration_proxy(iteration_proxy const&) = default;
iteration_proxy& operator=(iteration_proxy const&) = default;
@@ -221,15 +219,16 @@ namespace std
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template<typename IteratorType>
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
: public std::integral_constant<std::size_t, 2>
{};
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
: public std::integral_constant<std::size_t, 2> {};
template<std::size_t N, typename IteratorType>
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
{
public:
using type = decltype(get<N>(std::declval<::nlohmann::detail::iteration_proxy_value<IteratorType>>()));
using type = decltype(
get<N>(std::declval <
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
};
#if defined(__clang__)
#pragma clang diagnostic pop
@@ -238,6 +237,6 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType>>
} // namespace std
#if JSON_HAS_RANGES
template<typename IteratorType>
inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
template <typename IteratorType>
inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
#endif
@@ -8,24 +8,24 @@
#pragma once
#include <iterator> // random_access_iterator_tag
#include <iterator> // random_access_iterator_tag
#include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/void_t.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename It, typename = void>
struct iterator_types
{};
struct iterator_types {};
template<typename It>
struct iterator_types<
struct iterator_types <
It,
void_t<typename It::difference_type, typename It::value_type, typename It::pointer, typename It::reference, typename It::iterator_category>>
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
typename It::reference, typename It::iterator_category >>
{
using difference_type = typename It::difference_type;
using value_type = typename It::value_type;
@@ -38,11 +38,14 @@ struct iterator_types<
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
template<typename T, typename = void>
struct iterator_traits
{};
{
};
template<typename T>
struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>> : iterator_types<T>
{};
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
: iterator_types<T>
{
};
template<typename T>
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
@@ -8,9 +8,9 @@
#pragma once
#include <cstddef> // ptrdiff_t
#include <iterator> // reverse_iterator
#include <utility> // declval
#include <cstddef> // ptrdiff_t
#include <iterator> // reverse_iterator
#include <utility> // declval
#include <nlohmann/detail/abi_macros.hpp>
@@ -52,16 +52,13 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
/// create reverse iterator from iterator
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it)
{}
: base_iterator(it) {}
/// create reverse iterator from base class
explicit json_reverse_iterator(const base_iterator& it) noexcept
: base_iterator(it)
{}
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++)
json_reverse_iterator operator++(int) & // NOLINT(cert-dcl21-cpp)
json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
{
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
}
@@ -73,7 +70,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
}
/// post-decrement (it--)
json_reverse_iterator operator--(int) & // NOLINT(cert-dcl21-cpp)
json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
{
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
}
@@ -125,7 +122,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
reference value() const
{
auto it = --this->base();
return it.operator*();
return it.operator * ();
}
};
@@ -8,8 +8,8 @@
#pragma once
#include <cstddef> // ptrdiff_t
#include <limits> // numeric_limits
#include <cstddef> // ptrdiff_t
#include <limits> // numeric_limits
#include <nlohmann/detail/macro_scope.hpp>
@@ -33,7 +33,7 @@ class primitive_iterator_t
static constexpr difference_type begin_value = 0;
static constexpr difference_type end_value = begin_value + 1;
JSON_PRIVATE_UNLESS_TESTED :
JSON_PRIVATE_UNLESS_TESTED:
/// iterator as signed integer type
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
@@ -95,7 +95,7 @@ class primitive_iterator_t
return *this;
}
primitive_iterator_t operator++(int) & noexcept // NOLINT(cert-dcl21-cpp)
primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
++m_it;
@@ -108,7 +108,7 @@ class primitive_iterator_t
return *this;
}
primitive_iterator_t operator--(int) & noexcept // NOLINT(cert-dcl21-cpp)
primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
{
auto result = *this;
--m_it;
@@ -8,7 +8,7 @@
#pragma once
#include <type_traits> // conditional, is_same
#include <type_traits> // conditional, is_same
#include <nlohmann/detail/abi_macros.hpp>
@@ -26,11 +26,14 @@ of @ref basic_json do not require complex case distinctions
By default, this class is used because it is empty and thus has no effect
on the behavior of @ref basic_json.
*/
struct json_default_base
{};
struct json_default_base {};
template<class T>
using json_base_class = typename std::conditional<std::is_same<T, void>::value, json_default_base, T>::type;
using json_base_class = typename std::conditional <
std::is_same<T, void>::value,
json_default_base,
T
>::type;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
+99 -68
View File
@@ -8,18 +8,18 @@
#pragma once
#include <algorithm> // all_of
#include <cctype> // isdigit
#include <cerrno> // errno, ERANGE
#include <cstdlib> // strtoull
#include <algorithm> // all_of
#include <cctype> // isdigit
#include <cerrno> // errno, ERANGE
#include <cstdlib> // strtoull
#ifndef JSON_NO_IO
#include <iosfwd> // ostream
#endif // JSON_NO_IO
#include <limits> // max
#include <numeric> // accumulate
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <iosfwd> // ostream
#endif // JSON_NO_IO
#include <limits> // max
#include <numeric> // accumulate
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -60,14 +60,17 @@ class json_pointer
/// @brief create JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
explicit json_pointer(const string_t& s = "")
: reference_tokens(split(s))
: reference_tokens(split(s))
{}
/// @brief return a string representation of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
string_t to_string() const
{
return std::accumulate(reference_tokens.begin(), reference_tokens.end(), string_t{}, [](const string_t& a, const string_t& b) {
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
string_t{},
[](const string_t& a, const string_t& b)
{
return detail::concat(a, '/', detail::escape(b));
});
}
@@ -94,7 +97,9 @@ class json_pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
json_pointer& operator/=(const json_pointer& ptr)
{
reference_tokens.insert(reference_tokens.end(), ptr.reference_tokens.begin(), ptr.reference_tokens.end());
reference_tokens.insert(reference_tokens.end(),
ptr.reference_tokens.begin(),
ptr.reference_tokens.end());
return *this;
}
@@ -115,14 +120,15 @@ class json_pointer
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
friend json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs)
friend json_pointer operator/(const json_pointer& lhs,
const json_pointer& rhs)
{
return json_pointer(lhs) /= rhs;
}
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
{
return json_pointer(lhs) /= std::move(token);
}
@@ -223,11 +229,11 @@ class json_pointer
const char* p = s.c_str();
char* p_end = nullptr;
errno = 0; // strtoull doesn't reset errno
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
if (p == p_end // invalid input or empty string
|| errno == ERANGE // out of range
|| JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
errno = 0; // strtoull doesn't reset errno
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
if (p == p_end // invalid input or empty string
|| errno == ERANGE // out of range
|| JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
{
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
}
@@ -236,13 +242,13 @@ class json_pointer
// https://github.com/nlohmann/json/pull/2203
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
{
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
}
return static_cast<size_type>(res);
}
JSON_PRIVATE_UNLESS_TESTED :
JSON_PRIVATE_UNLESS_TESTED:
json_pointer top() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
@@ -251,7 +257,7 @@ class json_pointer
}
json_pointer result = *this;
result.reference_tokens = { reference_tokens[0] };
result.reference_tokens = {reference_tokens[0]};
return result;
}
@@ -353,12 +359,17 @@ class json_pointer
if (ptr->is_null())
{
// check if reference token is a number
const bool nums = std::all_of(reference_token.begin(), reference_token.end(), [](const unsigned char x) {
const bool nums =
std::all_of(reference_token.begin(), reference_token.end(),
[](const unsigned char x)
{
return std::isdigit(x);
});
// change value to array for numbers or "-" or to object otherwise
*ptr = (nums || reference_token == "-") ? detail::value_t::array : detail::value_t::object;
*ptr = (nums || reference_token == "-")
? detail::value_t::array
: detail::value_t::object;
}
switch (ptr->type())
@@ -426,10 +437,9 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(
402,
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
ptr));
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
// note: at performs range check
@@ -485,10 +495,7 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" cannot be used for const access
JSON_THROW(detail::out_of_range::create(
402,
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
ptr));
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
}
// use unchecked array access
@@ -537,10 +544,9 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(
402,
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
ptr));
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
// note: at performs range check
@@ -670,8 +676,7 @@ class json_pointer
// check if nonempty reference string begins with slash
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
{
JSON_THROW(
detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
}
// extract the reference tokens:
@@ -680,14 +685,14 @@ class json_pointer
for (
// search for the first slash after the first character
std::size_t slash = reference_string.find_first_of('/', 1),
// set the beginning of the first reference token
// set the beginning of the first reference token
start = 1;
// we can stop if start == 0 (if slash == string_t::npos)
start != 0;
// set the beginning of the next reference token
// (will eventually be 0 if slash == string_t::npos)
start = (slash == string_t::npos) ? 0 : slash + 1,
// find next slash
// find next slash
slash = reference_string.find_first_of('/', start))
{
// use the text between the beginning of the reference token
@@ -695,12 +700,16 @@ class json_pointer
auto reference_token = reference_string.substr(start, slash - start);
// check reference tokens are properly escaped
for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
for (std::size_t pos = reference_token.find_first_of('~');
pos != string_t::npos;
pos = reference_token.find_first_of('~', pos + 1))
{
JSON_ASSERT(reference_token[pos] == '~');
// ~ must be followed by 0 or 1
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1')))
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
(reference_token[pos + 1] != '0' &&
reference_token[pos + 1] != '1')))
{
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
}
@@ -723,7 +732,9 @@ class json_pointer
@note Empty objects or arrays are flattened to `null`.
*/
template<typename BasicJsonType>
static void flatten(const string_t& reference_string, const BasicJsonType& value, BasicJsonType& result)
static void flatten(const string_t& reference_string,
const BasicJsonType& value,
BasicJsonType& result)
{
switch (value.type())
{
@@ -739,7 +750,8 @@ class json_pointer
// iterate array and use index as reference string
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
{
flatten(detail::concat(reference_string, '/', std::to_string(i)), value.m_data.m_value.array->operator[](i), result);
flatten(detail::concat(reference_string, '/', std::to_string(i)),
value.m_data.m_value.array->operator[](i), result);
}
}
break;
@@ -791,7 +803,8 @@ class json_pointer
@throw type_error.313 if value cannot be unflattened
*/
template<typename BasicJsonType>
static BasicJsonType unflatten(const BasicJsonType& value)
static BasicJsonType
unflatten(const BasicJsonType& value)
{
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
{
@@ -826,7 +839,7 @@ class json_pointer
return result;
}
json_pointer<string_t> convert() &&
json_pointer<string_t> convert()&&
{
json_pointer<string_t> result;
result.reference_tokens = std::move(reference_tokens);
@@ -853,51 +866,58 @@ class json_pointer
/// @brief 3-way compares two JSON pointers
template<typename RefStringTypeRhs>
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
{
return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
}
#else
/// @brief compares two JSON pointers for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
/// @brief compares JSON pointer and string for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template<typename RefStringTypeLhs, typename StringType>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs);
/// @brief compares string and JSON pointer for equality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
template<typename RefStringTypeRhs, typename StringType>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
friend bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs);
/// @brief compares two JSON pointers for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
/// @brief compares JSON pointer and string for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template<typename RefStringTypeLhs, typename StringType>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs);
/// @brief compares string and JSON pointer for inequality
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
template<typename RefStringTypeRhs, typename StringType>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
friend bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs);
/// @brief compares two JSON pointer for less-than
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
// NOLINTNEXTLINE(readability-redundant-declaration)
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
#endif
private:
@@ -908,47 +928,58 @@ class json_pointer
#if !JSON_HAS_THREE_WAY_COMPARISON
// functions cannot be defined inside class due to ODR violations
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept
{
return lhs.reference_tokens == rhs.reference_tokens;
}
template<typename RefStringTypeLhs, typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs)
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs)
{
return lhs == json_pointer<RefStringTypeLhs>(rhs);
}
template<typename RefStringTypeRhs, typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
inline bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs)
inline bool operator==(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs)
{
return json_pointer<RefStringTypeRhs>(lhs) == rhs;
}
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept
{
return !(lhs == rhs);
}
template<typename RefStringTypeLhs, typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
template<typename RefStringTypeLhs,
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs)
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
const StringType& rhs)
{
return !(lhs == rhs);
}
template<typename RefStringTypeRhs, typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
template<typename RefStringTypeRhs,
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
inline bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs)
inline bool operator!=(const StringType& lhs,
const json_pointer<RefStringTypeRhs>& rhs)
{
return !(lhs == rhs);
}
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
const json_pointer<RefStringTypeRhs>& rhs) noexcept
{
return lhs.reference_tokens < rhs.reference_tokens;
}
+9 -7
View File
@@ -25,20 +25,22 @@ class json_ref
using value_type = BasicJsonType;
json_ref(value_type&& value)
: owned_value(std::move(value))
: owned_value(std::move(value))
{}
json_ref(const value_type& value)
: value_ref(&value)
: value_ref(&value)
{}
json_ref(std::initializer_list<json_ref> init)
: owned_value(init)
: owned_value(init)
{}
template<class... Args, enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0>
json_ref(Args&&... args)
: owned_value(std::forward<Args>(args)...)
template <
class... Args,
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
json_ref(Args && ... args)
: owned_value(std::forward<Args>(args)...)
{}
// class should be movable only
@@ -64,7 +66,7 @@ class json_ref
value_type const* operator->() const
{
return &**this;
return &** this;
}
private:
File diff suppressed because it is too large Load Diff
+25 -28
View File
@@ -9,10 +9,10 @@
#pragma once
#include <array> // array
#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 <utility> // index_sequence, make_index_sequence, index_sequence_for
#include <array> // array
#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 <utility> // index_sequence, make_index_sequence, index_sequence_for
#include <nlohmann/detail/macro_scope.hpp>
@@ -28,8 +28,8 @@ using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::typ
// the following utilities are natively available in C++14
using std::enable_if_t;
using std::index_sequence;
using std::index_sequence_for;
using std::make_index_sequence;
using std::index_sequence_for;
#else
@@ -61,7 +61,7 @@ using enable_if_t = typename std::enable_if<B, T>::type;
// // will be deduced to `0, 1, 2, 3, 4`.
// user_function(make_integer_sequence<int, 5>());
// }
template<typename T, T... Ints>
template <typename T, T... Ints>
struct integer_sequence
{
using value_type = T;
@@ -76,37 +76,38 @@ struct integer_sequence
// A helper template for an `integer_sequence` of `size_t`,
// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
// `std::index_sequence`.
template<size_t... Ints>
template <size_t... Ints>
using index_sequence = integer_sequence<size_t, Ints...>;
namespace utility_internal
{
template<typename Seq, size_t SeqSize, size_t Rem>
template <typename Seq, size_t SeqSize, size_t Rem>
struct Extend;
// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
template<typename T, T... Ints, size_t SeqSize>
template <typename T, T... Ints, size_t SeqSize>
struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
{
using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
};
template<typename T, T... Ints, size_t SeqSize>
template <typename T, T... Ints, size_t SeqSize>
struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
{
using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
};
// Recursion helper for 'make_integer_sequence<T, N>'.
// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
template<typename T, size_t N>
template <typename T, size_t N>
struct Gen
{
using type = typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
using type =
typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
};
template<typename T>
template <typename T>
struct Gen<T, 0>
{
using type = integer_sequence<T>;
@@ -121,7 +122,7 @@ struct Gen<T, 0>
// This template alias is equivalent to
// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
// replacement for C++14's `std::make_integer_sequence`.
template<typename T, T N>
template <typename T, T N>
using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
// make_index_sequence
@@ -129,7 +130,7 @@ using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
// and is designed to be a drop-in replacement for C++14's
// `std::make_index_sequence`.
template<size_t N>
template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
// index_sequence_for
@@ -137,7 +138,7 @@ using make_index_sequence = make_integer_sequence<size_t, N>;
// Converts a typename pack into an index sequence of the same length, and
// is designed to be a drop-in replacement for C++14's
// `std::index_sequence_for()`
template<typename... Ts>
template <typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
//// END OF CODE FROM GOOGLE ABSEIL
@@ -145,12 +146,8 @@ using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
#endif
// dispatch utility (taken from ranges-v3)
template<unsigned N>
struct priority_tag : priority_tag<N - 1>
{};
template<>
struct priority_tag<0>
{};
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
// taken from ranges-v3
template<typename T>
@@ -160,14 +157,14 @@ struct static_const
};
#ifndef JSON_HAS_CPP_17
template<typename T>
constexpr T static_const<T>::value;
template<typename T>
constexpr T static_const<T>::value;
#endif
template<typename T, typename... Args>
inline constexpr std::array<T, sizeof...(Args)> make_array(Args&&... args)
constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
{
return std::array<T, sizeof...(Args)>{ { static_cast<T>(std::forward<Args>(args))... } };
return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
}
} // namespace detail
+7 -4
View File
@@ -27,7 +27,10 @@ struct nonesuch
void operator=(nonesuch&&) = delete;
};
template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
template<class Default,
class AlwaysVoid,
template<class...> class Op,
class... Args>
struct detector
{
using value_t = std::false_type;
@@ -45,8 +48,7 @@ template<template<class...> class Op, class... Args>
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
template<template<class...> class Op, class... Args>
struct is_detected_lazy : is_detected<Op, Args...>
{};
struct is_detected_lazy : is_detected<Op, Args...> { };
template<template<class...> class Op, class... Args>
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
@@ -61,7 +63,8 @@ template<class Expected, template<class...> class Op, class... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template<class To, template<class...> class Op, class... Args>
using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
using is_detected_convertible =
std::is_convertible<detected_t<Op, Args...>, To>;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
@@ -15,9 +15,7 @@ namespace detail
{
// dispatching helper struct
template<class T>
struct identity_tag
{};
template <class T> struct identity_tag {};
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
+74 -39
View File
@@ -8,9 +8,9 @@
#pragma once
#include <cstdint> // size_t
#include <string> // string
#include <utility> // declval
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
#include <nlohmann/detail/abi_macros.hpp>
#include <nlohmann/detail/meta/detected.hpp>
@@ -24,47 +24,58 @@ template<typename T>
using null_function_t = decltype(std::declval<T&>().null());
template<typename T>
using boolean_function_t = decltype(std::declval<T&>().boolean(std::declval<bool>()));
using boolean_function_t =
decltype(std::declval<T&>().boolean(std::declval<bool>()));
template<typename T, typename Integer>
using number_integer_function_t = decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
using number_integer_function_t =
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
template<typename T, typename Unsigned>
using number_unsigned_function_t = decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
using number_unsigned_function_t =
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
template<typename T, typename Float, typename String>
using number_float_function_t = decltype(std::declval<T&>().number_float(std::declval<Float>(), std::declval<const String&>()));
using number_float_function_t = decltype(std::declval<T&>().number_float(
std::declval<Float>(), std::declval<const String&>()));
template<typename T, typename String>
using string_function_t = decltype(std::declval<T&>().string(std::declval<String&>()));
using string_function_t =
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&>()));
using binary_function_t =
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
template<typename T>
using start_object_function_t = decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
using start_object_function_t =
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
template<typename T, typename String>
using key_function_t = decltype(std::declval<T&>().key(std::declval<String&>()));
using key_function_t =
decltype(std::declval<T&>().key(std::declval<String&>()));
template<typename T>
using end_object_function_t = decltype(std::declval<T&>().end_object());
template<typename T>
using start_array_function_t = decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
using start_array_function_t =
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
template<typename T>
using end_array_function_t = decltype(std::declval<T&>().end_array());
template<typename T, typename Exception>
using parse_error_function_t =
decltype(std::declval<T&>().parse_error(std::declval<std::size_t>(), std::declval<const std::string&>(), std::declval<const Exception&>()));
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string&>(),
std::declval<const Exception&>()));
template<typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
@@ -75,21 +86,27 @@ struct is_sax
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value && is_detected_exact<bool, boolean_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, number_integer_function_t, SAX, number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX, 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, binary_function_t, SAX, binary_t>::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, end_object_function_t, SAX>::value && is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value && is_detected_exact<bool, parse_error_function_t, SAX, exception_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, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template<typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
private:
static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
@@ -99,25 +116,43 @@ struct is_sax_static_asserts
using exception_t = typename BasicJsonType::exception;
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value, "Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, "Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, "Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value,
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(is_detected_exact<bool, string_function_t, SAX, string_t>::value, "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, "Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, "Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, "Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, "Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, "Missing/invalid function: bool end_array()");
static_assert(is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"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,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
} // namespace detail
+2 -2
View File
@@ -11,7 +11,7 @@
#include <nlohmann/detail/macro_scope.hpp>
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
#include <experimental/filesystem>
#include <experimental/filesystem>
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
@@ -19,7 +19,7 @@ namespace std_fs = std::experimental::filesystem;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
#elif JSON_HAS_FILESYSTEM
#include <filesystem>
#include <filesystem> // NOLINT(build/c++17)
NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
+250 -243
View File
@@ -8,11 +8,11 @@
#pragma once
#include <limits> // numeric_limits
#include <string> // char_traits
#include <tuple> // tuple
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <limits> // numeric_limits
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <tuple> // tuple
#include <string> // char_traits
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -47,22 +47,19 @@ namespace detail
// In this case, T has to be properly CV-qualified to constraint the function arguments
// (e.g. to_json(BasicJsonType&, const T&))
template<typename>
struct is_basic_json : std::false_type
{};
template<typename> struct is_basic_json : std::false_type {};
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type
{};
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
// used by exceptions create() member functions
// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
// false_type otherwise
template<typename BasicJsonContext>
struct is_basic_json_context
: std::integral_constant<bool,
is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value ||
std::is_same<BasicJsonContext, std::nullptr_t>::value>
struct is_basic_json_context :
std::integral_constant < bool,
is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
{};
//////////////////////
@@ -73,12 +70,10 @@ template<typename>
class json_ref;
template<typename>
struct is_json_ref : std::false_type
{};
struct is_json_ref : std::false_type {};
template<typename T>
struct is_json_ref<json_ref<T>> : std::true_type
{};
struct is_json_ref<json_ref<T>> : std::true_type {};
//////////////////////////
// aliases for detected //
@@ -116,61 +111,63 @@ using get_template_function = decltype(std::declval<T>().template get<U>());
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
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>
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>
struct has_from_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>>
struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;
static constexpr bool value = is_detected_exact<void, from_json_function, serializer, const BasicJsonType&, T&>::value;
static constexpr bool value =
is_detected_exact<void, from_json_function, serializer,
const BasicJsonType&, T&>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
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>
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<!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>;
static constexpr bool value = is_detected_exact<T, from_json_function, serializer, const BasicJsonType&>::value;
static constexpr bool value =
is_detected_exact<T, from_json_function, serializer,
const BasicJsonType&>::value;
};
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
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>
struct has_to_json<BasicJsonType, T, enable_if_t<!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>;
static constexpr bool value = is_detected_exact<void, to_json_function, serializer, BasicJsonType&, T>::value;
static constexpr bool value =
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
T>::value;
};
template<typename T>
using detect_key_compare = typename T::key_compare;
template<typename T>
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value>
{};
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
// obtains the actual object key comparator
template<typename BasicJsonType>
@@ -178,7 +175,8 @@ struct actual_object_comparator
{
using object_t = typename BasicJsonType::object_t;
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
using type = typename std::conditional<has_key_compare<object_t>::value, typename object_t::key_compare, object_comparator_t>::type;
using type = typename std::conditional < has_key_compare<object_t>::value,
typename object_t::key_compare, object_comparator_t>::type;
};
template<typename BasicJsonType>
@@ -246,67 +244,54 @@ struct char_traits<signed char> : std::char_traits<char>
///////////////////
// https://en.cppreference.com/w/cpp/types/conjunction
template<class...>
struct conjunction : std::true_type
{};
template<class B>
struct conjunction<B> : B
{};
template<class...> struct conjunction : std::true_type { };
template<class B> struct conjunction<B> : B { };
template<class B, class... Bn>
struct conjunction<B, Bn...> : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type
{};
struct conjunction<B, Bn...>
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
// https://en.cppreference.com/w/cpp/types/negation
template<class B>
struct negation : std::integral_constant<bool, !B::value>
{};
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
template<typename T>
struct is_default_constructible : std::is_default_constructible<T>
{};
template <typename T>
struct is_default_constructible : std::is_default_constructible<T> {};
template<typename T1, typename T2>
struct is_default_constructible<std::pair<T1, T2>> : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
{};
template <typename T1, typename T2>
struct is_default_constructible<std::pair<T1, T2>>
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
template<typename T1, typename T2>
struct is_default_constructible<const std::pair<T1, T2>> : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
{};
template <typename T1, typename T2>
struct is_default_constructible<const std::pair<T1, T2>>
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
template<typename... Ts>
struct is_default_constructible<std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
{};
template <typename... Ts>
struct is_default_constructible<std::tuple<Ts...>>
: conjunction<is_default_constructible<Ts>...> {};
template<typename... Ts>
struct is_default_constructible<const std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
{};
template <typename... Ts>
struct is_default_constructible<const std::tuple<Ts...>>
: conjunction<is_default_constructible<Ts>...> {};
template<typename T, typename... Args>
struct is_constructible : std::is_constructible<T, Args...>
{};
template <typename T, typename... Args>
struct is_constructible : std::is_constructible<T, Args...> {};
template<typename T1, typename T2>
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>>
{};
template <typename T1, typename T2>
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
template<typename T1, typename T2>
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>>
{};
template <typename T1, typename T2>
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
template<typename... Ts>
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>>
{};
template <typename... Ts>
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
template<typename... Ts>
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>>
{};
template <typename... Ts>
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
template<typename T, typename = void>
struct is_iterator_traits : std::false_type
{};
struct is_iterator_traits : std::false_type {};
template<typename T>
struct is_iterator_traits<iterator_traits<T>>
@@ -315,9 +300,12 @@ struct is_iterator_traits<iterator_traits<T>>
using traits = iterator_traits<T>;
public:
static constexpr auto value = is_detected<value_type_t, traits>::value && is_detected<difference_type_t, traits>::value &&
is_detected<pointer_t, traits>::value && is_detected<iterator_category_t, traits>::value &&
is_detected<reference_t, traits>::value;
static constexpr auto value =
is_detected<value_type_t, traits>::value &&
is_detected<difference_type_t, traits>::value &&
is_detected<pointer_t, traits>::value &&
is_detected<iterator_category_t, traits>::value &&
is_detected<reference_t, traits>::value;
};
template<typename T>
@@ -332,7 +320,8 @@ struct is_range
// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
// and https://en.cppreference.com/w/cpp/iterator/sentinel_for
// but reimplementing these would be too much work, as a lot of other concepts are used underneath
static constexpr auto is_iterator_begin = is_iterator_traits<iterator_traits<iterator>>::value;
static constexpr auto is_iterator_begin =
is_iterator_traits<iterator_traits<iterator>>::value;
public:
static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
@@ -349,62 +338,73 @@ using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
// and is written by Xiang Fan who agreed to using it in this library.
template<typename T, typename = void>
struct is_complete_type : std::false_type
{};
struct is_complete_type : std::false_type {};
template<typename T>
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type
{};
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
template<typename BasicJsonType, typename CompatibleObjectType, typename = void>
struct is_compatible_object_type_impl : std::false_type
{};
template<typename BasicJsonType, typename CompatibleObjectType,
typename = void>
struct is_compatible_object_type_impl : std::false_type {};
template<typename BasicJsonType, typename CompatibleObjectType>
struct is_compatible_object_type_impl<
BasicJsonType,
CompatibleObjectType,
enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value && is_detected<key_type_t, CompatibleObjectType>::value>>
struct is_compatible_object_type_impl <
BasicJsonType, CompatibleObjectType,
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
is_detected<key_type_t, CompatibleObjectType>::value >>
{
using object_t = typename BasicJsonType::object_t;
// macOS's is_constructible does not play well with nonesuch...
static constexpr bool value = is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value &&
is_constructible<typename object_t::mapped_type, typename CompatibleObjectType::mapped_type>::value;
static constexpr bool value =
is_constructible<typename object_t::key_type,
typename CompatibleObjectType::key_type>::value &&
is_constructible<typename object_t::mapped_type,
typename CompatibleObjectType::mapped_type>::value;
};
template<typename BasicJsonType, typename CompatibleObjectType>
struct is_compatible_object_type : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType>
{};
struct is_compatible_object_type
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
template<typename BasicJsonType, typename ConstructibleObjectType, typename = void>
struct is_constructible_object_type_impl : std::false_type
{};
template<typename BasicJsonType, typename ConstructibleObjectType,
typename = void>
struct is_constructible_object_type_impl : std::false_type {};
template<typename BasicJsonType, typename ConstructibleObjectType>
struct is_constructible_object_type_impl<
BasicJsonType,
ConstructibleObjectType,
enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value && is_detected<key_type_t, ConstructibleObjectType>::value>>
struct is_constructible_object_type_impl <
BasicJsonType, ConstructibleObjectType,
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
is_detected<key_type_t, ConstructibleObjectType>::value >>
{
using object_t = typename BasicJsonType::object_t;
static constexpr bool value = (is_default_constructible<ConstructibleObjectType>::value &&
(std::is_move_assignable<ConstructibleObjectType>::value || std::is_copy_assignable<ConstructibleObjectType>::value) &&
(is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value &&
std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value)) ||
(has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value ||
has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value);
static constexpr bool value =
(is_default_constructible<ConstructibleObjectType>::value &&
(std::is_move_assignable<ConstructibleObjectType>::value ||
std::is_copy_assignable<ConstructibleObjectType>::value) &&
(is_constructible<typename ConstructibleObjectType::key_type,
typename object_t::key_type>::value &&
std::is_same <
typename object_t::mapped_type,
typename ConstructibleObjectType::mapped_type >::value)) ||
(has_from_json<BasicJsonType,
typename ConstructibleObjectType::mapped_type>::value ||
has_non_default_from_json <
BasicJsonType,
typename ConstructibleObjectType::mapped_type >::value);
};
template<typename BasicJsonType, typename ConstructibleObjectType>
struct is_constructible_object_type : is_constructible_object_type_impl<BasicJsonType, ConstructibleObjectType>
{};
struct is_constructible_object_type
: is_constructible_object_type_impl<BasicJsonType,
ConstructibleObjectType> {};
template<typename BasicJsonType, typename CompatibleStringType>
struct is_compatible_string_type
{
static constexpr auto value = is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
static constexpr auto value =
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
};
template<typename BasicJsonType, typename ConstructibleStringType>
@@ -417,164 +417,174 @@ struct is_constructible_string_type
using laundered_type = ConstructibleStringType;
#endif
static constexpr auto value = conjunction<is_constructible<laundered_type, typename BasicJsonType::string_t>,
is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, laundered_type>>::value;
static constexpr auto value =
conjunction <
is_constructible<laundered_type, typename BasicJsonType::string_t>,
is_detected_exact<typename BasicJsonType::string_t::value_type,
value_type_t, laundered_type >>::value;
};
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
struct is_compatible_array_type_impl : std::false_type
{};
struct is_compatible_array_type_impl : std::false_type {};
template<typename BasicJsonType, typename CompatibleArrayType>
struct is_compatible_array_type_impl<BasicJsonType,
CompatibleArrayType,
enable_if_t<is_detected<iterator_t, CompatibleArrayType>::value &&
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value>>
struct is_compatible_array_type_impl <
BasicJsonType, CompatibleArrayType,
enable_if_t <
is_detected<iterator_t, CompatibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
{
static constexpr bool value = is_constructible<BasicJsonType, range_value_t<CompatibleArrayType>>::value;
static constexpr bool value =
is_constructible<BasicJsonType,
range_value_t<CompatibleArrayType>>::value;
};
template<typename BasicJsonType, typename CompatibleArrayType>
struct is_compatible_array_type : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType>
{};
struct is_compatible_array_type
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
struct is_constructible_array_type_impl : std::false_type
{};
struct is_constructible_array_type_impl : std::false_type {};
template<typename BasicJsonType, typename ConstructibleArrayType>
struct is_constructible_array_type_impl<BasicJsonType,
ConstructibleArrayType,
enable_if_t<std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value>> : std::true_type
{};
struct is_constructible_array_type_impl <
BasicJsonType, ConstructibleArrayType,
enable_if_t<std::is_same<ConstructibleArrayType,
typename BasicJsonType::value_type>::value >>
: std::true_type {};
template<typename BasicJsonType, typename ConstructibleArrayType>
struct is_constructible_array_type_impl<
BasicJsonType,
ConstructibleArrayType,
enable_if_t<!std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value &&
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value && is_default_constructible<ConstructibleArrayType>::value &&
(std::is_move_assignable<ConstructibleArrayType>::value || std::is_copy_assignable<ConstructibleArrayType>::value) &&
is_detected<iterator_t, ConstructibleArrayType>::value &&
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value &&
is_detected<range_value_t, ConstructibleArrayType>::value &&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value &&
is_complete_type<detected_t<range_value_t, ConstructibleArrayType>>::value>>
struct is_constructible_array_type_impl <
BasicJsonType, ConstructibleArrayType,
enable_if_t < !std::is_same<ConstructibleArrayType,
typename BasicJsonType::value_type>::value&&
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
is_default_constructible<ConstructibleArrayType>::value&&
(std::is_move_assignable<ConstructibleArrayType>::value ||
std::is_copy_assignable<ConstructibleArrayType>::value)&&
is_detected<iterator_t, ConstructibleArrayType>::value&&
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
is_detected<range_value_t, ConstructibleArrayType>::value&&
// special case for types like std::filesystem::path whose iterator's value_type are themselves
// c.f. https://github.com/nlohmann/json/pull/3073
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
is_complete_type <
detected_t<range_value_t, ConstructibleArrayType >>::value >>
{
using value_type = range_value_t<ConstructibleArrayType>;
static constexpr bool value = std::is_same<value_type, typename BasicJsonType::array_t::value_type>::value ||
has_from_json<BasicJsonType, value_type>::value || has_non_default_from_json<BasicJsonType, value_type>::value;
static constexpr bool value =
std::is_same<value_type,
typename BasicJsonType::array_t::value_type>::value ||
has_from_json<BasicJsonType,
value_type>::value ||
has_non_default_from_json <
BasicJsonType,
value_type >::value;
};
template<typename BasicJsonType, typename ConstructibleArrayType>
struct is_constructible_array_type : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType>
{};
struct is_constructible_array_type
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
template<typename RealIntegerType, typename CompatibleNumberIntegerType, typename = void>
struct is_compatible_integer_type_impl : std::false_type
{};
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
typename = void>
struct is_compatible_integer_type_impl : std::false_type {};
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type_impl<RealIntegerType,
CompatibleNumberIntegerType,
enable_if_t<std::is_integral<RealIntegerType>::value && std::is_integral<CompatibleNumberIntegerType>::value &&
!std::is_same<bool, CompatibleNumberIntegerType>::value>>
struct is_compatible_integer_type_impl <
RealIntegerType, CompatibleNumberIntegerType,
enable_if_t < std::is_integral<RealIntegerType>::value&&
std::is_integral<CompatibleNumberIntegerType>::value&&
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value = is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value && CompatibleLimits::is_integer &&
RealLimits::is_signed == CompatibleLimits::is_signed;
static constexpr auto value =
is_constructible<RealIntegerType,
CompatibleNumberIntegerType>::value &&
CompatibleLimits::is_integer &&
RealLimits::is_signed == CompatibleLimits::is_signed;
};
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type : is_compatible_integer_type_impl<RealIntegerType, CompatibleNumberIntegerType>
{};
struct is_compatible_integer_type
: is_compatible_integer_type_impl<RealIntegerType,
CompatibleNumberIntegerType> {};
template<typename BasicJsonType, typename CompatibleType, typename = void>
struct is_compatible_type_impl : std::false_type
{};
struct is_compatible_type_impl: std::false_type {};
template<typename BasicJsonType, typename CompatibleType>
struct is_compatible_type_impl<BasicJsonType, CompatibleType, enable_if_t<is_complete_type<CompatibleType>::value>>
struct is_compatible_type_impl <
BasicJsonType, CompatibleType,
enable_if_t<is_complete_type<CompatibleType>::value >>
{
static constexpr bool value = has_to_json<BasicJsonType, CompatibleType>::value;
static constexpr bool value =
has_to_json<BasicJsonType, CompatibleType>::value;
};
template<typename BasicJsonType, typename CompatibleType>
struct is_compatible_type : is_compatible_type_impl<BasicJsonType, CompatibleType>
{};
struct is_compatible_type
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
template<typename T1, typename T2>
struct is_constructible_tuple : std::false_type
{};
struct is_constructible_tuple : std::false_type {};
template<typename T1, typename... Args>
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...>
{};
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
template<typename BasicJsonType, typename T>
struct is_json_iterator_of : std::false_type
{};
struct is_json_iterator_of : std::false_type {};
template<typename BasicJsonType>
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type
{};
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
template<typename BasicJsonType>
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
{};
// checks if a given type T is a template specialization of Primary
template<template<typename...> class Primary, typename T>
struct is_specialization_of : std::false_type
{};
template<template <typename...> class Primary, typename T>
struct is_specialization_of : std::false_type {};
template<template<typename...> class Primary, typename... Args>
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type
{};
template<template <typename...> class Primary, typename... Args>
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
template<typename T>
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
// checks if A and B are comparable using Compare functor
template<typename Compare, typename A, typename B, typename = void>
struct is_comparable : std::false_type
{};
struct is_comparable : std::false_type {};
template<typename Compare, typename A, typename B>
struct is_comparable<
Compare,
A,
B,
void_t<decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>>
: std::true_type
{};
struct is_comparable<Compare, A, B, void_t<
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
>> : std::true_type {};
template<typename T>
using detect_is_transparent = typename T::is_transparent;
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
// see is_usable_as_basic_json_key_type below
template<typename Comparator,
typename ObjectKeyType,
typename KeyTypeCVRef,
bool RequireTransparentComparator = true,
bool ExcludeObjectKeyType = RequireTransparentComparator,
typename KeyType = uncvref_t<KeyTypeCVRef>>
using is_usable_as_key_type =
typename std::conditional<is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value &&
!(ExcludeObjectKeyType && std::is_same<KeyType, ObjectKeyType>::value) &&
(!RequireTransparentComparator || is_detected<detect_is_transparent, Comparator>::value) && !is_json_pointer<KeyType>::value,
template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
using is_usable_as_key_type = typename std::conditional <
is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
ObjectKeyType>::value)
&& (!RequireTransparentComparator
|| is_detected <detect_is_transparent, Comparator>::value)
&& !is_json_pointer<KeyType>::value,
std::true_type,
std::false_type>::type;
std::false_type >::type;
// type trait to check if KeyType can be used as object key
// true if:
@@ -582,53 +592,48 @@ using is_usable_as_key_type =
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
// - the comparator is transparent or RequireTransparentComparator is false
// - KeyType is not a JSON iterator or json_pointer
template<typename BasicJsonType,
typename KeyTypeCVRef,
bool RequireTransparentComparator = true,
bool ExcludeObjectKeyType = RequireTransparentComparator,
typename KeyType = uncvref_t<KeyTypeCVRef>>
using is_usable_as_basic_json_key_type = typename std::conditional<is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
typename BasicJsonType::object_t::key_type,
KeyTypeCVRef,
RequireTransparentComparator,
ExcludeObjectKeyType>::value &&
!is_json_iterator_of<BasicJsonType, KeyType>::value,
std::true_type,
std::false_type>::type;
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
using is_usable_as_basic_json_key_type = typename std::conditional <
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
RequireTransparentComparator, ExcludeObjectKeyType>::value
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
std::true_type,
std::false_type >::type;
template<typename ObjectType, typename KeyType>
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
// type trait to check if object_t has an erase() member functions accepting KeyType
template<typename BasicJsonType, typename KeyType>
using has_erase_with_key_type =
typename std::conditional<is_detected<detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType>::value, std::true_type, std::false_type>::type;
using has_erase_with_key_type = typename std::conditional <
is_detected <
detect_erase_with_key_type,
typename BasicJsonType::object_t, KeyType >::value,
std::true_type,
std::false_type >::type;
// a naive helper to check if a type is an ordered_map (exploits the fact that
// ordered_map inherits capacity() from std::vector)
template<typename T>
template <typename T>
struct is_ordered_map
{
using one = char;
struct two
{
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
};
template<typename C>
static one test(decltype(&C::capacity));
template<typename C>
static two test(...);
template <typename C> static one test( decltype(&C::capacity) ) ;
template <typename C> static two test(...);
enum
{
value = sizeof(test<T>(nullptr)) == sizeof(char)
}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
};
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
template<typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0>
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
T conditional_static_cast(U value)
{
return static_cast<T>(value);
@@ -651,14 +656,17 @@ using all_unsigned = conjunction<std::is_unsigned<Types>...>;
// there's a disjunction trait in another PR; replace when merged
template<typename... Types>
using same_sign = std::integral_constant<bool, all_signed<Types...>::value || all_unsigned<Types...>::value>;
using same_sign = std::integral_constant < bool,
all_signed<Types...>::value || all_unsigned<Types...>::value >;
template<typename OfType, typename T>
using never_out_of_range =
std::integral_constant<bool,
(std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T))>;
using never_out_of_range = std::integral_constant < bool,
(std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
|| (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
template<typename OfType, typename T, bool OfTypeSigned = std::is_signed<OfType>::value, bool TSigned = std::is_signed<T>::value>
template<typename OfType, typename T,
bool OfTypeSigned = std::is_signed<OfType>::value,
bool TSigned = std::is_signed<T>::value>
struct value_in_range_of_impl2;
template<typename OfType, typename T>
@@ -697,13 +705,12 @@ struct value_in_range_of_impl2<OfType, T, true, true>
static constexpr bool test(T val)
{
using CommonType = typename std::common_type<OfType, T>::type;
return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) &&
static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
&& static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
}
};
template<typename OfType,
typename T,
template<typename OfType, typename T,
bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
typename = detail::enable_if_t<all_integral<OfType, T>::value>>
struct value_in_range_of_impl1;
@@ -727,7 +734,7 @@ struct value_in_range_of_impl1<OfType, T, true>
};
template<typename OfType, typename T>
inline constexpr bool value_in_range_of(T val)
constexpr bool value_in_range_of(T val)
{
return value_in_range_of_impl1<OfType, T>::test(val);
}
@@ -743,21 +750,22 @@ namespace impl
{
template<typename T>
inline constexpr bool is_c_string()
constexpr bool is_c_string()
{
using TUnExt = typename std::remove_extent<T>::type;
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
using TUnPtr = typename std::remove_pointer<T>::type;
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
return (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
return
(std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
|| (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
}
} // namespace impl
// checks whether T is a [cv] char */[cv] char[] C string
template<typename T>
struct is_c_string : bool_constant<impl::is_c_string<T>()>
{};
struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
template<typename T>
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
@@ -770,7 +778,7 @@ namespace impl
{
template<typename T>
inline constexpr bool is_transparent()
constexpr bool is_transparent()
{
return is_detected<detect_is_transparent, T>::value;
}
@@ -779,8 +787,7 @@ inline constexpr bool is_transparent()
// checks whether T has a member named is_transparent
template<typename T>
struct is_transparent : bool_constant<impl::is_transparent<T>()>
{};
struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
///////////////////////////////////////////////////////////////////////////////
+2 -4
View File
@@ -14,13 +14,11 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
template<typename... Ts>
struct make_void
template<typename ...Ts> struct make_void
{
using type = void;
};
template<typename... Ts>
using void_t = typename make_void<Ts...>::type;
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
} // namespace detail
NLOHMANN_JSON_NAMESPACE_END
+179 -132
View File
@@ -8,16 +8,16 @@
#pragma once
#include <algorithm> // reverse
#include <array> // array
#include <cmath> // isnan, isinf
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <cstring> // memcpy
#include <limits> // numeric_limits
#include <map> // map
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <algorithm> // reverse
#include <array> // array
#include <map> // map
#include <cmath> // isnan, isinf
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <cstring> // memcpy
#include <limits> // numeric_limits
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/input/binary_reader.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@@ -48,8 +48,7 @@ class binary_writer
@param[in] adapter output adapter to write to
*/
explicit binary_writer(output_adapter_t<CharType> adapter)
: oa(std::move(adapter))
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
{
JSON_ASSERT(oa);
}
@@ -99,7 +98,9 @@ class binary_writer
case value_t::boolean:
{
oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4));
oa->write_character(j.m_data.m_value.boolean
? to_char_type(0xF5)
: to_char_type(0xF4));
break;
}
@@ -252,7 +253,9 @@ class binary_writer
// LCOV_EXCL_STOP
// step 2: write the string
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
@@ -351,7 +354,9 @@ class binary_writer
// LCOV_EXCL_STOP
// step 2: write each element
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
N);
break;
}
@@ -409,15 +414,17 @@ class binary_writer
{
switch (j.type())
{
case value_t::null: // nil
case value_t::null: // nil
{
oa->write_character(to_char_type(0xC0));
break;
}
case value_t::boolean: // true and false
case value_t::boolean: // true and false
{
oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2));
oa->write_character(j.m_data.m_value.boolean
? to_char_type(0xC3)
: to_char_type(0xC2));
break;
}
@@ -566,7 +573,9 @@ class binary_writer
}
// step 2: write the string
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
@@ -603,7 +612,7 @@ class binary_writer
case value_t::binary:
{
// step 0: determine if the binary type has a set subtype to
// determine whether or not to use the ext or fixext types
// determine whether to use the ext or fixext types
const bool use_ext = j.m_data.m_value.binary->has_subtype();
// step 1: write control byte and the byte string length
@@ -617,29 +626,30 @@ class binary_writer
switch (N)
{
case 1:
output_type = 0xD4; // fixext 1
output_type = 0xD4; // fixext 1
break;
case 2:
output_type = 0xD5; // fixext 2
output_type = 0xD5; // fixext 2
break;
case 4:
output_type = 0xD6; // fixext 4
output_type = 0xD6; // fixext 4
break;
case 8:
output_type = 0xD7; // fixext 8
output_type = 0xD7; // fixext 8
break;
case 16:
output_type = 0xD8; // fixext 16
output_type = 0xD8; // fixext 16
break;
default:
output_type = 0xC7; // ext 8
output_type = 0xC7; // ext 8
fixed = false;
break;
}
}
else
{
output_type = 0xC4; // bin 8
output_type = 0xC4; // bin 8
fixed = false;
}
@@ -651,16 +661,18 @@ class binary_writer
}
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
const std::uint8_t output_type = use_ext ? 0xC8 // ext 16
: 0xC5; // bin 16
const std::uint8_t output_type = use_ext
? 0xC8 // ext 16
: 0xC5; // bin 16
oa->write_character(to_char_type(output_type));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
const std::uint8_t output_type = use_ext ? 0xC9 // ext 32
: 0xC6; // bin 32
const std::uint8_t output_type = use_ext
? 0xC9 // ext 32
: 0xC6; // bin 32
oa->write_character(to_char_type(output_type));
write_number(static_cast<std::uint32_t>(N));
@@ -673,7 +685,9 @@ class binary_writer
}
// step 2: write the byte string
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
N);
break;
}
@@ -722,7 +736,9 @@ class binary_writer
@param[in] add_prefix whether prefixes need to be used for this value
@param[in] use_bjdata whether write in BJData format, default is false
*/
void write_ubjson(const BasicJsonType& j, const bool use_count, const bool use_type, const bool add_prefix = true, const bool use_bjdata = false)
void write_ubjson(const BasicJsonType& j, const bool use_count,
const bool use_type, const bool add_prefix = true,
const bool use_bjdata = false)
{
switch (j.type())
{
@@ -739,7 +755,9 @@ class binary_writer
{
if (add_prefix)
{
oa->write_character(j.m_data.m_value.boolean ? to_char_type('T') : to_char_type('F'));
oa->write_character(j.m_data.m_value.boolean
? to_char_type('T')
: to_char_type('F'));
}
break;
}
@@ -769,7 +787,9 @@ class binary_writer
oa->write_character(to_char_type('S'));
}
write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
@@ -785,11 +805,13 @@ class binary_writer
{
JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin() + 1, j.end(), [this, first_prefix, use_bjdata](const BasicJsonType& v) {
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix, use_bjdata](const BasicJsonType & v)
{
return ubjson_prefix(v, use_bjdata) == first_prefix;
});
std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
{
@@ -840,7 +862,9 @@ class binary_writer
if (use_type)
{
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), j.m_data.m_value.binary->size());
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
j.m_data.m_value.binary->size());
}
else
{
@@ -861,13 +885,9 @@ class binary_writer
case value_t::object:
{
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() &&
j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() &&
j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
{
if (!write_bjdata_ndarray(*j.m_data.m_value.object,
use_count,
use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
{
break;
}
@@ -883,11 +903,13 @@ class binary_writer
{
JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin(), j.end(), [this, first_prefix, use_bjdata](const BasicJsonType& v) {
const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix, use_bjdata](const BasicJsonType & v)
{
return ubjson_prefix(v, use_bjdata) == first_prefix;
});
std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
{
@@ -906,7 +928,9 @@ class binary_writer
for (const auto& el : *j.m_data.m_value.object)
{
write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
oa->write_characters(reinterpret_cast<const CharType*>(el.first.c_str()), el.first.size());
oa->write_characters(
reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size());
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
}
@@ -942,22 +966,26 @@ class binary_writer
static_cast<void>(j);
}
return /*id*/ 1ul + name.size() + /*zero-terminator*/ 1u;
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
}
/*!
@brief Writes the given @a element_type and @a name to the output adapter
*/
void write_bson_entry_header(const string_t& name, const std::uint8_t element_type)
void write_bson_entry_header(const string_t& name,
const std::uint8_t element_type)
{
oa->write_character(to_char_type(element_type)); // boolean
oa->write_characters(reinterpret_cast<const CharType*>(name.c_str()), name.size() + 1u);
oa->write_character(to_char_type(element_type)); // boolean
oa->write_characters(
reinterpret_cast<const CharType*>(name.c_str()),
name.size() + 1u);
}
/*!
@brief Writes a BSON element with key @a name and boolean value @a value
*/
void write_bson_boolean(const string_t& name, const bool value)
void write_bson_boolean(const string_t& name,
const bool value)
{
write_bson_entry_header(name, 0x08);
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
@@ -966,7 +994,8 @@ class binary_writer
/*!
@brief Writes a BSON element with key @a name and double value @a value
*/
void write_bson_double(const string_t& name, const double value)
void write_bson_double(const string_t& name,
const double value)
{
write_bson_entry_header(name, 0x01);
write_number<double>(value, true);
@@ -983,12 +1012,15 @@ class binary_writer
/*!
@brief Writes a BSON element with key @a name and string value @a value
*/
void write_bson_string(const string_t& name, const string_t& value)
void write_bson_string(const string_t& name,
const string_t& value)
{
write_bson_entry_header(name, 0x02);
write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
oa->write_characters(reinterpret_cast<const CharType*>(value.c_str()), value.size() + 1);
oa->write_characters(
reinterpret_cast<const CharType*>(value.c_str()),
value.size() + 1);
}
/*!
@@ -1004,23 +1036,25 @@ class binary_writer
*/
static std::size_t calc_bson_integer_size(const std::int64_t value)
{
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() ? sizeof(std::int32_t)
: sizeof(std::int64_t);
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
? sizeof(std::int32_t)
: sizeof(std::int64_t);
}
/*!
@brief Writes a BSON element with key @a name and integer @a value
*/
void write_bson_integer(const string_t& name, const std::int64_t value)
void write_bson_integer(const string_t& name,
const std::int64_t value)
{
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>(static_cast<std::int32_t>(value), true);
}
else
{
write_bson_entry_header(name, 0x12); // int64
write_bson_entry_header(name, 0x12); // int64
write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
}
}
@@ -1030,13 +1064,16 @@ class binary_writer
*/
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
{
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) ? sizeof(std::int32_t) : sizeof(std::int64_t);
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
? sizeof(std::int32_t)
: sizeof(std::int64_t);
}
/*!
@brief Writes a BSON element with key @a name and unsigned @a value
*/
void write_bson_unsigned(const string_t& name, const BasicJsonType& j)
void write_bson_unsigned(const string_t& name,
const BasicJsonType& j)
{
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
@@ -1050,19 +1087,17 @@ class binary_writer
}
else
{
JSON_THROW(out_of_range::create(
407,
concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"),
&j));
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
}
}
/*!
@brief Writes a BSON element with key @a name and object @a value
*/
void write_bson_object_entry(const string_t& name, const typename BasicJsonType::object_t& value)
void write_bson_object_entry(const string_t& name,
const typename BasicJsonType::object_t& value)
{
write_bson_entry_header(name, 0x03); // object
write_bson_entry_header(name, 0x03); // object
write_bson_object(value);
}
@@ -1073,12 +1108,10 @@ class binary_writer
{
std::size_t array_index = 0ul;
const std::size_t embedded_document_size = std::accumulate(std::begin(value),
std::end(value),
static_cast<std::size_t>(0),
[&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type& el) {
return result + calc_bson_element_size(std::to_string(array_index++), el);
});
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
{
return result + calc_bson_element_size(std::to_string(array_index++), el);
});
return sizeof(std::int32_t) + embedded_document_size + 1ul;
}
@@ -1094,9 +1127,10 @@ class binary_writer
/*!
@brief Writes a BSON element with key @a name and array @a value
*/
void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value)
void write_bson_array(const string_t& name,
const typename BasicJsonType::array_t& value)
{
write_bson_entry_header(name, 0x04); // array
write_bson_entry_header(name, 0x04); // array
write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
std::size_t array_index = 0ul;
@@ -1112,7 +1146,8 @@ class binary_writer
/*!
@brief Writes a BSON element with key @a name and binary value @a value
*/
void write_bson_binary(const string_t& name, const binary_t& value)
void write_bson_binary(const string_t& name,
const binary_t& value)
{
write_bson_entry_header(name, 0x05);
@@ -1126,7 +1161,8 @@ class binary_writer
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
@return The calculated size for the BSON document entry for @a j with the given @a name.
*/
static std::size_t calc_bson_element_size(const string_t& name, const BasicJsonType& j)
static std::size_t calc_bson_element_size(const string_t& name,
const BasicJsonType& j)
{
const auto header_size = calc_bson_entry_header_size(name, j);
switch (j.type())
@@ -1161,7 +1197,7 @@ class binary_writer
// LCOV_EXCL_START
case value_t::discarded:
default:
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
return 0ul;
// LCOV_EXCL_STOP
}
@@ -1173,7 +1209,8 @@ class binary_writer
@param name The name to associate with the JSON entity @a j within the
current BSON document
*/
void write_bson_element(const string_t& name, const BasicJsonType& j)
void write_bson_element(const string_t& name,
const BasicJsonType& j)
{
switch (j.type())
{
@@ -1207,7 +1244,7 @@ class binary_writer
// LCOV_EXCL_START
case value_t::discarded:
default:
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
return;
// LCOV_EXCL_STOP
}
@@ -1221,10 +1258,11 @@ class binary_writer
*/
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
{
const std::size_t document_size =
std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), [](size_t result, const typename BasicJsonType::object_t::value_type& el) {
return result += calc_bson_element_size(el.first, el.second);
});
const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
{
return result += calc_bson_element_size(el.first, el.second);
});
return sizeof(std::int32_t) + document_size + 1ul;
}
@@ -1278,8 +1316,11 @@ class binary_writer
////////////
// UBJSON: write number (floating point)
template<typename NumberType, typename std::enable_if<std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
template<typename NumberType, typename std::enable_if<
std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix,
const bool use_bjdata)
{
if (add_prefix)
{
@@ -1289,8 +1330,11 @@ class binary_writer
}
// UBJSON: write number (unsigned integer)
template<typename NumberType, typename std::enable_if<std::is_unsigned<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
template<typename NumberType, typename std::enable_if<
std::is_unsigned<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix,
const bool use_bjdata)
{
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
@@ -1373,8 +1417,12 @@ class binary_writer
}
// UBJSON: write number (signed integer)
template<typename NumberType, typename std::enable_if<std::is_signed<NumberType>::value && !std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
template < typename NumberType, typename std::enable_if <
std::is_signed<NumberType>::value&&
!std::is_floating_point<NumberType>::value, int >::type = 0 >
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix,
const bool use_bjdata)
{
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
{
@@ -1384,8 +1432,7 @@ class binary_writer
}
write_number(static_cast<std::int8_t>(n), use_bjdata);
}
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)()))
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)
{
@@ -1401,8 +1448,7 @@ class binary_writer
}
write_number(static_cast<std::int16_t>(n), use_bjdata);
}
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n &&
n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
{
if (add_prefix)
{
@@ -1418,8 +1464,7 @@ class binary_writer
}
write_number(static_cast<std::int32_t>(n), use_bjdata);
}
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n &&
n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
{
if (add_prefix)
{
@@ -1468,43 +1513,36 @@ class binary_writer
case value_t::number_integer:
{
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
{
return 'i';
}
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
{
return 'U';
}
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
{
return 'I';
}
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
{
return 'u';
}
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
{
return 'l';
}
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
{
return 'm';
}
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
{
return 'L';
}
// anything else is treated as high-precision number
return 'H'; // LCOV_EXCL_LINE
return 'H'; // LCOV_EXCL_LINE
}
case value_t::number_unsigned:
@@ -1542,7 +1580,7 @@ class binary_writer
return 'M';
}
// anything else is treated as high-precision number
return 'H'; // LCOV_EXCL_LINE
return 'H'; // LCOV_EXCL_LINE
}
case value_t::number_float:
@@ -1551,7 +1589,7 @@ class binary_writer
case value_t::string:
return 'S';
case value_t::array: // fallthrough
case value_t::array: // fallthrough
case value_t::binary:
return '[';
@@ -1579,8 +1617,9 @@ class binary_writer
*/
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
{
std::map<string_t, CharType> bjdtype = { { "uint8", 'U' }, { "int8", 'i' }, { "uint16", 'u' }, { "int16", 'I' }, { "uint32", 'm' }, { "int32", 'l' },
{ "uint64", 'M' }, { "int64", 'L' }, { "single", 'd' }, { "double", 'D' }, { "char", 'C' } };
std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
};
string_t key = "_ArrayType_";
auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
@@ -1609,7 +1648,7 @@ class binary_writer
oa->write_character('#');
key = "_ArraySize_";
write_ubjson(value.at(key), use_count, use_type, true, true);
write_ubjson(value.at(key), use_count, use_type, true, true);
key = "_ArrayData_";
if (dtype == 'U' || dtype == 'C')
@@ -1722,24 +1761,27 @@ class binary_writer
void write_compact_float(const number_float_t n, detail::input_format_t format)
{
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
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))
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)));
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));
oa->write_character(format == detail::input_format_t::cbor
? get_cbor_float_prefix(n)
: get_msgpack_float_prefix(n));
write_number(n);
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
}
@@ -1748,13 +1790,15 @@ class binary_writer
// between uint8_t and CharType. In case CharType is not unsigned,
// such a conversion is required to allow values greater than 128.
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value>* = nullptr>
template < typename C = CharType,
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
{
return *reinterpret_cast<char*>(&x);
}
template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_unsigned<char>::value>* = nullptr>
template < typename C = CharType,
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_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
@@ -1764,16 +1808,19 @@ class binary_writer
return result;
}
template<typename C = CharType, enable_if_t<std::is_unsigned<C>::value>* = nullptr>
template<typename C = CharType,
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
static constexpr CharType to_char_type(std::uint8_t x) noexcept
{
return x;
}
template<typename InputCharType,
typename C = CharType,
enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value && std::is_same<char, typename std::remove_cv<InputCharType>::type>::value>* =
nullptr>
template < typename InputCharType, typename C = CharType,
enable_if_t <
std::is_signed<C>::value &&
std::is_signed<char>::value &&
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
> * = nullptr >
static constexpr CharType to_char_type(InputCharType x) noexcept
{
return x;
@@ -8,17 +8,17 @@
#pragma once
#include <algorithm> // copy
#include <cstddef> // size_t
#include <iterator> // back_inserter
#include <memory> // shared_ptr, make_shared
#include <string> // basic_string
#include <vector> // vector
#include <algorithm> // copy
#include <cstddef> // size_t
#include <iterator> // back_inserter
#include <memory> // shared_ptr, make_shared
#include <string> // basic_string
#include <vector> // vector
#ifndef JSON_NO_IO
#include <ios> // streamsize
#include <ostream> // basic_ostream
#endif // JSON_NO_IO
#endif // JSON_NO_IO
#include <nlohmann/detail/macro_scope.hpp>
@@ -27,8 +27,7 @@ namespace detail
{
/// abstract output adapter interface
template<typename CharType>
struct output_adapter_protocol
template<typename CharType> struct output_adapter_protocol
{
virtual void write_character(CharType c) = 0;
virtual void write_characters(const CharType* s, std::size_t length) = 0;
@@ -51,7 +50,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
{
public:
explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
: v(vec)
: v(vec)
{}
void write_character(CharType c) override
@@ -76,7 +75,7 @@ class output_stream_adapter : public output_adapter_protocol<CharType>
{
public:
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
: stream(s)
: stream(s)
{}
void write_character(CharType c) override
@@ -101,7 +100,7 @@ class output_string_adapter : public output_adapter_protocol<CharType>
{
public:
explicit output_string_adapter(StringType& s) noexcept
: str(s)
: str(s)
{}
void write_character(CharType c) override
@@ -125,18 +124,15 @@ class output_adapter
public:
template<typename AllocatorType = std::allocator<CharType>>
output_adapter(std::vector<CharType, AllocatorType>& vec)
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec))
{}
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
#ifndef JSON_NO_IO
output_adapter(std::basic_ostream<CharType>& s)
: oa(std::make_shared<output_stream_adapter<CharType>>(s))
{}
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
#endif // JSON_NO_IO
output_adapter(StringType& s)
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s))
{}
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
operator output_adapter_t<CharType>()
{
+117 -116
View File
@@ -9,18 +9,18 @@
#pragma once
#include <algorithm> // reverse, remove, fill, find, none_of
#include <array> // array
#include <clocale> // localeconv, lconv
#include <cmath> // labs, isfinite, isnan, signbit
#include <cstddef> // size_t, ptrdiff_t
#include <cstdint> // uint8_t
#include <cstdio> // snprintf
#include <iomanip> // setfill, setw
#include <limits> // numeric_limits
#include <string> // string, char_traits
#include <type_traits> // is_same
#include <utility> // move
#include <algorithm> // reverse, remove, fill, find, none_of
#include <array> // array
#include <clocale> // localeconv, lconv
#include <cmath> // labs, isfinite, isnan, signbit
#include <cstddef> // size_t, ptrdiff_t
#include <cstdint> // uint8_t
#include <cstdio> // snprintf
#include <limits> // numeric_limits
#include <string> // string, char_traits
#include <iomanip> // setfill, setw
#include <type_traits> // is_same
#include <utility> // move
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/exceptions.hpp>
@@ -42,9 +42,9 @@ namespace detail
/// how to treat decoding errors
enum class error_handler_t
{
strict, ///< throw a type_error exception in case of invalid UTF-8
replace, ///< replace invalid UTF-8 sequences with U+FFFD
ignore ///< ignore invalid UTF-8 sequences
strict, ///< throw a type_error exception in case of invalid UTF-8
replace, ///< replace invalid UTF-8 sequences with U+FFFD
ignore ///< ignore invalid UTF-8 sequences
};
template<typename BasicJsonType>
@@ -64,14 +64,15 @@ class serializer
@param[in] ichar indentation character to use
@param[in] error_handler_ how to react on decoding errors
*/
serializer(output_adapter_t<char> s, const char ichar, error_handler_t error_handler_ = error_handler_t::strict)
: o(std::move(s))
, loc(std::localeconv())
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->thousands_sep)))
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->decimal_point)))
, indent_char(ichar)
, indent_string(512, indent_char)
, error_handler(error_handler_)
serializer(output_adapter_t<char> s, const char ichar,
error_handler_t error_handler_ = error_handler_t::strict)
: o(std::move(s))
, loc(std::localeconv())
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
, indent_char(ichar)
, indent_string(512, indent_char)
, error_handler(error_handler_)
{}
// delete because of pointer members
@@ -103,7 +104,11 @@ class serializer
@param[in] indent_step the indent level
@param[in] current_indent the current indent level (only used internally)
*/
void dump(const BasicJsonType& val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent = 0)
void dump(const BasicJsonType& val,
const bool pretty_print,
const bool ensure_ascii,
const unsigned int indent_step,
const unsigned int current_indent = 0)
{
switch (val.m_data.m_type)
{
@@ -200,7 +205,8 @@ class serializer
}
// first n-1 elements
for (auto i = val.m_data.m_value.array->cbegin(); i != val.m_data.m_value.array->cend() - 1; ++i)
for (auto i = val.m_data.m_value.array->cbegin();
i != val.m_data.m_value.array->cend() - 1; ++i)
{
o->write_characters(indent_string.c_str(), new_indent);
dump(*i, true, ensure_ascii, indent_step, new_indent);
@@ -221,7 +227,8 @@ class serializer
o->write_character('[');
// first n-1 elements
for (auto i = val.m_data.m_value.array->cbegin(); i != val.m_data.m_value.array->cend() - 1; ++i)
for (auto i = val.m_data.m_value.array->cbegin();
i != val.m_data.m_value.array->cend() - 1; ++i)
{
dump(*i, false, ensure_ascii, indent_step, current_indent);
o->write_character(',');
@@ -264,7 +271,8 @@ class serializer
if (!val.m_data.m_value.binary->empty())
{
for (auto i = val.m_data.m_value.binary->cbegin(); i != val.m_data.m_value.binary->cend() - 1; ++i)
for (auto i = val.m_data.m_value.binary->cbegin();
i != val.m_data.m_value.binary->cend() - 1; ++i)
{
dump_integer(*i);
o->write_characters(", ", 2);
@@ -294,7 +302,8 @@ class serializer
if (!val.m_data.m_value.binary->empty())
{
for (auto i = val.m_data.m_value.binary->cbegin(); i != val.m_data.m_value.binary->cend() - 1; ++i)
for (auto i = val.m_data.m_value.binary->cbegin();
i != val.m_data.m_value.binary->cend() - 1; ++i)
{
dump_integer(*i);
o->write_character(',');
@@ -359,12 +368,12 @@ class serializer
return;
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
}
JSON_PRIVATE_UNLESS_TESTED :
JSON_PRIVATE_UNLESS_TESTED:
/*!
@brief dump escaped string
@@ -399,49 +408,49 @@ class serializer
{
switch (codepoint)
{
case 0x08: // backspace
case 0x08: // backspace
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = 'b';
break;
}
case 0x09: // horizontal tab
case 0x09: // horizontal tab
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = 't';
break;
}
case 0x0A: // newline
case 0x0A: // newline
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = 'n';
break;
}
case 0x0C: // formfeed
case 0x0C: // formfeed
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = 'f';
break;
}
case 0x0D: // carriage return
case 0x0D: // carriage return
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = 'r';
break;
}
case 0x22: // quotation mark
case 0x22: // quotation mark
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = '\"';
break;
}
case 0x5C: // reverse solidus
case 0x5C: // reverse solidus
{
string_buffer[bytes++] = '\\';
string_buffer[bytes++] = '\\';
@@ -457,15 +466,14 @@ class serializer
if (codepoint <= 0xFFFF)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", static_cast<std::uint16_t>(codepoint)));
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
static_cast<std::uint16_t>(codepoint)));
bytes += 6;
}
else
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
static_cast<void>((std::snprintf)(string_buffer.data() + bytes,
13,
"\\u%04x\\u%04x",
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
bytes += 12;
@@ -502,8 +510,7 @@ class serializer
{
case error_handler_t::strict:
{
JSON_THROW(
type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
}
case error_handler_t::ignore:
@@ -560,8 +567,8 @@ class serializer
break;
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
break;
}
@@ -595,8 +602,7 @@ class serializer
{
case error_handler_t::strict:
{
JSON_THROW(
type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
}
case error_handler_t::ignore:
@@ -622,8 +628,8 @@ class serializer
break;
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
}
}
}
@@ -637,7 +643,7 @@ class serializer
@param[in] x unsigned integer number to count its digits
@return number of decimal digits
*/
inline unsigned int count_digits(number_unsigned_t x) noexcept
unsigned int count_digits(number_unsigned_t x) noexcept
{
unsigned int n_digits = 1;
for (;;)
@@ -678,13 +684,13 @@ class serializer
}
// templates to avoid warnings about useless casts
template<typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
bool is_negative_number(NumberType x)
{
return x < 0;
}
template<typename NumberType, enable_if_t<std::is_unsigned<NumberType>::value, int> = 0>
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
bool is_negative_number(NumberType /*unused*/)
{
return false;
@@ -699,27 +705,29 @@ class serializer
@param[in] x integer number (signed or unsigned) to dump
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
*/
template<typename NumberType,
detail::enable_if_t<std::is_integral<NumberType>::value || std::is_same<NumberType, number_unsigned_t>::value ||
std::is_same<NumberType, number_integer_t>::value || std::is_same<NumberType, binary_char_t>::value,
int> = 0>
template < typename NumberType, detail::enable_if_t <
std::is_integral<NumberType>::value ||
std::is_same<NumberType, number_unsigned_t>::value ||
std::is_same<NumberType, number_integer_t>::value ||
std::is_same<NumberType, binary_char_t>::value,
int > = 0 >
void dump_integer(NumberType x)
{
static constexpr std::array<std::array<char, 2>, 100> digits_to_99{ {
{ { '0', '0' } }, { { '0', '1' } }, { { '0', '2' } }, { { '0', '3' } }, { { '0', '4' } }, { { '0', '5' } }, { { '0', '6' } }, { { '0', '7' } },
{ { '0', '8' } }, { { '0', '9' } }, { { '1', '0' } }, { { '1', '1' } }, { { '1', '2' } }, { { '1', '3' } }, { { '1', '4' } }, { { '1', '5' } },
{ { '1', '6' } }, { { '1', '7' } }, { { '1', '8' } }, { { '1', '9' } }, { { '2', '0' } }, { { '2', '1' } }, { { '2', '2' } }, { { '2', '3' } },
{ { '2', '4' } }, { { '2', '5' } }, { { '2', '6' } }, { { '2', '7' } }, { { '2', '8' } }, { { '2', '9' } }, { { '3', '0' } }, { { '3', '1' } },
{ { '3', '2' } }, { { '3', '3' } }, { { '3', '4' } }, { { '3', '5' } }, { { '3', '6' } }, { { '3', '7' } }, { { '3', '8' } }, { { '3', '9' } },
{ { '4', '0' } }, { { '4', '1' } }, { { '4', '2' } }, { { '4', '3' } }, { { '4', '4' } }, { { '4', '5' } }, { { '4', '6' } }, { { '4', '7' } },
{ { '4', '8' } }, { { '4', '9' } }, { { '5', '0' } }, { { '5', '1' } }, { { '5', '2' } }, { { '5', '3' } }, { { '5', '4' } }, { { '5', '5' } },
{ { '5', '6' } }, { { '5', '7' } }, { { '5', '8' } }, { { '5', '9' } }, { { '6', '0' } }, { { '6', '1' } }, { { '6', '2' } }, { { '6', '3' } },
{ { '6', '4' } }, { { '6', '5' } }, { { '6', '6' } }, { { '6', '7' } }, { { '6', '8' } }, { { '6', '9' } }, { { '7', '0' } }, { { '7', '1' } },
{ { '7', '2' } }, { { '7', '3' } }, { { '7', '4' } }, { { '7', '5' } }, { { '7', '6' } }, { { '7', '7' } }, { { '7', '8' } }, { { '7', '9' } },
{ { '8', '0' } }, { { '8', '1' } }, { { '8', '2' } }, { { '8', '3' } }, { { '8', '4' } }, { { '8', '5' } }, { { '8', '6' } }, { { '8', '7' } },
{ { '8', '8' } }, { { '8', '9' } }, { { '9', '0' } }, { { '9', '1' } }, { { '9', '2' } }, { { '9', '3' } }, { { '9', '4' } }, { { '9', '5' } },
{ { '9', '6' } }, { { '9', '7' } }, { { '9', '8' } }, { { '9', '9' } },
} };
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
{
{
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
}
};
// special case for "0"
if (x == 0)
@@ -729,7 +737,7 @@ class serializer
}
// use a pointer to fill the buffer
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
number_unsigned_t abs_value;
@@ -802,10 +810,9 @@ class serializer
// guaranteed to round-trip, using strtof and strtod, resp.
//
// NB: The test below works if <long double> == <double>.
static constexpr bool is_ieee_single_or_double = (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 && std::numeric_limits<number_float_t>::digits == 53 &&
std::numeric_limits<number_float_t>::max_exponent == 1024);
static constexpr bool is_ieee_single_or_double
= (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 && 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>());
}
@@ -856,7 +863,10 @@ class serializer
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
// determine if we need to append ".0"
const bool value_is_int_like = std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, [](char c) {
const bool value_is_int_like =
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
[](char c)
{
return c == '.' || c == 'e';
});
@@ -889,43 +899,34 @@ class serializer
*/
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
{
static const std::array<std::uint8_t, 400> utf8d = { {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 00..1F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 20..3F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 40..5F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // 60..7F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, // 80..9F
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, // A0..BF
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, // C0..DF
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
0x3, // E0..EF
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
0x8, // F0..FF
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1,
0x1, // s0..s0
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
1, // s1..s2
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, // s3..s4
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1,
1, // s5..s6
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1 // s7..s8
} };
static const std::array<std::uint8_t, 400> utf8d =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
}
};
JSON_ASSERT(byte < utf8d.size());
const std::uint8_t type = utf8d[byte];
codep = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte);
codep = (state != UTF8_ACCEPT)
? (byte & 0x3fu) | (codep << 6u)
: (0xFFu >> type) & (byte);
const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
JSON_ASSERT(index < utf8d.size());
state = utf8d[index];
return state;
@@ -938,8 +939,8 @@ class serializer
*/
number_unsigned_t remove_sign(number_unsigned_t x)
{
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return x; // LCOV_EXCL_LINE
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
return x; // LCOV_EXCL_LINE
}
/*
@@ -951,9 +952,9 @@ class serializer
* absolute values of INT_MIN and INT_MAX are usually not the same. See
* #1708 for details.
*/
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
number_unsigned_t remove_sign(number_integer_t x) noexcept
{
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
}
@@ -962,7 +963,7 @@ class serializer
output_adapter_t<char> o = nullptr;
/// a (hopefully) large enough character buffer
std::array<char, 64> number_buffer{ {} };
std::array<char, 64> number_buffer{{}};
/// the locale
const std::lconv* loc = nullptr;
@@ -972,7 +973,7 @@ class serializer
const char decimal_point = '\0';
/// string buffer
std::array<char, 512> string_buffer{ {} };
std::array<char, 512> string_buffer{{}};
/// the indentation character
const char indent_char;
+44 -51
View File
@@ -8,9 +8,9 @@
#pragma once
#include <cstring> // strlen
#include <string> // string
#include <utility> // forward
#include <cstring> // strlen
#include <string> // string
#include <utility> // forward
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/detected.hpp>
@@ -25,26 +25,26 @@ inline std::size_t concat_length()
}
template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args&... rest);
inline std::size_t concat_length(const char* cstr, const Args& ... rest);
template<typename StringType, typename... Args>
inline std::size_t concat_length(const StringType& str, const Args&... rest);
inline std::size_t concat_length(const StringType& str, const Args& ... rest);
template<typename... Args>
inline std::size_t concat_length(const char /*c*/, const Args&... rest)
inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
{
return 1 + concat_length(rest...);
}
template<typename... Args>
inline std::size_t concat_length(const char* cstr, const Args&... rest)
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
{
// cppcheck-suppress ignoredReturnValue
return ::strlen(cstr) + concat_length(rest...);
}
template<typename StringType, typename... Args>
inline std::size_t concat_length(const StringType& str, const Args&... rest)
inline std::size_t concat_length(const StringType& str, const Args& ... rest)
{
return str.size() + concat_length(rest...);
}
@@ -54,13 +54,13 @@ inline void concat_into(OutStringType& /*out*/)
{}
template<typename StringType, typename Arg>
using string_can_append = decltype(std::declval<StringType&>().append(std::declval<Arg&&>()));
using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
template<typename StringType, typename Arg>
using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
template<typename StringType, typename Arg>
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval<Arg&&>());
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
template<typename StringType, typename Arg>
using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
@@ -77,71 +77,64 @@ using string_can_append_data = decltype(std::declval<StringType&>().append(std::
template<typename StringType, typename Arg>
using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && detect_string_can_append_op<OutStringType, Arg>::value, int> = 0>
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest);
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
detect_string_can_append_iter<OutStringType, Arg>::value,
int> = 0>
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& !detect_string_can_append_op<OutStringType, Arg>::value
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
!detect_string_can_append_iter<OutStringType, Arg>::value && detect_string_can_append_data<OutStringType, Arg>::value,
int> = 0>
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& !detect_string_can_append_op<OutStringType, Arg>::value
&& !detect_string_can_append_iter<OutStringType, Arg>::value
&& detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
template<typename OutStringType, typename Arg, typename... Args, enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest)
template<typename OutStringType, typename Arg, typename... Args,
enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
{
out.append(std::forward<Arg>(arg));
concat_into(out, std::forward<Args>(rest)...);
}
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && detect_string_can_append_op<OutStringType, Arg>::value, int>>
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest)
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& detect_string_can_append_op<OutStringType, Arg>::value, int > >
inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
{
out += std::forward<Arg>(arg);
concat_into(out, std::forward<Args>(rest)...);
}
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
detect_string_can_append_iter<OutStringType, Arg>::value,
int>>
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest)
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& !detect_string_can_append_op<OutStringType, Arg>::value
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > >
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
{
out.append(arg.begin(), arg.end());
concat_into(out, std::forward<Args>(rest)...);
}
template<typename OutStringType,
typename Arg,
typename... Args,
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
!detect_string_can_append_iter<OutStringType, Arg>::value && detect_string_can_append_data<OutStringType, Arg>::value,
int>>
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest)
template < typename OutStringType, typename Arg, typename... Args,
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
&& !detect_string_can_append_op<OutStringType, Arg>::value
&& !detect_string_can_append_iter<OutStringType, Arg>::value
&& detect_string_can_append_data<OutStringType, Arg>::value, int > >
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
{
out.append(arg.data(), arg.size());
concat_into(out, std::forward<Args>(rest)...);
}
template<typename OutStringType = std::string, typename... Args>
inline OutStringType concat(Args&&... args)
inline OutStringType concat(Args && ... args)
{
OutStringType str;
str.reserve(concat_length(args...));
+10 -9
View File
@@ -28,13 +28,14 @@ enforced with an assertion.**
@since version 2.0.0
*/
template<typename StringType>
inline void replace_substring(StringType& s, const StringType& f, const StringType& t)
inline void replace_substring(StringType& s, const StringType& f,
const StringType& t)
{
JSON_ASSERT(!f.empty());
for (auto pos = s.find(f); // find first occurrence of f
pos != StringType::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t, and
pos = s.find(f, pos + t.size())) // find next occurrence of f
for (auto pos = s.find(f); // find first occurrence of f
pos != StringType::npos; // make sure f was found
s.replace(pos, f.size(), t), // replace with t, and
pos = s.find(f, pos + t.size())) // find next occurrence of f
{}
}
@@ -48,8 +49,8 @@ inline void replace_substring(StringType& s, const StringType& f, const StringTy
template<typename StringType>
inline StringType escape(StringType s)
{
replace_substring(s, StringType{ "~" }, StringType{ "~0" });
replace_substring(s, StringType{ "/" }, StringType{ "~1" });
replace_substring(s, StringType{"~"}, StringType{"~0"});
replace_substring(s, StringType{"/"}, StringType{"~1"});
return s;
}
@@ -63,8 +64,8 @@ inline StringType escape(StringType s)
template<typename StringType>
static void unescape(StringType& s)
{
replace_substring(s, StringType{ "~1" }, StringType{ "/" });
replace_substring(s, StringType{ "~0" }, StringType{ "~" });
replace_substring(s, StringType{"~1"}, StringType{"/"});
replace_substring(s, StringType{"~0"}, StringType{"~"});
}
} // namespace detail
+15 -20
View File
@@ -8,14 +8,14 @@
#pragma once
#include <array> // array
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <string> // string
#include <array> // array
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <string> // string
#include <nlohmann/detail/macro_scope.hpp>
#if JSON_HAS_THREE_WAY_COMPARISON
#include <compare> // partial_ordering
#include <compare> // partial_ordering
#endif
NLOHMANN_JSON_NAMESPACE_BEGIN
@@ -78,29 +78,24 @@ Returns an ordering that is similar to Python:
@since version 1.0.0
*/
#if JSON_HAS_THREE_WAY_COMPARISON
inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
#else
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
#endif
{
static constexpr std::array<std::uint8_t, 9> order = { {
0 /* null */,
3 /* object */,
4 /* array */,
5 /* string */,
1 /* boolean */,
2 /* integer */,
2 /* unsigned */,
2 /* float */,
6 /* binary */
} };
static constexpr std::array<std::uint8_t, 9> order = {{
0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
6 /* binary */
}
};
const auto l_index = static_cast<std::size_t>(lhs);
const auto r_index = static_cast<std::size_t>(rhs);
#if JSON_HAS_THREE_WAY_COMPARISON
if (l_index < order.size() && r_index < order.size())
{
return order[l_index] <=> order[r_index]; // *NOPAD*
return order[l_index] <=> order[r_index]; // *NOPAD*
}
return std::partial_ordering::unordered;
#else
@@ -115,7 +110,7 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
{
return std::is_lt(lhs <=> rhs); // *NOPAD*
return std::is_lt(lhs <=> rhs); // *NOPAD*
}
#endif
+693 -554
View File
File diff suppressed because it is too large Load Diff
+11 -10
View File
@@ -9,11 +9,11 @@
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
#include <nlohmann/detail/abi_macros.hpp>
@@ -36,16 +36,17 @@ struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType = std::map,
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string,
class BooleanType = bool,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
+58 -55
View File
@@ -8,14 +8,14 @@
#pragma once
#include <functional> // equal_to, less
#include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator
#include <stdexcept> // for out_of_range
#include <type_traits> // enable_if, is_convertible
#include <utility> // pair
#include <vector> // vector
#include <functional> // equal_to, less
#include <initializer_list> // initializer_list
#include <iterator> // input_iterator_tag, iterator_traits
#include <memory> // allocator
#include <stdexcept> // for out_of_range
#include <type_traits> // enable_if, is_convertible
#include <utility> // pair
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
@@ -24,8 +24,9 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
/// 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>
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;
@@ -42,19 +43,13 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
// Explicit constructors instead of `using Container::Container`
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
ordered_map() noexcept(noexcept(Container()))
: Container{}
{}
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc)))
: Container{ alloc }
{}
template<class It>
ordered_map() noexcept(noexcept(Container())) : Container{} {}
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
template <class It>
ordered_map(It first, It last, const Allocator& alloc = Allocator())
: Container{ first, last, alloc }
{}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator())
: Container{ init, alloc }
{}
: Container{first, last, alloc} {}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
@@ -62,25 +57,26 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
{
if (m_compare(it->first, key))
{
return { it, false };
return {it, false};
}
}
Container::emplace_back(key, std::forward<T>(t));
return { std::prev(this->end()), true };
return {std::prev(this->end()), true};
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
std::pair<iterator, bool> emplace(KeyType&& key, T&& t)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
std::pair<iterator, bool> emplace(KeyType && key, T && t)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (m_compare(it->first, key))
{
return { it, false };
return {it, false};
}
}
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
return { std::prev(this->end()), true };
return {std::prev(this->end()), true};
}
T& operator[](const key_type& key)
@@ -88,8 +84,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return emplace(key, T{}).first->second;
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
T& operator[](KeyType&& key)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
T & operator[](KeyType && key)
{
return emplace(std::forward<KeyType>(key), T{}).first->second;
}
@@ -99,8 +96,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return at(key);
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
const T& operator[](KeyType&& key) const
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
const T & operator[](KeyType && key) const
{
return at(std::forward<KeyType>(key));
}
@@ -118,8 +116,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
JSON_THROW(std::out_of_range("key not found"));
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
T& at(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
@@ -145,8 +144,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
JSON_THROW(std::out_of_range("key not found"));
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
const T& at(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
@@ -168,8 +168,8 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
// 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) };
it->~value_type(); // Destroy but keep allocation
new (&*it) value_type{std::move(*next)};
}
Container::pop_back();
return 1;
@@ -178,8 +178,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return 0;
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
size_type erase(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
@@ -188,8 +189,8 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
// 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) };
it->~value_type(); // Destroy but keep allocation
new (&*it) value_type{std::move(*next)};
}
Container::pop_back();
return 1;
@@ -235,8 +236,8 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
{
it->~value_type(); // destroy but keep allocation
new (&*it) value_type{ std::move(*std::next(it, elements_affected)) }; // "move" next element to it
it->~value_type(); // destroy but keep allocation
new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
}
// [ a, b, c, d, h, i, j, h, i, j ]
@@ -268,8 +269,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return 0;
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
size_type count(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
@@ -293,8 +295,9 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return Container::end();
}
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
iterator find(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
template<class KeyType, detail::enable_if_t<
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
{
for (auto it = this->begin(); it != this->end(); ++it)
{
@@ -318,27 +321,27 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
return Container::end();
}
std::pair<iterator, bool> insert(value_type&& value)
std::pair<iterator, bool> insert( value_type&& value )
{
return emplace(value.first, std::move(value.second));
}
std::pair<iterator, bool> insert(const value_type& value)
std::pair<iterator, bool> insert( const value_type& value )
{
for (auto it = this->begin(); it != this->end(); ++it)
{
if (m_compare(it->first, value.first))
{
return { it, false };
return {it, false};
}
}
Container::push_back(value);
return { --this->end(), true };
return {--this->end(), true};
}
template<typename InputIt>
using require_input_iter =
typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, std::input_iterator_tag>::value>::type;
using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
std::input_iterator_tag>::value>::type;
template<typename InputIt, typename = require_input_iter<InputIt>>
void insert(InputIt first, InputIt last)
@@ -349,7 +352,7 @@ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
}
}
private:
private:
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
};
File diff suppressed because it is too large Load Diff
+129 -129
View File
@@ -7,21 +7,21 @@
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<!-- Namespace nlohmann -->
<Type Name="nlohmann::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::detail::value_t::discarded">discarded</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
@@ -37,21 +37,21 @@
<!-- Namespace nlohmann::json_abi -->
<Type Name="nlohmann::json_abi::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi::detail::value_t::discarded">discarded</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
@@ -65,30 +65,30 @@
</Expand>
</Type>
<!-- Namespace nlohmann::json_abi_v3_11_2 -->
<Type Name="nlohmann::json_abi_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<!-- Namespace nlohmann::json_abi_v3_11_3 -->
<Type Name="nlohmann::json_abi_v3_11_3::basic_json&lt;*&gt;">
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_v3_11_3::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<Type Name="std::pair&lt;*, nlohmann::json_abi_v3_11_3::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
@@ -97,21 +97,21 @@
<!-- Namespace nlohmann::json_abi_diag -->
<Type Name="nlohmann::json_abi_diag::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag::detail::value_t::discarded">discarded</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
@@ -125,30 +125,30 @@
</Expand>
</Type>
<!-- Namespace nlohmann::json_abi_diag_v3_11_2 -->
<Type Name="nlohmann::json_abi_diag_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<!-- Namespace nlohmann::json_abi_diag_v3_11_3 -->
<Type Name="nlohmann::json_abi_diag_v3_11_3::basic_json&lt;*&gt;">
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_v3_11_3::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_v3_11_3::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
@@ -157,21 +157,21 @@
<!-- Namespace nlohmann::json_abi_ldvcmp -->
<Type Name="nlohmann::json_abi_ldvcmp::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_ldvcmp::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
@@ -185,30 +185,30 @@
</Expand>
</Type>
<!-- Namespace nlohmann::json_abi_ldvcmp_v3_11_2 -->
<Type Name="nlohmann::json_abi_ldvcmp_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<!-- Namespace nlohmann::json_abi_ldvcmp_v3_11_3 -->
<Type Name="nlohmann::json_abi_ldvcmp_v3_11_3::basic_json&lt;*&gt;">
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_ldvcmp_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_ldvcmp_v3_11_3::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_ldvcmp_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<Type Name="std::pair&lt;*, nlohmann::json_abi_ldvcmp_v3_11_3::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
@@ -217,21 +217,21 @@
<!-- Namespace nlohmann::json_abi_diag_ldvcmp -->
<Type Name="nlohmann::json_abi_diag_ldvcmp::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
@@ -245,30 +245,30 @@
</Expand>
</Type>
<!-- Namespace nlohmann::json_abi_diag_ldvcmp_v3_11_2 -->
<Type Name="nlohmann::json_abi_diag_ldvcmp_v3_11_2::basic_json&lt;*&gt;">
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::object">{*(m_value.object)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::array">{*(m_value.array)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::string">{*(m_value.string)}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::boolean">{m_value.boolean}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_integer">{m_value.number_integer}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_unsigned">{m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::number_float">{m_value.number_float}</DisplayString>
<DisplayString Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::discarded">discarded</DisplayString>
<!-- Namespace nlohmann::json_abi_diag_ldvcmp_v3_11_3 -->
<Type Name="nlohmann::json_abi_diag_ldvcmp_v3_11_3::basic_json&lt;*&gt;">
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::null">null</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::object">{*(m_data.m_value.object)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::array">{*(m_data.m_value.array)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::string">{*(m_data.m_value.string)}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::boolean">{m_data.m_value.boolean}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::number_integer">{m_data.m_value.number_integer}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::number_unsigned">{m_data.m_value.number_unsigned}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::number_float">{m_data.m_value.number_float}</DisplayString>
<DisplayString Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::discarded">discarded</DisplayString>
<Expand>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::object">
*(m_value.object),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::object">
*(m_data.m_value.object),view(simple)
</ExpandedItem>
<ExpandedItem Condition="m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_2::detail::value_t::array">
*(m_value.array),view(simple)
<ExpandedItem Condition="m_data.m_type == nlohmann::json_abi_diag_ldvcmp_v3_11_3::detail::value_t::array">
*(m_data.m_value.array),view(simple)
</ExpandedItem>
</Expand>
</Type>
<!-- Skip the pair first/second members in the treeview while traversing a map.
Only works in VS 2015 Update 2 and beyond using the new visualization -->
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_ldvcmp_v3_11_2::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<Type Name="std::pair&lt;*, nlohmann::json_abi_diag_ldvcmp_v3_11_3::basic_json&lt;*&gt;&gt;" IncludeView="MapHelper">
<DisplayString>{second}</DisplayString>
<Expand>
<ExpandedItem>second</ExpandedItem>
File diff suppressed because it is too large Load Diff
+47 -29
View File
@@ -9,11 +9,11 @@
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____
@@ -24,6 +24,8 @@
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file contains all macro definitions affecting or depending on the ABI
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
@@ -63,44 +65,59 @@
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH)
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION)
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@@ -120,16 +137,17 @@ struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType = std::map,
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string,
class BooleanType = bool,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
+1 -1
View File
@@ -18,7 +18,7 @@
#define STRINGIZE(x) STRINGIZE_EX(x)
template<typename T>
std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
{
#if DOCTEST_MSVC && !DOCTEST_CLANG
ns = __FUNCSIG__;
+3 -5
View File
@@ -11,10 +11,8 @@
#include "config.hpp"
// define custom namespace
#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{
#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann {
#define NLOHMANN_JSON_NAMESPACE_END }
#include <nlohmann/json_fwd.hpp>
@@ -27,7 +25,7 @@ TEST_CASE("custom namespace")
std::string expected = "nlohmann::basic_json";
// fallback for Clang
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
+5 -5
View File
@@ -20,20 +20,20 @@ TEST_CASE("default namespace")
{
std::string expected = "nlohmann::json_abi";
#if JSON_DIAGNOSTICS
#if JSON_DIAGNOSTICS
expected += "_diag";
#endif
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
expected += "_ldvcmp";
#endif
#endif
expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
// fallback for Clang
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
+5 -5
View File
@@ -21,18 +21,18 @@ TEST_CASE("default namespace without version component")
{
std::string expected = "nlohmann::json_abi";
#if JSON_DIAGNOSTICS
#if JSON_DIAGNOSTICS
expected += "_diag";
#endif
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
expected += "_ldvcmp";
#endif
#endif
expected += "::basic_json";
// fallback for Clang
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
CHECK(namespace_name<nlohmann::json>(ns) == expected);
}
+1 -1
View File
@@ -25,6 +25,6 @@ std::size_t json_sizeof_diag_off_explicit()
void json_at_diag_off()
{
using nlohmann::json;
json j = json{ { "foo", json::object() } };
json j = json{{"foo", json::object()}};
j.at(json::json_pointer("/foo/bar"));
}
+1 -1
View File
@@ -25,6 +25,6 @@ std::size_t json_sizeof_diag_on_explicit()
void json_at_diag_on()
{
using nlohmann::json;
json j = json{ { "foo", json::object() } };
json j = json{{"foo", json::object()}};
j.at(json::json_pointer("/foo/bar"));
}
+42 -42
View File
@@ -6,12 +6,12 @@
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include <benchmark/benchmark.h>
#include <nlohmann/json.hpp>
#include <fstream>
#include <numeric>
#include <test_data.hpp>
#include <vector>
#include <nlohmann/json.hpp>
#include <benchmark/benchmark.h>
#include <test_data.hpp>
using json = nlohmann::json;
@@ -39,13 +39,13 @@ static void ParseFile(benchmark::State& state, const char* filename)
std::ifstream file(filename, std::ios::binary | std::ios::ate);
state.SetBytesProcessed(state.iterations() * file.tellg());
}
BENCHMARK_CAPTURE(ParseFile, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseFile, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseFile, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseFile, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseFile, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseFile, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseFile, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseFile, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseFile, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseFile, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseFile, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseFile, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseFile, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseFile, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseFile, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
@@ -72,13 +72,13 @@ static void ParseString(benchmark::State& state, const char* filename)
state.SetBytesProcessed(state.iterations() * str.size());
}
BENCHMARK_CAPTURE(ParseString, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseString, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseString, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseString, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseString, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseString, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseString, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseString, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ParseString, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ParseString, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ParseString, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ParseString, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ParseString, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ParseString, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ParseString, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
@@ -98,22 +98,22 @@ static void Dump(benchmark::State& state, const char* filename, int indent)
state.SetBytesProcessed(state.iterations() * j.dump(indent).size());
}
BENCHMARK_CAPTURE(Dump, jeopardy / -, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", -1);
BENCHMARK_CAPTURE(Dump, jeopardy / 4, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", 4);
BENCHMARK_CAPTURE(Dump, canada / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", -1);
BENCHMARK_CAPTURE(Dump, canada / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", 4);
BENCHMARK_CAPTURE(Dump, citm_catalog / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", -1);
BENCHMARK_CAPTURE(Dump, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
BENCHMARK_CAPTURE(Dump, twitter / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", -1);
BENCHMARK_CAPTURE(Dump, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
BENCHMARK_CAPTURE(Dump, floats / -, TEST_DATA_DIRECTORY "/regression/floats.json", -1);
BENCHMARK_CAPTURE(Dump, floats / 4, TEST_DATA_DIRECTORY "/regression/floats.json", 4);
BENCHMARK_CAPTURE(Dump, signed_ints / -, TEST_DATA_DIRECTORY "/regression/signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, signed_ints / 4, TEST_DATA_DIRECTORY "/regression/signed_ints.json", 4);
BENCHMARK_CAPTURE(Dump, unsigned_ints / -, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", -1);
BENCHMARK_CAPTURE(Dump, unsigned_ints / 4, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 4);
BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
BENCHMARK_CAPTURE(Dump, jeopardy / -, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", -1);
BENCHMARK_CAPTURE(Dump, jeopardy / 4, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", 4);
BENCHMARK_CAPTURE(Dump, canada / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", -1);
BENCHMARK_CAPTURE(Dump, canada / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", 4);
BENCHMARK_CAPTURE(Dump, citm_catalog / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", -1);
BENCHMARK_CAPTURE(Dump, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
BENCHMARK_CAPTURE(Dump, twitter / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", -1);
BENCHMARK_CAPTURE(Dump, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
BENCHMARK_CAPTURE(Dump, floats / -, TEST_DATA_DIRECTORY "/regression/floats.json", -1);
BENCHMARK_CAPTURE(Dump, floats / 4, TEST_DATA_DIRECTORY "/regression/floats.json", 4);
BENCHMARK_CAPTURE(Dump, signed_ints / -, TEST_DATA_DIRECTORY "/regression/signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, signed_ints / 4, TEST_DATA_DIRECTORY "/regression/signed_ints.json", 4);
BENCHMARK_CAPTURE(Dump, unsigned_ints / -, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", -1);
BENCHMARK_CAPTURE(Dump, unsigned_ints / 4, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 4);
BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", -1);
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
//////////////////////////////////////////////////////////////////////////////
// serialize CBOR
@@ -131,13 +131,13 @@ static void ToCbor(benchmark::State& state, const char* filename)
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
}
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
//////////////////////////////////////////////////////////////////////////////
@@ -162,8 +162,8 @@ static void BinaryToCbor(benchmark::State& state)
++it;
}
json::binary_t bin{ in };
json j{ { "type", "binary" }, { "data", bin } };
json::binary_t bin{in};
json j{{"type", "binary"}, {"data", bin}};
while (state.KeepRunning())
{
@@ -6,8 +6,7 @@
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "Foo.hpp"
#include <nlohmann/json.hpp>
#include "Foo.hpp"
class Bar : public Foo
{};
class Bar : public Foo {};
@@ -9,5 +9,4 @@
#pragma once
#include <nlohmann/json.hpp>
class Foo
{};
class Foo {};
+1 -1
View File
@@ -10,7 +10,7 @@
int main()
{
nlohmann::ordered_json json = { "Test" };
nlohmann::ordered_json json = {"Test"};
json.dump();
// regression for #3013 (ordered_json::reset() compile error with nvcc)
+1 -1
View File
@@ -12,9 +12,9 @@ an implementation of the `LLVMFuzzerTestOneInput` function which processes a
passed byte array.
*/
#include <vector> // for vector
#include <cstdint> // for uint8_t
#include <iostream> // for cin
#include <vector> // for vector
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
+4 -7
View File
@@ -8,10 +8,10 @@
#pragma once
#include <cstdio> // fopen, fclose, FILE
#include <doctest.h>
#include <memory> // unique_ptr
#include <cstdio> // fopen, fclose, FILE
#include <memory> // unique_ptr
#include <test_data.hpp>
#include <doctest.h>
namespace utils
{
@@ -24,10 +24,7 @@ inline bool check_testsuite_downloaded()
TEST_CASE("check test suite is downloaded")
{
REQUIRE_MESSAGE(
utils::check_testsuite_downloaded(),
"Test data not found in '" TEST_DATA_DIRECTORY
"'. Please execute target 'download_test_data' before running this test suite. See <https://github.com/nlohmann/json#execute-unit-tests> for more information.");
REQUIRE_MESSAGE(utils::check_testsuite_downloaded(), "Test data not found in '" TEST_DATA_DIRECTORY "'. Please execute target 'download_test_data' before running this test suite. See <https://github.com/nlohmann/json#execute-unit-tests> for more information.");
}
} // namespace utils
+4 -4
View File
@@ -8,9 +8,9 @@
#pragma once
#include <cstdint> // uint8_t
#include <fstream> // ifstream, istreambuf_iterator, ios
#include <vector> // vector
#include <cstdint> // uint8_t
#include <fstream> // ifstream, istreambuf_iterator, ios
#include <vector> // vector
namespace utils
{
@@ -30,4 +30,4 @@ inline std::vector<std::uint8_t> read_binary_file(const std::string& filename)
return byte_vector;
}
} // namespace utils
} // namespace utils
+16 -24
View File
@@ -11,10 +11,10 @@
#include <nlohmann/json.hpp>
using nlohmann::json;
#include <climits> // SIZE_MAX
#include <limits> // numeric_limits
#include <climits> // SIZE_MAX
#include <limits> // numeric_limits
template<typename OfType, typename T, bool MinInRange, bool MaxInRange>
template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
struct trait_test_arg
{
using of_type = OfType;
@@ -23,7 +23,7 @@ struct trait_test_arg
static constexpr bool max_in_range = MaxInRange;
};
TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test)
TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) // NOLINT(readability-math-missing-parentheses)
{
using nlohmann::detail::value_in_range_of;
@@ -92,10 +92,10 @@ TEST_CASE("32bit")
REQUIRE(SIZE_MAX == 0xffffffff);
}
TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test,
trait_test_arg<std::size_t, std::int32_t, false, true>,
trait_test_arg<std::size_t, std::uint32_t, true, true>,
trait_test_arg<std::size_t, std::int64_t, false, false>,
TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
trait_test_arg<std::size_t, std::int32_t, false, true>, \
trait_test_arg<std::size_t, std::uint32_t, true, true>, \
trait_test_arg<std::size_t, std::int64_t, false, false>, \
trait_test_arg<std::size_t, std::uint64_t, true, false>);
TEST_CASE("BJData")
@@ -106,35 +106,27 @@ TEST_CASE("BJData")
{
SECTION("optimized array: negative size")
{
std::vector<uint8_t> const vM = { '[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']' };
std::vector<uint8_t> const vMX = { '[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']' };
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
std::vector<uint8_t> const vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
json _;
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM),
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
json::out_of_range&);
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vM, true, false).is_discarded());
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX),
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
json::out_of_range&);
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vMX, true, false).is_discarded());
}
SECTION("optimized array: integer value overflow")
{
std::vector<uint8_t> const vL = { '[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F };
std::vector<uint8_t> const vM = { '[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']' };
std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
json _;
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL),
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
json::out_of_range&);
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vL, true, false).is_discarded());
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM),
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
json::out_of_range&);
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
CHECK(json::from_bjdata(vM, true, false).is_discarded());
}
}
+92 -71
View File
@@ -14,37 +14,43 @@ using nlohmann::json;
TEST_CASE("algorithms")
{
json j_array = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz" };
json j_object = { { "one", 1 }, { "two", 2 } };
json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
json j_object = {{"one", 1}, {"two", 2}};
SECTION("non-modifying sequence operations")
{
SECTION("std::all_of")
{
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json& value) {
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
{
return !value.empty();
}));
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json& value) {
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.type() == json::value_t::number_integer;
}));
}
SECTION("std::any_of")
{
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() && 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)
{
return value.get<int>() > 1;
}));
}
SECTION("std::none_of")
{
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json& value) {
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
{
return value.empty();
}));
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json& value) {
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
{
return value.get<int>() <= 0;
}));
}
@@ -55,7 +61,8 @@ TEST_CASE("algorithms")
{
int sum = 0;
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json& value) {
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
{
if (value.is_number())
{
sum += static_cast<int>(value);
@@ -67,7 +74,8 @@ TEST_CASE("algorithms")
SECTION("writing")
{
auto add17 = [](json& value) {
auto add17 = [](json & value)
{
if (value.is_array())
{
value.push_back(17);
@@ -76,7 +84,7 @@ TEST_CASE("algorithms")
std::for_each(j_array.begin(), j_array.end(), add17);
CHECK(j_array[6] == json({ 1, 2, 3, 17 }));
CHECK(j_array[6] == json({1, 2, 3, 17}));
}
}
@@ -87,20 +95,22 @@ TEST_CASE("algorithms")
SECTION("std::count_if")
{
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json& value) {
return (value.is_number());
}) == 3);
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&) {
return true;
}) == 9);
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
{
return (value.is_number());
}) == 3);
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
{
return true;
}) == 9);
}
SECTION("std::mismatch")
{
json j_array2 = { 13, 29, 3, { { "one", 1 }, { "two", 2 }, { "three", 3 } }, true, false, { 1, 2, 3 }, "foo", "baz" };
json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
CHECK(*res.first == json({ { "one", 1 }, { "two", 2 } }));
CHECK(*res.second == json({ { "one", 1 }, { "two", 2 }, { "three", 3 } }));
CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
}
SECTION("std::equal")
@@ -115,9 +125,11 @@ TEST_CASE("algorithms")
SECTION("using user-defined comparison")
{
// 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(!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) {
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
[](const json & a, const json & b)
{
return (a.size() == b.size());
}));
}
@@ -131,7 +143,9 @@ TEST_CASE("algorithms")
SECTION("std::find_if")
{
auto it = std::find_if(j_array.begin(), j_array.end(), [](const json& value) {
auto it = std::find_if(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_boolean();
});
CHECK(std::distance(j_array.begin(), it) == 4);
@@ -139,7 +153,9 @@ TEST_CASE("algorithms")
SECTION("std::find_if_not")
{
auto it = std::find_if_not(j_array.begin(), j_array.end(), [](const json& value) {
auto it = std::find_if_not(j_array.begin(), j_array.end(),
[](const json & value)
{
return value.is_number();
});
CHECK(std::distance(j_array.begin(), it) == 3);
@@ -148,9 +164,11 @@ TEST_CASE("algorithms")
SECTION("std::adjacent_find")
{
CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
CHECK(std::adjacent_find(j_array.begin(), j_array.end(), [](const json& v1, const json& v2) {
return v1.type() == v2.type();
}) == j_array.begin());
CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
[](const json & v1, const json & v2)
{
return v1.type() == v2.type();
}) == j_array.begin());
}
}
@@ -159,18 +177,19 @@ TEST_CASE("algorithms")
SECTION("std::reverse")
{
std::reverse(j_array.begin(), j_array.end());
CHECK(j_array == json({ "baz", "foo", { 1, 2, 3 }, false, true, { { "one", 1 }, { "two", 2 } }, 3, 29, 13 }));
CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
}
SECTION("std::rotate")
{
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
CHECK(j_array == json({ 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", 13 }));
CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
}
SECTION("std::partition")
{
auto it = std::partition(j_array.begin(), j_array.end(), [](const json& v) {
auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
{
return v.is_string();
});
CHECK(std::distance(j_array.begin(), it) == 2);
@@ -184,34 +203,33 @@ TEST_CASE("algorithms")
{
SECTION("with standard comparison")
{
json j = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", nullptr };
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::sort(j.begin(), j.end());
CHECK(j == json({ nullptr, false, true, 3, 13, 29, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, "baz", "foo" }));
CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}
SECTION("with user-defined comparison")
{
json j = { 3, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, nullptr };
std::sort(j.begin(), j.end(), [](const json& a, const json& b) {
json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
std::sort(j.begin(), j.end(), [](const json & a, const json & b)
{
return a.size() < b.size();
});
CHECK(j == json({ nullptr, 3, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 } }));
CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
}
SECTION("sorting an object")
{
json j({ { "one", 1 }, { "two", 2 } });
CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()),
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators",
json::invalid_iterator&);
json j({{"one", 1}, {"two", 2}});
CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
}
}
SECTION("std::partial_sort")
{
json j = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", nullptr };
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
std::partial_sort(j.begin(), j.begin() + 4, j.end());
CHECK(j == json({ nullptr, false, true, 3, { { "one", 1 }, { "two", 2 } }, 29, { 1, 2, 3 }, "foo", "baz", 13 }));
CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
}
}
@@ -220,53 +238,53 @@ TEST_CASE("algorithms")
SECTION("std::merge")
{
{
json j1 = { 2, 4, 6, 8 };
json j2 = { 1, 2, 3, 5, 7 };
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({ 1, 2, 2, 3, 4, 5, 6, 7, 8 }));
CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
}
}
SECTION("std::set_difference")
{
json j1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
json j2 = { 1, 2, 3, 5, 7 };
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({ 4, 6, 8 }));
CHECK(j3 == json({4, 6, 8}));
}
SECTION("std::set_intersection")
{
json j1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
json j2 = { 1, 2, 3, 5, 7 };
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({ 1, 2, 3, 5, 7 }));
CHECK(j3 == json({1, 2, 3, 5, 7}));
}
SECTION("std::set_union")
{
json j1 = { 2, 4, 6, 8 };
json j2 = { 1, 2, 3, 5, 7 };
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({ 1, 2, 3, 4, 5, 6, 7, 8 }));
CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
}
SECTION("std::set_symmetric_difference")
{
json j1 = { 2, 4, 6, 8 };
json j2 = { 1, 2, 3, 5, 7 };
json j1 = {2, 4, 6, 8};
json j2 = {1, 2, 3, 5, 7};
json j3;
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
CHECK(j3 == json({ 1, 3, 4, 5, 6, 7, 8 }));
CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
}
}
@@ -275,29 +293,29 @@ TEST_CASE("algorithms")
std::make_heap(j_array.begin(), j_array.end());
CHECK(std::is_heap(j_array.begin(), j_array.end()));
std::sort_heap(j_array.begin(), j_array.end());
CHECK(j_array == json({ false, true, 3, 13, 29, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, "baz", "foo" }));
CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
}
SECTION("iota")
{
SECTION("int")
{
json json_arr = { 0, 5, 2, 4, 10, 20, 30, 40, 50, 1 };
json json_arr = {0, 5, 2, 4, 10, 20, 30, 40, 50, 1};
std::iota(json_arr.begin(), json_arr.end(), 0);
CHECK(json_arr == json({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
CHECK(json_arr == json({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
}
SECTION("double")
{
json json_arr = { 0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5 };
json json_arr = {0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5};
std::iota(json_arr.begin(), json_arr.end(), 0.5);
CHECK(json_arr == json({ 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5 }));
CHECK(json_arr == json({0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5}));
}
SECTION("char")
{
json json_arr = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1' };
json json_arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1'};
std::iota(json_arr.begin(), json_arr.end(), '0');
CHECK(json_arr == json({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }));
CHECK(json_arr == json({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}));
}
}
@@ -306,7 +324,7 @@ TEST_CASE("algorithms")
SECTION("copy without if")
{
json dest_arr;
const json source_arr = { 1, 2, 3, 4 };
const json source_arr = {1, 2, 3, 4};
std::copy(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr));
@@ -315,30 +333,33 @@ TEST_CASE("algorithms")
SECTION("copy if")
{
json dest_arr;
const json source_arr = { 0, 3, 6, 9, 12, 15, 20 };
const json source_arr = {0, 3, 6, 9, 12, 15, 20};
std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json& _value) {
std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json & _value)
{
return _value.get<int>() % 3 == 0;
});
CHECK(dest_arr == json({ 0, 3, 6, 9, 12, 15 }));
CHECK(dest_arr == json({0, 3, 6, 9, 12, 15}));
}
SECTION("copy n")
{
const json source_arr = { 0, 1, 2, 3, 4, 5, 6, 7 };
const json source_arr = {0, 1, 2, 3, 4, 5, 6, 7};
json dest_arr;
const unsigned char numToCopy = 2;
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
CHECK(dest_arr == json{ 0, 1 });
CHECK(dest_arr == json{0, 1});
}
SECTION("copy n chars")
{
const json source_arr = { '1', '2', '3', '4', '5', '6', '7' };
const json source_arr = {'1', '2', '3', '4', '5', '6', '7'};
json dest_arr;
const unsigned char numToCopy = 4;
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
CHECK(dest_arr == json{ '1', '2', '3', '4' });
CHECK(dest_arr == json{'1', '2', '3', '4'});
}
}
}
+41 -23
View File
@@ -21,30 +21,35 @@ struct bad_allocator : std::allocator<T>
using std::allocator<T>::allocator;
bad_allocator() = default;
template<class U>
bad_allocator(const bad_allocator<U>& /*unused*/)
{}
template<class U> bad_allocator(const bad_allocator<U>& /*unused*/) { }
template<class... Args>
void construct(T* /*unused*/, Args&&... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
{
throw std::bad_alloc();
}
template<class U>
template <class U>
struct rebind
{
using other = bad_allocator<U>;
};
};
} // namespace
} // namespace
TEST_CASE("bad_alloc")
{
SECTION("bad_alloc")
{
// create JSON type using the throwing allocator
using bad_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, bad_allocator>;
using bad_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
bad_allocator>;
// creating an object should throw
CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&);
@@ -63,7 +68,7 @@ struct my_allocator : std::allocator<T>
using std::allocator<T>::allocator;
template<class... Args>
void construct(T* p, Args&&... args)
void construct(T* p, Args&& ... args)
{
if (next_construct_fails)
{
@@ -93,11 +98,11 @@ struct my_allocator : std::allocator<T>
throw std::bad_alloc();
}
static_cast<void>(p); // fix MSVC's C4100 warning
static_cast<void>(p); // fix MSVC's C4100 warning
p->~T();
}
template<class U>
template <class U>
struct rebind
{
using other = my_allocator<U>;
@@ -113,12 +118,19 @@ void my_allocator_clean_up(T* p)
alloc.destroy(p);
alloc.deallocate(p, 1);
}
} // namespace
} // namespace
TEST_CASE("controlled bad_alloc")
{
// create JSON type using the throwing allocator
using my_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, my_allocator>;
using my_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
my_allocator>;
SECTION("class json_value")
{
@@ -169,7 +181,7 @@ TEST_CASE("controlled bad_alloc")
SECTION("basic_json(const CompatibleObjectType&)")
{
next_construct_fails = false;
const std::map<std::string, std::string> v{ { "foo", "bar" } };
const std::map<std::string, std::string> v {{"foo", "bar"}};
CHECK_NOTHROW(my_json(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
@@ -179,7 +191,7 @@ TEST_CASE("controlled bad_alloc")
SECTION("basic_json(const CompatibleArrayType&)")
{
next_construct_fails = false;
const std::vector<std::string> v{ "foo", "bar", "baz" };
const std::vector<std::string> v {"foo", "bar", "baz"};
CHECK_NOTHROW(my_json(v));
next_construct_fails = true;
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
@@ -213,30 +225,36 @@ template<class T>
struct allocator_no_forward : std::allocator<T>
{
allocator_no_forward() = default;
template<class U>
allocator_no_forward(allocator_no_forward<U> /*unused*/)
{}
template <class U>
allocator_no_forward(allocator_no_forward<U> /*unused*/) {}
template<class U>
template <class U>
struct rebind
{
using other = allocator_no_forward<U>;
using other = allocator_no_forward<U>;
};
template<class... Args>
void construct(T* p, const Args&... args) noexcept(noexcept(::new(static_cast<void*>(p)) T(args...)))
template <class... Args>
void construct(T* p, const Args& ... args) noexcept(noexcept(::new (static_cast<void*>(p)) T(args...)))
{
// force copy even if move is available
::new (static_cast<void*>(p)) T(args...);
}
};
} // namespace
} // namespace
TEST_CASE("bad my_allocator::construct")
{
SECTION("my_allocator::construct doesn't forward")
{
using bad_alloc_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, allocator_no_forward>;
using bad_alloc_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
allocator_no_forward>;
bad_alloc_json j;
j["test"] = bad_alloc_json::array_t();
+32 -29
View File
@@ -16,8 +16,8 @@
/* forward declarations */
class alt_string;
bool operator<(const char* op1, const alt_string& op2) noexcept;
void int_to_string(alt_string& target, std::size_t value);
bool operator<(const char* op1, const alt_string& op2) noexcept; // NOLINT(misc-use-internal-linkage)
void int_to_string(alt_string& target, std::size_t value); // NOLINT(misc-use-internal-linkage)
/*
* This is virtually a string class.
@@ -30,19 +30,13 @@ class alt_string
static constexpr auto npos = static_cast<std::size_t>(-1);
alt_string(const char* str)
: str_impl(str)
{}
alt_string(const char* str, std::size_t count)
: str_impl(str, count)
{}
alt_string(size_t count, char chr)
: str_impl(count, chr)
{}
alt_string(const char* str): str_impl(str) {}
alt_string(const char* str, std::size_t count): str_impl(str, count) {}
alt_string(size_t count, char chr): str_impl(count, chr) {}
alt_string() = default;
template<typename... TParams>
alt_string& append(TParams&&... params)
template <typename...TParams>
alt_string& append(TParams&& ...params)
{
str_impl.append(std::forward<TParams>(params)...);
return *this;
@@ -53,7 +47,7 @@ class alt_string
str_impl.push_back(c);
}
template<typename op_type>
template <typename op_type>
bool operator==(const op_type& op) const
{
return str_impl == op;
@@ -64,7 +58,7 @@ class alt_string
return str_impl == op.str_impl;
}
template<typename op_type>
template <typename op_type>
bool operator!=(const op_type& op) const
{
return str_impl != op;
@@ -80,17 +74,17 @@ class alt_string
return str_impl.size();
}
void resize(std::size_t n)
void resize (std::size_t n)
{
str_impl.resize(n);
}
void resize(std::size_t n, char c)
void resize (std::size_t n, char c)
{
str_impl.resize(n, c);
}
template<typename op_type>
template <typename op_type>
bool operator<(const op_type& op) const noexcept
{
return str_impl < op;
@@ -154,7 +148,7 @@ class alt_string
alt_string substr(std::size_t pos = 0, std::size_t count = npos) const
{
const std::string s = str_impl.substr(pos, count);
return { s.data(), s.size() };
return {s.data(), s.size()};
}
alt_string& replace(std::size_t pos, std::size_t count, const alt_string& str)
@@ -164,7 +158,7 @@ class alt_string
}
private:
std::string str_impl{};
std::string str_impl {}; // NOLINT(readability-redundant-member-init)
friend bool operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept;
};
@@ -174,7 +168,16 @@ void int_to_string(alt_string& target, std::size_t value)
target = std::to_string(value).c_str();
}
using alt_json = nlohmann::basic_json<std::map, std::vector, alt_string, bool, std::int64_t, std::uint64_t, double, std::allocator, nlohmann::adl_serializer>;
using alt_json = nlohmann::basic_json <
std::map,
std::vector,
alt_string,
bool,
std::int64_t,
std::uint64_t,
double,
std::allocator,
nlohmann::adl_serializer >;
bool operator<(const char* op1, const alt_string& op2) noexcept
{
@@ -229,7 +232,7 @@ TEST_CASE("alternative string type")
{
alt_json doc;
doc["object"] = { { "currency", "USD" }, { "value", 42.99 } };
doc["object"] = { {"currency", "USD"}, {"value", 42.99} };
alt_string dump = doc.dump();
CHECK(dump == R"({"object":{"currency":"USD","value":42.99}})");
}
@@ -256,11 +259,11 @@ TEST_CASE("alternative string type")
for (const auto& item : doc_array.items())
{
if (item.key() == "0")
if (item.key() == "0" )
{
CHECK(item.value() == "foo");
CHECK( item.value() == "foo" );
}
else if (item.key() == "1")
else if (item.key() == "1" )
{
CHECK(item.value() == "bar");
}
@@ -277,14 +280,14 @@ TEST_CASE("alternative string type")
doc["Who are you?"] = "I'm Batman";
CHECK("I'm Batman" == doc["Who are you?"]);
CHECK(doc["Who are you?"] == "I'm Batman");
CHECK(doc["Who are you?"] == "I'm Batman");
CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
{
const alt_json& const_doc = doc;
+1 -5
View File
@@ -18,11 +18,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wstrict-overflow")
static int assert_counter;
/// set failure variable to true instead of calling assert(x)
#define JSON_ASSERT(x) \
{ \
if (!(x)) \
++assert_counter; \
}
#define JSON_ASSERT(x) {if (!(x)) ++assert_counter; }
#include <nlohmann/json.hpp>
using nlohmann::json;
+2 -2
View File
@@ -11,8 +11,8 @@
#include <nlohmann/json.hpp>
using nlohmann::json;
#include "make_test_data_available.hpp"
#include <fstream>
#include "make_test_data_available.hpp"
TEST_CASE("Binary Formats" * doctest::skip())
{
@@ -142,7 +142,7 @@ TEST_CASE("Binary Formats" * doctest::skip())
const auto bjdata_1_size = json::to_bjdata(j).size();
const auto bjdata_2_size = json::to_bjdata(j, true).size();
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
const auto bson_size = json::to_bson({ { "", j } }).size(); // wrap array in object for BSON
const auto bson_size = json::to_bson({{"", j}}).size(); // wrap array in object for BSON
const auto cbor_size = json::to_cbor(j).size();
const auto msgpack_size = json::to_msgpack(j).size();
const auto ubjson_1_size = json::to_ubjson(j).size();
+895 -1002
View File
File diff suppressed because it is too large Load Diff
+444 -563
View File
File diff suppressed because it is too large Load Diff
@@ -45,7 +45,7 @@ TEST_CASE("byte_container_with_subtype")
SECTION("comparisons")
{
std::vector<std::uint8_t> const bytes = { { 0xCA, 0xFE, 0xBA, 0xBE } };
std::vector<std::uint8_t> const bytes = {{0xCA, 0xFE, 0xBA, 0xBE}};
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container1;
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container2({}, 42);
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container3(bytes);
+36 -36
View File
@@ -18,7 +18,7 @@ TEST_CASE("capacity")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of empty")
@@ -36,7 +36,7 @@ TEST_CASE("capacity")
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of empty")
@@ -56,7 +56,7 @@ TEST_CASE("capacity")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of empty")
@@ -74,8 +74,8 @@ TEST_CASE("capacity")
SECTION("filled array")
{
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
const json j_const = { 1, 2, 3 };
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of empty")
{
@@ -95,7 +95,7 @@ TEST_CASE("capacity")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of empty")
@@ -113,8 +113,8 @@ TEST_CASE("capacity")
SECTION("filled object")
{
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of empty")
{
@@ -132,7 +132,7 @@ TEST_CASE("capacity")
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of empty")
@@ -150,7 +150,7 @@ TEST_CASE("capacity")
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of empty")
@@ -168,7 +168,7 @@ TEST_CASE("capacity")
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of empty")
@@ -186,7 +186,7 @@ TEST_CASE("capacity")
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of empty")
@@ -207,7 +207,7 @@ TEST_CASE("capacity")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of size")
@@ -227,7 +227,7 @@ TEST_CASE("capacity")
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of size")
@@ -249,7 +249,7 @@ TEST_CASE("capacity")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of size")
@@ -269,8 +269,8 @@ TEST_CASE("capacity")
SECTION("filled array")
{
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
const json j_const = { 1, 2, 3 };
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of size")
{
@@ -292,7 +292,7 @@ TEST_CASE("capacity")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of size")
@@ -312,8 +312,8 @@ TEST_CASE("capacity")
SECTION("filled object")
{
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of size")
{
@@ -333,7 +333,7 @@ TEST_CASE("capacity")
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of size")
@@ -353,7 +353,7 @@ TEST_CASE("capacity")
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of size")
@@ -373,7 +373,7 @@ TEST_CASE("capacity")
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of size")
@@ -393,7 +393,7 @@ TEST_CASE("capacity")
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of size")
@@ -416,7 +416,7 @@ TEST_CASE("capacity")
{
SECTION("boolean")
{
json j = true; // NOLINT(misc-const-correctness)
json j = true; // NOLINT(misc-const-correctness)
const json j_const = true;
SECTION("result of max_size")
@@ -428,7 +428,7 @@ TEST_CASE("capacity")
SECTION("string")
{
json j = "hello world"; // NOLINT(misc-const-correctness)
json j = "hello world"; // NOLINT(misc-const-correctness)
const json j_const = "hello world";
SECTION("result of max_size")
@@ -442,7 +442,7 @@ TEST_CASE("capacity")
{
SECTION("empty array")
{
json j = json::array(); // NOLINT(misc-const-correctness)
json j = json::array(); // NOLINT(misc-const-correctness)
const json j_const = json::array();
SECTION("result of max_size")
@@ -454,8 +454,8 @@ TEST_CASE("capacity")
SECTION("filled array")
{
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
const json j_const = { 1, 2, 3 };
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
const json j_const = {1, 2, 3};
SECTION("result of max_size")
{
@@ -469,7 +469,7 @@ TEST_CASE("capacity")
{
SECTION("empty object")
{
json j = json::object(); // NOLINT(misc-const-correctness)
json j = json::object(); // NOLINT(misc-const-correctness)
const json j_const = json::object();
SECTION("result of max_size")
@@ -481,8 +481,8 @@ TEST_CASE("capacity")
SECTION("filled object")
{
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
SECTION("result of max_size")
{
@@ -494,7 +494,7 @@ TEST_CASE("capacity")
SECTION("number (integer)")
{
json j = -23; // NOLINT(misc-const-correctness)
json j = -23; // NOLINT(misc-const-correctness)
const json j_const = -23;
SECTION("result of max_size")
@@ -506,7 +506,7 @@ TEST_CASE("capacity")
SECTION("number (unsigned)")
{
json j = 23u; // NOLINT(misc-const-correctness)
json j = 23u; // NOLINT(misc-const-correctness)
const json j_const = 23u;
SECTION("result of max_size")
@@ -518,7 +518,7 @@ TEST_CASE("capacity")
SECTION("number (float)")
{
json j = 23.42; // NOLINT(misc-const-correctness)
json j = 23.42; // NOLINT(misc-const-correctness)
const json j_const = 23.42;
SECTION("result of max_size")
@@ -530,7 +530,7 @@ TEST_CASE("capacity")
SECTION("null")
{
json j = nullptr; // NOLINT(misc-const-correctness)
json j = nullptr; // NOLINT(misc-const-correctness)
const json j_const = nullptr;
SECTION("result of max_size")
+691 -790
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -49,7 +49,7 @@ TEST_CASE("const_iterator class")
{
SECTION("create from uninitialized iterator")
{
const json::iterator it{};
const json::iterator it {};
json::const_iterator const cit(it);
}
@@ -141,14 +141,14 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator const it = j.cbegin();
CHECK(*it == json("bar"));
}
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator const it = j.cbegin();
CHECK(*it == json(1));
}
@@ -174,14 +174,14 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator const it = j.cbegin();
CHECK(std::string(it->type_name()) == "string");
}
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator const it = j.cbegin();
CHECK(std::string(it->type_name()) == "number");
}
@@ -214,7 +214,7 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
@@ -223,7 +223,7 @@ TEST_CASE("const_iterator class")
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
@@ -265,7 +265,7 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
@@ -274,7 +274,7 @@ TEST_CASE("const_iterator class")
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
@@ -314,7 +314,7 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
@@ -323,7 +323,7 @@ TEST_CASE("const_iterator class")
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
@@ -363,7 +363,7 @@ TEST_CASE("const_iterator class")
SECTION("object")
{
json const j({ { "foo", "bar" } });
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
@@ -372,7 +372,7 @@ TEST_CASE("const_iterator class")
SECTION("array")
{
json const j({ 1, 2, 3, 4 });
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
+19 -18
View File
@@ -131,14 +131,14 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator const it = j.begin();
CHECK(*it == json("bar"));
}
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator const it = j.begin();
CHECK(*it == json(1));
}
@@ -164,14 +164,14 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator const it = j.begin();
CHECK(std::string(it->type_name()) == "string");
}
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator const it = j.begin();
CHECK(std::string(it->type_name()) == "number");
}
@@ -204,7 +204,7 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
@@ -213,7 +213,7 @@ TEST_CASE("iterator class")
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
@@ -255,7 +255,7 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
@@ -264,7 +264,7 @@ TEST_CASE("iterator class")
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
@@ -304,7 +304,7 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
@@ -313,7 +313,7 @@ TEST_CASE("iterator class")
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
@@ -353,7 +353,7 @@ TEST_CASE("iterator class")
SECTION("object")
{
json j({ { "foo", "bar" } });
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
@@ -362,7 +362,7 @@ TEST_CASE("iterator class")
SECTION("array")
{
json j({ 1, 2, 3, 4 });
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
@@ -387,18 +387,18 @@ TEST_CASE("iterator class")
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
}
}
SECTION("post-decrement")
@@ -406,18 +406,18 @@ TEST_CASE("iterator class")
SECTION("primitive_iterator_t")
{
using Iter = nlohmann::detail::primitive_iterator_t;
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value);
}
SECTION("iter_impl")
{
using Iter = nlohmann::detail::iter_impl<json>;
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
SECTION("json_reverse_iterator")
{
using Base = nlohmann::detail::iter_impl<json>;
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
}
}
}
@@ -462,6 +462,7 @@ TEST_CASE("iterator class")
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
}
}
}
}
+4 -4
View File
@@ -19,15 +19,15 @@ json::lexer::token_type scan_string(const char* s, bool ignore_comments = false)
json::lexer::token_type scan_string(const char* s, const bool ignore_comments)
{
auto ia = nlohmann::detail::input_adapter(s);
return nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments).scan(); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
return nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments).scan(); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
}
} // namespace
} // namespace
std::string get_error_message(const char* s, bool ignore_comments = false);
std::string get_error_message(const char* s, bool ignore_comments = false); // NOLINT(misc-use-internal-linkage)
std::string get_error_message(const char* s, const bool ignore_comments)
{
auto ia = nlohmann::detail::input_adapter(s);
auto lexer = nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
auto lexer = nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
lexer.scan();
return lexer.get_error_message();
}
File diff suppressed because it is too large Load Diff
+181 -174
View File
@@ -23,8 +23,7 @@ using nlohmann::json;
// this can be replaced with the doctest stl extension header in version 2.5
namespace doctest
{
template<>
struct StringMaker<std::partial_ordering>
template<> struct StringMaker<std::partial_ordering>
{
static String convert(const std::partial_ordering& order)
{
@@ -47,7 +46,7 @@ struct StringMaker<std::partial_ordering>
return "{?}";
}
};
} // namespace doctest
} // namespace doctest
#endif
@@ -55,12 +54,12 @@ namespace
{
// helper function to check std::less<json::value_t>
// see https://en.cppreference.com/w/cpp/utility/functional/less
template<typename A, typename B, typename U = std::less<json::value_t>>
template <typename A, typename B, typename U = std::less<json::value_t>>
bool f(A a, B b, U u = U())
{
return u(a, b);
}
} // namespace
} // namespace
TEST_CASE("lexicographical comparison operators")
{
@@ -87,23 +86,33 @@ TEST_CASE("lexicographical comparison operators")
SECTION("types")
{
std::vector<json::value_t> j_types = {
json::value_t::null, json::value_t::boolean, json::value_t::number_integer, json::value_t::number_unsigned, json::value_t::number_float,
json::value_t::object, json::value_t::array, json::value_t::string, json::value_t::binary, json::value_t::discarded
std::vector<json::value_t> j_types =
{
json::value_t::null,
json::value_t::boolean,
json::value_t::number_integer,
json::value_t::number_unsigned,
json::value_t::number_float,
json::value_t::object,
json::value_t::array,
json::value_t::string,
json::value_t::binary,
json::value_t::discarded
};
std::vector<std::vector<bool>> expected_lt = {
std::vector<std::vector<bool>> expected_lt =
{
//0 1 2 3 4 5 6 7 8 9
{ f_, _t, _t, _t, _t, _t, _t, _t, _t, f_ }, // 0
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, f_ }, // 1
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 2
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 3
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 4
{ f_, f_, f_, f_, f_, f_, _t, _t, _t, f_ }, // 5
{ f_, f_, f_, f_, f_, f_, f_, _t, _t, f_ }, // 6
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, f_ }, // 7
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
{f_, _t, _t, _t, _t, _t, _t, _t, _t, f_}, // 0
{f_, f_, _t, _t, _t, _t, _t, _t, _t, f_}, // 1
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 2
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 3
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 4
{f_, f_, f_, f_, f_, f_, _t, _t, _t, f_}, // 5
{f_, f_, f_, f_, f_, f_, f_, _t, _t, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
};
SECTION("comparison: less")
@@ -131,18 +140,19 @@ TEST_CASE("lexicographical comparison operators")
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
SECTION("comparison: 3-way")
{
std::vector<std::vector<std::partial_ordering>> expected = {
std::vector<std::vector<std::partial_ordering>> expected =
{
//0 1 2 3 4 5 6 7 8 9
{ eq, lt, lt, lt, lt, lt, lt, lt, lt, un }, // 0
{ gt, eq, lt, lt, lt, lt, lt, lt, lt, un }, // 1
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 2
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 3
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 4
{ gt, gt, gt, gt, gt, eq, lt, lt, lt, un }, // 5
{ gt, gt, gt, gt, gt, gt, eq, lt, lt, un }, // 6
{ gt, gt, gt, gt, gt, gt, gt, eq, lt, un }, // 7
{ gt, gt, gt, gt, gt, gt, gt, gt, eq, un }, // 8
{ un, un, un, un, un, un, un, un, un, un }, // 9
{eq, lt, lt, lt, lt, lt, lt, lt, lt, un}, // 0
{gt, eq, lt, lt, lt, lt, lt, lt, lt, un}, // 1
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 2
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 3
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 4
{gt, gt, gt, gt, gt, eq, lt, lt, lt, un}, // 5
{gt, gt, gt, gt, gt, gt, eq, lt, lt, un}, // 6
{gt, gt, gt, gt, gt, gt, gt, eq, lt, un}, // 7
{gt, gt, gt, gt, gt, gt, gt, gt, eq, un}, // 8
{un, un, un, un, un, un, un, un, un, un}, // 9
};
// check expected partial_ordering against expected boolean
@@ -167,7 +177,7 @@ TEST_CASE("lexicographical comparison operators")
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
}
}
}
@@ -176,109 +186,102 @@ TEST_CASE("lexicographical comparison operators")
SECTION("values")
{
json j_values = {
nullptr,
nullptr, // 0 1
-17,
42, // 2 3
8u,
13u, // 4 5
3.14159,
23.42, // 6 7
nan,
nan, // 8 9
"foo",
"bar", // 10 11
true,
false, // 12 13
{ 1, 2, 3 },
{ "one", "two", "three" }, // 14 15
{ { "first", 1 }, { "second", 2 } },
{ { "a", "A" }, { "b", { "B" } } }, // 16 17
json::binary({ 1, 2, 3 }),
json::binary({ 1, 2, 4 }), // 18 19
json(json::value_t::discarded),
json(json::value_t::discarded) // 20 21
json j_values =
{
nullptr, nullptr, // 0 1
-17, 42, // 2 3
8u, 13u, // 4 5
3.14159, 23.42, // 6 7
nan, nan, // 8 9
"foo", "bar", // 10 11
true, false, // 12 13
{1, 2, 3}, {"one", "two", "three"}, // 14 15
{{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}, // 16 17
json::binary({1, 2, 3}), json::binary({1, 2, 4}), // 18 19
json(json::value_t::discarded), json(json::value_t::discarded) // 20 21
};
std::vector<std::vector<bool>> expected_eq = {
std::vector<std::vector<bool>> expected_eq =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{ _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 0
{ _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 1
{ f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 2
{ f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 3
{ f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 4
{ f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 5
{ f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 6
{ f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 7
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 10
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 11
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 12
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_ }, // 13
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_ }, // 14
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_ }, // 15
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_ }, // 16
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_ }, // 17
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_ }, // 18
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_ }, // 19
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
{f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
{f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
{f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
{f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
std::vector<std::vector<bool>> expected_lt = {
std::vector<std::vector<bool>> expected_lt =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_ }, // 0
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_ }, // 1
{ f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 2
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 3
{ f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 4
{ f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 5
{ f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 6
{ f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 7
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 8
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 9
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 10
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 11
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 12
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 13
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_ }, // 14
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 15
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_ }, // 16
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_ }, // 17
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_ }, // 18
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 19
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 0
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 1
{f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 3
{f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 4
{f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 5
{f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 6
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 7
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 8
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 11
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 12
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
SECTION("compares unordered")
{
std::vector<std::vector<bool>> expected = {
std::vector<std::vector<bool>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 0
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 1
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 2
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 3
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 4
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 5
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 6
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 7
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 8
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 9
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 10
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 11
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 12
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 13
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 14
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 15
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 16
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 17
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 18
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 19
{ _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t }, // 20
{ _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t }, // 21
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 0
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 1
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 3
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 4
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 5
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 7
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 8
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 19
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 20
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 21
};
// check if two values compare unordered as expected
@@ -298,30 +301,31 @@ TEST_CASE("lexicographical comparison operators")
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
SECTION("compares unordered (inverse)")
{
std::vector<std::vector<bool>> expected = {
std::vector<std::vector<bool>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 0
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 1
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 2
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 3
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 4
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 5
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 6
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 7
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 10
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 11
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 12
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 13
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 14
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 15
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 16
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 17
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 18
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 19
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 14
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 15
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 16
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 17
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 18
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
};
// check that two values compare unordered as expected (with legacy-mode enabled)
@@ -492,30 +496,31 @@ TEST_CASE("lexicographical comparison operators")
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
SECTION("comparison: 3-way")
{
std::vector<std::vector<std::partial_ordering>> expected = {
std::vector<std::vector<std::partial_ordering>> expected =
{
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
{ eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un }, // 0
{ eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un }, // 1
{ gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 2
{ gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 3
{ gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 4
{ gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 5
{ gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 6
{ gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 7
{ gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 8
{ gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 9
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un }, // 10
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un }, // 11
{ gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un }, // 12
{ gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un }, // 13
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un }, // 14
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un }, // 15
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un }, // 16
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un }, // 17
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un }, // 18
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un }, // 19
{ un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un }, // 20
{ un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un }, // 21
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 0
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 1
{gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 2
{gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 3
{gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 4
{gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 5
{gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 6
{gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 7
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 8
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 9
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 10
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 11
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un}, // 12
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un}, // 13
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un}, // 14
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un}, // 15
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un}, // 16
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un}, // 17
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un}, // 18
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un}, // 19
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 20
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 21
};
// check expected partial_ordering against expected booleans
@@ -547,7 +552,7 @@ TEST_CASE("lexicographical comparison operators")
{
CAPTURE(i)
CAPTURE(j)
CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
}
}
}
@@ -571,18 +576,20 @@ TEST_CASE("lexicographical comparison operators")
[1,2,[3,4,5],4,5]
)";
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& j) noexcept {
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{
// filter all number(2) elements
return j != json(2);
});
CHECK(j_object == json({ { "bar", { { "baz", 1 } } } }));
CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& j) noexcept {
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
{
return j != json(2);
});
CHECK(j_array == json({ 1, { 3, 4, 5 }, 4, 5 }));
CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
}
}
#endif
+4 -3
View File
@@ -52,7 +52,8 @@ TEST_CASE("concepts")
// X::size_type must return an unsigned integer
CHECK((std::is_unsigned<json::size_type>::value));
// X::size_type can represent any non-negative value of X::difference_type
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <= (std::numeric_limits<json::size_type>::max)());
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
(std::numeric_limits<json::size_type>::max)());
// the expression "X u" has the post-condition "u.empty()"
{
@@ -129,7 +130,7 @@ TEST_CASE("concepts")
SECTION("Swappable")
{
{
json j{ 1, 2, 3 };
json j {1, 2, 3};
json::iterator it1 = j.begin();
json::iterator it2 = j.end();
swap(it1, it2);
@@ -137,7 +138,7 @@ TEST_CASE("concepts")
CHECK(it2 == j.begin());
}
{
json j{ 1, 2, 3 };
json j {1, 2, 3};
json::const_iterator it1 = j.cbegin();
json::const_iterator it2 = j.cend();
swap(it1, it2);
+140 -186
View File
@@ -131,7 +131,7 @@ TEST_CASE("constructors")
SECTION("filled object")
{
json::object_t const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) }, { "d", json(false) }, { "e", json("string") }, { "f", json() } };
json::object_t const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
}
@@ -140,14 +140,12 @@ TEST_CASE("constructors")
SECTION("create an object (implicit)")
{
// reference object
json::object_t const o_reference{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
json::object_t const o_reference {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j_reference(o_reference);
SECTION("std::map<json::string_t, json>")
{
std::map<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
std::map<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
@@ -155,10 +153,11 @@ TEST_CASE("constructors")
SECTION("std::map<std::string, std::string> #600")
{
const std::map<std::string, std::string> m{
{ "a", "b" },
{ "c", "d" },
{ "e", "f" },
const std::map<std::string, std::string> m
{
{"a", "b"},
{"c", "d"},
{"e", "f"},
};
json const j(m);
@@ -167,8 +166,7 @@ TEST_CASE("constructors")
SECTION("std::map<const char*, json>")
{
std::map<const char*, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
std::map<const char*, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
@@ -176,8 +174,7 @@ TEST_CASE("constructors")
SECTION("std::multimap<json::string_t, json>")
{
std::multimap<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
std::multimap<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
@@ -185,8 +182,7 @@ TEST_CASE("constructors")
SECTION("std::unordered_map<json::string_t, json>")
{
std::unordered_map<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
std::unordered_map<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
@@ -194,8 +190,7 @@ TEST_CASE("constructors")
SECTION("std::unordered_multimap<json::string_t, json>")
{
std::unordered_multimap<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
std::unordered_multimap<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json const j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
@@ -203,7 +198,7 @@ TEST_CASE("constructors")
SECTION("associative container literal")
{
json const j({ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) }, { "d", json(false) }, { "e", json("string") }, { "f", json() } });
json const j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
@@ -220,7 +215,7 @@ TEST_CASE("constructors")
SECTION("filled array")
{
json::array_t const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
json::array_t const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
}
@@ -229,12 +224,12 @@ TEST_CASE("constructors")
SECTION("create an array (implicit)")
{
// reference array
json::array_t const a_reference{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
json::array_t const a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j_reference(a_reference);
SECTION("std::list<json>")
{
std::list<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::list<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
@@ -242,7 +237,7 @@ TEST_CASE("constructors")
SECTION("std::pair")
{
std::pair<float, std::string> const p{ 1.0f, "string" };
std::pair<float, std::string> const p{1.0f, "string"};
json const j(p);
CHECK(j.type() == json::value_t::array);
@@ -254,7 +249,7 @@ TEST_CASE("constructors")
SECTION("std::pair with discarded values")
{
json const j{ 1, 2.0, "string" };
json const j{1, 2.0, "string"};
const auto p = j.get<std::pair<int, float>>();
CHECK(p.first == j[0]);
@@ -263,7 +258,7 @@ TEST_CASE("constructors")
SECTION("std::tuple")
{
const auto t = std::make_tuple(1.0, std::string{ "string" }, 42, std::vector<int>{ 0, 1 });
const auto t = std::make_tuple(1.0, std::string{"string"}, 42, std::vector<int> {0, 1});
json const j(t);
CHECK(j.type() == json::value_t::array);
@@ -278,7 +273,7 @@ TEST_CASE("constructors")
SECTION("std::tuple with discarded values")
{
json const j{ 1, 2.0, "string", 42 };
json const j{1, 2.0, "string", 42};
const auto t = j.get<std::tuple<int, float, std::string>>();
CHECK(std::get<0>(t) == j[0]);
@@ -288,7 +283,7 @@ TEST_CASE("constructors")
SECTION("std::pair/tuple/array failures")
{
json const j{ 1 };
json const j{1};
CHECK_THROWS_WITH_AS((j.get<std::pair<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
CHECK_THROWS_WITH_AS((j.get<std::tuple<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
@@ -297,7 +292,7 @@ TEST_CASE("constructors")
SECTION("std::forward_list<json>")
{
std::forward_list<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::forward_list<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
@@ -305,7 +300,7 @@ TEST_CASE("constructors")
SECTION("std::array<json, 6>")
{
std::array<json, 6> const a{ { json(1), json(1u), json(2.2), json(false), json("string"), json() } };
std::array<json, 6> const a {{json(1), json(1u), json(2.2), json(false), json("string"), json()}};
json const j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
@@ -316,10 +311,10 @@ TEST_CASE("constructors")
SECTION("std::valarray<int>")
{
std::valarray<int> const va = { 1, 2, 3, 4, 5 };
std::valarray<int> const va = {1, 2, 3, 4, 5};
json const j(va);
CHECK(j.type() == json::value_t::array);
CHECK(j == json({ 1, 2, 3, 4, 5 }));
CHECK(j == json({1, 2, 3, 4, 5}));
auto jva = j.get<std::valarray<int>>();
CHECK(jva.size() == va.size());
@@ -331,10 +326,10 @@ TEST_CASE("constructors")
SECTION("std::valarray<double>")
{
std::valarray<double> const va = { 1.2, 2.3, 3.4, 4.5, 5.6 };
std::valarray<double> const va = {1.2, 2.3, 3.4, 4.5, 5.6};
json const j(va);
CHECK(j.type() == json::value_t::array);
CHECK(j == json({ 1.2, 2.3, 3.4, 4.5, 5.6 }));
CHECK(j == json({1.2, 2.3, 3.4, 4.5, 5.6}));
auto jva = j.get<std::valarray<double>>();
CHECK(jva.size() == va.size());
@@ -346,7 +341,7 @@ TEST_CASE("constructors")
SECTION("std::vector<json>")
{
std::vector<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::vector<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
@@ -354,7 +349,7 @@ TEST_CASE("constructors")
SECTION("std::deque<json>")
{
std::deque<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::deque<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
@@ -362,7 +357,7 @@ TEST_CASE("constructors")
SECTION("std::set<json>")
{
std::set<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::set<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
// we cannot really check for equality here
@@ -370,7 +365,7 @@ TEST_CASE("constructors")
SECTION("std::unordered_set<json>")
{
std::unordered_set<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
std::unordered_set<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json const j(a);
CHECK(j.type() == json::value_t::array);
// we cannot really check for equality here
@@ -378,7 +373,7 @@ TEST_CASE("constructors")
SECTION("sequence container literal")
{
json const j({ json(1), json(1u), json(2.2), json(false), json("string"), json() });
json const j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
@@ -395,7 +390,7 @@ TEST_CASE("constructors")
SECTION("filled string")
{
json::string_t const s{ "Hello world" };
json::string_t const s {"Hello world"};
json const j(s);
CHECK(j.type() == json::value_t::string);
}
@@ -404,12 +399,12 @@ TEST_CASE("constructors")
SECTION("create a string (implicit)")
{
// reference string
json::string_t const s_reference{ "Hello world" };
json::string_t const s_reference {"Hello world"};
json const j_reference(s_reference);
SECTION("std::string")
{
std::string const s{ "Hello world" };
std::string const s {"Hello world"};
json const j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
@@ -417,7 +412,7 @@ TEST_CASE("constructors")
SECTION("char[]")
{
char const s[]{ "Hello world" }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
char const s[] {"Hello world"}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
json const j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
@@ -425,7 +420,7 @@ TEST_CASE("constructors")
SECTION("const char*")
{
const char* s{ "Hello world" };
const char* s {"Hello world"};
json const j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
@@ -462,7 +457,7 @@ TEST_CASE("constructors")
SECTION("from std::vector<bool>::reference")
{
std::vector<bool> v{ true };
std::vector<bool> v{true};
json const j(v[0]);
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::reference>::value);
CHECK(j.type() == json::value_t::boolean);
@@ -470,7 +465,7 @@ TEST_CASE("constructors")
SECTION("from std::vector<bool>::const_reference")
{
const std::vector<bool> v{ true };
const std::vector<bool> v{true};
json const j(v[0]);
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::const_reference>::value);
CHECK(j.type() == json::value_t::boolean);
@@ -488,7 +483,7 @@ TEST_CASE("constructors")
SECTION("filled binary")
{
json::binary_t const b({ 1, 2, 3 });
json::binary_t const b({1, 2, 3});
json const j(b);
CHECK(j.type() == json::value_t::binary);
}
@@ -842,7 +837,7 @@ TEST_CASE("constructors")
CHECK(j.type() == json::value_t::number_float);
// check round trip of NaN
json::number_float_t const d{ j };
json::number_float_t const d{j};
CHECK((std::isnan(d) && std::isnan(n)) == true);
// check that NaN is serialized to null
@@ -857,7 +852,7 @@ TEST_CASE("constructors")
CHECK(j.type() == json::value_t::number_float);
// check round trip of infinity
json::number_float_t const d{ j };
json::number_float_t const d{j};
CHECK(d == n);
// check that inf is serialized to null
@@ -923,13 +918,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{});
json const j(json::initializer_list_t {});
CHECK(j.type() == json::value_t::object);
}
SECTION("implicit")
{
json const j{};
json const j {};
CHECK(j.type() == json::value_t::null);
}
}
@@ -940,13 +935,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(json::array_t()) });
json const j(json::initializer_list_t {json(json::array_t())});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ json::array_t() };
json const j {json::array_t()};
CHECK(j.type() == json::value_t::array);
}
}
@@ -955,13 +950,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(json::object_t()) });
json const j(json::initializer_list_t {json(json::object_t())});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ json::object_t() };
json const j {json::object_t()};
CHECK(j.type() == json::value_t::array);
}
}
@@ -970,13 +965,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json("Hello world") });
json const j(json::initializer_list_t {json("Hello world")});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ "Hello world" };
json const j {"Hello world"};
CHECK(j.type() == json::value_t::array);
}
}
@@ -985,13 +980,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(true) });
json const j(json::initializer_list_t {json(true)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ true };
json const j {true};
CHECK(j.type() == json::value_t::array);
}
}
@@ -1000,13 +995,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(1) });
json const j(json::initializer_list_t {json(1)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ 1 };
json const j {1};
CHECK(j.type() == json::value_t::array);
}
}
@@ -1015,13 +1010,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(1u) });
json const j(json::initializer_list_t {json(1u)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ 1u };
json const j {1u};
CHECK(j.type() == json::value_t::array);
}
}
@@ -1030,13 +1025,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ json(42.23) });
json const j(json::initializer_list_t {json(42.23)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ 42.23 };
json const j {42.23};
CHECK(j.type() == json::value_t::array);
}
}
@@ -1046,13 +1041,13 @@ TEST_CASE("constructors")
{
SECTION("explicit")
{
json const j(json::initializer_list_t{ 1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t() });
json const j(json::initializer_list_t {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json const j{ 1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t() };
json const j {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
CHECK(j.type() == json::value_t::array);
}
}
@@ -1061,13 +1056,13 @@ TEST_CASE("constructors")
{
SECTION("object")
{
json const j{ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } };
json const j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} };
CHECK(j.type() == json::value_t::object);
}
SECTION("array")
{
json const j{ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false }, 13 };
json const j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 };
CHECK(j.type() == json::value_t::array);
}
}
@@ -1082,16 +1077,14 @@ TEST_CASE("constructors")
SECTION("object")
{
json const j = json::object({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } });
json const j = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
CHECK(j.type() == json::value_t::object);
}
SECTION("object with error")
{
json _;
CHECK_THROWS_WITH_AS(_ = json::object({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false }, 13 }),
"[json.exception.type_error.301] cannot create object from initializer list",
json::type_error&);
CHECK_THROWS_WITH_AS(_ = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), "[json.exception.type_error.301] cannot create object from initializer list", json::type_error&);
}
SECTION("empty array")
@@ -1102,7 +1095,7 @@ TEST_CASE("constructors")
SECTION("array")
{
json const j = json::array({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } });
json const j = json::array({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
CHECK(j.type() == json::value_t::array);
}
}
@@ -1116,7 +1109,7 @@ TEST_CASE("constructors")
// This should break through any short string optimization in std::string
std::string source(1024, '!');
const auto* source_addr = source.data();
json j = { std::move(source) };
json j = {std::move(source)};
const auto* target_addr = j[0].get_ref<std::string const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1127,7 +1120,7 @@ TEST_CASE("constructors")
// This should break through any short string optimization in std::string
std::string source(1024, '!');
const auto* source_addr = source.data();
json j = { { "key", std::move(source) } };
json j = {{"key", std::move(source)}};
const auto* target_addr = j["key"].get_ref<std::string const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1138,7 +1131,7 @@ TEST_CASE("constructors")
// This should break through any short string optimization in std::string
std::string source(1024, '!');
const auto* source_addr = source.data();
json j = { { std::move(source), 42 } };
json j = {{std::move(source), 42}};
const auto* target_addr = j.get_ref<json::object_t&>().begin()->first.data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1149,9 +1142,9 @@ TEST_CASE("constructors")
{
SECTION("constructor with implicit types (array)")
{
json::array_t source = { 1, 2, 3 };
json::array_t source = {1, 2, 3};
const auto* source_addr = source.data();
json j{ std::move(source) };
json j {std::move(source)};
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1159,9 +1152,9 @@ TEST_CASE("constructors")
SECTION("constructor with implicit types (object)")
{
json::array_t source = { 1, 2, 3 };
json::array_t source = {1, 2, 3};
const auto* source_addr = source.data();
json const j{ { "key", std::move(source) } };
json const j {{"key", std::move(source)}};
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1169,9 +1162,9 @@ TEST_CASE("constructors")
SECTION("assignment with implicit types (array)")
{
json::array_t source = { 1, 2, 3 };
json::array_t source = {1, 2, 3};
const auto* source_addr = source.data();
json j = { std::move(source) };
json j = {std::move(source)};
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1179,9 +1172,9 @@ TEST_CASE("constructors")
SECTION("assignment with implicit types (object)")
{
json::array_t source = { 1, 2, 3 };
json::array_t source = {1, 2, 3};
const auto* source_addr = source.data();
json j = { { "key", std::move(source) } };
json j = {{"key", std::move(source)}};
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
const bool success = (target_addr == source_addr);
CHECK(success);
@@ -1192,33 +1185,33 @@ TEST_CASE("constructors")
{
SECTION("constructor with implicit types (array)")
{
json::object_t source = { { "hello", "world" } };
json::object_t source = {{"hello", "world"}};
const json* source_addr = &source.at("hello");
json j{ std::move(source) };
json j {std::move(source)};
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json::object_t source = { { "hello", "world" } };
json::object_t source = {{"hello", "world"}};
const json* source_addr = &source.at("hello");
json j{ { "key", std::move(source) } };
json j {{"key", std::move(source)}};
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("assignment with implicit types (array)")
{
json::object_t source = { { "hello", "world" } };
json::object_t source = {{"hello", "world"}};
const json* source_addr = &source.at("hello");
json j = { std::move(source) };
json j = {std::move(source)};
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("assignment with implicit types (object)")
{
json::object_t source = { { "hello", "world" } };
json::object_t source = {{"hello", "world"}};
const json* source_addr = &source.at("hello");
json j = { { "key", std::move(source) } };
json j = {{"key", std::move(source)}};
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
}
@@ -1227,36 +1220,37 @@ TEST_CASE("constructors")
{
SECTION("constructor with implicit types (array)")
{
json source{ 1, 2, 3 };
json source {1, 2, 3};
const json* source_addr = &source[0];
json j{ std::move(source), {} };
json j {std::move(source), {}};
CHECK(&j[0][0] == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json source{ 1, 2, 3 };
json source {1, 2, 3};
const json* source_addr = &source[0];
json j{ { "key", std::move(source) } };
json j {{"key", std::move(source)}};
CHECK(&j["key"][0] == source_addr);
}
SECTION("assignment with implicit types (array)")
{
json source{ 1, 2, 3 };
json source {1, 2, 3};
const json* source_addr = &source[0];
json j = { std::move(source), {} };
json j = {std::move(source), {}};
CHECK(&j[0][0] == source_addr);
}
SECTION("assignment with implicit types (object)")
{
json source{ 1, 2, 3 };
json source {1, 2, 3};
const json* source_addr = &source[0];
json j = { { "key", std::move(source) } };
json j = {{"key", std::move(source)}};
CHECK(&j["key"][0] == source_addr);
}
}
}
}
@@ -1264,14 +1258,14 @@ TEST_CASE("constructors")
{
SECTION("cnt = 0")
{
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json const arr(0, v);
CHECK(arr.size() == 0);
}
SECTION("cnt = 1")
{
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json const arr(1, v);
CHECK(arr.size() == 1);
for (const auto& x : arr)
@@ -1282,7 +1276,7 @@ TEST_CASE("constructors")
SECTION("cnt = 3")
{
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json const arr(3, v);
CHECK(arr.size() == 3);
for (const auto& x : arr)
@@ -1299,12 +1293,12 @@ TEST_CASE("constructors")
SECTION("json(begin(), end())")
{
{
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json const j_new(jobject.begin(), jobject.end());
CHECK(j_new == jobject);
}
{
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json const j_new(jobject.cbegin(), jobject.cend());
CHECK(j_new == jobject);
}
@@ -1313,12 +1307,12 @@ TEST_CASE("constructors")
SECTION("json(begin(), begin())")
{
{
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json const j_new(jobject.begin(), jobject.begin());
CHECK(j_new == json::object());
}
{
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json const j_new(jobject.cbegin(), jobject.cbegin());
CHECK(j_new == json::object());
}
@@ -1326,32 +1320,24 @@ TEST_CASE("constructors")
SECTION("construct from subrange")
{
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json const j_new(jobject.find("b"), jobject.find("e"));
CHECK(j_new == json({ { "b", 1 }, { "c", 17u }, { "d", false } }));
CHECK(j_new == json({{"b", 1}, {"c", 17u}, {"d", false}}));
}
SECTION("incompatible iterators")
{
{
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
json jobject2 = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
CHECK_THROWS_WITH_AS(json(jobject.begin(), jobject2.end()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jobject2.begin(), jobject.end()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
CHECK_THROWS_WITH_AS(json(jobject.begin(), jobject2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jobject2.begin(), jobject.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
}
{
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
json const jobject2 = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
CHECK_THROWS_WITH_AS(json(jobject.cbegin(), jobject2.cend()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jobject2.cbegin(), jobject.cend()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json const jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
CHECK_THROWS_WITH_AS(json(jobject.cbegin(), jobject2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jobject2.cbegin(), jobject.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
}
}
}
@@ -1361,12 +1347,12 @@ TEST_CASE("constructors")
SECTION("json(begin(), end())")
{
{
json jarray = { 1, 2, 3, 4, 5 };
json jarray = {1, 2, 3, 4, 5};
json const j_new(jarray.begin(), jarray.end());
CHECK(j_new == jarray);
}
{
json const jarray = { 1, 2, 3, 4, 5 };
json const jarray = {1, 2, 3, 4, 5};
json const j_new(jarray.cbegin(), jarray.cend());
CHECK(j_new == jarray);
}
@@ -1375,12 +1361,12 @@ TEST_CASE("constructors")
SECTION("json(begin(), begin())")
{
{
json jarray = { 1, 2, 3, 4, 5 };
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.begin(), jarray.begin());
CHECK(j_new == json::array());
}
{
json const jarray = { 1, 2, 3, 4, 5 };
json const jarray = {1, 2, 3, 4, 5};
json const j_new(jarray.cbegin(), jarray.cbegin());
CHECK(j_new == json::array());
}
@@ -1389,38 +1375,30 @@ TEST_CASE("constructors")
SECTION("construct from subrange")
{
{
json jarray = { 1, 2, 3, 4, 5 };
json jarray = {1, 2, 3, 4, 5};
json const j_new(jarray.begin() + 1, jarray.begin() + 3);
CHECK(j_new == json({ 2, 3 }));
CHECK(j_new == json({2, 3}));
}
{
json const jarray = { 1, 2, 3, 4, 5 };
json const jarray = {1, 2, 3, 4, 5};
json const j_new(jarray.cbegin() + 1, jarray.cbegin() + 3);
CHECK(j_new == json({ 2, 3 }));
CHECK(j_new == json({2, 3}));
}
}
SECTION("incompatible iterators")
{
{
json jarray = { 1, 2, 3, 4 };
json jarray2 = { 2, 3, 4, 5 };
CHECK_THROWS_WITH_AS(json(jarray.begin(), jarray2.end()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jarray2.begin(), jarray.end()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
json jarray = {1, 2, 3, 4};
json jarray2 = {2, 3, 4, 5};
CHECK_THROWS_WITH_AS(json(jarray.begin(), jarray2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jarray2.begin(), jarray.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
}
{
json const jarray = { 1, 2, 3, 4 };
json const jarray2 = { 2, 3, 4, 5 };
CHECK_THROWS_WITH_AS(json(jarray.cbegin(), jarray2.cend()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jarray2.cbegin(), jarray.cend()),
"[json.exception.invalid_iterator.201] iterators are not compatible",
json::invalid_iterator&);
json const jarray = {1, 2, 3, 4};
json const jarray2 = {2, 3, 4, 5};
CHECK_THROWS_WITH_AS(json(jarray.cbegin(), jarray2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(jarray2.cbegin(), jarray.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
}
}
}
@@ -1433,15 +1411,11 @@ TEST_CASE("constructors")
{
{
json j;
CHECK_THROWS_WITH_AS(json(j.begin(), j.end()),
"[json.exception.invalid_iterator.206] cannot construct with iterators from null",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.end()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null", json::invalid_iterator&);
}
{
json const j;
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cend()),
"[json.exception.invalid_iterator.206] cannot construct with iterators from null",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cend()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null", json::invalid_iterator&);
}
}
@@ -1518,12 +1492,12 @@ TEST_CASE("constructors")
SECTION("binary")
{
{
json j = json::binary({ 1, 2, 3 });
json j = json::binary({1, 2, 3});
json const j_new(j.begin(), j.end());
CHECK((j == j_new));
}
{
json const j = json::binary({ 1, 2, 3 });
json const j = json::binary({1, 2, 3});
json const j_new(j.cbegin(), j.cend());
CHECK((j == j_new));
}
@@ -1537,16 +1511,12 @@ TEST_CASE("constructors")
{
json j = "foo";
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json const j = "bar";
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
@@ -1555,16 +1525,12 @@ TEST_CASE("constructors")
{
json j = false;
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json const j = true;
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
@@ -1573,16 +1539,12 @@ TEST_CASE("constructors")
{
json j = 17;
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json const j = 17;
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
@@ -1591,16 +1553,12 @@ TEST_CASE("constructors")
{
json j = 17u;
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json const j = 17u;
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
@@ -1609,16 +1567,12 @@ TEST_CASE("constructors")
{
json j = 23.42;
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
{
json const j = 23.42;
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
"[json.exception.invalid_iterator.204] iterators out of range",
json::invalid_iterator&);
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
}
}
}

Some files were not shown because too many files have changed in this diff Show More