mirror of
https://github.com/nlohmann/json.git
synced 2024-08-23 05:22:28 +02:00
Merge branch 'release/v2.0.2'
This commit is contained in:
commit
3586767c05
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -12,3 +12,5 @@ me.nlohmann.json.docset
|
||||||
|
|
||||||
android
|
android
|
||||||
doc/xml
|
doc/xml
|
||||||
|
|
||||||
|
benchmarks/files/numbers/*.json
|
||||||
|
|
|
@ -168,3 +168,9 @@ script:
|
||||||
- if [ `which valgrind` ]; then
|
- if [ `which valgrind` ]; then
|
||||||
valgrind --error-exitcode=1 --leak-check=full ./json_unit ;
|
valgrind --error-exitcode=1 --leak-check=full ./json_unit ;
|
||||||
fi
|
fi
|
||||||
|
- if [ `which brew` ]; then
|
||||||
|
brew update ;
|
||||||
|
brew tap nlohmann/json ;
|
||||||
|
brew install nlohmann_json --HEAD ;
|
||||||
|
brew test nlohmann_json ;
|
||||||
|
fi
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
# define the project
|
# define the project
|
||||||
project(nlohmann_json VERSION 2.0.0 LANGUAGES CXX)
|
project(nlohmann_json VERSION 2.0.2 LANGUAGES CXX)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
|
|
16
ChangeLog.md
16
ChangeLog.md
|
@ -1,9 +1,21 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
|
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [Unreleased](https://github.com/nlohmann/json/tree/HEAD)
|
## [v2.0.2](https://github.com/nlohmann/json/releases/tag/v2.0.2) (2016-07-30)
|
||||||
|
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.1...v2.0.2)
|
||||||
|
|
||||||
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...HEAD)
|
- value\(\) does not work with \_json\_pointer types [\#283](https://github.com/nlohmann/json/issues/283)
|
||||||
|
- Easy serialization of classes [\#280](https://github.com/nlohmann/json/issues/280)
|
||||||
|
|
||||||
|
- Build error for std::int64 [\#282](https://github.com/nlohmann/json/issues/282)
|
||||||
|
|
||||||
|
- hexify\(\) function emits conversion warning [\#270](https://github.com/nlohmann/json/issues/270)
|
||||||
|
|
||||||
|
- let the makefile choose the correct sed [\#279](https://github.com/nlohmann/json/pull/279) ([murinicanor](https://github.com/murinicanor))
|
||||||
|
- Update hexify to use array lookup instead of ternary \(\#270\) [\#275](https://github.com/nlohmann/json/pull/275) ([dtoma](https://github.com/dtoma))
|
||||||
|
|
||||||
|
## [v2.0.1](https://github.com/nlohmann/json/releases/tag/v2.0.1) (2016-06-28)
|
||||||
|
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.0...v2.0.1)
|
||||||
|
|
||||||
- dump\(\) performance degradation in v2 [\#272](https://github.com/nlohmann/json/issues/272)
|
- dump\(\) performance degradation in v2 [\#272](https://github.com/nlohmann/json/issues/272)
|
||||||
|
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -10,6 +10,7 @@ all: json_unit
|
||||||
# clean up
|
# clean up
|
||||||
clean:
|
clean:
|
||||||
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM
|
rm -fr json_unit json_benchmarks fuzz fuzz-testing *.dSYM
|
||||||
|
rm -fr benchmarks/files/numbers/*.json
|
||||||
$(MAKE) clean -Cdoc
|
$(MAKE) clean -Cdoc
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,6 +86,7 @@ pretty:
|
||||||
|
|
||||||
# benchmarks
|
# benchmarks
|
||||||
json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp src/json.hpp
|
json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/cxxopts.hpp src/json.hpp
|
||||||
|
cd benchmarks/files/numbers ; python generate.py
|
||||||
$(CXX) -std=c++11 $(CXXFLAGS) -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
|
$(CXX) -std=c++11 $(CXXFLAGS) -O3 -flto -I src -I benchmarks $< $(LDFLAGS) -o $@
|
||||||
./json_benchmarks
|
./json_benchmarks
|
||||||
|
|
||||||
|
@ -93,7 +95,9 @@ json_benchmarks: benchmarks/benchmarks.cpp benchmarks/benchpress.hpp benchmarks/
|
||||||
# changelog
|
# changelog
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
NEXT_VERSION ?= "unreleased"
|
||||||
|
|
||||||
ChangeLog.md:
|
ChangeLog.md:
|
||||||
github_changelog_generator -o ChangeLog.md --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s
|
github_changelog_generator -o ChangeLog.md --simple-list --release-url https://github.com/nlohmann/json/releases/tag/%s --future-release $(NEXT_VERSION)
|
||||||
gsed -i 's|https://github.com/nlohmann/json/releases/tag/HEAD|https://github.com/nlohmann/json/tree/HEAD|' ChangeLog.md
|
gsed -i 's|https://github.com/nlohmann/json/releases/tag/HEAD|https://github.com/nlohmann/json/tree/HEAD|' ChangeLog.md
|
||||||
gsed -i '2i All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).' ChangeLog.md
|
gsed -i '2i All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).' ChangeLog.md
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
|
[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk?svg=true)](https://ci.appveyor.com/project/nlohmann/json)
|
||||||
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
|
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
|
||||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
|
[![Coverity Scan Build Status](https://scan.coverity.com/projects/5550/badge.svg)](https://scan.coverity.com/projects/nlohmann-json)
|
||||||
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/wuiuqYiYqRTdI3rG)
|
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/p5o4znPnGHJpDVqN)
|
||||||
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
|
[![Documentation](https://img.shields.io/badge/docs-doxygen-blue.svg)](http://nlohmann.github.io/json)
|
||||||
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
|
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
|
||||||
[![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
|
[![Github Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
|
||||||
|
@ -24,7 +24,7 @@ Other aspects were not so important to us:
|
||||||
|
|
||||||
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
|
- **Memory efficiency**. Each JSON object has an overhead of one pointer (the maximal size of a union) and one enumeration element (1 byte). The default generalization uses the following C++ data types: `std::string` for strings, `int64_t`, `uint64_t` or `double` for numbers, `std::map` for objects, `std::vector` for arrays, and `bool` for Booleans. However, you can template the generalized class `basic_json` to your needs.
|
||||||
|
|
||||||
- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).
|
- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) may be even faster (but would consist of more files which makes the integration harder).
|
||||||
|
|
||||||
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
|
See the [contribution guidelines](https://github.com/nlohmann/json/blob/master/.github/CONTRIBUTING.md#please-dont) for more information.
|
||||||
|
|
||||||
|
@ -485,6 +485,7 @@ I deeply appreciate the help of the following people.
|
||||||
- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
|
- [Tom Needham](https://github.com/06needhamt) fixed a subtle bug with MSVC 2015 which was also proposed by [Michael K.](https://github.com/Epidal).
|
||||||
- [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
- [Mário Feroldi](https://github.com/thelostt) fixed a small typo.
|
||||||
- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
- [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release.
|
||||||
|
- [Damien](https://github.com/dtoma) fixed one of the last conversion warnings.
|
||||||
|
|
||||||
Thanks a lot for helping out!
|
Thanks a lot for helping out!
|
||||||
|
|
||||||
|
@ -504,7 +505,7 @@ $ make
|
||||||
$ ./json_unit "*"
|
$ ./json_unit "*"
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
All tests passed (5568718 assertions in 32 test cases)
|
All tests passed (8905012 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).
|
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
|
||||||
|
|
|
@ -44,6 +44,36 @@ BENCHMARK("parse twitter.json", [](benchpress::context* ctx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
BENCHMARK("parse numbers/floats.json", [](benchpress::context* ctx)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ctx->num_iterations(); ++i)
|
||||||
|
{
|
||||||
|
std::ifstream input_file("benchmarks/files/numbers/floats.json");
|
||||||
|
nlohmann::json j;
|
||||||
|
j << input_file;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
BENCHMARK("parse numbers/signed_ints.json", [](benchpress::context* ctx)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ctx->num_iterations(); ++i)
|
||||||
|
{
|
||||||
|
std::ifstream input_file("benchmarks/files/numbers/signed_ints.json");
|
||||||
|
nlohmann::json j;
|
||||||
|
j << input_file;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
BENCHMARK("parse numbers/unsigned_ints.json", [](benchpress::context* ctx)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < ctx->num_iterations(); ++i)
|
||||||
|
{
|
||||||
|
std::ifstream input_file("benchmarks/files/numbers/unsigned_ints.json");
|
||||||
|
nlohmann::json j;
|
||||||
|
j << input_file;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
|
BENCHMARK("dump jeopardy.json", [](benchpress::context* ctx)
|
||||||
{
|
{
|
||||||
std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
|
std::ifstream input_file("benchmarks/files/jeopardy/jeopardy.json");
|
||||||
|
|
25
benchmarks/files/numbers/generate.py
Executable file
25
benchmarks/files/numbers/generate.py
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import sys
|
||||||
|
|
||||||
|
random.seed(0)
|
||||||
|
|
||||||
|
# floats
|
||||||
|
result_floats = []
|
||||||
|
for x in range(0, 1000000):
|
||||||
|
result_floats.append(random.uniform(-100000000.0, 100000000.0))
|
||||||
|
json.dump(result_floats, open("floats.json", "w"), indent=2)
|
||||||
|
|
||||||
|
# unsigned integers
|
||||||
|
result_uints = []
|
||||||
|
for x in range(0, 1000000):
|
||||||
|
result_uints.append(random.randint(0, 18446744073709551615))
|
||||||
|
json.dump(result_uints, open("unsigned_ints.json", "w"), indent=2)
|
||||||
|
|
||||||
|
# signed integers
|
||||||
|
result_sints = []
|
||||||
|
for x in range(0, 1000000):
|
||||||
|
result_sints.append(random.randint(-9223372036854775808, 9223372036854775807))
|
||||||
|
json.dump(result_sints, open("signed_ints.json", "w"), indent=2)
|
|
@ -5,7 +5,7 @@
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
DOXYFILE_ENCODING = UTF-8
|
DOXYFILE_ENCODING = UTF-8
|
||||||
PROJECT_NAME = "JSON for Modern C++"
|
PROJECT_NAME = "JSON for Modern C++"
|
||||||
PROJECT_NUMBER = 2.0.0
|
PROJECT_NUMBER = 2.0.2
|
||||||
PROJECT_BRIEF =
|
PROJECT_BRIEF =
|
||||||
PROJECT_LOGO =
|
PROJECT_LOGO =
|
||||||
OUTPUT_DIRECTORY = .
|
OUTPUT_DIRECTORY = .
|
||||||
|
|
21
doc/Makefile
21
doc/Makefile
|
@ -1,4 +1,5 @@
|
||||||
SRCDIR = ../src
|
SRCDIR = ../src
|
||||||
|
SED:=$(shell command -v gsed || which sed)
|
||||||
|
|
||||||
all: doxygen
|
all: doxygen
|
||||||
|
|
||||||
|
@ -52,10 +53,10 @@ clean:
|
||||||
# create Doxygen documentation
|
# create Doxygen documentation
|
||||||
doxygen: create_output create_links
|
doxygen: create_output create_links
|
||||||
doxygen
|
doxygen
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
|
|
||||||
upload: clean doxygen check_output
|
upload: clean doxygen check_output
|
||||||
cd html ; ../scripts/git-update-ghpages nlohmann/json
|
cd html ; ../scripts/git-update-ghpages nlohmann/json
|
||||||
|
@ -70,14 +71,14 @@ upload: clean doxygen check_output
|
||||||
# create docset for Dash
|
# create docset for Dash
|
||||||
docset: create_output
|
docset: create_output
|
||||||
cp Doxyfile Doxyfile_docset
|
cp Doxyfile Doxyfile_docset
|
||||||
gsed -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset
|
$(SED) -i 's/DISABLE_INDEX = NO/DISABLE_INDEX = YES/' Doxyfile_docset
|
||||||
gsed -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset
|
$(SED) -i 's/SEARCHENGINE = YES/SEARCHENGINE = NO/' Doxyfile_docset
|
||||||
gsed -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset
|
$(SED) -i 's@HTML_EXTRA_STYLESHEET = css/mylayout.css@HTML_EXTRA_STYLESHEET = css/mylayout_docset.css@' Doxyfile_docset
|
||||||
rm -fr html *.docset
|
rm -fr html *.docset
|
||||||
doxygen Doxyfile_docset
|
doxygen Doxyfile_docset
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
gsed -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType >@@g' html/*.html
|
||||||
make -C html
|
make -C html
|
||||||
mv html/*.docset .
|
mv html/*.docset .
|
||||||
gsed -i 's@<string>doxygen</string>@<string>json</string>@' me.nlohmann.json.docset/Contents/Info.plist
|
$(SED) -i 's@<string>doxygen</string>@<string>json</string>@' me.nlohmann.json.docset/Contents/Info.plist
|
||||||
rm -fr Doxyfile_docset html
|
rm -fr Doxyfile_docset html
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/k5KRwVJ42VggxxzX"><b>online</b></a>
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/p5o4znPnGHJpDVqN"><b>online</b></a>
|
29
doc/examples/basic_json__value_ptr.cpp
Normal file
29
doc/examples/basic_json__value_ptr.cpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON object with different entry types
|
||||||
|
json j =
|
||||||
|
{
|
||||||
|
{"integer", 1},
|
||||||
|
{"floating", 42.23},
|
||||||
|
{"string", "hello world"},
|
||||||
|
{"boolean", true},
|
||||||
|
{"object", {{"key1", 1}, {"key2", 2}}},
|
||||||
|
{"array", {1, 2, 3}}
|
||||||
|
};
|
||||||
|
|
||||||
|
// access existing values
|
||||||
|
int v_integer = j.value("/integer"_json_pointer, 0);
|
||||||
|
double v_floating = j.value("/floating"_json_pointer, 47.11);
|
||||||
|
|
||||||
|
// access nonexisting values and rely on default value
|
||||||
|
std::string v_string = j.value("/nonexisting"_json_pointer, "oops");
|
||||||
|
bool v_boolean = j.value("/nonexisting"_json_pointer, false);
|
||||||
|
|
||||||
|
// output values
|
||||||
|
std::cout << std::boolalpha << v_integer << " " << v_floating
|
||||||
|
<< " " << v_string << " " << v_boolean << "\n";
|
||||||
|
}
|
1
doc/examples/basic_json__value_ptr.link
Normal file
1
doc/examples/basic_json__value_ptr.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/K4L4D6nibuGXbjfd"><b>online</b></a>
|
1
doc/examples/basic_json__value_ptr.output
Normal file
1
doc/examples/basic_json__value_ptr.output
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1 42.23 oops false
|
|
@ -12,7 +12,6 @@ int main()
|
||||||
auto count_three = j_object.count("three");
|
auto count_three = j_object.count("three");
|
||||||
|
|
||||||
// print values
|
// print values
|
||||||
std::cout << std::boolalpha;
|
|
||||||
std::cout << "number of elements with key \"two\": " << count_two << '\n';
|
std::cout << "number of elements with key \"two\": " << count_two << '\n';
|
||||||
std::cout << "number of elements with key \"three\": " << count_three << '\n';
|
std::cout << "number of elements with key \"three\": " << count_three << '\n';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<a target="_blank" href="http://melpon.org/wandbox/permlink/XoXqF9LlWu8jlNgE"><b>online</b></a>
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/yv5TMrq9qREivvHf"><b>online</b></a>
|
BIN
doc/images/callback_events.png
Normal file
BIN
doc/images/callback_events.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
|
@ -268,4 +268,4 @@ The container functions known from STL have been extended to support the differe
|
||||||
@author [Niels Lohmann](http://nlohmann.me)
|
@author [Niels Lohmann](http://nlohmann.me)
|
||||||
@see https://github.com/nlohmann/json to download the source code
|
@see https://github.com/nlohmann/json to download the source code
|
||||||
|
|
||||||
@version 2.0.0
|
@version 2.0.2
|
||||||
|
|
BIN
doc/json.gif
BIN
doc/json.gif
Binary file not shown.
Before Width: | Height: | Size: 441 KiB After Width: | Height: | Size: 440 KiB |
955
src/json.hpp
955
src/json.hpp
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
__| | __| | | | JSON for Modern C++ (fuzz test support)
|
||||||
| | |__ | | | | | | version 2.0.0
|
| | |__ | | | | | | version 2.0.2
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Run "make fuzz_testing" and follow the instructions.
|
Run "make fuzz_testing" and follow the instructions.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
__ _____ _____ _____
|
__ _____ _____ _____
|
||||||
__| | __| | | | JSON for Modern C++ (test suite)
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
| | |__ | | | | | | version 2.0.0
|
| | |__ | | | | | | version 2.0.2
|
||||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
@ -1685,6 +1685,28 @@ TEST_CASE("object inspection")
|
||||||
json j_discarded(json::value_t::discarded);
|
json j_discarded(json::value_t::discarded);
|
||||||
CHECK(j_discarded.dump() == "<discarded>");
|
CHECK(j_discarded.dump() == "<discarded>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("check that precision is reset after serialization")
|
||||||
|
{
|
||||||
|
// create stringstream and set precision
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.precision(3);
|
||||||
|
ss << 3.141592653589793 << std::fixed;
|
||||||
|
CHECK(ss.str() == "3.14");
|
||||||
|
|
||||||
|
// reset stringstream
|
||||||
|
ss.str(std::string());
|
||||||
|
|
||||||
|
// use stringstream for JSON serialization
|
||||||
|
json j_number = 3.141592653589793;
|
||||||
|
ss << j_number;
|
||||||
|
|
||||||
|
// check that precision has been overridden during serialization
|
||||||
|
CHECK(ss.str() == "3.141592653589793");
|
||||||
|
|
||||||
|
// check that precision has been restored
|
||||||
|
CHECK(ss.precision() == 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("return the type of the object (explicit)")
|
SECTION("return the type of the object (explicit)")
|
||||||
|
@ -3745,6 +3767,8 @@ TEST_CASE("element access")
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access specified element with default value")
|
SECTION("access specified element with default value")
|
||||||
|
{
|
||||||
|
SECTION("given a key")
|
||||||
{
|
{
|
||||||
SECTION("access existing value")
|
SECTION("access existing value")
|
||||||
{
|
{
|
||||||
|
@ -3867,6 +3891,135 @@ TEST_CASE("element access")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("given a JSON pointer")
|
||||||
|
{
|
||||||
|
SECTION("access existing value")
|
||||||
|
{
|
||||||
|
CHECK(j.value("/integer"_json_pointer, 2) == 1);
|
||||||
|
CHECK(j.value("/integer"_json_pointer, 1.0) == Approx(1));
|
||||||
|
CHECK(j.value("/unsigned"_json_pointer, 2) == 1u);
|
||||||
|
CHECK(j.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
|
||||||
|
CHECK(j.value("/null"_json_pointer, json(1)) == json());
|
||||||
|
CHECK(j.value("/boolean"_json_pointer, false) == true);
|
||||||
|
CHECK(j.value("/string"_json_pointer, "bar") == "hello world");
|
||||||
|
CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||||
|
CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||||
|
CHECK(j.value("/floating"_json_pointer, 12) == 42);
|
||||||
|
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||||
|
CHECK(j.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||||
|
|
||||||
|
CHECK(j_const.value("/integer"_json_pointer, 2) == 1);
|
||||||
|
CHECK(j_const.value("/integer"_json_pointer, 1.0) == Approx(1));
|
||||||
|
CHECK(j_const.value("/unsigned"_json_pointer, 2) == 1u);
|
||||||
|
CHECK(j_const.value("/unsigned"_json_pointer, 1.0) == Approx(1u));
|
||||||
|
CHECK(j_const.value("/boolean"_json_pointer, false) == true);
|
||||||
|
CHECK(j_const.value("/string"_json_pointer, "bar") == "hello world");
|
||||||
|
CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||||
|
CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||||
|
CHECK(j_const.value("/floating"_json_pointer, 12) == 42);
|
||||||
|
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||||
|
CHECK(j_const.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("access non-existing value")
|
||||||
|
{
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, 2) == 2);
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, 2u) == 2u);
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, false) == false);
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, "bar") == "bar");
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||||
|
CHECK(j.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100}));
|
||||||
|
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, 2) == 2);
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, 2u) == 2u);
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, false) == false);
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, "bar") == "bar");
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, 12.34) == Approx(12.34));
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, json({{"foo", "bar"}})) == json({{"foo", "bar"}}));
|
||||||
|
CHECK(j_const.value("/not/existing"_json_pointer, json({10, 100})) == json({10, 100}));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("access on non-object type")
|
||||||
|
{
|
||||||
|
SECTION("null")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::null);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with null");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with null");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("boolean")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::boolean);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with boolean");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||||
|
"cannot use value() with boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("string")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::string);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with string");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||||
|
"cannot use value() with string");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::array);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with array");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with array");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("number (integer)")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::number_integer);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||||
|
"cannot use value() with number");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("number (unsigned)")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::number_unsigned);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||||
|
"cannot use value() with number");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("number (floating-point)")
|
||||||
|
{
|
||||||
|
json j_nonobject(json::value_t::number_float);
|
||||||
|
const json j_nonobject_const(j_nonobject);
|
||||||
|
CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error);
|
||||||
|
CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number");
|
||||||
|
CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1),
|
||||||
|
"cannot use value() with number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("front and back")
|
SECTION("front and back")
|
||||||
{
|
{
|
||||||
// "array" is the smallest key
|
// "array" is the smallest key
|
||||||
|
@ -9694,6 +9847,39 @@ TEST_CASE("parser class")
|
||||||
CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'");
|
||||||
// improve code coverage
|
// improve code coverage
|
||||||
CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument);
|
||||||
|
// unescaped control characters
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), std::invalid_argument);
|
||||||
|
CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), std::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("escaped")
|
SECTION("escaped")
|
||||||
|
@ -10304,10 +10490,23 @@ TEST_CASE("parser class")
|
||||||
CHECK(j_empty_array == json());
|
CHECK(j_empty_array == json());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("copy constructor")
|
||||||
|
{
|
||||||
|
json::string_t* s = new json::string_t("[1,2,3,4]");
|
||||||
|
json::parser p(*s);
|
||||||
|
delete s;
|
||||||
|
CHECK(p.parse() == json({1, 2, 3, 4}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("README", "[hide]")
|
TEST_CASE("README", "[hide]")
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
// redirect std::cout for the README file
|
||||||
|
auto old_cout_buffer = std::cout.rdbuf();
|
||||||
|
std::ostringstream new_stream;
|
||||||
|
std::cout.rdbuf(new_stream.rdbuf());
|
||||||
{
|
{
|
||||||
// create an empty structure (null)
|
// create an empty structure (null)
|
||||||
json j;
|
json j;
|
||||||
|
@ -10556,6 +10755,10 @@ TEST_CASE("README", "[hide]")
|
||||||
// { "op":"add","path":"/foo","value":"bar" }
|
// { "op":"add","path":"/foo","value":"bar" }
|
||||||
// ]
|
// ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// restore old std::cout
|
||||||
|
std::cout.rdbuf(old_cout_buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("algorithms")
|
TEST_CASE("algorithms")
|
||||||
|
@ -12084,17 +12287,21 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
{
|
{
|
||||||
SECTION("full enumeration of Unicode code points")
|
SECTION("full enumeration of Unicode code points")
|
||||||
{
|
{
|
||||||
// create a string from a codepoint
|
// create an escaped string from a code point
|
||||||
auto codepoint_to_unicode = [](std::size_t cp)
|
const auto codepoint_to_unicode = [](std::size_t cp)
|
||||||
{
|
{
|
||||||
char* buffer = new char[10];
|
// copd points are represented as a six-character sequence: a
|
||||||
sprintf(buffer, "\\u%04lx", cp);
|
// reverse solidus, followed by the lowercase letter u, followed
|
||||||
std::string result(buffer);
|
// by four hexadecimal digits that encode the character's code
|
||||||
delete[] buffer;
|
// point
|
||||||
return result;
|
std::stringstream ss;
|
||||||
|
ss << "\\u" << std::setw(4) << std::setfill('0') << std::hex << cp;
|
||||||
|
return ss.str();
|
||||||
};
|
};
|
||||||
|
|
||||||
// generate all codepoints
|
// generate all UTF-8 code points; in total, 1112064 code points are
|
||||||
|
// generated: 0x1FFFFF code points - 2048 invalid values between
|
||||||
|
// 0xD800 and 0xDFFF.
|
||||||
for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
|
for (std::size_t cp = 0; cp <= 0x10FFFFu; ++cp)
|
||||||
{
|
{
|
||||||
// The Unicode standard permanently reserves these code point
|
// The Unicode standard permanently reserves these code point
|
||||||
|
@ -12104,34 +12311,57 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
// no UTF forms, including UTF-16, can encode these code points.
|
// no UTF forms, including UTF-16, can encode these code points.
|
||||||
if (cp >= 0xD800u and cp <= 0xDFFFu)
|
if (cp >= 0xD800u and cp <= 0xDFFFu)
|
||||||
{
|
{
|
||||||
|
// if we would not skip these code points, we would get a
|
||||||
|
// "missing low surrogate" exception
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string res;
|
// string to store the code point as in \uxxxx format
|
||||||
|
std::string escaped_string;
|
||||||
|
// string to store the code point as unescaped character sequence
|
||||||
|
std::string unescaped_string;
|
||||||
|
|
||||||
if (cp < 0x10000u)
|
if (cp < 0x10000u)
|
||||||
{
|
{
|
||||||
// codepoint can be represented with 16 bit
|
// code points in the Basic Multilingual Plane can be
|
||||||
res += codepoint_to_unicode(cp);
|
// represented with one \\uxxxx sequence
|
||||||
|
escaped_string = codepoint_to_unicode(cp);
|
||||||
|
|
||||||
|
// All Unicode characters may be placed within the quotation
|
||||||
|
// marks, except for the characters that must be escaped:
|
||||||
|
// quotation mark, reverse solidus, and the control characters
|
||||||
|
// (U+0000 through U+001F); we ignore these code points as
|
||||||
|
// they are checked with codepoint_to_unicode.
|
||||||
|
if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
|
||||||
|
{
|
||||||
|
unescaped_string = json::lexer::to_unicode(cp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// codepoint can be represented with a pair
|
// To escape an extended character that is not in the Basic
|
||||||
res += codepoint_to_unicode(0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu));
|
// Multilingual Plane, the character is represented as a
|
||||||
res += codepoint_to_unicode(0xdc00u + ((cp - 0x10000u) & 0x3ffu));
|
// 12-character sequence, encoding the UTF-16 surrogate pair
|
||||||
|
const auto codepoint1 = 0xd800u + (((cp - 0x10000u) >> 10) & 0x3ffu);
|
||||||
|
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
|
||||||
|
escaped_string = codepoint_to_unicode(codepoint1);
|
||||||
|
escaped_string += codepoint_to_unicode(codepoint2);
|
||||||
|
unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
// all other code points are valid and must not yield parse errors
|
||||||
{
|
CAPTURE(cp);
|
||||||
json j1, j2;
|
CAPTURE(escaped_string);
|
||||||
CHECK_NOTHROW(j1 = json::parse("\"" + res + "\""));
|
CAPTURE(unescaped_string);
|
||||||
|
|
||||||
|
json j1, j2, j3, j4;
|
||||||
|
CHECK_NOTHROW(j1 = json::parse("\"" + escaped_string + "\""));
|
||||||
CHECK_NOTHROW(j2 = json::parse(j1.dump()));
|
CHECK_NOTHROW(j2 = json::parse(j1.dump()));
|
||||||
CHECK(j1 == j2);
|
CHECK(j1 == j2);
|
||||||
}
|
|
||||||
catch (std::invalid_argument)
|
CHECK_NOTHROW(j3 = json::parse("\"" + unescaped_string + "\""));
|
||||||
{
|
CHECK_NOTHROW(j4 = json::parse(j3.dump()));
|
||||||
// we ignore parsing errors
|
CHECK(j3 == j4);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12144,6 +12374,8 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
CHECK_NOTHROW(j << f);
|
CHECK_NOTHROW(j << f);
|
||||||
|
|
||||||
// the array has 1112064 + 1 elemnts (a terminating "null" value)
|
// the array has 1112064 + 1 elemnts (a terminating "null" value)
|
||||||
|
// Note: 1112064 = 0x1FFFFF code points - 2048 invalid values between
|
||||||
|
// 0xD800 and 0xDFFF.
|
||||||
CHECK(j.size() == 1112065);
|
CHECK(j.size() == 1112065);
|
||||||
|
|
||||||
SECTION("check JSON Pointers")
|
SECTION("check JSON Pointers")
|
||||||
|
@ -14128,6 +14360,19 @@ TEST_CASE("regression tests")
|
||||||
// check roundtrip
|
// check roundtrip
|
||||||
CHECK(doc.patch(json::diff(doc, expected)) == expected);
|
CHECK(doc.patch(json::diff(doc, expected)) == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("issue #283 - value() does not work with _json_pointer types")
|
||||||
|
{
|
||||||
|
json j =
|
||||||
|
{
|
||||||
|
{"object", {{"key1", 1}, {"key2", 2}}},
|
||||||
|
};
|
||||||
|
|
||||||
|
int at_integer = j.at("/object/key2"_json_pointer);
|
||||||
|
int val_integer = j.value("/object/key2"_json_pointer, 0);
|
||||||
|
|
||||||
|
CHECK(at_integer == val_integer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// special test case to check if memory is leaked if constructor throws
|
// special test case to check if memory is leaked if constructor throws
|
||||||
|
|
Loading…
Reference in a new issue