Merge branch 'develop' of https://github.com/nlohmann/json into issue2324
This commit is contained in:
commit
581f92b601
50
.github/workflows/ubuntu.yml
vendored
50
.github/workflows/ubuntu.yml
vendored
@ -3,13 +3,61 @@ name: Ubuntu
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
gcc_build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install_gcc
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install gcc-10 g++-10
|
||||
shell: bash
|
||||
- name: cmake
|
||||
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
|
||||
env:
|
||||
CC: gcc-10
|
||||
CXX: g++-10
|
||||
- name: build
|
||||
run: cmake --build build --parallel 10
|
||||
- name: test
|
||||
run: cd build ; ctest -j 10 --output-on-failure
|
||||
|
||||
clang_build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install_gcc
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install clang-10
|
||||
shell: bash
|
||||
- name: cmake
|
||||
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
|
||||
env:
|
||||
CC: clang-10
|
||||
CXX: clang++-10
|
||||
- name: build
|
||||
run: cmake --build build --parallel 10
|
||||
- name: test
|
||||
run: cd build ; ctest -j 10 --output-on-failure
|
||||
|
||||
clang_build_cxx20:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install_gcc
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install clang-10
|
||||
shell: bash
|
||||
- name: cmake
|
||||
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_STANDARD_REQUIRED=ON
|
||||
env:
|
||||
CC: clang-10
|
||||
CXX: clang++-10
|
||||
- name: build
|
||||
run: cmake --build build --parallel 10
|
||||
- name: test
|
||||
|
14
.github/workflows/windows.yml
vendored
14
.github/workflows/windows.yml
vendored
@ -15,20 +15,6 @@ jobs:
|
||||
- name: test
|
||||
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
|
||||
|
||||
clang9:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: install Clang
|
||||
run: curl -fsSL -o LLVM9.exe https://releases.llvm.org/9.0.0/LLVM-9.0.0-win64.exe ; 7z x LLVM9.exe -y -o"C:/Program Files/LLVM"
|
||||
- name: cmake
|
||||
run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DJSON_BuildTests=On
|
||||
- name: build
|
||||
run: cmake --build build --parallel 10
|
||||
- name: test
|
||||
run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure
|
||||
|
||||
clang10:
|
||||
runs-on: windows-latest
|
||||
|
||||
|
21
.travis.yml
21
.travis.yml
@ -124,18 +124,6 @@ matrix:
|
||||
|
||||
# OSX / Clang
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.3
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.4
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10.2
|
||||
|
||||
@ -222,7 +210,7 @@ matrix:
|
||||
compiler: gcc
|
||||
env:
|
||||
- COMPILER=g++-9
|
||||
- CXXFLAGS=-std=c++2a
|
||||
- CXX_STANDARD=17
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
@ -306,11 +294,11 @@ matrix:
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang++-7
|
||||
- CXXFLAGS=-std=c++1z
|
||||
- CXX_STANDARD=17
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
|
||||
packages: ['g++-6', 'clang-7', 'ninja-build']
|
||||
packages: ['g++-7', 'clang-7', 'ninja-build']
|
||||
|
||||
################
|
||||
# build script #
|
||||
@ -333,6 +321,9 @@ script:
|
||||
# by default, use implicit conversions
|
||||
- if [[ "${IMPLICIT_CONVERSIONS}" == "" ]]; then export IMPLICIT_CONVERSIONS=ON; fi
|
||||
|
||||
# append CXX_STANDARD to CMAKE_OPTIONS if required
|
||||
- CMAKE_OPTIONS+=${CXX_STANDARD:+ -DCMAKE_CXX_STANDARD=$CXX_STANDARD -DCMAKE_CXX_STANDARD_REQUIRED=ON}
|
||||
|
||||
# compile and execute unit tests
|
||||
- mkdir -p build && cd build
|
||||
- cmake .. ${CMAKE_OPTIONS} -DJSON_MultipleHeaders=${MULTIPLE_HEADERS} -DJSON_ImplicitConversions=${IMPLICIT_CONVERSIONS} -DJSON_BuildTests=On -GNinja && cmake --build . --config Release
|
||||
|
@ -6,6 +6,15 @@ cmake_minimum_required(VERSION 3.1)
|
||||
##
|
||||
project(nlohmann_json VERSION 3.9.1 LANGUAGES CXX)
|
||||
|
||||
##
|
||||
## MAIN_PROJECT CHECK
|
||||
## determine if nlohmann_json is built as a subproject (using add_subdirectory) or if it is the main project
|
||||
##
|
||||
set(MAIN_PROJECT OFF)
|
||||
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(MAIN_PROJECT ON)
|
||||
endif()
|
||||
|
||||
##
|
||||
## INCLUDE
|
||||
##
|
||||
@ -21,8 +30,8 @@ if (POLICY CMP0077)
|
||||
cmake_policy(SET CMP0077 NEW)
|
||||
endif ()
|
||||
|
||||
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
|
||||
option(JSON_Install "Install CMake targets during install step." ON)
|
||||
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ${MAIN_PROJECT})
|
||||
option(JSON_Install "Install CMake targets during install step." ${MAIN_PROJECT})
|
||||
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
|
||||
option(JSON_ImplicitConversions "Enable implicit conversions." ON)
|
||||
|
||||
@ -101,9 +110,8 @@ CONFIGURE_FILE(
|
||||
## TESTS
|
||||
## create and configure the unit test target
|
||||
##
|
||||
include(CTest) #adds option BUILD_TESTING (default ON)
|
||||
|
||||
if(BUILD_TESTING AND JSON_BuildTests)
|
||||
if (JSON_BuildTests)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
4
Makefile
4
Makefile
@ -84,6 +84,7 @@ doctest:
|
||||
# -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
|
||||
# -Wno-padded: padding is nothing to warn about
|
||||
# -Wno-range-loop-analysis: items tests "for(const auto i...)"
|
||||
# -Wno-extra-semi-stmt: spurious warnings for semicolons after JSON_ASSERT()
|
||||
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
|
||||
# -Wno-weak-vtables: exception class is defined inline, but has virtual method
|
||||
pedantic_clang:
|
||||
@ -100,6 +101,7 @@ pedantic_clang:
|
||||
-Wno-missing-prototypes \
|
||||
-Wno-padded \
|
||||
-Wno-range-loop-analysis \
|
||||
-Wno-extra-semi-stmt \
|
||||
-Wno-switch-enum -Wno-covered-switch-default \
|
||||
-Wno-weak-vtables" cmake -S . -B cmake-build-pedantic -GNinja -DCMAKE_BUILD_TYPE=Debug -DJSON_MultipleHeaders=ON -DJSON_BuildTests=On
|
||||
cmake --build cmake-build-pedantic
|
||||
@ -608,7 +610,7 @@ ChangeLog.md:
|
||||
release:
|
||||
rm -fr release_files
|
||||
mkdir release_files
|
||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build
|
||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) meson.build LICENSE.MIT
|
||||
gpg --armor --detach-sig include.zip
|
||||
mv include.zip include.zip.asc release_files
|
||||
gpg --armor --detach-sig $(AMALGAMATED_FILE)
|
||||
|
31
README.md
31
README.md
@ -14,7 +14,6 @@
|
||||
[](https://wandbox.org/permlink/3lCHrFUZANONKv7a)
|
||||
[](https://nlohmann.github.io/json/doxygen/index.html)
|
||||
[](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fnlohmann%2Fjson?ref=badge_shield)
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
[](https://github.com/nlohmann/json/issues)
|
||||
@ -76,6 +75,7 @@ You can sponsor this library at [GitHub Sponsors](https://github.com/sponsors/nl
|
||||
- [Michael Hartmann](https://github.com/reFX-Mike)
|
||||
- [Stefan Hagen](https://github.com/sthagen)
|
||||
- [Steve Sperandeo](https://github.com/homer6)
|
||||
- [Robert Jefe Lindstädt](https://github.com/eljefedelrodeodeljefe)
|
||||
|
||||
Thanks everyone!
|
||||
|
||||
@ -231,6 +231,15 @@ Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if
|
||||
|
||||
If you are using [`wsjcpp`](https://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch.
|
||||
|
||||
If you are using [`CPM.cmake`](https://github.com/TheLartians/CPM.cmake), you can check this [`example`](https://github.com/TheLartians/CPM.cmake/tree/master/examples/json). After [adding CPM script](https://github.com/TheLartians/CPM.cmake#adding-cpm) to your project, implement the following snippet to your CMake:
|
||||
|
||||
```cmake
|
||||
CPMAddPackage(
|
||||
NAME nlohmann_json
|
||||
GITHUB_REPOSITORY nlohmann/json
|
||||
VERSION 3.9.1)
|
||||
```
|
||||
|
||||
### Pkg-config
|
||||
|
||||
If you are using bare Makefiles, you can use `pkg-config` to generate the include flags that point to where the library is installed:
|
||||
@ -247,7 +256,7 @@ json = dependency('nlohmann_json', required: true)
|
||||
|
||||
## Examples
|
||||
|
||||
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
|
||||
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
|
||||
|
||||
### JSON as first-class data type
|
||||
|
||||
@ -316,7 +325,7 @@ json j2 = {
|
||||
};
|
||||
```
|
||||
|
||||
Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a9ad7ec0bc1082ed09d10900fbb20a21f.html#a9ad7ec0bc1082ed09d10900fbb20a21f) and [`json::object()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aaf509a7c029100d292187068f61c99b8.html#aaf509a7c029100d292187068f61c99b8) will help:
|
||||
Note that in all these cases, you never need to "tell" the compiler which JSON value type you want to use. If you want to be explicit or express some edge cases, the functions [`json::array()`](https://nlohmann.github.io/json/api/basic_json/array/) and [`json::object()`](https://nlohmann.github.io/json/api/basic_json/object/) will help:
|
||||
|
||||
```cpp
|
||||
// a way to express the empty array []
|
||||
@ -351,7 +360,7 @@ auto j2 = R"(
|
||||
|
||||
Note that without appending the `_json` suffix, the passed string literal is not parsed, but just used as JSON string value. That is, `json j = "{ \"happy\": true, \"pi\": 3.141 }"` would just store the string `"{ "happy": true, "pi": 3.141 }"` rather than parsing the actual object.
|
||||
|
||||
The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a265a473e939184aa42655c9ccdf34e58.html#a265a473e939184aa42655c9ccdf34e58):
|
||||
The above example can also be expressed explicitly using [`json::parse()`](https://nlohmann.github.io/json/api/basic_json/parse/):
|
||||
|
||||
```cpp
|
||||
// parse explicitly
|
||||
@ -394,9 +403,9 @@ std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::
|
||||
std::cout << j_string << " == " << serialized_string << std::endl;
|
||||
```
|
||||
|
||||
[`.dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) always returns the serialized value, and [`.get<std::string>()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_aa6602bb24022183ab989439e19345d08.html#aa6602bb24022183ab989439e19345d08) returns the originally stored string value.
|
||||
[`.dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) returns the originally stored string value.
|
||||
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
|
||||
#### To/from streams (e.g. files, string streams)
|
||||
|
||||
@ -884,7 +893,7 @@ Some important things:
|
||||
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
|
||||
* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
|
||||
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
|
||||
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
|
||||
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/api/basic_json/at/) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
|
||||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
||||
|
||||
#### Simplify your life with macros
|
||||
@ -1222,10 +1231,6 @@ The following compilers are currently used in continuous integration at [Travis]
|
||||
|
||||
| Compiler | Operating System | CI Provider |
|
||||
|-----------------------------------------------------------------|--------------------|----------------|
|
||||
| Apple Clang 9.1.0 (clang-902.0.39.1); Xcode 9.3 | macOS 10.13.3 | Travis |
|
||||
| Apple Clang 9.1.0 (clang-902.0.39.2); Xcode 9.4.1 | macOS 10.13.6 | Travis |
|
||||
| Apple Clang 10.0.0 (clang-1000.11.45.2); Xcode 10.0 | macOS 10.13.6 | Travis |
|
||||
| Apple Clang 10.0.0 (clang-1000.11.45.5); Xcode 10.1 | macOS 10.13.6 | Travis |
|
||||
| Apple Clang 10.0.1 (clang-1001.0.46.4); Xcode 10.2.1 | macOS 10.14.4 | Travis |
|
||||
| Apple Clang 11.0.0 (clang-1100.0.33.12); Xcode 11.2.1 | macOS 10.14.6 | Travis |
|
||||
| Apple Clang 11.0.3 (clang-1103.0.32.59); Xcode 11.4.1 | macOS 10.15.4 | GitHub Actions |
|
||||
@ -1574,7 +1579,7 @@ The library supports **Unicode input** as follows:
|
||||
- [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) will not be replaced by the library.
|
||||
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
||||
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/api/basic_json/dump/) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
||||
|
||||
### Comments in JSON
|
||||
|
||||
@ -1608,7 +1613,7 @@ Here is a related issue [#1924](https://github.com/nlohmann/json/issues/1924).
|
||||
|
||||
### Further notes
|
||||
|
||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a233b02b0839ef798942dd46157cc0fe6.html#a233b02b0839ef798942dd46157cc0fe6) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a73ae333487310e3302135189ce8ff5d8.html#a73ae333487310e3302135189ce8ff5d8). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
|
||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/api/basic_json/operator%5B%5D/) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/api/basic_json/at/). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
|
||||
- As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
|
||||
- The code can be compiled without C++ **runtime type identification** features; that is, you can use the `-fno-rtti` compiler flag.
|
||||
- **Exceptions** are used widely within the library. They can, however, be switched off with either using the compiler flag `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION`. In this case, exceptions are replaced by `abort()` calls. You can further control this behavior by defining `JSON_THROW_USER` (overriding `throw`), `JSON_TRY_USER` (overriding `try`), and `JSON_CATCH_USER` (overriding `catch`). Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
|
||||
|
@ -1,10 +1,10 @@
|
||||
# License
|
||||
|
||||
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
|
||||
<img align="right" src="https://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
|
||||
|
||||
The class is licensed under the [MIT License](http://opensource.org/licenses/MIT):
|
||||
The class is licensed under the [MIT License](https://opensource.org/licenses/MIT):
|
||||
|
||||
Copyright © 2013-2020 [Niels Lohmann](http://nlohmann.me)
|
||||
Copyright © 2013-2020 [Niels Lohmann](https://nlohmann.me)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
@ -14,8 +14,8 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I
|
||||
|
||||
* * *
|
||||
|
||||
The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
|
||||
The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2008-2009 [Björn Hoehrmann](http://bjoern.hoehrmann.de/) <bjoern@hoehrmann.de>
|
||||
|
||||
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](http://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](http://florian.loitsch.com/)
|
||||
The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the [MIT License](https://opensource.org/licenses/MIT) (see above). Copyright © 2009 [Florian Loitsch](https://florian.loitsch.com/)
|
||||
|
||||
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](http://creativecommons.org/publicdomain/zero/1.0/).
|
||||
The class contains a copy of [Hedley](https://nemequ.github.io/hedley/) from Evan Nemerson which is licensed as [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Project information
|
||||
site_name: JSON for Modern C++
|
||||
site_author: Niels Lohmann
|
||||
site_url: https://squidfunk.github.io/mkdocs-material/
|
||||
site_url: https://json.nlohmann.me/
|
||||
|
||||
# Repository
|
||||
repo_name: nlohmann/json
|
||||
|
@ -39,15 +39,15 @@ class byte_container_with_subtype : public BinaryType
|
||||
: container_type(std::move(b))
|
||||
{}
|
||||
|
||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
|
||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype_) noexcept(noexcept(container_type(b)))
|
||||
: container_type(b)
|
||||
, m_subtype(subtype)
|
||||
, m_subtype(subtype_)
|
||||
, m_has_subtype(true)
|
||||
{}
|
||||
|
||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
|
||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype_) noexcept(noexcept(container_type(std::move(b))))
|
||||
: container_type(std::move(b))
|
||||
, m_subtype(subtype)
|
||||
, m_subtype(subtype_)
|
||||
, m_has_subtype(true)
|
||||
{}
|
||||
|
||||
@ -80,9 +80,9 @@ class byte_container_with_subtype : public BinaryType
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
void set_subtype(std::uint8_t subtype) noexcept
|
||||
void set_subtype(std::uint8_t subtype_) noexcept
|
||||
{
|
||||
m_subtype = subtype;
|
||||
m_subtype = subtype_;
|
||||
m_has_subtype = true;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <cstddef> // size_t, uint8_t
|
||||
#include <functional> // hash
|
||||
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // char_traits, string
|
||||
#include <utility> // make_pair, move
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
@ -2340,7 +2341,7 @@ class binary_reader
|
||||
break;
|
||||
}
|
||||
result.push_back(static_cast<typename string_t::value_type>(current));
|
||||
};
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -371,15 +371,37 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
|
||||
}
|
||||
|
||||
// Convenience shorthand from container to iterator
|
||||
template<typename ContainerType>
|
||||
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
|
||||
{
|
||||
// Enable ADL
|
||||
using std::begin;
|
||||
using std::end;
|
||||
// Enables ADL on begin(container) and end(container)
|
||||
// Encloses the using declarations in namespace for not to leak them to outside scope
|
||||
|
||||
namespace container_input_adapter_factory_impl
|
||||
{
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
template<typename ContainerType, typename Enable = void>
|
||||
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>())));
|
||||
|
||||
static adapter_type create(const ContainerType& container)
|
||||
{
|
||||
return input_adapter(begin(container), end(container));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
|
||||
{
|
||||
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
|
||||
}
|
||||
|
||||
// Special cases with fast paths
|
||||
inline file_input_adapter input_adapter(std::FILE* file)
|
||||
|
@ -1541,17 +1541,17 @@ scan_number_done:
|
||||
// literals
|
||||
case 't':
|
||||
{
|
||||
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
|
||||
std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), 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 = {{'f', 'a', 'l', 's', 'e'}};
|
||||
std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), 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 = {{'n', 'u', 'l', 'l'}};
|
||||
std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
|
||||
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,10 @@ This class implements a both iterators (iterator and const_iterator) for the
|
||||
template<typename BasicJsonType>
|
||||
class iter_impl
|
||||
{
|
||||
/// 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>;
|
||||
/// allow basic_json to access private members
|
||||
friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
|
||||
friend other_iter_impl;
|
||||
friend BasicJsonType;
|
||||
friend iteration_proxy<iter_impl>;
|
||||
friend iteration_proxy_value<iter_impl>;
|
||||
@ -390,10 +392,11 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: equal
|
||||
@brief comparison: equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator==(const iter_impl& other) const
|
||||
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
|
||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
||||
@ -417,16 +420,17 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: not equal
|
||||
@brief comparison: not equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator!=(const iter_impl& other) const
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: smaller
|
||||
@brief comparison: smaller
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator<(const iter_impl& other) const
|
||||
@ -453,7 +457,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: less than or equal
|
||||
@brief comparison: less than or equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator<=(const iter_impl& other) const
|
||||
@ -462,7 +466,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: greater than
|
||||
@brief comparison: greater than
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator>(const iter_impl& other) const
|
||||
@ -471,7 +475,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: greater than or equal
|
||||
@brief comparison: greater than or equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator>=(const iter_impl& other) const
|
||||
@ -480,7 +484,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief add to iterator
|
||||
@brief add to iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl& operator+=(difference_type i)
|
||||
@ -509,7 +513,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief subtract from iterator
|
||||
@brief subtract from iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl& operator-=(difference_type i)
|
||||
@ -518,7 +522,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief add to iterator
|
||||
@brief add to iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl operator+(difference_type i) const
|
||||
@ -529,7 +533,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief addition of distance and iterator
|
||||
@brief addition of distance and iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
friend iter_impl operator+(difference_type i, const iter_impl& it)
|
||||
@ -540,7 +544,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief subtract from iterator
|
||||
@brief subtract from iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl operator-(difference_type i) const
|
||||
@ -551,7 +555,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return difference
|
||||
@brief return difference
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
difference_type operator-(const iter_impl& other) const
|
||||
@ -572,7 +576,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief access to successor
|
||||
@brief access to successor
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
reference operator[](difference_type n) const
|
||||
@ -603,7 +607,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the key of an object iterator
|
||||
@brief return the key of an object iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
const typename object_t::key_type& key() const
|
||||
@ -619,7 +623,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the value of an iterator
|
||||
@brief return the value of an iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
reference value() const
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <cstddef> // ptrdiff_t
|
||||
#include <limits> // numeric_limits
|
||||
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
|
@ -17,19 +17,14 @@ class json_ref
|
||||
|
||||
json_ref(value_type&& value)
|
||||
: owned_value(std::move(value))
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
json_ref(const value_type& value)
|
||||
: value_ref(const_cast<value_type*>(&value))
|
||||
, is_rvalue(false)
|
||||
: value_ref(&value)
|
||||
{}
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@ -37,8 +32,6 @@ class json_ref
|
||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
||||
json_ref(Args && ... args)
|
||||
: owned_value(std::forward<Args>(args)...)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
// class should be movable only
|
||||
@ -50,27 +43,26 @@ class json_ref
|
||||
|
||||
value_type moved_or_copied() const
|
||||
{
|
||||
if (is_rvalue)
|
||||
if (value_ref == nullptr)
|
||||
{
|
||||
return std::move(*value_ref);
|
||||
return std::move(owned_value);
|
||||
}
|
||||
return *value_ref;
|
||||
}
|
||||
|
||||
value_type const& operator*() const
|
||||
{
|
||||
return *static_cast<value_type const*>(value_ref);
|
||||
return value_ref ? *value_ref : owned_value;
|
||||
}
|
||||
|
||||
value_type const* operator->() const
|
||||
{
|
||||
return static_cast<value_type const*>(value_ref);
|
||||
return &** this;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type* value_ref = nullptr;
|
||||
const bool is_rvalue = true;
|
||||
value_type const* value_ref = nullptr;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
@ -2,19 +2,32 @@
|
||||
|
||||
#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>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// alias templates to reduce boilerplate
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
template<typename T>
|
||||
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
|
||||
// implementation of C++14 index_sequence and affiliates
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
|
||||
// the following utilities are natively available in C++14
|
||||
using std::enable_if_t;
|
||||
using std::index_sequence;
|
||||
using std::make_index_sequence;
|
||||
using std::index_sequence_for;
|
||||
|
||||
#else
|
||||
|
||||
// alias templates to reduce boilerplate
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
// source: https://stackoverflow.com/a/32223343
|
||||
template<std::size_t... Ints>
|
||||
struct index_sequence
|
||||
@ -45,6 +58,8 @@ template<> struct make_index_sequence<1> : index_sequence<0> {};
|
||||
template<typename... Ts>
|
||||
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> {};
|
||||
@ -58,5 +73,6 @@ struct static_const
|
||||
|
||||
template<typename T>
|
||||
constexpr T static_const<T>::value;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <limits> // numeric_limits
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
#include <tuple> // tuple
|
||||
|
||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
@ -168,7 +169,9 @@ struct is_iterator_traits<iterator_traits<T>>
|
||||
is_detected<reference_t, traits>::value;
|
||||
};
|
||||
|
||||
// source: https://stackoverflow.com/a/37193089/4116453
|
||||
// The following implementation of is_complete_type is taken from
|
||||
// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
|
||||
// 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 {};
|
||||
@ -186,7 +189,6 @@ struct is_compatible_object_type_impl <
|
||||
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...
|
||||
|
@ -881,6 +881,7 @@ class serializer
|
||||
}
|
||||
};
|
||||
|
||||
JSON_ASSERT(byte < utf8d.size());
|
||||
const std::uint8_t type = utf8d[byte];
|
||||
|
||||
codep = (state != UTF8_ACCEPT)
|
||||
|
@ -73,6 +73,10 @@ SOFTWARE.
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <nlohmann/ordered_map.hpp>
|
||||
|
||||
#if defined(JSON_HAS_CPP_17)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@ -923,14 +927,14 @@ class basic_json
|
||||
AllocatorType<T> alloc;
|
||||
using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
|
||||
|
||||
auto deleter = [&](T * object)
|
||||
auto deleter = [&](T * obj)
|
||||
{
|
||||
AllocatorTraits::deallocate(alloc, object, 1);
|
||||
AllocatorTraits::deallocate(alloc, obj, 1);
|
||||
};
|
||||
std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
|
||||
AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
|
||||
JSON_ASSERT(object != nullptr);
|
||||
return object.release();
|
||||
std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
|
||||
AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
|
||||
JSON_ASSERT(obj != nullptr);
|
||||
return obj.release();
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
@ -168,6 +168,19 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
Container::push_back(value);
|
||||
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;
|
||||
|
||||
template<typename InputIt, typename = require_input_iter<InputIt>>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
for (auto it = first; it != last; ++it)
|
||||
{
|
||||
insert(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nlohmann
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#undef JSON_HEDLEY_ALWAYS_INLINE
|
||||
#undef JSON_HEDLEY_ARM_VERSION
|
||||
#undef JSON_HEDLEY_ARM_VERSION_CHECK
|
||||
|
@ -2736,19 +2736,33 @@ class other_error : public exception
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// alias templates to reduce boilerplate
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
template<typename T>
|
||||
using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
|
||||
// implementation of C++14 index_sequence and affiliates
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
|
||||
// the following utilities are natively available in C++14
|
||||
using std::enable_if_t;
|
||||
using std::index_sequence;
|
||||
using std::make_index_sequence;
|
||||
using std::index_sequence_for;
|
||||
|
||||
#else
|
||||
|
||||
// alias templates to reduce boilerplate
|
||||
template<bool B, typename T = void>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
// source: https://stackoverflow.com/a/32223343
|
||||
template<std::size_t... Ints>
|
||||
struct index_sequence
|
||||
@ -2779,6 +2793,8 @@ template<> struct make_index_sequence<1> : index_sequence<0> {};
|
||||
template<typename... Ts>
|
||||
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> {};
|
||||
@ -2792,6 +2808,7 @@ struct static_const
|
||||
|
||||
template<typename T>
|
||||
constexpr T static_const<T>::value;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@ -2801,6 +2818,7 @@ constexpr T static_const<T>::value;
|
||||
#include <limits> // numeric_limits
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
#include <tuple> // tuple
|
||||
|
||||
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
|
||||
@ -3174,7 +3192,9 @@ struct is_iterator_traits<iterator_traits<T>>
|
||||
is_detected<reference_t, traits>::value;
|
||||
};
|
||||
|
||||
// source: https://stackoverflow.com/a/37193089/4116453
|
||||
// The following implementation of is_complete_type is taken from
|
||||
// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
|
||||
// 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 {};
|
||||
@ -3192,7 +3212,6 @@ struct is_compatible_object_type_impl <
|
||||
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...
|
||||
@ -4515,15 +4534,15 @@ class byte_container_with_subtype : public BinaryType
|
||||
: container_type(std::move(b))
|
||||
{}
|
||||
|
||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
|
||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype_) noexcept(noexcept(container_type(b)))
|
||||
: container_type(b)
|
||||
, m_subtype(subtype)
|
||||
, m_subtype(subtype_)
|
||||
, m_has_subtype(true)
|
||||
{}
|
||||
|
||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b))))
|
||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype_) noexcept(noexcept(container_type(std::move(b))))
|
||||
: container_type(std::move(b))
|
||||
, m_subtype(subtype)
|
||||
, m_subtype(subtype_)
|
||||
, m_has_subtype(true)
|
||||
{}
|
||||
|
||||
@ -4556,9 +4575,9 @@ class byte_container_with_subtype : public BinaryType
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
void set_subtype(std::uint8_t subtype) noexcept
|
||||
void set_subtype(std::uint8_t subtype_) noexcept
|
||||
{
|
||||
m_subtype = subtype;
|
||||
m_subtype = subtype_;
|
||||
m_has_subtype = true;
|
||||
}
|
||||
|
||||
@ -4653,6 +4672,9 @@ class byte_container_with_subtype : public BinaryType
|
||||
#include <cstddef> // size_t, uint8_t
|
||||
#include <functional> // hash
|
||||
|
||||
// #include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
@ -4781,6 +4803,7 @@ std::size_t hash(const BasicJsonType& j)
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // char_traits, string
|
||||
#include <utility> // make_pair, move
|
||||
#include <vector> // vector
|
||||
|
||||
// #include <nlohmann/detail/exceptions.hpp>
|
||||
|
||||
@ -5160,15 +5183,37 @@ typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapte
|
||||
}
|
||||
|
||||
// Convenience shorthand from container to iterator
|
||||
template<typename ContainerType>
|
||||
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
|
||||
{
|
||||
// Enable ADL
|
||||
using std::begin;
|
||||
using std::end;
|
||||
// Enables ADL on begin(container) and end(container)
|
||||
// Encloses the using declarations in namespace for not to leak them to outside scope
|
||||
|
||||
namespace container_input_adapter_factory_impl
|
||||
{
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
template<typename ContainerType, typename Enable = void>
|
||||
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>())));
|
||||
|
||||
static adapter_type create(const ContainerType& container)
|
||||
{
|
||||
return input_adapter(begin(container), end(container));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename ContainerType>
|
||||
typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
|
||||
{
|
||||
return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
|
||||
}
|
||||
|
||||
// Special cases with fast paths
|
||||
inline file_input_adapter input_adapter(std::FILE* file)
|
||||
@ -7488,17 +7533,17 @@ scan_number_done:
|
||||
// literals
|
||||
case 't':
|
||||
{
|
||||
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
|
||||
std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), 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 = {{'f', 'a', 'l', 's', 'e'}};
|
||||
std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), 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 = {{'n', 'u', 'l', 'l'}};
|
||||
std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
|
||||
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
|
||||
}
|
||||
|
||||
@ -10047,7 +10092,7 @@ class binary_reader
|
||||
break;
|
||||
}
|
||||
result.push_back(static_cast<typename string_t::value_type>(current));
|
||||
};
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -10689,6 +10734,9 @@ class parser
|
||||
#include <cstddef> // ptrdiff_t
|
||||
#include <limits> // numeric_limits
|
||||
|
||||
// #include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
@ -10877,8 +10925,10 @@ This class implements a both iterators (iterator and const_iterator) for the
|
||||
template<typename BasicJsonType>
|
||||
class iter_impl
|
||||
{
|
||||
/// 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>;
|
||||
/// allow basic_json to access private members
|
||||
friend iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
|
||||
friend other_iter_impl;
|
||||
friend BasicJsonType;
|
||||
friend iteration_proxy<iter_impl>;
|
||||
friend iteration_proxy_value<iter_impl>;
|
||||
@ -11229,10 +11279,11 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: equal
|
||||
@brief comparison: equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator==(const iter_impl& other) const
|
||||
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
|
||||
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
|
||||
@ -11256,16 +11307,17 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: not equal
|
||||
@brief comparison: not equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator!=(const iter_impl& other) const
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: smaller
|
||||
@brief comparison: smaller
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator<(const iter_impl& other) const
|
||||
@ -11292,7 +11344,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: less than or equal
|
||||
@brief comparison: less than or equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator<=(const iter_impl& other) const
|
||||
@ -11301,7 +11353,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: greater than
|
||||
@brief comparison: greater than
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator>(const iter_impl& other) const
|
||||
@ -11310,7 +11362,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief comparison: greater than or equal
|
||||
@brief comparison: greater than or equal
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
bool operator>=(const iter_impl& other) const
|
||||
@ -11319,7 +11371,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief add to iterator
|
||||
@brief add to iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl& operator+=(difference_type i)
|
||||
@ -11348,7 +11400,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief subtract from iterator
|
||||
@brief subtract from iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl& operator-=(difference_type i)
|
||||
@ -11357,7 +11409,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief add to iterator
|
||||
@brief add to iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl operator+(difference_type i) const
|
||||
@ -11368,7 +11420,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief addition of distance and iterator
|
||||
@brief addition of distance and iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
friend iter_impl operator+(difference_type i, const iter_impl& it)
|
||||
@ -11379,7 +11431,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief subtract from iterator
|
||||
@brief subtract from iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
iter_impl operator-(difference_type i) const
|
||||
@ -11390,7 +11442,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return difference
|
||||
@brief return difference
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
difference_type operator-(const iter_impl& other) const
|
||||
@ -11411,7 +11463,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief access to successor
|
||||
@brief access to successor
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
reference operator[](difference_type n) const
|
||||
@ -11442,7 +11494,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the key of an object iterator
|
||||
@brief return the key of an object iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
const typename object_t::key_type& key() const
|
||||
@ -11458,7 +11510,7 @@ class iter_impl
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the value of an iterator
|
||||
@brief return the value of an iterator
|
||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||
*/
|
||||
reference value() const
|
||||
@ -12605,19 +12657,14 @@ class json_ref
|
||||
|
||||
json_ref(value_type&& value)
|
||||
: owned_value(std::move(value))
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
json_ref(const value_type& value)
|
||||
: value_ref(const_cast<value_type*>(&value))
|
||||
, is_rvalue(false)
|
||||
: value_ref(&value)
|
||||
{}
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
@ -12625,8 +12672,6 @@ class json_ref
|
||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
||||
json_ref(Args && ... args)
|
||||
: owned_value(std::forward<Args>(args)...)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
// class should be movable only
|
||||
@ -12638,27 +12683,26 @@ class json_ref
|
||||
|
||||
value_type moved_or_copied() const
|
||||
{
|
||||
if (is_rvalue)
|
||||
if (value_ref == nullptr)
|
||||
{
|
||||
return std::move(*value_ref);
|
||||
return std::move(owned_value);
|
||||
}
|
||||
return *value_ref;
|
||||
}
|
||||
|
||||
value_type const& operator*() const
|
||||
{
|
||||
return *static_cast<value_type const*>(value_ref);
|
||||
return value_ref ? *value_ref : owned_value;
|
||||
}
|
||||
|
||||
value_type const* operator->() const
|
||||
{
|
||||
return static_cast<value_type const*>(value_ref);
|
||||
return &** this;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type* value_ref = nullptr;
|
||||
const bool is_rvalue = true;
|
||||
value_type const* value_ref = nullptr;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
@ -16392,6 +16436,7 @@ class serializer
|
||||
}
|
||||
};
|
||||
|
||||
JSON_ASSERT(byte < utf8d.size());
|
||||
const std::uint8_t type = utf8d[byte];
|
||||
|
||||
codep = (state != UTF8_ACCEPT)
|
||||
@ -16634,11 +16679,28 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
Container::push_back(value);
|
||||
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;
|
||||
|
||||
template<typename InputIt, typename = require_input_iter<InputIt>>
|
||||
void insert(InputIt first, InputIt last)
|
||||
{
|
||||
for (auto it = first; it != last; ++it)
|
||||
{
|
||||
insert(*it);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nlohmann
|
||||
|
||||
|
||||
#if defined(JSON_HAS_CPP_17)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@ -17489,14 +17551,14 @@ class basic_json
|
||||
AllocatorType<T> alloc;
|
||||
using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
|
||||
|
||||
auto deleter = [&](T * object)
|
||||
auto deleter = [&](T * obj)
|
||||
{
|
||||
AllocatorTraits::deallocate(alloc, object, 1);
|
||||
AllocatorTraits::deallocate(alloc, obj, 1);
|
||||
};
|
||||
std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
|
||||
AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
|
||||
JSON_ASSERT(object != nullptr);
|
||||
return object.release();
|
||||
std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
|
||||
AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
|
||||
JSON_ASSERT(obj != nullptr);
|
||||
return obj.release();
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
@ -25382,6 +25444,8 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
|
||||
#undef JSON_EXPLICIT
|
||||
|
||||
// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
|
||||
|
||||
|
||||
#undef JSON_HEDLEY_ALWAYS_INLINE
|
||||
#undef JSON_HEDLEY_ARM_VERSION
|
||||
#undef JSON_HEDLEY_ARM_VERSION_CHECK
|
||||
|
@ -867,8 +867,9 @@ TEST_CASE("Negative size of binary value")
|
||||
|
||||
0x00 // end marker
|
||||
};
|
||||
CHECK_THROWS_AS(json::from_bson(input), json::parse_error);
|
||||
CHECK_THROWS_WITH(json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1");
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_bson(input), json::parse_error);
|
||||
CHECK_THROWS_WITH(_ = json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON binary: byte array length cannot be negative, is -1");
|
||||
}
|
||||
|
||||
TEST_CASE("Unsupported BSON input")
|
||||
|
@ -1591,14 +1591,16 @@ TEST_CASE("CBOR")
|
||||
{
|
||||
// array with three empty byte strings
|
||||
std::vector<std::uint8_t> input = {0x83, 0x40, 0x40, 0x40};
|
||||
CHECK_NOTHROW(json::from_cbor(input));
|
||||
json _;
|
||||
CHECK_NOTHROW(_ = json::from_cbor(input));
|
||||
}
|
||||
|
||||
SECTION("binary in object")
|
||||
{
|
||||
// object mapping "foo" to empty byte string
|
||||
std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x40};
|
||||
CHECK_NOTHROW(json::from_cbor(input));
|
||||
json _;
|
||||
CHECK_NOTHROW(_ = json::from_cbor(input));
|
||||
}
|
||||
|
||||
SECTION("SAX callback with binary")
|
||||
@ -2551,8 +2553,9 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), b);
|
||||
|
||||
// check that parsing fails in error mode
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
|
||||
// check that parsing succeeds and gets original value in ignore mode
|
||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||
@ -2570,8 +2573,9 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
|
||||
|
||||
// check that parsing fails in error mode
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
|
||||
// check that parsing succeeds and gets original value in ignore mode
|
||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||
@ -2585,9 +2589,10 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
|
||||
|
||||
// check that parsing fails in all modes
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2602,8 +2607,9 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
|
||||
|
||||
// check that parsing fails in error mode
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
|
||||
// check that parsing succeeds and gets original value in ignore mode
|
||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||
@ -2618,9 +2624,10 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
|
||||
|
||||
// check that parsing fails in all modes
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2637,8 +2644,9 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
|
||||
|
||||
// check that parsing fails in error mode
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
|
||||
// check that parsing succeeds and gets original value in ignore mode
|
||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||
@ -2655,9 +2663,10 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
|
||||
|
||||
// check that parsing fails in all modes
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2678,8 +2687,9 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
|
||||
|
||||
// check that parsing fails in error mode
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
|
||||
// check that parsing succeeds and gets original value in ignore mode
|
||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||
@ -2700,9 +2710,10 @@ TEST_CASE("Tagged values")
|
||||
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
|
||||
|
||||
// check that parsing fails in all modes
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2717,8 +2728,9 @@ TEST_CASE("Tagged values")
|
||||
CHECK(vec == std::vector<std::uint8_t> {0xA1, 0x66, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, 0xD8, 0x2A, 0x44, 0xCA, 0xFE, 0xBA, 0xBE});
|
||||
|
||||
// parse error when parsing tagged value
|
||||
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
|
||||
CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8");
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error);
|
||||
CHECK_THROWS_WITH(_ = json::from_cbor(vec), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8");
|
||||
|
||||
// binary without subtype when tags are ignored
|
||||
json jb = json::from_cbor(vec, true, true, json::cbor_tag_handler_t::ignore);
|
||||
|
@ -135,7 +135,7 @@ TEST_CASE("lexer class")
|
||||
// store scan() result
|
||||
const auto res = scan_string(s.c_str());
|
||||
|
||||
CAPTURE(s);
|
||||
CAPTURE(s)
|
||||
|
||||
switch (c)
|
||||
{
|
||||
|
@ -509,7 +509,7 @@ TEST_CASE("parser class")
|
||||
CHECK(parser_helper("\"€\"").get<json::string_t>() == "€");
|
||||
CHECK(parser_helper("\"🎈\"").get<json::string_t>() == "🎈");
|
||||
|
||||
CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == u8"\U00013060");
|
||||
CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
|
||||
CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "🌞");
|
||||
}
|
||||
}
|
||||
@ -1879,7 +1879,8 @@ TEST_CASE("parser class")
|
||||
|
||||
SECTION("error messages for comments")
|
||||
{
|
||||
CHECK_THROWS_WITH_AS(json::parse("/a", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid comment; expecting '/' or '*' after '/'; last read: '/a'", json::parse_error);
|
||||
CHECK_THROWS_WITH_AS(json::parse("/*", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid comment; missing closing '*/'; last read: '/*<U+0000>'", json::parse_error);
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::parse("/a", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid comment; expecting '/' or '*' after '/'; last read: '/a'", json::parse_error);
|
||||
CHECK_THROWS_WITH_AS(_ = json::parse("/*", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid comment; missing closing '*/'; last read: '/*<U+0000>'", json::parse_error);
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +48,6 @@ using nlohmann::json;
|
||||
#define JSON_HAS_CPP_14
|
||||
#endif
|
||||
|
||||
#if defined(JSON_HAS_CPP_17)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
TEST_CASE("value conversion")
|
||||
{
|
||||
SECTION("get an object (explicit)")
|
||||
@ -1706,3 +1702,11 @@ TEST_CASE("JSON to enum mapping")
|
||||
CHECK(TS_INVALID == json("what?").get<TaskState>());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
#undef JSON_HAS_CPP_17
|
||||
#endif
|
||||
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
#undef JSON_HAS_CPP_14
|
||||
#endif
|
||||
|
@ -537,7 +537,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("with empty range")
|
||||
{
|
||||
std::vector<uint8_t> v;
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
SaxEventLogger l;
|
||||
@ -553,7 +554,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 1")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -569,7 +571,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 2")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -585,7 +588,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 3")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -601,7 +605,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 4")
|
||||
{
|
||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -617,7 +622,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 5")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xC1};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -652,7 +658,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 7")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -668,7 +675,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 8")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -684,7 +692,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 9")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -700,7 +709,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 10")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -716,7 +726,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 11")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -732,7 +743,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 12")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -748,7 +760,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 13")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -764,7 +777,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 14")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -780,7 +794,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 15")
|
||||
{
|
||||
uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
@ -796,7 +811,8 @@ TEST_CASE("deserialization")
|
||||
SECTION("case 16")
|
||||
{
|
||||
uint8_t v[] = {'{', '\"', '\"', ':', '1', '1'};
|
||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
json _;
|
||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||
|
||||
json j_error;
|
||||
|
@ -1448,3 +1448,11 @@ TEST_CASE("items()")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
#undef JSON_HAS_CPP_17
|
||||
#endif
|
||||
|
||||
#ifdef JSON_HAS_CPP_14
|
||||
#undef JSON_HAS_CPP_14
|
||||
#endif
|
||||
|
@ -76,4 +76,18 @@ TEST_CASE("ordered_json")
|
||||
CHECK(multi_ordered.dump() == "{\"z\":1,\"m\":2,\"y\":4}");
|
||||
CHECK(multi_ordered.erase("m") == 1);
|
||||
CHECK(multi_ordered.dump() == "{\"z\":1,\"y\":4}");
|
||||
|
||||
// Ranged insert test.
|
||||
// It seems that values shouldn't be overwritten. Only new values are added
|
||||
json j1 {{"c", 1}, {"b", 2}, {"a", 3}};
|
||||
const json j2 {{"c", 77}, {"d", 42}, {"a", 4}};
|
||||
j1.insert( j2.cbegin(), j2.cend() );
|
||||
CHECK(j1.size() == 4);
|
||||
CHECK(j1.dump() == "{\"a\":3,\"b\":2,\"c\":1,\"d\":42}");
|
||||
|
||||
ordered_json oj1 {{"c", 1}, {"b", 2}, {"a", 3}};
|
||||
const ordered_json oj2 {{"c", 77}, {"d", 42}, {"a", 4}};
|
||||
oj1.insert( oj2.cbegin(), oj2.cend() );
|
||||
CHECK(oj1.size() == 4);
|
||||
CHECK(oj1.dump() == "{\"c\":1,\"b\":2,\"a\":3,\"d\":42}");
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ TEST_CASE("regression tests 1")
|
||||
|
||||
SECTION("issue #146 - character following a surrogate pair is skipped")
|
||||
{
|
||||
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
|
||||
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == "\xf0\x93\x81\xa0\x61\x62\x63");
|
||||
}
|
||||
|
||||
SECTION("issue #171 - Cannot index by key of type static constexpr const char*")
|
||||
|
@ -51,6 +51,10 @@ using nlohmann::json;
|
||||
#include <variant>
|
||||
#endif
|
||||
|
||||
#ifdef JSON_HAS_CPP_20
|
||||
#include <span>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// for #1021
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -484,4 +488,14 @@ TEST_CASE("regression tests 2")
|
||||
json j = json::parse(ss, nullptr, true, true);
|
||||
CHECK(j.dump() == "{}");
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_20
|
||||
SECTION("issue #2546 - parsing containers of std::byte")
|
||||
{
|
||||
const char DATA[] = R"("Hello, world!")";
|
||||
const auto s = std::as_bytes(std::span(DATA));
|
||||
json j = json::parse(s);
|
||||
CHECK(j.dump() == "\"Hello, world!\"");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -805,12 +805,13 @@ TEST_CASE("UBJSON")
|
||||
std::vector<uint8_t> vec1 = {'H', 'i', '1'};
|
||||
CHECK(json::from_ubjson(vec1, true, false).is_discarded());
|
||||
|
||||
json _;
|
||||
std::vector<uint8_t> vec2 = {'H', 'i', 2, '1', 'A', '3'};
|
||||
CHECK_THROWS_WITH_AS(json::from_ubjson(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A", json::parse_error);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A", json::parse_error);
|
||||
std::vector<uint8_t> vec3 = {'H', 'i', 2, '1', '.'};
|
||||
CHECK_THROWS_WITH_AS(json::from_ubjson(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1.", json::parse_error);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1.", json::parse_error);
|
||||
std::vector<uint8_t> vec4 = {'H', 2, '1', '0'};
|
||||
CHECK_THROWS_WITH_AS(json::from_ubjson(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x02", json::parse_error);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x02", json::parse_error);
|
||||
}
|
||||
|
||||
SECTION("serialization")
|
||||
|
@ -112,13 +112,13 @@ static void to_json(BasicJsonType& j, country c)
|
||||
switch (c)
|
||||
{
|
||||
case country::china:
|
||||
j = u8"中华人民共和国";
|
||||
j = "中华人民共和国";
|
||||
return;
|
||||
case country::france:
|
||||
j = "France";
|
||||
return;
|
||||
case country::russia:
|
||||
j = u8"Российская Федерация";
|
||||
j = "Российская Федерация";
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
@ -201,9 +201,9 @@ static void from_json(const BasicJsonType& j, country& c)
|
||||
const auto str = j.template get<std::string>();
|
||||
static const std::map<std::string, country> m =
|
||||
{
|
||||
{u8"中华人民共和国", country::china},
|
||||
{"中华人民共和国", country::china},
|
||||
{"France", country::france},
|
||||
{u8"Российская Федерация", country::russia}
|
||||
{"Российская Федерация", country::russia}
|
||||
};
|
||||
|
||||
const auto it = m.find(str);
|
||||
@ -248,7 +248,7 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
|
||||
const udt::name n{"theo"};
|
||||
const udt::country c{udt::country::france};
|
||||
const udt::person sfinae_addict{a, n, c};
|
||||
const udt::person senior_programmer{{42}, {u8"王芳"}, udt::country::china};
|
||||
const udt::person senior_programmer{{42}, {"王芳"}, udt::country::china};
|
||||
const udt::address addr{"Paris"};
|
||||
const udt::contact cpp_programmer{sfinae_addict, addr};
|
||||
const udt::contact_book book{{"C++"}, {cpp_programmer, {senior_programmer, addr}}};
|
||||
@ -265,14 +265,14 @@ TEST_CASE("basic usage" * doctest::test_suite("udt"))
|
||||
|
||||
CHECK(
|
||||
json(book) ==
|
||||
u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json);
|
||||
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json);
|
||||
|
||||
}
|
||||
|
||||
SECTION("conversion from json via free-functions")
|
||||
{
|
||||
const auto big_json =
|
||||
u8R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json;
|
||||
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"_json;
|
||||
SECTION("via explicit calls to get")
|
||||
{
|
||||
const auto parsed_book = big_json.get<udt::contact_book>();
|
||||
|
@ -106,7 +106,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, met
|
||||
class person_with_private_alphabet
|
||||
{
|
||||
public:
|
||||
bool operator==(const person_with_private_alphabet& other)
|
||||
bool operator==(const person_with_private_alphabet& other) const
|
||||
{
|
||||
return a == other.a &&
|
||||
b == other.b &&
|
||||
@ -169,7 +169,7 @@ class person_with_private_alphabet
|
||||
class person_with_public_alphabet
|
||||
{
|
||||
public:
|
||||
bool operator==(const person_with_public_alphabet& other)
|
||||
bool operator==(const person_with_public_alphabet& other) const
|
||||
{
|
||||
return a == other.a &&
|
||||
b == other.b &&
|
||||
|
@ -1201,7 +1201,8 @@ TEST_CASE("Unicode" * doctest::skip())
|
||||
SECTION("with an iterator")
|
||||
{
|
||||
std::string i = "\xef\xbb\xbf{\n \"foo\": true\n}";
|
||||
CHECK_NOTHROW(json::parse(i.begin(), i.end()));
|
||||
json _;
|
||||
CHECK_NOTHROW(_ = json::parse(i.begin(), i.end()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ const char* end(const MyContainer& c)
|
||||
return c.data + strlen(c.data);
|
||||
}
|
||||
|
||||
TEST_CASE("Custom container")
|
||||
TEST_CASE("Custom container non-member begin/end")
|
||||
{
|
||||
|
||||
MyContainer data{"[1,2,3,4]"};
|
||||
@ -75,6 +75,31 @@ TEST_CASE("Custom container")
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Custom container member begin/end")
|
||||
{
|
||||
struct MyContainer2
|
||||
{
|
||||
const char* data;
|
||||
|
||||
const char* begin() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
const char* end() const
|
||||
{
|
||||
return data + strlen(data);
|
||||
}
|
||||
};
|
||||
|
||||
MyContainer2 data{"[1,2,3,4]"};
|
||||
json as_json = json::parse(data);
|
||||
CHECK(as_json.at(0) == 1);
|
||||
CHECK(as_json.at(1) == 2);
|
||||
CHECK(as_json.at(2) == 3);
|
||||
CHECK(as_json.at(3) == 4);
|
||||
}
|
||||
|
||||
TEST_CASE("Custom iterator")
|
||||
{
|
||||
const char* raw_data = "[1,2,3,4]";
|
||||
|
4
test/thirdparty/doctest/LICENSE.txt
vendored
4
test/thirdparty/doctest/LICENSE.txt
vendored
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016-2019 Viktor Kirilov
|
||||
Copyright (c) 2016-2020 Viktor Kirilov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
998
test/thirdparty/doctest/doctest.h
vendored
Executable file → Normal file
998
test/thirdparty/doctest/doctest.h
vendored
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user