Merge branch 'develop' into coverity_scan
This commit is contained in:
commit
0e90bcb539
5 changed files with 202 additions and 401 deletions
|
@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. This projec
|
|||
|
||||
[Full Changelog](https://github.com/nlohmann/json/compare/v1.1.0...HEAD)
|
||||
|
||||
- concatenate objects [\#252](https://github.com/nlohmann/json/issues/252)
|
||||
- Unit test fails when doing a CMake out-of-tree build [\#241](https://github.com/nlohmann/json/issues/241)
|
||||
- Additional integration options [\#237](https://github.com/nlohmann/json/issues/237)
|
||||
- Can't use basic\_json::iterator as a base iterator for std::move\_iterator [\#233](https://github.com/nlohmann/json/issues/233)
|
||||
|
@ -14,6 +15,7 @@ All notable changes to this project will be documented in this file. This projec
|
|||
- Add support for afl-fuzz testing [\#207](https://github.com/nlohmann/json/pull/207) ([mykter](https://github.com/mykter))
|
||||
- Issue \#178 - Extending support to full uint64\_t/int64\_t range and unsigned type \(updated\) [\#193](https://github.com/nlohmann/json/pull/193) ([twelsby](https://github.com/twelsby))
|
||||
|
||||
- Maybe a bug [\#258](https://github.com/nlohmann/json/issues/258)
|
||||
- -Wconversion warnings [\#239](https://github.com/nlohmann/json/issues/239)
|
||||
- ambiguous overload for 'push\_back' and 'operator+=' [\#235](https://github.com/nlohmann/json/issues/235)
|
||||
- double values are serialized with commas as decimal points [\#228](https://github.com/nlohmann/json/issues/228)
|
||||
|
@ -26,11 +28,18 @@ All notable changes to this project will be documented in this file. This projec
|
|||
- Floating point exceptions [\#181](https://github.com/nlohmann/json/issues/181)
|
||||
- In basic\_json::basic\_json\(const CompatibleArrayType& val\), the requirement of CompatibleArrayType is not strict enough. [\#174](https://github.com/nlohmann/json/issues/174)
|
||||
- Implicit assignment to std::string fails [\#144](https://github.com/nlohmann/json/issues/144)
|
||||
- Fix Issue \#265 [\#266](https://github.com/nlohmann/json/pull/266) ([06needhamt](https://github.com/06needhamt))
|
||||
- Issue \#195 - update Travis to Trusty due to gcc/clang strtod\(\) bug [\#196](https://github.com/nlohmann/json/pull/196) ([twelsby](https://github.com/twelsby))
|
||||
|
||||
- Compiler Errors With JSON.hpp [\#265](https://github.com/nlohmann/json/issues/265)
|
||||
- VS2015 compile fail [\#260](https://github.com/nlohmann/json/issues/260)
|
||||
- Error when using json in g++ [\#254](https://github.com/nlohmann/json/issues/254)
|
||||
- Update long-term goals [\#246](https://github.com/nlohmann/json/issues/246)
|
||||
- Error compile Android NDK error: 'strtof' is not a member of 'std' [\#219](https://github.com/nlohmann/json/issues/219)
|
||||
- Conflicting typedef of ssize\_t on Windows 32 bit when using Boost.Python [\#204](https://github.com/nlohmann/json/issues/204)
|
||||
- Integer conversion to unsigned [\#178](https://github.com/nlohmann/json/issues/178)
|
||||
|
||||
- Define CMake/CTest tests [\#247](https://github.com/nlohmann/json/pull/247) ([robertmrk](https://github.com/robertmrk))
|
||||
- Out of tree builds and a few other miscellaneous CMake cleanups. [\#242](https://github.com/nlohmann/json/pull/242) ([ChrisKitching](https://github.com/ChrisKitching))
|
||||
- Implement additional integration options [\#238](https://github.com/nlohmann/json/pull/238) ([robertmrk](https://github.com/robertmrk))
|
||||
- make serialization locale-independent [\#232](https://github.com/nlohmann/json/pull/232) ([nlohmann](https://github.com/nlohmann))
|
||||
|
|
145
README.md
145
README.md
|
@ -16,7 +16,7 @@ There are myriads of [JSON](http://json.org) libraries out there, and each may e
|
|||
|
||||
- **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of modern C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
|
||||
|
||||
- **Trivial integration**. Our whole code consists of a single header file `json.hpp`. That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
||||
- **Trivial integration**. Our whole code consists of a single header file [`json.hpp`](https://github.com/nlohmann/json/blob/develop/src/json.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.
|
||||
|
||||
- **Serious testing**. Our class is heavily [unit-tested](https://github.com/nlohmann/json/blob/master/test/src/unit.cpp) and covers [100%](https://coveralls.io/r/nlohmann/json) of the code, including all exceptional behavior. Furthermore, we checked with [Valgrind](http://valgrind.org) that there are no memory leaks.
|
||||
|
||||
|
@ -28,6 +28,7 @@ Other aspects were not so important to us:
|
|||
|
||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
|
||||
|
||||
|
||||
## Integration
|
||||
|
||||
The single required source, file `json.hpp` is in the `src` directory or [released here](https://github.com/nlohmann/json/releases). All you need to do is add
|
||||
|
@ -43,48 +44,6 @@ to the files you want to use JSON objects. That's it. Do not forget to set the n
|
|||
|
||||
:beer: If you are using OS X and [Homebrew](http://brew.sh), just type `brew tap nlohmann/json` and `brew install nlohmann_json` and you're set. If you want the bleeding edge rather than the latest release, use `brew install nlohmann_json --HEAD`.
|
||||
|
||||
## Supported compilers
|
||||
|
||||
Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
|
||||
|
||||
- GCC 4.9 - 6.0 (and possibly later)
|
||||
- Clang 3.4 - 3.9 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / 14.0 (and possibly later)
|
||||
|
||||
I would be happy to learn about other compilers/versions.
|
||||
|
||||
Please note:
|
||||
|
||||
- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues.
|
||||
- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
|
||||
|
||||
```
|
||||
APP_STL := c++_shared
|
||||
NDK_TOOLCHAIN_VERSION := clang3.6
|
||||
APP_CPPFLAGS += -frtti -fexceptions
|
||||
```
|
||||
|
||||
The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10.
|
||||
|
||||
- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
|
||||
|
||||
The following compilers are currently used in [continuous integration](https://travis-ci.org/nlohmann/json):
|
||||
|
||||
| Compiler | Operating System | Version String |
|
||||
|-----------------|------------------------------|----------------|
|
||||
| GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 |
|
||||
| GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 |
|
||||
| GCC 6.1.1 | Ubuntu 14.04.4 LTS | g++-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 |
|
||||
| Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) |
|
||||
| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) |
|
||||
| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
|
||||
| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) |
|
||||
| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) |
|
||||
| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
|
||||
| Clang Xcode 8.0 | Darwin Kernel Version 15.5.0 (OSX 10.11.5) | Apple LLVM version 8.0.0 (clang-800.0.24.1) |
|
||||
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 |
|
||||
|
||||
## Examples
|
||||
|
||||
|
@ -167,6 +126,7 @@ json empty_object_explicit = json::object();
|
|||
json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
|
||||
```
|
||||
|
||||
|
||||
### Serialization / Deserialization
|
||||
|
||||
You can create an object (deserialization) by appending `_json` to a string literal:
|
||||
|
@ -175,7 +135,7 @@ You can create an object (deserialization) by appending `_json` to a string lite
|
|||
// create object from string literal
|
||||
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
|
||||
|
||||
// or even nicer (thanks http://isocpp.org/blog/2015/01/json-for-modern-cpp)
|
||||
// or even nicer with a raw string literal
|
||||
auto j2 = R"(
|
||||
{
|
||||
"happy": true,
|
||||
|
@ -220,6 +180,7 @@ These operators work for any subclasses of `std::istream` or `std::ostream`.
|
|||
|
||||
Please note that setting the exception bit for `failbit` is inappropriate for this use case. It will result in program termination due to the `noexcept` specifier in use.
|
||||
|
||||
|
||||
### STL-like access
|
||||
|
||||
We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement.
|
||||
|
@ -287,6 +248,7 @@ int fob_present = o.count("fob"); // 0
|
|||
o.erase("foo");
|
||||
```
|
||||
|
||||
|
||||
### Conversion from STL containers
|
||||
|
||||
Any sequence container (`std::array`, `std::vector`, `std::deque`, `std::forward_list`, `std::list`) whose values can be used to construct JSON types (e.g., integers, floating point numbers, Booleans, string types, or again STL containers described in this section) can be used to create a JSON array. The same holds for similar associative containers (`std::set`, `std::multiset`, `std::unordered_set`, `std::unordered_multiset`), but in these cases the order of the elements of the array depends how the elements are ordered in the respective STL container.
|
||||
|
@ -349,12 +311,51 @@ json j_ummap(c_ummap); // only one entry for key "three" is used
|
|||
// maybe {"one": true, "two": true, "three": true}
|
||||
```
|
||||
|
||||
### JSON Pointer and JSON Patch
|
||||
|
||||
The library supports **JSON Pointer** ([RFC 6901](https://tools.ietf.org/html/rfc6901)) as alternative means to address structured values. On top of this, **JSON Patch** ([RFC 6902](https://tools.ietf.org/html/rfc6902)) allows to describe differences between two JSON values - effectively allowing patch and diff operations known from Unix.
|
||||
|
||||
```cpp
|
||||
// a JSON value
|
||||
json j_original = R"({
|
||||
"baz": ["one", "two", "three"],
|
||||
"foo": "bar"
|
||||
})"_json;
|
||||
|
||||
// access members with a JSON pointer (RFC 6901)
|
||||
j_original["/baz/2"_json_pointer];
|
||||
// "two"
|
||||
|
||||
// a JSON patch (RFC 6902)
|
||||
json j_patch = R"([
|
||||
{ "op": "replace", "path": "/baz", "value": "boo" },
|
||||
{ "op": "add", "path": "/hello", "value": ["world"] },
|
||||
{ "op": "remove", "path": "/foo"}
|
||||
])"_json;
|
||||
|
||||
// apply the patch
|
||||
json j_result = j_original.patch(j_patch);
|
||||
// {
|
||||
// "baz": "boo",
|
||||
// "hello": ["world"]
|
||||
// }
|
||||
|
||||
// calculate a JSON patch from two JSON values
|
||||
json::diff(j_result, j_original);
|
||||
// [
|
||||
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
|
||||
// { "op":"remove","path":"/hello" },
|
||||
// { "op":"add","path":"/foo","value":"bar" }
|
||||
// ]
|
||||
```
|
||||
|
||||
|
||||
### Implicit conversions
|
||||
|
||||
The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted.
|
||||
|
||||
```cpp
|
||||
/// strings
|
||||
// strings
|
||||
std::string s1 = "Hello, world!";
|
||||
json js = s1;
|
||||
std::string s2 = js;
|
||||
|
@ -382,6 +383,51 @@ int vi = jn.get<int>();
|
|||
// etc.
|
||||
```
|
||||
|
||||
|
||||
## Supported compilers
|
||||
|
||||
Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
|
||||
|
||||
- GCC 4.9 - 6.0 (and possibly later)
|
||||
- Clang 3.4 - 3.9 (and possibly later)
|
||||
- Microsoft Visual C++ 2015 / 14.0 (and possibly later)
|
||||
|
||||
I would be happy to learn about other compilers/versions.
|
||||
|
||||
Please note:
|
||||
|
||||
- GCC 4.8 does not work because of two bugs ([55817](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55817) and [57824](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57824)) in the C++11 support. Note there is a [pull request](https://github.com/nlohmann/json/pull/212) to fix some of the issues.
|
||||
- Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
|
||||
|
||||
```
|
||||
APP_STL := c++_shared
|
||||
NDK_TOOLCHAIN_VERSION := clang3.6
|
||||
APP_CPPFLAGS += -frtti -fexceptions
|
||||
```
|
||||
|
||||
The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10.
|
||||
|
||||
- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
|
||||
|
||||
The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json) and [AppVeyor](https://ci.appveyor.com/project/nlohmann/json):
|
||||
|
||||
| Compiler | Operating System | Version String |
|
||||
|-----------------|------------------------------|----------------|
|
||||
| GCC 4.9.3 | Ubuntu 14.04.4 LTS | g++-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3 |
|
||||
| GCC 5.3.0 | Ubuntu 14.04.4 LTS | g++-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204 |
|
||||
| GCC 6.1.1 | Ubuntu 14.04.4 LTS | g++-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511 |
|
||||
| Clang 3.8.0 | Ubuntu 14.04.4 LTS | clang version 3.8.0 (tags/RELEASE_380/final) |
|
||||
| Clang Xcode 6.1 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.2 | Darwin Kernel Version 13.4.0 (OSX 10.9.5) | Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn) |
|
||||
| Clang Xcode 6.3 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.49) (based on LLVM 3.6.0svn) |
|
||||
| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
|
||||
| Clang Xcode 7.1 | Darwin Kernel Version 14.5.0 (OSX 10.10.5) | Apple LLVM version 7.0.0 (clang-700.1.76) |
|
||||
| Clang Xcode 7.2 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.0.2 (clang-700.1.81) |
|
||||
| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
|
||||
| Clang Xcode 8.0 | Darwin Kernel Version 15.5.0 (OSX 10.11.5) | Apple LLVM version 8.0.0 (clang-800.0.24.1) |
|
||||
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25123.0 |
|
||||
|
||||
|
||||
## License
|
||||
|
||||
<img align="right" src="http://opensource.org/trademarks/opensource/OSI-Approved-License-100x137.png">
|
||||
|
@ -390,11 +436,12 @@ The class is licensed under the [MIT License](http://opensource.org/licenses/MIT
|
|||
|
||||
Copyright © 2013-2016 [Niels Lohmann](http://nlohmann.me)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
## Thanks
|
||||
|
||||
|
@ -439,11 +486,13 @@ I deeply appreciate the help of the following people.
|
|||
|
||||
Thanks a lot for helping out!
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert).
|
||||
- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), 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.
|
||||
|
||||
|
||||
## Execute unit tests
|
||||
|
||||
To compile and run the tests, you need to execute
|
||||
|
@ -453,7 +502,7 @@ $ make
|
|||
$ ./json_unit "*"
|
||||
|
||||
===============================================================================
|
||||
All tests passed (5568705 assertions in 31 test cases)
|
||||
All tests passed (5568715 assertions in 32 test cases)
|
||||
```
|
||||
|
||||
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||
|
|
191
src/json.hpp
191
src/json.hpp
|
@ -711,73 +711,6 @@ class basic_json
|
|||
|
||||
private:
|
||||
|
||||
/*!
|
||||
@brief a type to hold JSON type information
|
||||
|
||||
This bitfield type holds information about JSON types. It is internally
|
||||
used to hold the basic JSON type enumeration, as well as additional
|
||||
information in the case of values that have been parsed from a string
|
||||
including whether of not it was created directly or parsed, and in the
|
||||
case of floating point numbers the number of significant figures in the
|
||||
original representaiton and if it was in exponential form, if a '+' was
|
||||
included in the exponent and the capitilization of the exponent marker.
|
||||
The sole purpose of this information is to permit accurate round trips.
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
union type_data_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// the type of the value (@ref value_t)
|
||||
uint16_t type : 4;
|
||||
/// whether the number was parsed from a string
|
||||
uint16_t parsed : 1;
|
||||
/// whether parsed number contained an exponent ('e'/'E')
|
||||
uint16_t has_exp : 1;
|
||||
/// whether parsed number contained a plus in the exponent
|
||||
uint16_t exp_plus : 1;
|
||||
/// whether parsed number's exponent was capitalized ('E')
|
||||
uint16_t exp_cap : 1;
|
||||
/// the number of figures for a parsed number
|
||||
uint16_t precision : 8;
|
||||
} bits;
|
||||
uint16_t data;
|
||||
|
||||
/// return the type as value_t
|
||||
operator value_t() const
|
||||
{
|
||||
return static_cast<value_t>(bits.type);
|
||||
}
|
||||
|
||||
/// test type for equality (ignore other fields)
|
||||
bool operator==(const value_t& rhs) const
|
||||
{
|
||||
return static_cast<value_t>(bits.type) == rhs;
|
||||
}
|
||||
|
||||
/// assignment
|
||||
type_data_t& operator=(value_t rhs)
|
||||
{
|
||||
bits.type = static_cast<uint16_t>(rhs) & 15; // avoid overflow
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// construct from value_t
|
||||
type_data_t(value_t t) noexcept
|
||||
{
|
||||
*reinterpret_cast<uint16_t*>(this) = 0;
|
||||
bits.type = static_cast<uint16_t>(t) & 15; // avoid overflow
|
||||
}
|
||||
|
||||
/// default constructor
|
||||
type_data_t() noexcept
|
||||
{
|
||||
data = 0;
|
||||
bits.type = reinterpret_cast<uint16_t>(value_t::null);
|
||||
}
|
||||
};
|
||||
|
||||
/// helper for exception-safe object creation
|
||||
template<typename T, typename... Args>
|
||||
static T* create(Args&& ... args)
|
||||
|
@ -6183,79 +6116,23 @@ class basic_json
|
|||
|
||||
case value_t::number_float:
|
||||
{
|
||||
// check if number was parsed from a string
|
||||
if (m_type.bits.parsed)
|
||||
if (m_value.number_float == 0)
|
||||
{
|
||||
// check if parsed number had an exponent given
|
||||
if (m_type.bits.has_exp)
|
||||
{
|
||||
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
|
||||
char buf[263];
|
||||
int len;
|
||||
|
||||
// handle capitalization of the exponent
|
||||
if (m_type.bits.exp_cap)
|
||||
{
|
||||
len = snprintf(buf, sizeof(buf), "%.*E",
|
||||
m_type.bits.precision, m_value.number_float) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = snprintf(buf, sizeof(buf), "%.*e",
|
||||
m_type.bits.precision, m_value.number_float) + 1;
|
||||
}
|
||||
|
||||
// remove '+' sign from the exponent if necessary
|
||||
if (not m_type.bits.exp_plus)
|
||||
{
|
||||
if (len > static_cast<int>(sizeof(buf)))
|
||||
{
|
||||
len = sizeof(buf);
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (buf[i] == '+')
|
||||
{
|
||||
for (; i + 1 < len; i++)
|
||||
{
|
||||
buf[i] = buf[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o << buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no exponent - output as a decimal
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(m_type.bits.precision)
|
||||
<< std::fixed << m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
// special case for zero to get "0.0"/"-0.0"
|
||||
o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_value.number_float == 0)
|
||||
{
|
||||
// special case for zero to get "0.0"/"-0.0"
|
||||
o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise 6, 15 or 16 digits of precision allows
|
||||
// round-trip IEEE 754 string->float->string,
|
||||
// string->double->string or string->long
|
||||
// double->string; to be safe, we read this value from
|
||||
// std::numeric_limits<number_float_t>::digits10
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
<< m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
// Otherwise 6, 15 or 16 digits of precision allows
|
||||
// round-trip IEEE 754 string->float->string,
|
||||
// string->double->string or string->long
|
||||
// double->string; to be safe, we read this value from
|
||||
// std::numeric_limits<number_float_t>::digits10
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
<< m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -6280,7 +6157,7 @@ class basic_json
|
|||
//////////////////////
|
||||
|
||||
/// the type of the current element
|
||||
type_data_t m_type = value_t::null;
|
||||
value_t m_type = value_t::null;
|
||||
|
||||
/// the value of the current element
|
||||
json_value m_value = {};
|
||||
|
@ -8457,18 +8334,12 @@ basic_json_parser_63:
|
|||
number_integer_t or @ref number_unsigned_t then it sets the result
|
||||
parameter accordingly.
|
||||
|
||||
The 'floating point representation' includes the number of significant
|
||||
figures after the radix point, whether the number is in exponential or
|
||||
decimal form, the capitalization of the exponent marker, and if the
|
||||
optional '+' is present in the exponent. This information is necessary
|
||||
to perform accurate round trips of floating point numbers.
|
||||
|
||||
If the number is a floating point number the number is then parsed
|
||||
using @a std:strtod (or @a std:strtof or @a std::strtold).
|
||||
|
||||
@param[out] result @ref basic_json object to receive the number, or
|
||||
NAN if the conversion read past the current token. The latter case
|
||||
needs to be treated by the caller function.
|
||||
NAN if the conversion read past the current token. The latter case
|
||||
needs to be treated by the caller function.
|
||||
*/
|
||||
void get_number(basic_json& result) const
|
||||
{
|
||||
|
@ -8476,15 +8347,6 @@ basic_json_parser_63:
|
|||
|
||||
const lexer::lexer_char_t* curptr = m_start;
|
||||
|
||||
// remember this number was parsed (for later serialization)
|
||||
result.m_type.bits.parsed = true;
|
||||
|
||||
// 'found_radix_point' will be set to 0xFF upon finding a radix
|
||||
// point and later used to mask in/out the precision depending
|
||||
// whether a radix is found i.e. 'precision &= found_radix_point'
|
||||
uint8_t found_radix_point = 0;
|
||||
uint8_t precision = 0;
|
||||
|
||||
// accumulate the integer conversion result (unsigned for now)
|
||||
number_unsigned_t value = 0;
|
||||
|
||||
|
@ -8517,22 +8379,11 @@ basic_json_parser_63:
|
|||
{
|
||||
// don't count '.' but change to float
|
||||
type = value_t::number_float;
|
||||
|
||||
// reset precision count
|
||||
precision = 0;
|
||||
found_radix_point = 0xFF;
|
||||
continue;
|
||||
}
|
||||
// assume exponent (if not then will fail parse): change to
|
||||
// float, stop counting and record exponent details
|
||||
type = value_t::number_float;
|
||||
result.m_type.bits.has_exp = true;
|
||||
|
||||
// exponent capitalization
|
||||
result.m_type.bits.exp_cap = (*curptr == 'E');
|
||||
|
||||
// exponent '+' sign
|
||||
result.m_type.bits.exp_plus = (*(++curptr) == '+');
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -8554,13 +8405,8 @@ basic_json_parser_63:
|
|||
value = temp;
|
||||
}
|
||||
}
|
||||
++precision;
|
||||
}
|
||||
|
||||
// If no radix point was found then precision would now be set to
|
||||
// the number of digits, which is wrong - clear it.
|
||||
result.m_type.bits.precision = precision & found_radix_point;
|
||||
|
||||
// save the value (if not a float)
|
||||
if (type == value_t::number_unsigned)
|
||||
{
|
||||
|
@ -10002,9 +9848,12 @@ basic_json_parser_63:
|
|||
// in a second pass, traverse the remaining elements
|
||||
|
||||
// remove my remaining elements
|
||||
const auto end_index = static_cast<difference_type>(result.size());
|
||||
while (i < source.size())
|
||||
{
|
||||
result.push_back(object(
|
||||
// add operations in reverse order to avoid invalid
|
||||
// indices
|
||||
result.insert(result.begin() + end_index, object(
|
||||
{
|
||||
{"op", "remove"},
|
||||
{"path", path + "/" + std::to_string(i)}
|
||||
|
|
|
@ -711,73 +711,6 @@ class basic_json
|
|||
|
||||
private:
|
||||
|
||||
/*!
|
||||
@brief a type to hold JSON type information
|
||||
|
||||
This bitfield type holds information about JSON types. It is internally
|
||||
used to hold the basic JSON type enumeration, as well as additional
|
||||
information in the case of values that have been parsed from a string
|
||||
including whether of not it was created directly or parsed, and in the
|
||||
case of floating point numbers the number of significant figures in the
|
||||
original representaiton and if it was in exponential form, if a '+' was
|
||||
included in the exponent and the capitilization of the exponent marker.
|
||||
The sole purpose of this information is to permit accurate round trips.
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
union type_data_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
/// the type of the value (@ref value_t)
|
||||
uint16_t type : 4;
|
||||
/// whether the number was parsed from a string
|
||||
uint16_t parsed : 1;
|
||||
/// whether parsed number contained an exponent ('e'/'E')
|
||||
uint16_t has_exp : 1;
|
||||
/// whether parsed number contained a plus in the exponent
|
||||
uint16_t exp_plus : 1;
|
||||
/// whether parsed number's exponent was capitalized ('E')
|
||||
uint16_t exp_cap : 1;
|
||||
/// the number of figures for a parsed number
|
||||
uint16_t precision : 8;
|
||||
} bits;
|
||||
uint16_t data;
|
||||
|
||||
/// return the type as value_t
|
||||
operator value_t() const
|
||||
{
|
||||
return static_cast<value_t>(bits.type);
|
||||
}
|
||||
|
||||
/// test type for equality (ignore other fields)
|
||||
bool operator==(const value_t& rhs) const
|
||||
{
|
||||
return static_cast<value_t>(bits.type) == rhs;
|
||||
}
|
||||
|
||||
/// assignment
|
||||
type_data_t& operator=(value_t rhs)
|
||||
{
|
||||
bits.type = static_cast<uint16_t>(rhs) & 15; // avoid overflow
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// construct from value_t
|
||||
type_data_t(value_t t) noexcept
|
||||
{
|
||||
*reinterpret_cast<uint16_t*>(this) = 0;
|
||||
bits.type = static_cast<uint16_t>(t) & 15; // avoid overflow
|
||||
}
|
||||
|
||||
/// default constructor
|
||||
type_data_t() noexcept
|
||||
{
|
||||
data = 0;
|
||||
bits.type = reinterpret_cast<uint16_t>(value_t::null);
|
||||
}
|
||||
};
|
||||
|
||||
/// helper for exception-safe object creation
|
||||
template<typename T, typename... Args>
|
||||
static T* create(Args&& ... args)
|
||||
|
@ -6183,79 +6116,23 @@ class basic_json
|
|||
|
||||
case value_t::number_float:
|
||||
{
|
||||
// check if number was parsed from a string
|
||||
if (m_type.bits.parsed)
|
||||
if (m_value.number_float == 0)
|
||||
{
|
||||
// check if parsed number had an exponent given
|
||||
if (m_type.bits.has_exp)
|
||||
{
|
||||
// buffer size: precision (2^8-1 = 255) + other ('-.e-xxx' = 7) + null (1)
|
||||
char buf[263];
|
||||
int len;
|
||||
|
||||
// handle capitalization of the exponent
|
||||
if (m_type.bits.exp_cap)
|
||||
{
|
||||
len = snprintf(buf, sizeof(buf), "%.*E",
|
||||
m_type.bits.precision, m_value.number_float) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = snprintf(buf, sizeof(buf), "%.*e",
|
||||
m_type.bits.precision, m_value.number_float) + 1;
|
||||
}
|
||||
|
||||
// remove '+' sign from the exponent if necessary
|
||||
if (not m_type.bits.exp_plus)
|
||||
{
|
||||
if (len > static_cast<int>(sizeof(buf)))
|
||||
{
|
||||
len = sizeof(buf);
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (buf[i] == '+')
|
||||
{
|
||||
for (; i + 1 < len; i++)
|
||||
{
|
||||
buf[i] = buf[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o << buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no exponent - output as a decimal
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(m_type.bits.precision)
|
||||
<< std::fixed << m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
// special case for zero to get "0.0"/"-0.0"
|
||||
o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_value.number_float == 0)
|
||||
{
|
||||
// special case for zero to get "0.0"/"-0.0"
|
||||
o << (std::signbit(m_value.number_float) ? "-0.0" : "0.0");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise 6, 15 or 16 digits of precision allows
|
||||
// round-trip IEEE 754 string->float->string,
|
||||
// string->double->string or string->long
|
||||
// double->string; to be safe, we read this value from
|
||||
// std::numeric_limits<number_float_t>::digits10
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
<< m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
// Otherwise 6, 15 or 16 digits of precision allows
|
||||
// round-trip IEEE 754 string->float->string,
|
||||
// string->double->string or string->long
|
||||
// double->string; to be safe, we read this value from
|
||||
// std::numeric_limits<number_float_t>::digits10
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale(std::locale(), new DecimalSeparator)); // fix locale problems
|
||||
ss << std::setprecision(std::numeric_limits<double>::digits10)
|
||||
<< m_value.number_float;
|
||||
o << ss.str();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -6280,7 +6157,7 @@ class basic_json
|
|||
//////////////////////
|
||||
|
||||
/// the type of the current element
|
||||
type_data_t m_type = value_t::null;
|
||||
value_t m_type = value_t::null;
|
||||
|
||||
/// the value of the current element
|
||||
json_value m_value = {};
|
||||
|
@ -7767,18 +7644,12 @@ class basic_json
|
|||
number_integer_t or @ref number_unsigned_t then it sets the result
|
||||
parameter accordingly.
|
||||
|
||||
The 'floating point representation' includes the number of significant
|
||||
figures after the radix point, whether the number is in exponential or
|
||||
decimal form, the capitalization of the exponent marker, and if the
|
||||
optional '+' is present in the exponent. This information is necessary
|
||||
to perform accurate round trips of floating point numbers.
|
||||
|
||||
If the number is a floating point number the number is then parsed
|
||||
using @a std:strtod (or @a std:strtof or @a std::strtold).
|
||||
|
||||
@param[out] result @ref basic_json object to receive the number, or
|
||||
NAN if the conversion read past the current token. The latter case
|
||||
needs to be treated by the caller function.
|
||||
NAN if the conversion read past the current token. The latter case
|
||||
needs to be treated by the caller function.
|
||||
*/
|
||||
void get_number(basic_json& result) const
|
||||
{
|
||||
|
@ -7786,15 +7657,6 @@ class basic_json
|
|||
|
||||
const lexer::lexer_char_t* curptr = m_start;
|
||||
|
||||
// remember this number was parsed (for later serialization)
|
||||
result.m_type.bits.parsed = true;
|
||||
|
||||
// 'found_radix_point' will be set to 0xFF upon finding a radix
|
||||
// point and later used to mask in/out the precision depending
|
||||
// whether a radix is found i.e. 'precision &= found_radix_point'
|
||||
uint8_t found_radix_point = 0;
|
||||
uint8_t precision = 0;
|
||||
|
||||
// accumulate the integer conversion result (unsigned for now)
|
||||
number_unsigned_t value = 0;
|
||||
|
||||
|
@ -7827,22 +7689,11 @@ class basic_json
|
|||
{
|
||||
// don't count '.' but change to float
|
||||
type = value_t::number_float;
|
||||
|
||||
// reset precision count
|
||||
precision = 0;
|
||||
found_radix_point = 0xFF;
|
||||
continue;
|
||||
}
|
||||
// assume exponent (if not then will fail parse): change to
|
||||
// float, stop counting and record exponent details
|
||||
type = value_t::number_float;
|
||||
result.m_type.bits.has_exp = true;
|
||||
|
||||
// exponent capitalization
|
||||
result.m_type.bits.exp_cap = (*curptr == 'E');
|
||||
|
||||
// exponent '+' sign
|
||||
result.m_type.bits.exp_plus = (*(++curptr) == '+');
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -7864,13 +7715,8 @@ class basic_json
|
|||
value = temp;
|
||||
}
|
||||
}
|
||||
++precision;
|
||||
}
|
||||
|
||||
// If no radix point was found then precision would now be set to
|
||||
// the number of digits, which is wrong - clear it.
|
||||
result.m_type.bits.precision = precision & found_radix_point;
|
||||
|
||||
// save the value (if not a float)
|
||||
if (type == value_t::number_unsigned)
|
||||
{
|
||||
|
@ -9312,9 +9158,12 @@ class basic_json
|
|||
// in a second pass, traverse the remaining elements
|
||||
|
||||
// remove my remaining elements
|
||||
const auto end_index = static_cast<difference_type>(result.size());
|
||||
while (i < source.size())
|
||||
{
|
||||
result.push_back(object(
|
||||
// add operations in reverse order to avoid invalid
|
||||
// indices
|
||||
result.insert(result.begin() + end_index, object(
|
||||
{
|
||||
{"op", "remove"},
|
||||
{"path", path + "/" + std::to_string(i)}
|
||||
|
|
|
@ -10371,7 +10371,7 @@ TEST_CASE("README", "[hide]")
|
|||
// create object from string literal
|
||||
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
|
||||
|
||||
// or even nicer (thanks http://isocpp.org/blog/2015/01/json-for-modern-cpp)
|
||||
// or even nicer with a raw string literal
|
||||
auto j2 = R"(
|
||||
{
|
||||
"happy": true,
|
||||
|
@ -10499,7 +10499,7 @@ TEST_CASE("README", "[hide]")
|
|||
}
|
||||
|
||||
{
|
||||
/// strings
|
||||
// strings
|
||||
std::string s1 = "Hello, world!";
|
||||
json js = s1;
|
||||
std::string s2 = js;
|
||||
|
@ -10522,6 +10522,40 @@ TEST_CASE("README", "[hide]")
|
|||
|
||||
// etc.
|
||||
}
|
||||
|
||||
{
|
||||
// a JSON value
|
||||
json j_original = R"({
|
||||
"baz": ["one", "two", "three"],
|
||||
"foo": "bar"
|
||||
})"_json;
|
||||
|
||||
// access members with a JSON pointer (RFC 6901)
|
||||
j_original["/baz/2"_json_pointer];
|
||||
// "two"
|
||||
|
||||
// a JSON patch (RFC 6902)
|
||||
json j_patch = R"([
|
||||
{ "op": "replace", "path": "/baz", "value": "boo" },
|
||||
{ "op": "add", "path": "/hello", "value": ["world"] },
|
||||
{ "op": "remove", "path": "/foo"}
|
||||
])"_json;
|
||||
|
||||
// apply the patch
|
||||
json j_result = j_original.patch(j_patch);
|
||||
// {
|
||||
// "baz": "boo",
|
||||
// "hello": ["world"]
|
||||
// }
|
||||
|
||||
// calculate a JSON patch from two JSON values
|
||||
json::diff(j_result, j_original);
|
||||
// [
|
||||
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
|
||||
// { "op":"remove","path":"/hello" },
|
||||
// { "op":"add","path":"/foo","value":"bar" }
|
||||
// ]
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("algorithms")
|
||||
|
@ -11900,14 +11934,14 @@ TEST_CASE("compliance tests from nativejson-benchmark")
|
|||
"test/data/json_roundtrip/roundtrip21.json",
|
||||
"test/data/json_roundtrip/roundtrip22.json",
|
||||
"test/data/json_roundtrip/roundtrip23.json",
|
||||
"test/data/json_roundtrip/roundtrip24.json",
|
||||
"test/data/json_roundtrip/roundtrip25.json",
|
||||
"test/data/json_roundtrip/roundtrip26.json",
|
||||
"test/data/json_roundtrip/roundtrip27.json",
|
||||
"test/data/json_roundtrip/roundtrip28.json",
|
||||
//"test/data/json_roundtrip/roundtrip24.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip25.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip26.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip27.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip28.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip29.json",
|
||||
"test/data/json_roundtrip/roundtrip30.json",
|
||||
"test/data/json_roundtrip/roundtrip31.json",
|
||||
//"test/data/json_roundtrip/roundtrip30.json", // roundtrip error
|
||||
//"test/data/json_roundtrip/roundtrip31.json", // roundtrip error
|
||||
"test/data/json_roundtrip/roundtrip32.json"
|
||||
})
|
||||
{
|
||||
|
@ -14050,8 +14084,10 @@ TEST_CASE("regression tests")
|
|||
//CHECK(j2b.dump() == "23.42");
|
||||
|
||||
CHECK(j3a.dump() == "10000");
|
||||
CHECK(j3b.dump() == "1E04");
|
||||
CHECK(j3c.dump() == "1e04");
|
||||
CHECK(j3b.dump() == "10000");
|
||||
CHECK(j3c.dump() == "10000");
|
||||
//CHECK(j3b.dump() == "1E04"); // roundtrip error
|
||||
//CHECK(j3c.dump() == "1e04"); // roundtrip error
|
||||
}
|
||||
|
||||
SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator")
|
||||
|
@ -14073,6 +14109,15 @@ TEST_CASE("regression tests")
|
|||
|
||||
CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}}));
|
||||
}
|
||||
|
||||
SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements")
|
||||
{
|
||||
json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json;
|
||||
json expected = R"( { "arr1": [1, 2] } )"_json;
|
||||
|
||||
// check roundtrip
|
||||
CHECK(doc.patch(json::diff(doc, expected)) == expected);
|
||||
}
|
||||
}
|
||||
|
||||
// special test case to check if memory is leaked if constructor throws
|
||||
|
|
Loading…
Reference in a new issue