Merge branch 'develop' of https://github.com/nlohmann/json into issue2324

This commit is contained in:
Niels Lohmann 2020-12-30 20:23:07 +01:00
commit 581f92b601
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
40 changed files with 1193 additions and 557 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -14,7 +14,6 @@
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/3lCHrFUZANONKv7a)
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](https://nlohmann.github.io/json/doxygen/index.html)
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fnlohmann%2Fjson.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fnlohmann%2Fjson?ref=badge_shield)
[![GitHub Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
[![GitHub Downloads](https://img.shields.io/github/downloads/nlohmann/json/total)](https://github.com/nlohmann/json/releases)
[![GitHub Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](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.

View File

@ -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 &copy; 2013-2020 [Niels Lohmann](http://nlohmann.me)
Copyright &copy; 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 &copy; 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 &copy; 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 &copy; 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 &copy; 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/).

View File

@ -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

View File

@ -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;
}

View File

@ -3,6 +3,8 @@
#include <cstddef> // size_t, uint8_t
#include <functional> // hash
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
namespace detail

View File

@ -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;
}

View File

@ -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)

View 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);
}

View File

@ -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

View File

@ -3,6 +3,8 @@
#include <cstddef> // ptrdiff_t
#include <limits> // numeric_limits
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
namespace detail

View File

@ -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

View File

@ -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

View File

@ -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...

View File

@ -881,6 +881,7 @@ class serializer
}
};
JSON_ASSERT(byte < utf8d.size());
const std::uint8_t type = utf8d[byte];
codep = (state != UTF8_ACCEPT)

View File

@ -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();
}
////////////////////////

View File

@ -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

View File

@ -1,3 +1,5 @@
#pragma once
#undef JSON_HEDLEY_ALWAYS_INLINE
#undef JSON_HEDLEY_ARM_VERSION
#undef JSON_HEDLEY_ARM_VERSION_CHECK

View File

@ -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

View File

@ -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")

View File

@ -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);

View File

@ -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)
{

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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}");
}

View File

@ -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*")

View File

@ -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
}

View File

@ -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")

View File

@ -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>();

View File

@ -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 &&

View File

@ -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()));
}
}

View File

@ -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]";

View File

@ -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

File diff suppressed because it is too large Load Diff