Merge branch 'develop' of https://github.com/nlohmann/json into clang_windows
Conflicts: include/nlohmann/detail/input/binary_reader.hpp include/nlohmann/detail/input/json_sax.hpp include/nlohmann/detail/input/lexer.hpp include/nlohmann/detail/input/parser.hpp include/nlohmann/detail/json_pointer.hpp include/nlohmann/detail/output/serializer.hpp include/nlohmann/json.hpp single_include/nlohmann/json.hpp
This commit is contained in:
		
						commit
						dc06f100be
					
				
					 28 changed files with 1441 additions and 910 deletions
				
			
		
							
								
								
									
										54
									
								
								.github/workflows/codeql-analysis.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.github/workflows/codeql-analysis.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
name: "Code scanning - action"
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [develop, ]
 | 
			
		||||
  pull_request:
 | 
			
		||||
    # The branches below must be a subset of the branches above
 | 
			
		||||
    branches: [develop]
 | 
			
		||||
  schedule:
 | 
			
		||||
    - cron: '0 19 * * 1'
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  CodeQL-Build:
 | 
			
		||||
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
    - name: Checkout repository
 | 
			
		||||
      uses: actions/checkout@v2
 | 
			
		||||
      with:
 | 
			
		||||
        # We must fetch at least the immediate parents so that if this is
 | 
			
		||||
        # a pull request then we can checkout the head.
 | 
			
		||||
        fetch-depth: 2
 | 
			
		||||
 | 
			
		||||
    # If this run was triggered by a pull request event, then checkout
 | 
			
		||||
    # the head of the pull request instead of the merge commit.
 | 
			
		||||
    - run: git checkout HEAD^2
 | 
			
		||||
      if: ${{ github.event_name == 'pull_request' }}
 | 
			
		||||
 | 
			
		||||
    # Initializes the CodeQL tools for scanning.
 | 
			
		||||
    - name: Initialize CodeQL
 | 
			
		||||
      uses: github/codeql-action/init@v1
 | 
			
		||||
      # Override language selection by uncommenting this and choosing your languages
 | 
			
		||||
      # with:
 | 
			
		||||
      #   languages: go, javascript, csharp, python, cpp, java
 | 
			
		||||
 | 
			
		||||
    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
 | 
			
		||||
    # If this step fails, then you should remove it and run the build manually (see below)
 | 
			
		||||
    - name: Autobuild
 | 
			
		||||
      uses: github/codeql-action/autobuild@v1
 | 
			
		||||
 | 
			
		||||
    # ℹ️ Command-line programs to run using the OS shell.
 | 
			
		||||
    # 📚 https://git.io/JvXDl
 | 
			
		||||
 | 
			
		||||
    # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
 | 
			
		||||
    #    and modify them (or add more) to build your code if your project
 | 
			
		||||
    #    uses a compiled language
 | 
			
		||||
 | 
			
		||||
    #- run: |
 | 
			
		||||
    #   make bootstrap
 | 
			
		||||
    #   make release
 | 
			
		||||
 | 
			
		||||
    - name: Perform CodeQL Analysis
 | 
			
		||||
      uses: github/codeql-action/analyze@v1
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +79,12 @@ if (MSVC)
 | 
			
		|||
    )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Install a pkg-config file, so other tools can find this.
 | 
			
		||||
CONFIGURE_FILE(
 | 
			
		||||
  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkg-config.pc.in"
 | 
			
		||||
  "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## TESTS
 | 
			
		||||
## create and configure the unit test target
 | 
			
		||||
| 
						 | 
				
			
			@ -139,4 +145,8 @@ endif()
 | 
			
		|||
        NAMESPACE ${PROJECT_NAME}::
 | 
			
		||||
        DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
 | 
			
		||||
    )
 | 
			
		||||
    install(
 | 
			
		||||
        FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc"
 | 
			
		||||
        DESTINATION lib/pkgconfig
 | 
			
		||||
    )
 | 
			
		||||
endif()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -97,6 +97,7 @@ doctest:
 | 
			
		|||
# -Wno-exit-time-destructors: warning in json code triggered by NLOHMANN_JSON_SERIALIZE_ENUM
 | 
			
		||||
# -Wno-float-equal: not all comparisons in the tests can be replaced by Approx
 | 
			
		||||
# -Wno-keyword-macro: unit-tests use "#define private public"
 | 
			
		||||
# -Wno-missing-prototypes: for NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
 | 
			
		||||
# -Wno-padded: padding is nothing to warn about
 | 
			
		||||
# -Wno-range-loop-analysis: items tests "for(const auto i...)"
 | 
			
		||||
# -Wno-switch-enum -Wno-covered-switch-default: pedantic/contradicting warnings about switches
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +114,7 @@ pedantic_clang:
 | 
			
		|||
		-Wno-exit-time-destructors \
 | 
			
		||||
		-Wno-float-equal \
 | 
			
		||||
		-Wno-keyword-macro \
 | 
			
		||||
		-Wno-missing-prototypes \
 | 
			
		||||
		-Wno-padded \
 | 
			
		||||
		-Wno-range-loop-analysis \
 | 
			
		||||
		-Wno-switch-enum -Wno-covered-switch-default \
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +255,7 @@ pedantic_gcc:
 | 
			
		|||
		-Wmismatched-tags                                 \
 | 
			
		||||
		-Wmissing-attributes                              \
 | 
			
		||||
		-Wmissing-braces                                  \
 | 
			
		||||
		-Wmissing-declarations                            \
 | 
			
		||||
		-Wno-missing-declarations                            \
 | 
			
		||||
		-Wmissing-field-initializers                      \
 | 
			
		||||
		-Wmissing-include-dirs                            \
 | 
			
		||||
		-Wmissing-profile                                 \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										53
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										53
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
- [Integration](#integration)
 | 
			
		||||
  - [CMake](#cmake)
 | 
			
		||||
  - [Package Managers](#package-managers)
 | 
			
		||||
  - [Pkg-config](#pkg-config)
 | 
			
		||||
- [Examples](#examples)
 | 
			
		||||
  - [JSON as first-class data type](#json-as-first-class-data-type)
 | 
			
		||||
  - [Serialization / Deserialization](#serialization--deserialization)
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +231,20 @@ Please file issues [here](https://github.com/build2-packaging/nlohmann-json) if
 | 
			
		|||
 | 
			
		||||
If you are using [`wsjcpp`](https://wsjcpp.org), you can use the command `wsjcpp install "https://github.com/nlohmann/json:develop"` to get the latest version. Note you can change the branch ":develop" to an existing tag or another branch.
 | 
			
		||||
 | 
			
		||||
### Pkg-config
 | 
			
		||||
 | 
			
		||||
If you are using bare Makefiles, you can use `pkg-config` to generate the include flags that point to where the library is installed:
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
pkg-config nlohmann_json --cflags
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Users of the Meson build system will also be able to use a system wide library, which will be found by `pkg-config`:
 | 
			
		||||
 | 
			
		||||
```meson
 | 
			
		||||
json = dependency('nlohmann_json', required: true)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
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)).
 | 
			
		||||
| 
						 | 
				
			
			@ -869,6 +884,42 @@ Some important things:
 | 
			
		|||
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
 | 
			
		||||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
 | 
			
		||||
 | 
			
		||||
#### Simplify your life with macros
 | 
			
		||||
 | 
			
		||||
If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.
 | 
			
		||||
 | 
			
		||||
There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
 | 
			
		||||
 | 
			
		||||
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
 | 
			
		||||
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.
 | 
			
		||||
 | 
			
		||||
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
 | 
			
		||||
 | 
			
		||||
##### Examples
 | 
			
		||||
 | 
			
		||||
The `to_json`/`from_json` functions for the `person` struct above can be created with:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
namespace ns {
 | 
			
		||||
    NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
namespace ns {
 | 
			
		||||
    class address {
 | 
			
		||||
      private:
 | 
			
		||||
        std::string street;
 | 
			
		||||
        int housenumber;
 | 
			
		||||
        int postcode;
 | 
			
		||||
        
 | 
			
		||||
      public:
 | 
			
		||||
        NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### How do I convert third-party types?
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1536,7 +1587,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).
 | 
			
		||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a233b02b0839ef798942dd46157cc0fe6.html#a233b02b0839ef798942dd46157cc0fe6) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a73ae333487310e3302135189ce8ff5d8.html#a73ae333487310e3302135189ce8ff5d8). Furthermore, you can define `JSON_ASSERT(x)` to replace calls to `assert(x)`.
 | 
			
		||||
- As the exact type of a number is not defined in the [JSON specification](https://tools.ietf.org/html/rfc8259.html), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
 | 
			
		||||
- 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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								cmake/pkg-config.pc.in
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								cmake/pkg-config.pc.in
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
Name: ${PROJECT_NAME}
 | 
			
		||||
Description: JSON for Modern C++
 | 
			
		||||
Version: ${PROJECT_VERSION}
 | 
			
		||||
Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +81,43 @@ Some important things:
 | 
			
		|||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Simplify your life with macros
 | 
			
		||||
 | 
			
		||||
If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.
 | 
			
		||||
 | 
			
		||||
There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
 | 
			
		||||
 | 
			
		||||
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
 | 
			
		||||
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.
 | 
			
		||||
 | 
			
		||||
In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
 | 
			
		||||
 | 
			
		||||
??? example
 | 
			
		||||
 | 
			
		||||
    The `to_json`/`from_json` functions for the `person` struct above can be created with:
 | 
			
		||||
    
 | 
			
		||||
    ```cpp
 | 
			
		||||
    namespace ns {
 | 
			
		||||
        NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
    
 | 
			
		||||
    Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:
 | 
			
		||||
    
 | 
			
		||||
    ```cpp
 | 
			
		||||
    namespace ns {
 | 
			
		||||
        class address {
 | 
			
		||||
          private:
 | 
			
		||||
            std::string street;
 | 
			
		||||
            int housenumber;
 | 
			
		||||
            int postcode;
 | 
			
		||||
            
 | 
			
		||||
          public:
 | 
			
		||||
            NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
## How do I convert third-party types?
 | 
			
		||||
 | 
			
		||||
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								doc/mkdocs/docs/features/macros.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								doc/mkdocs/docs/features/macros.md
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
# Supported Macros
 | 
			
		||||
 | 
			
		||||
Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header.
 | 
			
		||||
 | 
			
		||||
## `JSON_CATCH_USER(exception)`
 | 
			
		||||
 | 
			
		||||
This macro overrides `#!cpp catch` calls inside the library. The argument is the type of the exception to catch. As of version 3.8.0, the library only catches `std::out_of_range` exceptions internally to rethrow them as [`json::out_of_range`](../home/exceptions.md#out-of-range) exceptions. The macro is always followed by a scope.
 | 
			
		||||
 | 
			
		||||
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
 | 
			
		||||
 | 
			
		||||
## `JSON_NOEXCEPTION`
 | 
			
		||||
 | 
			
		||||
Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
 | 
			
		||||
When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`, 
 | 
			
		||||
`#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by `#!cpp std::abort()`.
 | 
			
		||||
 | 
			
		||||
The same effect is achieved by setting the compiler flag `-fno-exceptions`.
 | 
			
		||||
 | 
			
		||||
## `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`
 | 
			
		||||
 | 
			
		||||
When defined, the library will not create a compile error when a known unsupported compiler is detected. This allows to use the library with compilers that do not fully support C++11 and may only work if unsupported features are not used.
 | 
			
		||||
 | 
			
		||||
## `JSON_THROW_USER(exception)`
 | 
			
		||||
 | 
			
		||||
This macro overrides `#!cpp throw` calls inside the library. The argument is the exception to be thrown. Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
 | 
			
		||||
 | 
			
		||||
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
 | 
			
		||||
 | 
			
		||||
## `JSON_TRY_USER`
 | 
			
		||||
 | 
			
		||||
This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
 | 
			
		||||
 | 
			
		||||
See [Switch off exceptions](../home/exceptions.md#switch-off-exceptions) for an example.
 | 
			
		||||
 | 
			
		||||
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)`
 | 
			
		||||
 | 
			
		||||
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.
 | 
			
		||||
 | 
			
		||||
The macro is to be defined inside of the class/struct to create code for. Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members.
 | 
			
		||||
The first parameter is the name of the class/struct, and all remaining parameters name the members.
 | 
			
		||||
 | 
			
		||||
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
 | 
			
		||||
 | 
			
		||||
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
 | 
			
		||||
 | 
			
		||||
This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.
 | 
			
		||||
 | 
			
		||||
The macro is to be defined inside of the namespace of the class/struct to create code for. Private members cannot be accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios.
 | 
			
		||||
The first parameter is the name of the class/struct, and all remaining parameters name the members.
 | 
			
		||||
 | 
			
		||||
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.
 | 
			
		||||
 | 
			
		||||
## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
 | 
			
		||||
 | 
			
		||||
This macro simplifies the serialization/deserialization of enum types. See [Specializing enum conversion](enum_conversion.md) for more information.
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +32,24 @@ Exceptions are used widely within the library. They can, however, be switched of
 | 
			
		|||
 | 
			
		||||
Note that `JSON_THROW_USER` should leave the current scope (e.g., by throwing or aborting), as continuing after it may yield undefined behavior.
 | 
			
		||||
 | 
			
		||||
??? example
 | 
			
		||||
 | 
			
		||||
    The code below switches off exceptions and creates a log entry with a detailed error message in case of errors.
 | 
			
		||||
 | 
			
		||||
    ```cpp
 | 
			
		||||
    #include <iostream>
 | 
			
		||||
    
 | 
			
		||||
    #define JSON_TRY_USER if(true)
 | 
			
		||||
    #define JSON_CATCH_USER(exception) if(false)
 | 
			
		||||
    #define JSON_THROW_USER(exception)                           \
 | 
			
		||||
        {std::clog << "Error in " << __FILE__ << ":" << __LINE__ \
 | 
			
		||||
                   << " (function " << __FUNCTION__ << ") - "    \
 | 
			
		||||
                   << (exception).what() << std::endl;           \
 | 
			
		||||
         std::abort();}
 | 
			
		||||
    
 | 
			
		||||
    #include <nlohmann/json.hpp>
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
## Parse errors
 | 
			
		||||
 | 
			
		||||
This exception is thrown by the library when a parse error occurs. Parse errors
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,7 @@ nav:
 | 
			
		|||
    - features/json_patch.md
 | 
			
		||||
    - features/merge_patch.md
 | 
			
		||||
    - features/enum_conversion.md
 | 
			
		||||
    - features/macros.md
 | 
			
		||||
    - Parsing:
 | 
			
		||||
      - features/parsing/index.md
 | 
			
		||||
      - features/parsing/parse_exceptions.md
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array> // array
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cmath>   // signbit, isfinite
 | 
			
		||||
#include <cstdint> // intN_t, uintN_t
 | 
			
		||||
#include <cstring> // memcpy, memmove
 | 
			
		||||
| 
						 | 
				
			
			@ -63,8 +62,8 @@ struct diyfp // f * 2^e
 | 
			
		|||
    */
 | 
			
		||||
    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(x.e == y.e);
 | 
			
		||||
        assert(x.f >= y.f);
 | 
			
		||||
        JSON_ASSERT(x.e == y.e);
 | 
			
		||||
        JSON_ASSERT(x.f >= y.f);
 | 
			
		||||
 | 
			
		||||
        return {x.f - y.f, x.e};
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +139,7 @@ struct diyfp // f * 2^e
 | 
			
		|||
    */
 | 
			
		||||
    static diyfp normalize(diyfp x) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(x.f != 0);
 | 
			
		||||
        JSON_ASSERT(x.f != 0);
 | 
			
		||||
 | 
			
		||||
        while ((x.f >> 63u) == 0)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -159,8 +158,8 @@ struct diyfp // f * 2^e
 | 
			
		|||
    {
 | 
			
		||||
        const int delta = x.e - target_exponent;
 | 
			
		||||
 | 
			
		||||
        assert(delta >= 0);
 | 
			
		||||
        assert(((x.f << delta) >> delta) == x.f);
 | 
			
		||||
        JSON_ASSERT(delta >= 0);
 | 
			
		||||
        JSON_ASSERT(((x.f << delta) >> delta) == x.f);
 | 
			
		||||
 | 
			
		||||
        return {x.f << delta, target_exponent};
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -182,8 +181,8 @@ boundaries.
 | 
			
		|||
template<typename FloatType>
 | 
			
		||||
boundaries compute_boundaries(FloatType value)
 | 
			
		||||
{
 | 
			
		||||
    assert(std::isfinite(value));
 | 
			
		||||
    assert(value > 0);
 | 
			
		||||
    JSON_ASSERT(std::isfinite(value));
 | 
			
		||||
    JSON_ASSERT(value > 0);
 | 
			
		||||
 | 
			
		||||
    // Convert the IEEE representation into a diyfp.
 | 
			
		||||
    //
 | 
			
		||||
| 
						 | 
				
			
			@ -463,18 +462,18 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
 | 
			
		|||
    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
 | 
			
		||||
    // for |e| <= 1500, but doesn't require floating-point operations.
 | 
			
		||||
    // NB: log_10(2) ~= 78913 / 2^18
 | 
			
		||||
    assert(e >= -1500);
 | 
			
		||||
    assert(e <=  1500);
 | 
			
		||||
    JSON_ASSERT(e >= -1500);
 | 
			
		||||
    JSON_ASSERT(e <=  1500);
 | 
			
		||||
    const int f = kAlpha - e - 1;
 | 
			
		||||
    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
 | 
			
		||||
 | 
			
		||||
    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
 | 
			
		||||
    assert(index >= 0);
 | 
			
		||||
    assert(static_cast<std::size_t>(index) < kCachedPowers.size());
 | 
			
		||||
    JSON_ASSERT(index >= 0);
 | 
			
		||||
    JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
 | 
			
		||||
 | 
			
		||||
    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
 | 
			
		||||
    assert(kAlpha <= cached.e + e + 64);
 | 
			
		||||
    assert(kGamma >= cached.e + e + 64);
 | 
			
		||||
    JSON_ASSERT(kAlpha <= cached.e + e + 64);
 | 
			
		||||
    JSON_ASSERT(kGamma >= cached.e + e + 64);
 | 
			
		||||
 | 
			
		||||
    return cached;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -542,10 +541,10 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
 | 
			
		|||
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
 | 
			
		||||
                         std::uint64_t rest, std::uint64_t ten_k)
 | 
			
		||||
{
 | 
			
		||||
    assert(len >= 1);
 | 
			
		||||
    assert(dist <= delta);
 | 
			
		||||
    assert(rest <= delta);
 | 
			
		||||
    assert(ten_k > 0);
 | 
			
		||||
    JSON_ASSERT(len >= 1);
 | 
			
		||||
    JSON_ASSERT(dist <= delta);
 | 
			
		||||
    JSON_ASSERT(rest <= delta);
 | 
			
		||||
    JSON_ASSERT(ten_k > 0);
 | 
			
		||||
 | 
			
		||||
    //               <--------------------------- delta ---->
 | 
			
		||||
    //                                  <---- dist --------->
 | 
			
		||||
| 
						 | 
				
			
			@ -570,7 +569,7 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
 | 
			
		|||
            && delta - rest >= ten_k
 | 
			
		||||
            && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
 | 
			
		||||
    {
 | 
			
		||||
        assert(buf[len - 1] != '0');
 | 
			
		||||
        JSON_ASSERT(buf[len - 1] != '0');
 | 
			
		||||
        buf[len - 1]--;
 | 
			
		||||
        rest += ten_k;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -598,8 +597,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
    // Grisu2 generates the digits of M+ from left to right and stops as soon as
 | 
			
		||||
    // V is in [M-,M+].
 | 
			
		||||
 | 
			
		||||
    assert(M_plus.e >= kAlpha);
 | 
			
		||||
    assert(M_plus.e <= kGamma);
 | 
			
		||||
    JSON_ASSERT(M_plus.e >= kAlpha);
 | 
			
		||||
    JSON_ASSERT(M_plus.e <= kGamma);
 | 
			
		||||
 | 
			
		||||
    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
 | 
			
		||||
    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
 | 
			
		||||
| 
						 | 
				
			
			@ -620,7 +619,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
    //
 | 
			
		||||
    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
 | 
			
		||||
 | 
			
		||||
    assert(p1 > 0);
 | 
			
		||||
    JSON_ASSERT(p1 > 0);
 | 
			
		||||
 | 
			
		||||
    std::uint32_t pow10;
 | 
			
		||||
    const int k = find_largest_pow10(p1, pow10);
 | 
			
		||||
| 
						 | 
				
			
			@ -656,7 +655,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
 | 
			
		||||
        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
 | 
			
		||||
        //
 | 
			
		||||
        assert(d <= 9);
 | 
			
		||||
        JSON_ASSERT(d <= 9);
 | 
			
		||||
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
 | 
			
		||||
        //
 | 
			
		||||
        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
 | 
			
		||||
| 
						 | 
				
			
			@ -743,7 +742,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
    //
 | 
			
		||||
    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
 | 
			
		||||
 | 
			
		||||
    assert(p2 > delta);
 | 
			
		||||
    JSON_ASSERT(p2 > delta);
 | 
			
		||||
 | 
			
		||||
    int m = 0;
 | 
			
		||||
    for (;;)
 | 
			
		||||
| 
						 | 
				
			
			@ -754,7 +753,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
 | 
			
		||||
        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
 | 
			
		||||
        //
 | 
			
		||||
        assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
 | 
			
		||||
        JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
 | 
			
		||||
        p2 *= 10;
 | 
			
		||||
        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
 | 
			
		||||
        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
 | 
			
		||||
| 
						 | 
				
			
			@ -763,7 +762,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
 | 
			
		|||
        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
 | 
			
		||||
        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
 | 
			
		||||
        //
 | 
			
		||||
        assert(d <= 9);
 | 
			
		||||
        JSON_ASSERT(d <= 9);
 | 
			
		||||
        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
 | 
			
		||||
        //
 | 
			
		||||
        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
 | 
			
		||||
| 
						 | 
				
			
			@ -824,8 +823,8 @@ JSON_HEDLEY_NON_NULL(1)
 | 
			
		|||
inline void grisu2(char* buf, int& len, int& decimal_exponent,
 | 
			
		||||
                   diyfp m_minus, diyfp v, diyfp m_plus)
 | 
			
		||||
{
 | 
			
		||||
    assert(m_plus.e == m_minus.e);
 | 
			
		||||
    assert(m_plus.e == v.e);
 | 
			
		||||
    JSON_ASSERT(m_plus.e == m_minus.e);
 | 
			
		||||
    JSON_ASSERT(m_plus.e == v.e);
 | 
			
		||||
 | 
			
		||||
    //  --------(-----------------------+-----------------------)--------    (A)
 | 
			
		||||
    //          m-                      v                       m+
 | 
			
		||||
| 
						 | 
				
			
			@ -886,8 +885,8 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
 | 
			
		|||
    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
 | 
			
		||||
                  "internal error: not enough precision");
 | 
			
		||||
 | 
			
		||||
    assert(std::isfinite(value));
 | 
			
		||||
    assert(value > 0);
 | 
			
		||||
    JSON_ASSERT(std::isfinite(value));
 | 
			
		||||
    JSON_ASSERT(value > 0);
 | 
			
		||||
 | 
			
		||||
    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
 | 
			
		||||
    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
 | 
			
		||||
| 
						 | 
				
			
			@ -923,8 +922,8 @@ JSON_HEDLEY_NON_NULL(1)
 | 
			
		|||
JSON_HEDLEY_RETURNS_NON_NULL
 | 
			
		||||
inline char* append_exponent(char* buf, int e)
 | 
			
		||||
{
 | 
			
		||||
    assert(e > -1000);
 | 
			
		||||
    assert(e <  1000);
 | 
			
		||||
    JSON_ASSERT(e > -1000);
 | 
			
		||||
    JSON_ASSERT(e <  1000);
 | 
			
		||||
 | 
			
		||||
    if (e < 0)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -976,8 +975,8 @@ JSON_HEDLEY_RETURNS_NON_NULL
 | 
			
		|||
inline char* format_buffer(char* buf, int len, int decimal_exponent,
 | 
			
		||||
                           int min_exp, int max_exp)
 | 
			
		||||
{
 | 
			
		||||
    assert(min_exp < 0);
 | 
			
		||||
    assert(max_exp > 0);
 | 
			
		||||
    JSON_ASSERT(min_exp < 0);
 | 
			
		||||
    JSON_ASSERT(max_exp > 0);
 | 
			
		||||
 | 
			
		||||
    const int k = len;
 | 
			
		||||
    const int n = len + decimal_exponent;
 | 
			
		||||
| 
						 | 
				
			
			@ -1003,7 +1002,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
 | 
			
		|||
        // dig.its
 | 
			
		||||
        // len <= max_digits10 + 1
 | 
			
		||||
 | 
			
		||||
        assert(k > n);
 | 
			
		||||
        JSON_ASSERT(k > n);
 | 
			
		||||
 | 
			
		||||
        std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
 | 
			
		||||
        buf[n] = '.';
 | 
			
		||||
| 
						 | 
				
			
			@ -1061,7 +1060,7 @@ JSON_HEDLEY_RETURNS_NON_NULL
 | 
			
		|||
char* to_chars(char* first, const char* last, FloatType value)
 | 
			
		||||
{
 | 
			
		||||
    static_cast<void>(last); // maybe unused - fix warning
 | 
			
		||||
    assert(std::isfinite(value));
 | 
			
		||||
    JSON_ASSERT(std::isfinite(value));
 | 
			
		||||
 | 
			
		||||
    // Use signbit(value) instead of (value < 0) since signbit works for -0.
 | 
			
		||||
    if (std::signbit(value))
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,7 +1078,7 @@ char* to_chars(char* first, const char* last, FloatType value)
 | 
			
		|||
        return first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
 | 
			
		||||
    // Compute v = buffer * 10^decimal_exponent.
 | 
			
		||||
    // The decimal digits are stored in the buffer, which needs to be interpreted
 | 
			
		||||
| 
						 | 
				
			
			@ -1089,16 +1088,16 @@ char* to_chars(char* first, const char* last, FloatType value)
 | 
			
		|||
    int decimal_exponent = 0;
 | 
			
		||||
    dtoa_impl::grisu2(first, len, decimal_exponent, value);
 | 
			
		||||
 | 
			
		||||
    assert(len <= std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
    JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
 | 
			
		||||
    // Format the buffer like printf("%.*g", prec, value)
 | 
			
		||||
    constexpr int kMinExp = -4;
 | 
			
		||||
    // Use digits10 here to increase compatibility with version 2.
 | 
			
		||||
    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
 | 
			
		||||
 | 
			
		||||
    assert(last - first >= kMaxExp + 2);
 | 
			
		||||
    assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
    assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
 | 
			
		||||
    JSON_ASSERT(last - first >= kMaxExp + 2);
 | 
			
		||||
    JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
 | 
			
		||||
    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
 | 
			
		||||
 | 
			
		||||
    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
 | 
			
		||||
#include <algorithm> // generate_n
 | 
			
		||||
#include <array> // array
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cmath> // ldexp
 | 
			
		||||
#include <cstddef> // size_t
 | 
			
		||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +108,7 @@ class binary_reader
 | 
			
		|||
                break;
 | 
			
		||||
 | 
			
		||||
            default:            // LCOV_EXCL_LINE
 | 
			
		||||
                assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // strict mode: next byte must be EOF
 | 
			
		||||
| 
						 | 
				
			
			@ -717,8 +716,8 @@ class binary_reader
 | 
			
		|||
                {
 | 
			
		||||
                    const int exp = (half >> 10u) & 0x1Fu;
 | 
			
		||||
                    const unsigned int mant = half & 0x3FFu;
 | 
			
		||||
                    assert(0 <= exp&& exp <= 32);
 | 
			
		||||
                    assert(mant <= 1024);
 | 
			
		||||
                    JSON_ASSERT(0 <= exp&& exp <= 32);
 | 
			
		||||
                    JSON_ASSERT(mant <= 1024);
 | 
			
		||||
                    switch (exp)
 | 
			
		||||
                    {
 | 
			
		||||
                        case 0:
 | 
			
		||||
| 
						 | 
				
			
			@ -2295,7 +2294,7 @@ class binary_reader
 | 
			
		|||
                break;
 | 
			
		||||
 | 
			
		||||
            default:            // LCOV_EXCL_LINE
 | 
			
		||||
                assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return error_msg + " " + context + ": " + detail;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <array> // array
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cstddef> // size_t
 | 
			
		||||
#include <cstdio> //FILE *
 | 
			
		||||
#include <cstring> // strlen
 | 
			
		||||
| 
						 | 
				
			
			@ -297,13 +296,13 @@ class wide_string_input_adapter
 | 
			
		|||
        {
 | 
			
		||||
            fill_buffer<sizeof(WideCharType)>();
 | 
			
		||||
 | 
			
		||||
            assert(utf8_bytes_filled > 0);
 | 
			
		||||
            assert(utf8_bytes_index == 0);
 | 
			
		||||
            JSON_ASSERT(utf8_bytes_filled > 0);
 | 
			
		||||
            JSON_ASSERT(utf8_bytes_index == 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // use buffer
 | 
			
		||||
        assert(utf8_bytes_filled > 0);
 | 
			
		||||
        assert(utf8_bytes_index < utf8_bytes_filled);
 | 
			
		||||
        JSON_ASSERT(utf8_bytes_filled > 0);
 | 
			
		||||
        JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
 | 
			
		||||
        return utf8_bytes[utf8_bytes_index++];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <string> // string
 | 
			
		||||
#include <utility> // move
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +279,7 @@ class json_sax_dom_parser
 | 
			
		|||
                case 5:
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                default:
 | 
			
		||||
                    assert(false);
 | 
			
		||||
                    JSON_ASSERT(false);
 | 
			
		||||
                    // LCOV_EXCL_STOP
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +308,7 @@ class json_sax_dom_parser
 | 
			
		|||
            return &root;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 | 
			
		||||
        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 | 
			
		||||
 | 
			
		||||
        if (ref_stack.back()->is_array())
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -317,8 +316,8 @@ class json_sax_dom_parser
 | 
			
		|||
            return &(ref_stack.back()->m_value.array->back());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(ref_stack.back()->is_object());
 | 
			
		||||
        assert(object_element);
 | 
			
		||||
        JSON_ASSERT(ref_stack.back()->is_object());
 | 
			
		||||
        JSON_ASSERT(object_element);
 | 
			
		||||
        *object_element = BasicJsonType(std::forward<Value>(v));
 | 
			
		||||
        return object_element;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -447,8 +446,8 @@ class json_sax_dom_callback_parser
 | 
			
		|||
            *ref_stack.back() = discarded;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(!ref_stack.empty());
 | 
			
		||||
        assert(!keep_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!ref_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!keep_stack.empty());
 | 
			
		||||
        ref_stack.pop_back();
 | 
			
		||||
        keep_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -499,8 +498,8 @@ class json_sax_dom_callback_parser
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(!ref_stack.empty());
 | 
			
		||||
        assert(!keep_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!ref_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!keep_stack.empty());
 | 
			
		||||
        ref_stack.pop_back();
 | 
			
		||||
        keep_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -534,7 +533,7 @@ class json_sax_dom_callback_parser
 | 
			
		|||
                case 5:
 | 
			
		||||
                    JSON_THROW(*dynamic_cast<const detail::other_error*>(&ex));
 | 
			
		||||
                default:
 | 
			
		||||
                    assert(false);
 | 
			
		||||
                    JSON_ASSERT(false);
 | 
			
		||||
                    // LCOV_EXCL_STOP
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -565,7 +564,7 @@ class json_sax_dom_callback_parser
 | 
			
		|||
    template<typename Value>
 | 
			
		||||
    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
 | 
			
		||||
    {
 | 
			
		||||
        assert(!keep_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!keep_stack.empty());
 | 
			
		||||
 | 
			
		||||
        // do not handle this value if we know it would be added to a discarded
 | 
			
		||||
        // container
 | 
			
		||||
| 
						 | 
				
			
			@ -600,7 +599,7 @@ class json_sax_dom_callback_parser
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // we now only expect arrays and objects
 | 
			
		||||
        assert(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 | 
			
		||||
        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 | 
			
		||||
 | 
			
		||||
        // array
 | 
			
		||||
        if (ref_stack.back()->is_array())
 | 
			
		||||
| 
						 | 
				
			
			@ -610,9 +609,9 @@ class json_sax_dom_callback_parser
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // object
 | 
			
		||||
        assert(ref_stack.back()->is_object());
 | 
			
		||||
        JSON_ASSERT(ref_stack.back()->is_object());
 | 
			
		||||
        // check if we should store an element for the current key
 | 
			
		||||
        assert(!key_keep_stack.empty());
 | 
			
		||||
        JSON_ASSERT(!key_keep_stack.empty());
 | 
			
		||||
        const bool store_element = key_keep_stack.back();
 | 
			
		||||
        key_keep_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -621,7 +620,7 @@ class json_sax_dom_callback_parser
 | 
			
		|||
            return {false, nullptr};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(object_element);
 | 
			
		||||
        JSON_ASSERT(object_element);
 | 
			
		||||
        *object_element = std::move(value);
 | 
			
		||||
        return {true, object_element};
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -135,7 +135,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
    static char get_decimal_point() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        const auto* loc = localeconv();
 | 
			
		||||
        assert(loc != nullptr);
 | 
			
		||||
        JSON_ASSERT(loc != nullptr);
 | 
			
		||||
        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +161,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
    int get_codepoint()
 | 
			
		||||
    {
 | 
			
		||||
        // this function only makes sense after reading `\u`
 | 
			
		||||
        assert(current == 'u');
 | 
			
		||||
        JSON_ASSERT(current == 'u');
 | 
			
		||||
        int codepoint = 0;
 | 
			
		||||
 | 
			
		||||
        const auto factors = { 12u, 8u, 4u, 0u };
 | 
			
		||||
| 
						 | 
				
			
			@ -187,7 +187,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(0x0000 <= codepoint && codepoint <= 0xFFFF);
 | 
			
		||||
        JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
 | 
			
		||||
        return codepoint;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +208,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
    */
 | 
			
		||||
    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
 | 
			
		||||
    {
 | 
			
		||||
        assert(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
 | 
			
		||||
        JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
 | 
			
		||||
        add(current);
 | 
			
		||||
 | 
			
		||||
        for (auto range = ranges.begin(); range != ranges.end(); ++range)
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +249,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
        reset();
 | 
			
		||||
 | 
			
		||||
        // we entered the function by reading an open quote
 | 
			
		||||
        assert(current == '\"');
 | 
			
		||||
        JSON_ASSERT(current == '\"');
 | 
			
		||||
 | 
			
		||||
        while (true)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -369,7 +369,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
                            }
 | 
			
		||||
 | 
			
		||||
                            // result of the above calculation yields a proper codepoint
 | 
			
		||||
                            assert(0x00 <= codepoint && codepoint <= 0x10FFFF);
 | 
			
		||||
                            JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
 | 
			
		||||
 | 
			
		||||
                            // translate codepoint into bytes
 | 
			
		||||
                            if (codepoint < 0x80)
 | 
			
		||||
| 
						 | 
				
			
			@ -998,7 +998,7 @@ class lexer : public lexer_base<BasicJsonType>
 | 
			
		|||
 | 
			
		||||
            // all other characters are rejected outside scan_number()
 | 
			
		||||
            default:            // LCOV_EXCL_LINE
 | 
			
		||||
                assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
scan_number_minus:
 | 
			
		||||
| 
						 | 
				
			
			@ -1245,7 +1245,7 @@ scan_number_done:
 | 
			
		|||
            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
 | 
			
		||||
 | 
			
		||||
            // we checked the number format before
 | 
			
		||||
            assert(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
 | 
			
		||||
            if (errno == 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1261,7 +1261,7 @@ scan_number_done:
 | 
			
		|||
            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
 | 
			
		||||
 | 
			
		||||
            // we checked the number format before
 | 
			
		||||
            assert(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
 | 
			
		||||
            if (errno == 0)
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1278,7 +1278,7 @@ scan_number_done:
 | 
			
		|||
        strtof(value_float, token_buffer.data(), &endptr);
 | 
			
		||||
 | 
			
		||||
        // we checked the number format before
 | 
			
		||||
        assert(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 | 
			
		||||
 | 
			
		||||
        return token_type::value_float;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1292,7 +1292,7 @@ scan_number_done:
 | 
			
		|||
    token_type scan_literal(const char_type* literal_text, const std::size_t length,
 | 
			
		||||
                            token_type return_type)
 | 
			
		||||
    {
 | 
			
		||||
        assert(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
 | 
			
		||||
        JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
 | 
			
		||||
        for (std::size_t i = 1; i < length; ++i)
 | 
			
		||||
        {
 | 
			
		||||
            if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
 | 
			
		||||
| 
						 | 
				
			
			@ -1384,7 +1384,7 @@ scan_number_done:
 | 
			
		|||
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
 | 
			
		||||
        {
 | 
			
		||||
            assert(!token_string.empty());
 | 
			
		||||
            JSON_ASSERT(!token_string.empty());
 | 
			
		||||
            token_string.pop_back();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cmath> // isfinite
 | 
			
		||||
#include <cstdint> // uint8_t
 | 
			
		||||
#include <functional> // function
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +382,7 @@ class parser
 | 
			
		|||
                    // new value, we need to evaluate the new state first.
 | 
			
		||||
                    // By setting skip_to_state_evaluation to false, we
 | 
			
		||||
                    // are effectively jumping to the beginning of this if.
 | 
			
		||||
                    assert(!states.empty());
 | 
			
		||||
                    JSON_ASSERT(!states.empty());
 | 
			
		||||
                    states.pop_back();
 | 
			
		||||
                    skip_to_state_evaluation = true;
 | 
			
		||||
                    continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -439,7 +438,7 @@ class parser
 | 
			
		|||
                    // new value, we need to evaluate the new state first.
 | 
			
		||||
                    // By setting skip_to_state_evaluation to false, we
 | 
			
		||||
                    // are effectively jumping to the beginning of this if.
 | 
			
		||||
                    assert(!states.empty());
 | 
			
		||||
                    JSON_ASSERT(!states.empty());
 | 
			
		||||
                    states.pop_back();
 | 
			
		||||
                    skip_to_state_evaluation = true;
 | 
			
		||||
                    continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    explicit iter_impl(pointer object) noexcept : m_object(object)
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +171,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    void set_begin() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +208,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    void set_end() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -239,19 +239,19 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    reference operator*() const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                assert(m_it.object_iterator != m_object->m_value.object->end());
 | 
			
		||||
                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
 | 
			
		||||
                return m_it.object_iterator->second;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                assert(m_it.array_iterator != m_object->m_value.array->end());
 | 
			
		||||
                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
 | 
			
		||||
                return *m_it.array_iterator;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -276,19 +276,19 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    pointer operator->() const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
            case value_t::object:
 | 
			
		||||
            {
 | 
			
		||||
                assert(m_it.object_iterator != m_object->m_value.object->end());
 | 
			
		||||
                JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
 | 
			
		||||
                return &(m_it.object_iterator->second);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            case value_t::array:
 | 
			
		||||
            {
 | 
			
		||||
                assert(m_it.array_iterator != m_object->m_value.array->end());
 | 
			
		||||
                JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
 | 
			
		||||
                return &*m_it.array_iterator;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -321,7 +321,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    iter_impl& operator++()
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -364,7 +364,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    iter_impl& operator--()
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -402,7 +402,7 @@ class iter_impl
 | 
			
		|||
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +438,7 @@ class iter_impl
 | 
			
		|||
            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +486,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    iter_impl& operator+=(difference_type i)
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -557,7 +557,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    difference_type operator-(const iter_impl& other) const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +578,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    reference operator[](difference_type n) const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (m_object->m_type)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -609,7 +609,7 @@ class iter_impl
 | 
			
		|||
    */
 | 
			
		||||
    const typename object_t::key_type& key() const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,7 +74,7 @@ template<typename IteratorType> class iteration_proxy_value
 | 
			
		|||
    /// return key of the iterator
 | 
			
		||||
    const string_type& key() const
 | 
			
		||||
    {
 | 
			
		||||
        assert(anchor.m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(anchor.m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        switch (anchor.m_object->type())
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <algorithm> // all_of
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cctype> // isdigit
 | 
			
		||||
#include <limits> // max
 | 
			
		||||
#include <numeric> // accumulate
 | 
			
		||||
| 
						 | 
				
			
			@ -398,7 +397,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    BasicJsonType& get_and_create(BasicJsonType& j) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        auto result = &j;
 | 
			
		||||
 | 
			
		||||
        // in case no reference tokens exist, return a reference to the JSON value
 | 
			
		||||
| 
						 | 
				
			
			@ -471,7 +469,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        for (const auto& reference_token : reference_tokens)
 | 
			
		||||
        {
 | 
			
		||||
            // convert null values to arrays or objects before continuing
 | 
			
		||||
| 
						 | 
				
			
			@ -531,7 +528,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    BasicJsonType& get_checked(BasicJsonType* ptr) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        for (const auto& reference_token : reference_tokens)
 | 
			
		||||
        {
 | 
			
		||||
            switch (ptr->type())
 | 
			
		||||
| 
						 | 
				
			
			@ -581,7 +577,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        for (const auto& reference_token : reference_tokens)
 | 
			
		||||
        {
 | 
			
		||||
            switch (ptr->type())
 | 
			
		||||
| 
						 | 
				
			
			@ -624,7 +619,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        for (const auto& reference_token : reference_tokens)
 | 
			
		||||
        {
 | 
			
		||||
            switch (ptr->type())
 | 
			
		||||
| 
						 | 
				
			
			@ -665,7 +659,6 @@ class json_pointer
 | 
			
		|||
    */
 | 
			
		||||
    bool contains(const BasicJsonType* ptr) const
 | 
			
		||||
    {
 | 
			
		||||
        using size_type = typename BasicJsonType::size_type;
 | 
			
		||||
        for (const auto& reference_token : reference_tokens)
 | 
			
		||||
        {
 | 
			
		||||
            switch (ptr->type())
 | 
			
		||||
| 
						 | 
				
			
			@ -787,7 +780,7 @@ class json_pointer
 | 
			
		|||
                    pos != std::string::npos;
 | 
			
		||||
                    pos = reference_token.find_first_of('~', pos + 1))
 | 
			
		||||
            {
 | 
			
		||||
                assert(reference_token[pos] == '~');
 | 
			
		||||
                JSON_ASSERT(reference_token[pos] == '~');
 | 
			
		||||
 | 
			
		||||
                // ~ must be followed by 0 or 1
 | 
			
		||||
                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
 | 
			
		||||
| 
						 | 
				
			
			@ -822,7 +815,7 @@ class json_pointer
 | 
			
		|||
    static void replace_substring(std::string& s, const std::string& f,
 | 
			
		||||
                                  const std::string& t)
 | 
			
		||||
    {
 | 
			
		||||
        assert(!f.empty());
 | 
			
		||||
        JSON_ASSERT(!f.empty());
 | 
			
		||||
        for (auto pos = s.find(f);                // find first occurrence of f
 | 
			
		||||
                pos != std::string::npos;         // make sure f was found
 | 
			
		||||
                s.replace(pos, f.size(), t),      // replace with t, and
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,6 +77,12 @@
 | 
			
		|||
    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// allow to override assert
 | 
			
		||||
#if !defined(JSON_ASSERT)
 | 
			
		||||
    #include <cassert> // assert
 | 
			
		||||
    #define JSON_ASSERT(x) assert(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@brief macro to briefly define a mapping between an enum and JSON
 | 
			
		||||
@def NLOHMANN_JSON_SERIALIZE_ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -124,3 +130,44 @@
 | 
			
		|||
    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
 | 
			
		||||
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
 | 
			
		||||
    AllocatorType, JSONSerializer, BinaryType>
 | 
			
		||||
 | 
			
		||||
// Macros to simplify conversion from/to types
 | 
			
		||||
 | 
			
		||||
#define NLOHMANN_JSON_EXPAND( x ) x
 | 
			
		||||
#define NLOHMANN_JSON_GET_MACRO(_1,_2,_3,_4,_5,_6, _7, _8, _9, _10, _11, NAME,...) NAME
 | 
			
		||||
 | 
			
		||||
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, NLOHMANN_JSON_PASTE11, \
 | 
			
		||||
        NLOHMANN_JSON_PASTE10, NLOHMANN_JSON_PASTE9, NLOHMANN_JSON_PASTE8, NLOHMANN_JSON_PASTE7, \
 | 
			
		||||
        NLOHMANN_JSON_PASTE6, NLOHMANN_JSON_PASTE5, NLOHMANN_JSON_PASTE4, NLOHMANN_JSON_PASTE3, \
 | 
			
		||||
        NLOHMANN_JSON_PASTE2, NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
 | 
			
		||||
#define NLOHMANN_JSON_PASTE2(func,  v1)                                      func(v1)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE3(func,  v1, v2)                                  NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE4(func,  v1, v2, v3)                              NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE5(func,  v1, v2, v3, v4)                          NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE6(func,  v1, v2, v3, v4, v5)                      NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE7(func,  v1, v2, v3, v4, v5, v6)                  NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE8(func,  v1, v2, v3, v4, v5, v6, v7)              NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE9(func,  v1, v2, v3, v4, v5, v6, v7, v8)          NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9)      NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8, v9)
 | 
			
		||||
#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
 | 
			
		||||
 | 
			
		||||
#define NLOHMANN_JSON_TO(v1) j[#v1] = t.v1;
 | 
			
		||||
#define NLOHMANN_JSON_FROM(v1) j.at(#v1).get_to(t.v1);
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@brief macro
 | 
			
		||||
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
 | 
			
		||||
@since version 3.9.0
 | 
			
		||||
*/
 | 
			
		||||
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
 | 
			
		||||
    friend void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 | 
			
		||||
    friend void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@brief macro
 | 
			
		||||
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
 | 
			
		||||
@since version 3.9.0
 | 
			
		||||
*/
 | 
			
		||||
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
 | 
			
		||||
    void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 | 
			
		||||
    void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
// clean up
 | 
			
		||||
#undef JSON_ASSERT
 | 
			
		||||
#undef JSON_INTERNAL_CATCH
 | 
			
		||||
#undef JSON_CATCH
 | 
			
		||||
#undef JSON_THROW
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ class binary_writer
 | 
			
		|||
    */
 | 
			
		||||
    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
 | 
			
		||||
    {
 | 
			
		||||
        assert(oa);
 | 
			
		||||
        JSON_ASSERT(oa);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -754,7 +754,7 @@ class binary_writer
 | 
			
		|||
                bool prefix_required = true;
 | 
			
		||||
                if (use_type && !j.m_value.array->empty())
 | 
			
		||||
                {
 | 
			
		||||
                    assert(use_count);
 | 
			
		||||
                    JSON_ASSERT(use_count);
 | 
			
		||||
                    const CharType first_prefix = ubjson_prefix(j.front());
 | 
			
		||||
                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
 | 
			
		||||
                                                         [this, first_prefix](const BasicJsonType & v)
 | 
			
		||||
| 
						 | 
				
			
			@ -798,7 +798,7 @@ class binary_writer
 | 
			
		|||
 | 
			
		||||
                if (use_type && !j.m_value.binary->empty())
 | 
			
		||||
                {
 | 
			
		||||
                    assert(use_count);
 | 
			
		||||
                    JSON_ASSERT(use_count);
 | 
			
		||||
                    oa->write_character(to_char_type('$'));
 | 
			
		||||
                    oa->write_character('U');
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -842,7 +842,7 @@ class binary_writer
 | 
			
		|||
                bool prefix_required = true;
 | 
			
		||||
                if (use_type && !j.m_value.object->empty())
 | 
			
		||||
                {
 | 
			
		||||
                    assert(use_count);
 | 
			
		||||
                    JSON_ASSERT(use_count);
 | 
			
		||||
                    const CharType first_prefix = ubjson_prefix(j.front());
 | 
			
		||||
                    const bool same_prefix = std::all_of(j.begin(), j.end(),
 | 
			
		||||
                                                         [this, first_prefix](const BasicJsonType & v)
 | 
			
		||||
| 
						 | 
				
			
			@ -1134,7 +1134,7 @@ class binary_writer
 | 
			
		|||
 | 
			
		||||
            // LCOV_EXCL_START
 | 
			
		||||
            default:
 | 
			
		||||
                assert(false);
 | 
			
		||||
                JSON_ASSERT(false);
 | 
			
		||||
                return 0ul;
 | 
			
		||||
                // LCOV_EXCL_STOP
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1181,7 +1181,7 @@ class binary_writer
 | 
			
		|||
 | 
			
		||||
            // LCOV_EXCL_START
 | 
			
		||||
            default:
 | 
			
		||||
                assert(false);
 | 
			
		||||
                JSON_ASSERT(false);
 | 
			
		||||
                return;
 | 
			
		||||
                // LCOV_EXCL_STOP
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
 | 
			
		||||
#include <algorithm> // reverse, remove, fill, find, none_of
 | 
			
		||||
#include <array> // array
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <clocale> // localeconv, lconv
 | 
			
		||||
#include <cmath> // labs, isfinite, isnan, signbit
 | 
			
		||||
#include <cstddef> // size_t, ptrdiff_t
 | 
			
		||||
| 
						 | 
				
			
			@ -135,8 +134,8 @@ class serializer
 | 
			
		|||
                    }
 | 
			
		||||
 | 
			
		||||
                    // last element
 | 
			
		||||
                    assert(i != val.m_value.object->cend());
 | 
			
		||||
                    assert(std::next(i) == val.m_value.object->cend());
 | 
			
		||||
                    JSON_ASSERT(i != val.m_value.object->cend());
 | 
			
		||||
                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
 | 
			
		||||
                    o->write_characters(indent_string.c_str(), new_indent);
 | 
			
		||||
                    o->write_character('\"');
 | 
			
		||||
                    dump_escaped(i->first, ensure_ascii);
 | 
			
		||||
| 
						 | 
				
			
			@ -163,8 +162,8 @@ class serializer
 | 
			
		|||
                    }
 | 
			
		||||
 | 
			
		||||
                    // last element
 | 
			
		||||
                    assert(i != val.m_value.object->cend());
 | 
			
		||||
                    assert(std::next(i) == val.m_value.object->cend());
 | 
			
		||||
                    JSON_ASSERT(i != val.m_value.object->cend());
 | 
			
		||||
                    JSON_ASSERT(std::next(i) == val.m_value.object->cend());
 | 
			
		||||
                    o->write_character('\"');
 | 
			
		||||
                    dump_escaped(i->first, ensure_ascii);
 | 
			
		||||
                    o->write_characters("\":", 2);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +204,7 @@ class serializer
 | 
			
		|||
                    }
 | 
			
		||||
 | 
			
		||||
                    // last element
 | 
			
		||||
                    assert(!val.m_value.array->empty());
 | 
			
		||||
                    JSON_ASSERT(!val.m_value.array->empty());
 | 
			
		||||
                    o->write_characters(indent_string.c_str(), new_indent);
 | 
			
		||||
                    dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +225,7 @@ class serializer
 | 
			
		|||
                    }
 | 
			
		||||
 | 
			
		||||
                    // last element
 | 
			
		||||
                    assert(!val.m_value.array->empty());
 | 
			
		||||
                    JSON_ASSERT(!val.m_value.array->empty());
 | 
			
		||||
                    dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
 | 
			
		||||
 | 
			
		||||
                    o->write_character(']');
 | 
			
		||||
| 
						 | 
				
			
			@ -360,7 +359,7 @@ class serializer
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            default:            // LCOV_EXCL_LINE
 | 
			
		||||
                assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -559,7 +558,7 @@ class serializer
 | 
			
		|||
                        }
 | 
			
		||||
 | 
			
		||||
                        default:            // LCOV_EXCL_LINE
 | 
			
		||||
                            assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                            JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -622,7 +621,7 @@ class serializer
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
                default:            // LCOV_EXCL_LINE
 | 
			
		||||
                    assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                    JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -723,7 +722,7 @@ class serializer
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        // spare 1 byte for '\0'
 | 
			
		||||
        assert(n_chars < number_buffer.size() - 1);
 | 
			
		||||
        JSON_ASSERT(n_chars < number_buffer.size() - 1);
 | 
			
		||||
 | 
			
		||||
        // jump to the end to generate the string from backward
 | 
			
		||||
        // so we later avoid reversing the result
 | 
			
		||||
| 
						 | 
				
			
			@ -799,9 +798,9 @@ class serializer
 | 
			
		|||
        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
 | 
			
		||||
 | 
			
		||||
        // negative value indicates an error
 | 
			
		||||
        assert(len > 0);
 | 
			
		||||
        JSON_ASSERT(len > 0);
 | 
			
		||||
        // check if buffer was large enough
 | 
			
		||||
        assert(static_cast<std::size_t>(len) < number_buffer.size());
 | 
			
		||||
        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
 | 
			
		||||
 | 
			
		||||
        // erase thousands separator
 | 
			
		||||
        if (thousands_sep != '\0')
 | 
			
		||||
| 
						 | 
				
			
			@ -809,7 +808,7 @@ class serializer
 | 
			
		|||
            const auto end = std::remove(number_buffer.begin(),
 | 
			
		||||
                                         number_buffer.begin() + len, thousands_sep);
 | 
			
		||||
            std::fill(end, number_buffer.end(), '\0');
 | 
			
		||||
            assert((end - number_buffer.begin()) <= len);
 | 
			
		||||
            JSON_ASSERT((end - number_buffer.begin()) <= len);
 | 
			
		||||
            len = (end - number_buffer.begin());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -889,7 +888,7 @@ class serializer
 | 
			
		|||
                : (0xFFu >> type) & (byte);
 | 
			
		||||
 | 
			
		||||
        std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
 | 
			
		||||
        assert(index < 400);
 | 
			
		||||
        JSON_ASSERT(index < 400);
 | 
			
		||||
        state = utf8d[index];
 | 
			
		||||
        return state;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -901,7 +900,7 @@ class serializer
 | 
			
		|||
     */
 | 
			
		||||
    number_unsigned_t remove_sign(number_unsigned_t x)
 | 
			
		||||
    {
 | 
			
		||||
        assert(false); // LCOV_EXCL_LINE
 | 
			
		||||
        JSON_ASSERT(false); // LCOV_EXCL_LINE
 | 
			
		||||
        return x; // LCOV_EXCL_LINE
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -916,7 +915,7 @@ class serializer
 | 
			
		|||
     */
 | 
			
		||||
    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
 | 
			
		||||
        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
 | 
			
		||||
        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,6 @@ SOFTWARE.
 | 
			
		|||
#define NLOHMANN_JSON_VERSION_PATCH 0
 | 
			
		||||
 | 
			
		||||
#include <algorithm> // all_of, find, for_each
 | 
			
		||||
#include <cassert> // assert
 | 
			
		||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
 | 
			
		||||
#include <functional> // hash, less
 | 
			
		||||
#include <initializer_list> // initializer_list
 | 
			
		||||
| 
						 | 
				
			
			@ -924,7 +923,7 @@ class basic_json
 | 
			
		|||
        };
 | 
			
		||||
        std::unique_ptr<T, decltype(deleter)> object(AllocatorTraits::allocate(alloc, 1), deleter);
 | 
			
		||||
        AllocatorTraits::construct(alloc, object.get(), std::forward<Args>(args)...);
 | 
			
		||||
        assert(object != nullptr);
 | 
			
		||||
        JSON_ASSERT(object != nullptr);
 | 
			
		||||
        return object.release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1219,10 +1218,10 @@ class basic_json
 | 
			
		|||
    */
 | 
			
		||||
    void assert_invariant() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_type != value_t::object || m_value.object != nullptr);
 | 
			
		||||
        assert(m_type != value_t::array || m_value.array != nullptr);
 | 
			
		||||
        assert(m_type != value_t::string || m_value.string != nullptr);
 | 
			
		||||
        assert(m_type != value_t::binary || m_value.binary != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
| 
						 | 
				
			
			@ -1515,7 +1514,7 @@ class basic_json
 | 
			
		|||
                m_type = value_t::discarded;
 | 
			
		||||
                break;
 | 
			
		||||
            default:            // LCOV_EXCL_LINE
 | 
			
		||||
                assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
        }
 | 
			
		||||
        assert_invariant();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1915,8 +1914,8 @@ class basic_json
 | 
			
		|||
                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
 | 
			
		||||
    basic_json(InputIT first, InputIT last)
 | 
			
		||||
    {
 | 
			
		||||
        assert(first.m_object != nullptr);
 | 
			
		||||
        assert(last.m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(first.m_object != nullptr);
 | 
			
		||||
        JSON_ASSERT(last.m_object != nullptr);
 | 
			
		||||
 | 
			
		||||
        // make sure iterator fits the current value
 | 
			
		||||
        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
 | 
			
		||||
| 
						 | 
				
			
			@ -2238,7 +2237,8 @@ class basic_json
 | 
			
		|||
    @param[in] error_handler  how to react on decoding errors; there are three
 | 
			
		||||
    possible values: `strict` (throws and exception in case a decoding error
 | 
			
		||||
    occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
 | 
			
		||||
    and `ignore` (ignore invalid UTF-8 sequences during serialization).
 | 
			
		||||
    and `ignore` (ignore invalid UTF-8 sequences during serialization; all
 | 
			
		||||
    bytes are copied to the output unchanged).
 | 
			
		||||
 | 
			
		||||
    @return string containing the serialization of the JSON value
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3019,6 +3019,18 @@ class basic_json
 | 
			
		|||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // specialization to allow to call get_to with a basic_json value
 | 
			
		||||
    // see https://github.com/nlohmann/json/issues/2175
 | 
			
		||||
    template<typename ValueType,
 | 
			
		||||
             detail::enable_if_t <
 | 
			
		||||
                 detail::is_basic_json<ValueType>::value,
 | 
			
		||||
                 int> = 0>
 | 
			
		||||
    ValueType & get_to(ValueType& v) const
 | 
			
		||||
    {
 | 
			
		||||
        v = *this;
 | 
			
		||||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <
 | 
			
		||||
        typename T, std::size_t N,
 | 
			
		||||
        typename Array = T (&)[N],
 | 
			
		||||
| 
						 | 
				
			
			@ -3620,7 +3632,7 @@ class basic_json
 | 
			
		|||
        // const operator[] only works for objects
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(is_object()))
 | 
			
		||||
        {
 | 
			
		||||
            assert(m_value.object->find(key) != m_value.object->end());
 | 
			
		||||
            JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
 | 
			
		||||
            return m_value.object->find(key)->second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3712,7 +3724,7 @@ class basic_json
 | 
			
		|||
        // at only works for objects
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(is_object()))
 | 
			
		||||
        {
 | 
			
		||||
            assert(m_value.object->find(key) != m_value.object->end());
 | 
			
		||||
            JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
 | 
			
		||||
            return m_value.object->find(key)->second;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3772,7 +3784,7 @@ class basic_json
 | 
			
		|||
    template < class ValueType, typename std::enable_if <
 | 
			
		||||
                   std::is_convertible<basic_json_t, ValueType>::value
 | 
			
		||||
                   && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
 | 
			
		||||
    ValueType value(const typename object_t::key_type& key, ValueType && default_value) const
 | 
			
		||||
    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
 | 
			
		||||
    {
 | 
			
		||||
        // at only works for objects
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(is_object()))
 | 
			
		||||
| 
						 | 
				
			
			@ -3784,7 +3796,7 @@ class basic_json
 | 
			
		|||
                return *it;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return std::move(default_value);
 | 
			
		||||
            return default_value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name())));
 | 
			
		||||
| 
						 | 
				
			
			@ -3796,7 +3808,7 @@ class basic_json
 | 
			
		|||
    */
 | 
			
		||||
    string_t value(const typename object_t::key_type& key, const char* default_value) const
 | 
			
		||||
    {
 | 
			
		||||
        return value(key, std::move(string_t(default_value)));
 | 
			
		||||
        return value(key, string_t(default_value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -3844,7 +3856,7 @@ class basic_json
 | 
			
		|||
    */
 | 
			
		||||
    template<class ValueType, typename std::enable_if<
 | 
			
		||||
                 std::is_convertible<basic_json_t, ValueType>::value, int>::type = 0>
 | 
			
		||||
    ValueType value(const json_pointer& ptr, ValueType && default_value) const
 | 
			
		||||
    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
 | 
			
		||||
    {
 | 
			
		||||
        // at only works for objects
 | 
			
		||||
        if (JSON_HEDLEY_LIKELY(is_object()))
 | 
			
		||||
| 
						 | 
				
			
			@ -3856,7 +3868,7 @@ class basic_json
 | 
			
		|||
            }
 | 
			
		||||
            JSON_INTERNAL_CATCH (out_of_range&)
 | 
			
		||||
            {
 | 
			
		||||
                return std::move(default_value);
 | 
			
		||||
                return default_value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3870,7 +3882,7 @@ class basic_json
 | 
			
		|||
    JSON_HEDLEY_NON_NULL(3)
 | 
			
		||||
    string_t value(const json_pointer& ptr, const char* default_value) const
 | 
			
		||||
    {
 | 
			
		||||
        return value(ptr, std::move(string_t(default_value)));
 | 
			
		||||
        return value(ptr, string_t(default_value));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*!
 | 
			
		||||
| 
						 | 
				
			
			@ -5480,7 +5492,7 @@ class basic_json
 | 
			
		|||
    iterator insert_iterator(const_iterator pos, Args&& ... args)
 | 
			
		||||
    {
 | 
			
		||||
        iterator result(this);
 | 
			
		||||
        assert(m_value.array != nullptr);
 | 
			
		||||
        JSON_ASSERT(m_value.array != nullptr);
 | 
			
		||||
 | 
			
		||||
        auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
 | 
			
		||||
        m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
 | 
			
		||||
| 
						 | 
				
			
			@ -8245,7 +8257,7 @@ class basic_json
 | 
			
		|||
 | 
			
		||||
                // if there exists a parent it cannot be primitive
 | 
			
		||||
                default:            // LCOV_EXCL_LINE
 | 
			
		||||
                    assert(false);  // LCOV_EXCL_LINE
 | 
			
		||||
                    JSON_ASSERT(false);  // LCOV_EXCL_LINE
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -95,6 +95,7 @@ set(files
 | 
			
		|||
    src/unit-algorithms.cpp
 | 
			
		||||
    src/unit-allocator.cpp
 | 
			
		||||
    src/unit-alt-string.cpp
 | 
			
		||||
    src/unit-assert_macro.cpp
 | 
			
		||||
    src/unit-bson.cpp
 | 
			
		||||
    src/unit-capacity.cpp
 | 
			
		||||
    src/unit-cbor.cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -132,6 +133,7 @@ set(files
 | 
			
		|||
    src/unit-to_chars.cpp
 | 
			
		||||
    src/unit-ubjson.cpp
 | 
			
		||||
    src/unit-udt.cpp
 | 
			
		||||
    src/unit-udt_macro.cpp
 | 
			
		||||
    src/unit-unicode.cpp
 | 
			
		||||
    src/unit-user_defined_input.cpp
 | 
			
		||||
    src/unit-wstring.cpp)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										65
									
								
								test/src/unit-assert_macro.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								test/src/unit-assert_macro.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
/*
 | 
			
		||||
    __ _____ _____ _____
 | 
			
		||||
 __|  |   __|     |   | |  JSON for Modern C++ (test suite)
 | 
			
		||||
|  |  |__   |  |  | | | |  version 3.8.0
 | 
			
		||||
|_____|_____|_____|_|___|  https://github.com/nlohmann/json
 | 
			
		||||
 | 
			
		||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
 | 
			
		||||
SPDX-License-Identifier: MIT
 | 
			
		||||
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
 | 
			
		||||
 | 
			
		||||
Permission is hereby  granted, free of charge, to any  person obtaining a copy
 | 
			
		||||
of this software and associated  documentation files (the "Software"), to deal
 | 
			
		||||
in the Software  without restriction, including without  limitation the rights
 | 
			
		||||
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
 | 
			
		||||
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
 | 
			
		||||
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
 | 
			
		||||
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// avoid warning when assert does not abort
 | 
			
		||||
#if defined(__GNUC__)
 | 
			
		||||
    #pragma GCC diagnostic ignored "-Wstrict-overflow"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "doctest_compatibility.h"
 | 
			
		||||
 | 
			
		||||
/// global variable to record side effect of assert calls
 | 
			
		||||
static int assert_counter;
 | 
			
		||||
 | 
			
		||||
/// set failure variable to true instead of calling assert(x)
 | 
			
		||||
#define JSON_ASSERT(x) {if (!(x)) ++assert_counter; }
 | 
			
		||||
 | 
			
		||||
#include <nlohmann/json.hpp>
 | 
			
		||||
using nlohmann::json;
 | 
			
		||||
 | 
			
		||||
// the test assumes exceptions to work
 | 
			
		||||
#if not defined(JSON_NOEXCEPTION)
 | 
			
		||||
TEST_CASE("JSON_ASSERT(x)")
 | 
			
		||||
{
 | 
			
		||||
    SECTION("basic_json(first, second)")
 | 
			
		||||
    {
 | 
			
		||||
        assert_counter = 0;
 | 
			
		||||
        CHECK(assert_counter == 0);
 | 
			
		||||
 | 
			
		||||
        json::iterator it;
 | 
			
		||||
        json j;
 | 
			
		||||
 | 
			
		||||
        // in case assertions do not abort execution, an exception is thrown
 | 
			
		||||
        CHECK_THROWS_WITH_AS(json(it, j.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator);
 | 
			
		||||
 | 
			
		||||
        // check that assertion actually happened
 | 
			
		||||
        CHECK(assert_counter == 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1945,6 +1945,15 @@ TEST_CASE("regression tests")
 | 
			
		|||
                  )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("PR #2181 - regression bug with lvalue")
 | 
			
		||||
    {
 | 
			
		||||
        // see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060
 | 
			
		||||
        json j{{"x", "test"}};
 | 
			
		||||
        std::string defval = "default value";
 | 
			
		||||
        auto val = j.value("x", defval);
 | 
			
		||||
        auto val2 = j.value("y", defval);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined(JSON_NOEXCEPTION)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										130
									
								
								test/src/unit-udt_macro.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								test/src/unit-udt_macro.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
/*
 | 
			
		||||
    __ _____ _____ _____
 | 
			
		||||
 __|  |   __|     |   | |  JSON for Modern C++ (test suite)
 | 
			
		||||
|  |  |__   |  |  | | | |  version 3.8.0
 | 
			
		||||
|_____|_____|_____|_|___|  https://github.com/nlohmann/json
 | 
			
		||||
 | 
			
		||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
 | 
			
		||||
SPDX-License-Identifier: MIT
 | 
			
		||||
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
 | 
			
		||||
 | 
			
		||||
Permission is hereby  granted, free of charge, to any  person obtaining a copy
 | 
			
		||||
of this software and associated  documentation files (the "Software"), to deal
 | 
			
		||||
in the Software  without restriction, including without  limitation the rights
 | 
			
		||||
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
 | 
			
		||||
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
 | 
			
		||||
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
 | 
			
		||||
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "doctest_compatibility.h"
 | 
			
		||||
 | 
			
		||||
#include <nlohmann/json.hpp>
 | 
			
		||||
using nlohmann::json;
 | 
			
		||||
 | 
			
		||||
namespace persons
 | 
			
		||||
{
 | 
			
		||||
class person_with_private_data
 | 
			
		||||
{
 | 
			
		||||
  private:
 | 
			
		||||
    std::string name = "";
 | 
			
		||||
    int age = 0;
 | 
			
		||||
    json metadata = nullptr;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    bool operator==(const person_with_private_data& rhs) const
 | 
			
		||||
    {
 | 
			
		||||
        return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    person_with_private_data() = default;
 | 
			
		||||
    person_with_private_data(std::string name_, int age_, json metadata_)
 | 
			
		||||
        : name(std::move(name_))
 | 
			
		||||
        , age(age_)
 | 
			
		||||
        , metadata(std::move(metadata_))
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class person_without_private_data_1
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    std::string name = "";
 | 
			
		||||
    int age = 0;
 | 
			
		||||
    json metadata = nullptr;
 | 
			
		||||
 | 
			
		||||
    bool operator==(const person_without_private_data_1& rhs) const
 | 
			
		||||
    {
 | 
			
		||||
        return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    person_without_private_data_1() = default;
 | 
			
		||||
    person_without_private_data_1(std::string name_, int age_, json metadata_)
 | 
			
		||||
        : name(std::move(name_))
 | 
			
		||||
        , age(age_)
 | 
			
		||||
        , metadata(std::move(metadata_))
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_without_private_data_1, age, name, metadata)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class person_without_private_data_2
 | 
			
		||||
{
 | 
			
		||||
  public:
 | 
			
		||||
    std::string name = "";
 | 
			
		||||
    int age = 0;
 | 
			
		||||
    json metadata = nullptr;
 | 
			
		||||
 | 
			
		||||
    bool operator==(const person_without_private_data_2& rhs) const
 | 
			
		||||
    {
 | 
			
		||||
        return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    person_without_private_data_2() = default;
 | 
			
		||||
    person_without_private_data_2(std::string name_, int age_, json metadata_)
 | 
			
		||||
        : name(std::move(name_))
 | 
			
		||||
        , age(age_)
 | 
			
		||||
        , metadata(std::move(metadata_))
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata)
 | 
			
		||||
} // namespace persons
 | 
			
		||||
 | 
			
		||||
TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE", T,
 | 
			
		||||
                   persons::person_with_private_data,
 | 
			
		||||
                   persons::person_without_private_data_1,
 | 
			
		||||
                   persons::person_without_private_data_2)
 | 
			
		||||
{
 | 
			
		||||
    SECTION("person")
 | 
			
		||||
    {
 | 
			
		||||
        // serialization
 | 
			
		||||
        T p1("Erik", 1, {{"haircuts", 2}});
 | 
			
		||||
        CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}");
 | 
			
		||||
 | 
			
		||||
        // deserialization
 | 
			
		||||
        T p2 = json(p1);
 | 
			
		||||
        CHECK(p2 == p1);
 | 
			
		||||
 | 
			
		||||
        // roundtrip
 | 
			
		||||
        CHECK(T(json(p1)) == p1);
 | 
			
		||||
        CHECK(json(T(json(p1))) == json(p1));
 | 
			
		||||
 | 
			
		||||
        // check exception in case of missing field
 | 
			
		||||
        json j = json(p1);
 | 
			
		||||
        j.erase("age");
 | 
			
		||||
        T p3;
 | 
			
		||||
        CHECK_THROWS_WITH_AS(p3 = json(j), "[json.exception.out_of_range.403] key 'age' not found", json::out_of_range);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue