:twisted_rightwards_arrows: Merge branch 'release/2.0.9'
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 04a7cc1..5110aea 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -36,7 +36,7 @@
make re2c
```
- To run [`re2c`](http://re2c.org) and generate/overwrite file `src/json.hpp` with your changes in file `src/json.hpp.re2c`.
+ To run [`re2c`](http://re2c.org) and generate/overwrite file `src/json.hpp` with your changes in file `src/json.hpp.re2c`. We currently use re2c version 0.16. Please also use this version, because other re2c versions tend to create code that differs a lot from which makes diffs unusable.
2. [`test/src/unit.cpp`](https://github.com/nlohmann/json/blob/master/test/unit.cpp) - This contains the [Catch](https://github.com/philsquared/Catch) unit tests which currently cover [100 %](https://coveralls.io/github/nlohmann/json) of the library's code.
@@ -59,10 +59,13 @@
## Please don't
-- Only make changes to file `src/json.hpp` -- please read the paragraph above and understand why `src/json.hpp.re2c` exists.
+- Please do not only make changes to file `src/json.hpp` -- please read the paragraph above and understand why `src/json.hpp.re2c` exists.
- The C++11 support varies between different **compilers** and versions. Please note the [list of supported compilers](https://github.com/nlohmann/json/blob/master/README.md#supported-compilers). Some compilers like GCC 4.8 (and earlier), Clang 3.3 (and earlier), or Microsoft Visual Studio 13.0 and earlier are known not to work due to missing or incomplete C++11 support. Please refrain from proposing changes that work around these compiler's limitations with `#ifdef`s or other means.
- Specifically, I am aware of compilation problems with **Microsoft Visual Studio** (there even is an [issue label](https://github.com/nlohmann/json/issues?utf8=✓&q=label%3A%22visual+studio%22+) for these kind of bugs). I understand that even in 2016, complete C++11 support isn't there yet. But please also understand that I do not want to drop features or uglify the code just to make Microsoft's sub-standard compiler happy. The past has shown that there are ways to express the functionality such that the code compiles with the most recent MSVC - unfortunately, this is not the main objective of the project.
- Please refrain from proposing changes that would **break [JSON](http://json.org) conformance**. If you propose a conformant extension of JSON to be supported by the library, please motivate this extension.
+ - We shall not extend the library to **support comments**. There is quite some [controversy](https://www.reddit.com/r/programming/comments/4v6chu/why_json_doesnt_support_comments_douglas_crockford/) around this topic, and there were quite some [issues](https://github.com/nlohmann/json/issues/376) on this. We believe that JSON is fine without comments.
+ - We do not preserve the **insertion order of object elements**. The [JSON standard](https://tools.ietf.org/html/rfc7159.html) defines objects as "an unordered collection of zero or more name/value pairs". To this end, this library does not preserve insertion order of name/value pairs. (In fact, keys will be traversed in alphabetical order as `std::map` with `std::less` is used by default.) Note this behavior conforms to the standard, and we shall not it to any other order.
+
- Please do not open pull requests that address **multiple issues**.
## Wanted
diff --git a/.gitignore b/.gitignore
index bd8c869..42a18e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,5 @@
.idea
cmake-build-debug
+
+test/test-*
diff --git a/.travis.yml b/.travis.yml
index d989638..0f9010b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -39,7 +39,17 @@
sources: ['ubuntu-toolchain-r-test']
packages: [g++-4.9, valgrind]
after_success:
- - valgrind --error-exitcode=1 --leak-check=full test/json_unit
+ - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN=""
+
+ # cLang sanitizer
+
+ #- os: linux
+ # env:
+ # - LLVM_VERSION=3.8.1
+ # - SPECIAL=sanitizer
+ # compiler: clang
+ # before_script:
+ # - make clang_sanitize
# cppcheck
@@ -68,9 +78,10 @@
- tar xf lcov_1.11.orig.tar.gz
- sudo make -C lcov-1.11/ install
- gem install coveralls-lcov
+ - pip install --user cpp-coveralls
after_success:
- make clean
- - CXXFLAGS="--coverage -g -O0" CPPFLAGS="-DNDEBUG" make
+ - CXXFLAGS="--coverage -g -O0" CPPFLAGS="-DNDEBUG" make json_unit
- test/json_unit "*"
- coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
- lcov --directory src --directory test/src --capture --output-file coverage.info --rc lcov_branch_coverage=1 --no-external
@@ -236,11 +247,8 @@
- uname -a
- $CXX --version
- # compile
- - make
-
- # execute unit tests
- - test/json_unit "*"
+ # compile and execute unit tests
+ - make check
# check if homebrew works (only checks develop branch)
- if [ `which brew` ]; then
@@ -249,51 +257,3 @@
brew install nlohmann_json --HEAD ;
brew test nlohmann_json ;
fi
-
-#language: cpp
-#
-#dist: trusty
-#sudo: required
-#
-#env:
-# global:
-# # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
-# # via the "travis encrypt" command using the project repo's public key
-# - secure: "m89SSgE+ASLO38rSKx7MTXK3n5NkP9bIx95jwY71YEiuFzib30PDJ/DifKnXxBjvy/AkCGztErQRk/8ZCvq+4HXozU2knEGnL/RUitvlwbhzfh2D4lmS3BvWBGS3N3NewoPBrRmdcvnT0xjOGXxtZaJ3P74TkB9GBnlz/HmKORA="
-#
-## from http://stackoverflow.com/a/32127147/266378
-#matrix:
-# include:
-# - os: linux
-# compiler: gcc
-# addons:
-# apt:
-# sources: ['ubuntu-toolchain-r-test']
-# packages: ['g++-4.9', 'valgrind', 'python-pip', 'python-yaml']
-# before_script:
-# - pip install --user git+git://github.com/eddyxu/cpp-coveralls.git
-# after_success:
-# - make clean
-# - touch src/json.hpp
-# - make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage -std=c++11 -lstdc++" CXX=$COMPILER
-# - test/json_unit "*"
-# - coveralls --build-root test --exclude src/catch.hpp --exclude src/unit-algorithms.cpp --exclude src/unit-allocator.cpp --exclude src/unit-capacity.cpp --exclude src/unit-class_const_iterator.cpp --exclude src/unit-class_iterator.cpp --exclude src/unit-class_lexer.cpp --exclude src/unit-class_parser.cpp --exclude src/unit-comparison.cpp --exclude src/unit-concepts.cpp --exclude src/unit-constructor1.cpp --exclude src/unit-constructor2.cpp --exclude src/unit-convenience.cpp --exclude src/unit-conversions.cpp --exclude src/unit-deserialization.cpp --exclude src/unit-element_access1.cpp --exclude src/unit-element_access2.cpp --exclude src/unit-inspection.cpp --exclude src/unit-iterator_wrapper.cpp --exclude src/unit-iterators1.cpp --exclude src/unit-iterators2.cpp --exclude src/unit-json_patch.cpp --exclude src/unit-json_pointer.cpp --exclude src/unit-modifiers.cpp --exclude src/unit-pointer_access.cpp --exclude src/unit-readme.cpp --exclude src/unit-reference_access.cpp --exclude src/unit-regression.cpp --exclude src/unit-serialization.cpp --exclude src/unit-testsuites.cpp --exclude src/unit-unicode.cpp --include ../src/json.hpp --gcov-options '\-lp' --gcov 'gcov-4.9'
-# env: COMPILER=g++-4.9
-#
-# - os: linux
-# compiler: gcc
-# before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
-# addons:
-# apt:
-# sources: ['ubuntu-toolchain-r-test']
-# packages: ['g++-5', 'valgrind']
-# coverity_scan:
-# project:
-# name: "nlohmann/json"
-# description: "Build submitted via Travis CI"
-# notification_email: niels.lohmann@gmail.com
-# build_command_prepend: "make clean ; sudo cp $(which g++-5) $(which g++)"
-# build_command: "make"
-# branch_pattern: coverity_scan
-# env: COMPILER=g++-5
-#
diff --git a/CMakeLists.txt b/CMakeLists.txt
index efda6e9..8077036 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.0)
# define the project
-project(nlohmann_json VERSION 2.0.8 LANGUAGES CXX)
+project(nlohmann_json VERSION 2.0.9 LANGUAGES CXX)
enable_testing()
diff --git a/ChangeLog.md b/ChangeLog.md
index 287420c..9254576 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,29 @@
# Change Log
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
+## [v2.0.9](https://github.com/nlohmann/json/releases/tag/v2.0.9) (2016-12-16)
+[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.8...v2.0.9)
+
+- \#pragma GCC diagnostic ignored "-Wdocumentation" [\#393](https://github.com/nlohmann/json/issues/393)
+- How to parse this json file and write separate sub object as json files? [\#392](https://github.com/nlohmann/json/issues/392)
+- Integer-overflow \(OSS-Fuzz issue 267\) [\#389](https://github.com/nlohmann/json/issues/389)
+- Implement indefinite-length types from RFC 7049 [\#387](https://github.com/nlohmann/json/issues/387)
+- template parameter "T" is not used in declaring the parameter types of function template [\#386](https://github.com/nlohmann/json/issues/386)
+- Serializing json instances containing already serialized string values without escaping [\#385](https://github.com/nlohmann/json/issues/385)
+- Add test cases from RFC 7049 [\#384](https://github.com/nlohmann/json/issues/384)
+- Add a table of contents to the README file [\#383](https://github.com/nlohmann/json/issues/383)
+- Update FAQ section in the guidelines for contributing [\#382](https://github.com/nlohmann/json/issues/382)
+- Allow for forward declaring nlohmann::json [\#381](https://github.com/nlohmann/json/issues/381)
+- Bug in overflow detection when parsing integers [\#380](https://github.com/nlohmann/json/issues/380)
+- A unique name to mention the library? [\#377](https://github.com/nlohmann/json/issues/377)
+- Support for comments. [\#376](https://github.com/nlohmann/json/issues/376)
+- Non-unique keys in objects. [\#375](https://github.com/nlohmann/json/issues/375)
+- Request: binary serialization/deserialization [\#358](https://github.com/nlohmann/json/issues/358)
+
+- Replace class iterator and const\_iterator by using a single template class to reduce code. [\#395](https://github.com/nlohmann/json/pull/395) ([Bosswestfalen](https://github.com/Bosswestfalen))
+- Clang: quiet a warning [\#391](https://github.com/nlohmann/json/pull/391) ([jaredgrubb](https://github.com/jaredgrubb))
+- Fix issue \#380: Signed integer overflow check [\#390](https://github.com/nlohmann/json/pull/390) ([qwename](https://github.com/qwename))
+
## [v2.0.8](https://github.com/nlohmann/json/releases/tag/v2.0.8) (2016-12-02)
[Full Changelog](https://github.com/nlohmann/json/compare/v2.0.7...v2.0.8)
@@ -8,7 +31,6 @@
- Compiler warnings? [\#372](https://github.com/nlohmann/json/issues/372)
- docs: how to release a json object in memory? [\#371](https://github.com/nlohmann/json/issues/371)
- crash in dump [\#370](https://github.com/nlohmann/json/issues/370)
-- Conversion operators not considered [\#369](https://github.com/nlohmann/json/issues/369)
- Coverity issue \(FORWARD\_NULL\) in lexer\(std::istream& s\) [\#368](https://github.com/nlohmann/json/issues/368)
- json::parse on failed stream gets stuck [\#366](https://github.com/nlohmann/json/issues/366)
- Performance improvements [\#365](https://github.com/nlohmann/json/issues/365)
diff --git a/Makefile b/Makefile
index 3fd6d54..fcce453 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,8 @@
SED = sed
# main target
-all: json_unit
+all:
+ $(MAKE) -C test
# clean up
clean:
@@ -21,14 +22,14 @@
# build unit tests
json_unit:
- @$(MAKE) -C test
+ @$(MAKE) json_unit -C test
# run unit tests
-check: json_unit
- test/json_unit "*"
+check:
+ $(MAKE) check -C test
-check-fast: json_unit
- test/json_unit
+check-fast:
+ $(MAKE) check -C test TEST_PATTERN=""
##########################################################################
@@ -69,6 +70,7 @@
clang_sanitize: clean
CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE)
+
##########################################################################
# maintainer targets
##########################################################################
diff --git a/README.md b/README.md
index 0305ea0..97ae685 100644
--- a/README.md
+++ b/README.md
@@ -4,13 +4,29 @@
[![Build Status](https://ci.appveyor.com/api/projects/status/1acb366xfyg3qybk/branch/develop?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)
[![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/fsf5FqYe6GoX68W6)
+[![Try online](https://img.shields.io/badge/try-online-blue.svg)](http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK)
[![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 Releases](https://img.shields.io/github/release/nlohmann/json.svg)](https://github.com/nlohmann/json/releases)
[![Github Issues](https://img.shields.io/github/issues/nlohmann/json.svg)](http://github.com/nlohmann/json/issues)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/289/badge)](https://bestpractices.coreinfrastructure.org/projects/289)
+- [Design goals](#design-goals)
+- [Integration](#integration)
+- [Examples](#examples)
+ - [JSON as first-class data type](#json-as-first-class-data-type)
+ - [Serialization / Deserialization](#serialization--deserialization)
+ - [STL-like access](#stl-like-access)
+ - [Conversion from STL containers](#conversion-from-stl-containers)
+ - [JSON Pointer and JSON Patch](#json-pointer-and-json-patch)
+ - [Implicit conversions](#implicit-conversions)
+ - [Binary formats (CBOR and MessagePack)](#binary-formats-cbor-and-messagepack)
+- [Supported compilers](#supported-compilers)
+- [License](#license)
+- [Thanks](#thanks)
+- [Notes](#notes)
+- [Execute unit tests](#execute-unit-tests)
+
## Design goals
There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
@@ -48,6 +64,10 @@
## 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_a602f275f0359ab181221384989810604.html#a602f275f0359ab181221384989810604)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
+
+### JSON as first-class data type
+
Here are some examples to give you an idea how to use the class.
Assume you want to create the JSON object
@@ -421,6 +441,31 @@
// etc.
```
+### Binary formats (CBOR and MessagePack)
+
+Though JSON is a ubiquitous data format, it is not a very compact format suitable for data exchange, for instance over a network. Hence, the library supports [CBOR](http://cbor.io) (Concise Binary Object Representation) and [MessagePack](http://msgpack.org) to efficiently encode JSON values to byte vectors and to decode such vectors.
+
+```cpp
+// create a JSON value
+json j = R"({"compact": true, "schema": 0})"_json;
+
+// serialize to CBOR
+std::vector<uint8_t> v_cbor = json::to_cbor(j);
+
+// 0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_cbor = json::from_cbor(v_cbor);
+
+// serialize to MessagePack
+std::vector<uint8_t> v_msgpack = json::to_msgpack(j);
+
+// 0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x00
+
+// roundtrip
+json j_from_msgpack = json::from_msgpack(v_msgpack);
+```
+
## Supported compilers
@@ -537,6 +582,9 @@
- [Pierre-Antoine Lacaze](https://github.com/palacaze) found a subtle bug in the `dump()` function.
- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](http://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser and improved the benchmarking code.
- [cgzones](https://github.com/cgzones) had an idea how to fix the Coverity scan.
+- [Jared Grubb](https://github.com/jaredgrubb) silenced a nasty documentation warning.
+- [Yixin Zhang](https://github.com/qwename) fixed an integer overflow check.
+- [Bosswestfalen](https://github.com/Bosswestfalen) merged two iterator classes into a smaller one.
Thanks a lot for helping out!
@@ -560,7 +608,7 @@
$ make check
===============================================================================
-All tests passed (8905518 assertions in 36 test cases)
+All tests passed (11201893 assertions in 43 test cases)
```
Alternatively, you can use [CMake](https://cmake.org) and run
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 625f9c1..17c81d8 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "JSON for Modern C++"
-PROJECT_NUMBER = 2.0.8
+PROJECT_NUMBER = 2.0.9
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = .
diff --git a/doc/examples/README.link b/doc/examples/README.link
index 48a66aa..128ab1d 100644
--- a/doc/examples/README.link
+++ b/doc/examples/README.link
@@ -1 +1 @@
-<a target="_blank" href="http://melpon.org/wandbox/permlink/G6Pdtdxq01HJvvJz"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="http://melpon.org/wandbox/permlink/8soFCqS532vOyZcK"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_cbor.cpp b/doc/examples/from_cbor.cpp
new file mode 100644
index 0000000..92b0522
--- /dev/null
+++ b/doc/examples/from_cbor.cpp
@@ -0,0 +1,18 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+ // create byte vector
+ std::vector<uint8_t> v = {0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
+ 0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x00
+ };
+
+ // deserialize it with CBOR
+ json j = json::from_cbor(v);
+
+ // print the deserialized JSON value
+ std::cout << std::setw(2) << j << std::endl;
+}
diff --git a/doc/examples/from_cbor.link b/doc/examples/from_cbor.link
new file mode 100644
index 0000000..8120498
--- /dev/null
+++ b/doc/examples/from_cbor.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/TDPaxmQ7PsvfWxrs"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_cbor.output b/doc/examples/from_cbor.output
new file mode 100644
index 0000000..259f63b
--- /dev/null
+++ b/doc/examples/from_cbor.output
@@ -0,0 +1,4 @@
+{
+ "compact": true,
+ "schema": 0
+}
diff --git a/doc/examples/from_msgpack.cpp b/doc/examples/from_msgpack.cpp
new file mode 100644
index 0000000..d275f13
--- /dev/null
+++ b/doc/examples/from_msgpack.cpp
@@ -0,0 +1,18 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+ // create byte vector
+ std::vector<uint8_t> v = {0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
+ 0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d,
+ 0x61, 0x00
+ };
+
+ // deserialize it with MessagePack
+ json j = json::from_msgpack(v);
+
+ // print the deserialized JSON value
+ std::cout << std::setw(2) << j << std::endl;
+}
diff --git a/doc/examples/from_msgpack.link b/doc/examples/from_msgpack.link
new file mode 100644
index 0000000..0d5e783
--- /dev/null
+++ b/doc/examples/from_msgpack.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/7vRGmLdVcYM7POhE"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_msgpack.output b/doc/examples/from_msgpack.output
new file mode 100644
index 0000000..259f63b
--- /dev/null
+++ b/doc/examples/from_msgpack.output
@@ -0,0 +1,4 @@
+{
+ "compact": true,
+ "schema": 0
+}
diff --git a/doc/examples/to_cbor.cpp b/doc/examples/to_cbor.cpp
new file mode 100644
index 0000000..21a5ce8
--- /dev/null
+++ b/doc/examples/to_cbor.cpp
@@ -0,0 +1,19 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+ // create a JSON value
+ json j = R"({"compact": true, "schema": 0})"_json;
+
+ // serialize it to CBOR
+ std::vector<uint8_t> v = json::to_cbor(j);
+
+ // print the vector content
+ for (auto& byte : v)
+ {
+ std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
+ }
+ std::cout << std::endl;
+}
diff --git a/doc/examples/to_cbor.link b/doc/examples/to_cbor.link
new file mode 100644
index 0000000..3ab655c
--- /dev/null
+++ b/doc/examples/to_cbor.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/UaDbrgZ8OPWaShY8"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_cbor.output b/doc/examples/to_cbor.output
new file mode 100644
index 0000000..02c9ada
--- /dev/null
+++ b/doc/examples/to_cbor.output
@@ -0,0 +1 @@
+0xa2 0x67 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xf5 0x66 0x73 0x63 0x68 0x65 0x6d 0x61 0x00
diff --git a/doc/examples/to_msgpack.cpp b/doc/examples/to_msgpack.cpp
new file mode 100644
index 0000000..21c8817
--- /dev/null
+++ b/doc/examples/to_msgpack.cpp
@@ -0,0 +1,19 @@
+#include <json.hpp>
+
+using json = nlohmann::json;
+
+int main()
+{
+ // create a JSON value
+ json j = R"({"compact": true, "schema": 0})"_json;
+
+ // serialize it to MessagePack
+ std::vector<uint8_t> v = json::to_msgpack(j);
+
+ // print the vector content
+ for (auto& byte : v)
+ {
+ std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
+ }
+ std::cout << std::endl;
+}
diff --git a/doc/examples/to_msgpack.link b/doc/examples/to_msgpack.link
new file mode 100644
index 0000000..4c7d3a2
--- /dev/null
+++ b/doc/examples/to_msgpack.link
@@ -0,0 +1 @@
+<a target="_blank" href="http://melpon.org/wandbox/permlink/jvaU8GEfAusb5dKf"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_msgpack.output b/doc/examples/to_msgpack.output
new file mode 100644
index 0000000..4d6c40a
--- /dev/null
+++ b/doc/examples/to_msgpack.output
@@ -0,0 +1 @@
+0x82 0xa7 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xc3 0xa6 0x73 0x63 0x68 0x65 0x6d 0x61 0x00
diff --git a/doc/index.md b/doc/index.md
index 0b608eb..8292fe6 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -277,4 +277,4 @@
@author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code
-@version 2.0.8
+@version 2.0.9
diff --git a/doc/json.gif b/doc/json.gif
index a5f1187..7d3bf81 100644
--- a/doc/json.gif
+++ b/doc/json.gif
Binary files differ
diff --git a/src/json.hpp b/src/json.hpp
index 6fed0a1..23058be 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -34,7 +34,7 @@
#include <cassert> // assert
#include <cctype> // isdigit
#include <ciso646> // and, not, or
-#include <cmath> // isfinite, signbit
+#include <cmath> // isfinite, ldexp, signbit
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
#include <cstdint> // int64_t, uint64_t
#include <cstdlib> // strtod, strtof, strtold, strtoul
@@ -75,6 +75,12 @@
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+// disable documentation warnings on clang
+#if defined(__clang__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
// allow for portable deprecation warnings
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define JSON_DEPRECATED __attribute__((deprecated))
@@ -222,6 +228,7 @@
public:
// forward declarations
+ template<typename U> class iter_impl;
template<typename Base> class json_reverse_iterator;
class json_pointer;
@@ -256,9 +263,9 @@
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
/// an iterator for a basic_json container
- class iterator;
+ using iterator = iter_impl<basic_json>;
/// a const iterator for a basic_json container
- class const_iterator;
+ using const_iterator = iter_impl<const basic_json>;
/// a reverse iterator for a basic_json container
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
/// a const reverse iterator for a basic_json container
@@ -944,7 +951,7 @@
With a parser callback function, the result of parsing a JSON text can be
influenced. When passed to @ref parse(std::istream&, const
- parser_callback_t) or @ref parse(const char*, const parser_callback_t),
+ parser_callback_t) or @ref parse(const CharT, const parser_callback_t),
it is called on certain events (passed as @ref parse_event_t via parameter
@a event) with a set recursion depth @a depth and context JSON value
@a parsed. The return value of the callback function is a boolean
@@ -987,7 +994,7 @@
skipped completely or replaced by an empty discarded object.
@sa @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const char*, parser_callback_t) for examples
+ @ref parse(const CharT, const parser_callback_t) for examples
@since version 1.0.0
*/
@@ -6003,11 +6010,11 @@
@since version 1.0.0 (originally for @ref string_t)
*/
- template<typename CharPT, typename std::enable_if<
- std::is_pointer<CharPT>::value and
- std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
- sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
- static basic_json parse(const CharPT s,
+ template<typename CharT, typename std::enable_if<
+ std::is_pointer<CharT>::value and
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+ sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
+ static basic_json parse(const CharT s,
const parser_callback_t cb = nullptr)
{
return parser(reinterpret_cast<const char*>(s), cb).parse();
@@ -6032,7 +6039,7 @@
@liveexample{The example below demonstrates the `parse()` function with
and without callback function.,parse__istream__parser_callback_t}
- @sa @ref parse(const char*, const parser_callback_t) for a version
+ @sa @ref parse(const CharT, const parser_callback_t) for a version
that reads from a string
@since version 1.0.0
@@ -6217,6 +6224,1435 @@
/// @}
+ //////////////////////////////////////////
+ // binary serialization/deserialization //
+ //////////////////////////////////////////
+
+ /// @name binary serialization/deserialization support
+ /// @{
+
+ private:
+ template<typename T>
+ static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
+ {
+ assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
+
+ switch (bytes)
+ {
+ case 8:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
+ // intentional fall-through
+ }
+
+ case 4:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
+ // intentional fall-through
+ }
+
+ case 2:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
+ // intentional fall-through
+ }
+
+ case 1:
+ {
+ vec.push_back(static_cast<uint8_t>(number & 0xff));
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief take sufficient bytes from a vector to fill an integer variable
+
+ In the context of binary serialization formats, we need to read several
+ bytes from a byte vector and combine them to multi-byte integral data
+ types.
+
+ @param[in] vec byte vector to read from
+ @param[in] current_index the position in the vector after which to read
+
+ @return the next sizeof(T) bytes from @a vec, in reverse order as T
+
+ @tparam T the integral return type
+
+ @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the
+ vector @a vec to read
+
+ In the for loop, the bytes from the vector are copied in reverse order into
+ the return value. In the figures below, let sizeof(T)=4 and `i` be the loop
+ variable.
+
+ Precondition:
+
+ vec: | | | a | b | c | d | T: | | | | |
+ ^ ^ ^ ^
+ current_index i ptr sizeof(T)
+
+ Postcondition:
+
+ vec: | | | a | b | c | d | T: | d | c | b | a |
+ ^ ^ ^
+ | i ptr
+ current_index
+
+ @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.
+ */
+ template<typename T>
+ static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
+ {
+ if (current_index + sizeof(T) + 1 > vec.size())
+ {
+ throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
+ }
+
+ T result;
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
+ for (size_t i = 0; i < sizeof(T); ++i)
+ {
+ *ptr++ = vec[current_index + sizeof(T) - i];
+ }
+ return result;
+ }
+
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ This is a straightforward implementation of the MessagePack specification.
+
+ @param[in] j JSON value to serialize
+ @param[in,out] v byte vector to write the serialization to
+
+ @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+ */
+ static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ // nil
+ v.push_back(0xc0);
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ // true and false
+ v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // MessagePack does not differentiate between positive
+ // signed integers and unsigned integers. Therefore, we used
+ // the code from the value_t::number_unsigned case here.
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT8_MAX)
+ {
+ // uint 8
+ v.push_back(0xcc);
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT16_MAX)
+ {
+ // uint 16
+ v.push_back(0xcd);
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT32_MAX)
+ {
+ // uint 32
+ v.push_back(0xce);
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT64_MAX)
+ {
+ // uint 64
+ v.push_back(0xcf);
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ }
+ else
+ {
+ if (j.m_value.number_integer >= -32)
+ {
+ // negative fixnum
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
+ {
+ // int 8
+ v.push_back(0xd0);
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
+ {
+ // int 16
+ v.push_back(0xd1);
+ add_to_vector(v, 2, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
+ {
+ // int 32
+ v.push_back(0xd2);
+ add_to_vector(v, 4, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
+ {
+ // int 64
+ v.push_back(0xd3);
+ add_to_vector(v, 8, j.m_value.number_integer);
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT8_MAX)
+ {
+ // uint 8
+ v.push_back(0xcc);
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT16_MAX)
+ {
+ // uint 16
+ v.push_back(0xcd);
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT32_MAX)
+ {
+ // uint 32
+ v.push_back(0xce);
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT64_MAX)
+ {
+ // uint 64
+ v.push_back(0xcf);
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ // float 64
+ v.push_back(0xcb);
+ const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+ for (size_t i = 0; i < 8; ++i)
+ {
+ v.push_back(helper[7 - i]);
+ }
+ break;
+ }
+
+ case value_t::string:
+ {
+ const auto N = j.m_value.string->size();
+ if (N <= 31)
+ {
+ // fixstr
+ v.push_back(static_cast<uint8_t>(0xa0 | N));
+ }
+ else if (N <= 255)
+ {
+ // str 8
+ v.push_back(0xd9);
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 65535)
+ {
+ // str 16
+ v.push_back(0xda);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 4294967295)
+ {
+ // str 32
+ v.push_back(0xdb);
+ add_to_vector(v, 4, N);
+ }
+
+ // append string
+ std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+ std::back_inserter(v));
+ break;
+ }
+
+ case value_t::array:
+ {
+ const auto N = j.m_value.array->size();
+ if (N <= 15)
+ {
+ // fixarray
+ v.push_back(static_cast<uint8_t>(0x90 | N));
+ }
+ else if (N <= 0xffff)
+ {
+ // array 16
+ v.push_back(0xdc);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ // array 32
+ v.push_back(0xdd);
+ add_to_vector(v, 4, N);
+ }
+
+ // append each element
+ for (const auto& el : *j.m_value.array)
+ {
+ to_msgpack_internal(el, v);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ const auto N = j.m_value.object->size();
+ if (N <= 15)
+ {
+ // fixmap
+ v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
+ }
+ else if (N <= 65535)
+ {
+ // map 16
+ v.push_back(0xde);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 4294967295)
+ {
+ // map 32
+ v.push_back(0xdf);
+ add_to_vector(v, 4, N);
+ }
+
+ // append each element
+ for (const auto& el : *j.m_value.object)
+ {
+ to_msgpack_internal(el.first, v);
+ to_msgpack_internal(el.second, v);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief create a CBOR serialization of a given JSON value
+
+ This is a straightforward implementation of the CBOR specification.
+
+ @param[in] j JSON value to serialize
+ @param[in,out] v byte vector to write the serialization to
+
+ @sa https://tools.ietf.org/html/rfc7049
+ */
+ static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ v.push_back(0xf6);
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // CBOR does not differentiate between positive signed
+ // integers and unsigned integers. Therefore, we used the
+ // code from the value_t::number_unsigned case here.
+ if (j.m_value.number_integer <= 0x17)
+ {
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT8_MAX)
+ {
+ v.push_back(0x18);
+ // one-byte uint8_t
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT16_MAX)
+ {
+ v.push_back(0x19);
+ // two-byte uint16_t
+ add_to_vector(v, 2, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT32_MAX)
+ {
+ v.push_back(0x1a);
+ // four-byte uint32_t
+ add_to_vector(v, 4, j.m_value.number_integer);
+ }
+ else
+ {
+ v.push_back(0x1b);
+ // eight-byte uint64_t
+ add_to_vector(v, 8, j.m_value.number_integer);
+ }
+ }
+ else
+ {
+ // The conversions below encode the sign in the first byte,
+ // and the value is converted to a positive number.
+ const auto positive_number = -1 - j.m_value.number_integer;
+ if (j.m_value.number_integer >= -24)
+ {
+ v.push_back(static_cast<uint8_t>(0x20 + positive_number));
+ }
+ else if (positive_number <= UINT8_MAX)
+ {
+ // int 8
+ v.push_back(0x38);
+ add_to_vector(v, 1, positive_number);
+ }
+ else if (positive_number <= UINT16_MAX)
+ {
+ // int 16
+ v.push_back(0x39);
+ add_to_vector(v, 2, positive_number);
+ }
+ else if (positive_number <= UINT32_MAX)
+ {
+ // int 32
+ v.push_back(0x3a);
+ add_to_vector(v, 4, positive_number);
+ }
+ else
+ {
+ // int 64
+ v.push_back(0x3b);
+ add_to_vector(v, 8, positive_number);
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned <= 0x17)
+ {
+ v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= 0xff)
+ {
+ v.push_back(0x18);
+ // one-byte uint8_t
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffff)
+ {
+ v.push_back(0x19);
+ // two-byte uint16_t
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffffffff)
+ {
+ v.push_back(0x1a);
+ // four-byte uint32_t
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
+ {
+ v.push_back(0x1b);
+ // eight-byte uint64_t
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ // Double-Precision Float
+ v.push_back(0xfb);
+ const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+ for (size_t i = 0; i < 8; ++i)
+ {
+ v.push_back(helper[7 - i]);
+ }
+ break;
+ }
+
+ case value_t::string:
+ {
+ const auto N = j.m_value.string->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0x60 + N); // 1 byte for string + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0x78); // one-byte uint8_t for N
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0x79); // two-byte uint16_t for N
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0x7a); // four-byte uint32_t for N
+ add_to_vector(v, 4, N);
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0x7b); // eight-byte uint64_t for N
+ add_to_vector(v, 8, N);
+ }
+ // LCOV_EXCL_STOP
+
+ // append string
+ std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+ std::back_inserter(v));
+ break;
+ }
+
+ case value_t::array:
+ {
+ const auto N = j.m_value.array->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0x80 + N); // 1 byte for array + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0x98); // one-byte uint8_t for N
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0x99); // two-byte uint16_t for N
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0x9a); // four-byte uint32_t for N
+ add_to_vector(v, 4, N);
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0x9b); // eight-byte uint64_t for N
+ add_to_vector(v, 8, N);
+ }
+ // LCOV_EXCL_STOP
+
+ // append each element
+ for (const auto& el : *j.m_value.array)
+ {
+ to_cbor_internal(el, v);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ const auto N = j.m_value.object->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0xa0 + N); // 1 byte for object + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0xb8);
+ add_to_vector(v, 1, N); // one-byte uint8_t for N
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0xb9);
+ add_to_vector(v, 2, N); // two-byte uint16_t for N
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0xba);
+ add_to_vector(v, 4, N); // four-byte uint32_t for N
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0xbb);
+ add_to_vector(v, 8, N); // eight-byte uint64_t for N
+ }
+ // LCOV_EXCL_STOP
+
+ // append each element
+ for (const auto& el : *j.m_value.object)
+ {
+ to_cbor_internal(el.first, v);
+ to_cbor_internal(el.second, v);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief create a JSON value from a given MessagePack vector
+
+ @param[in] v MessagePack serialization
+ @param[in] idx byte index to start reading from @a v
+
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from MessagePack were
+ used in the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+ */
+ static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
+ {
+ // store and increment index
+ const size_t current_idx = idx++;
+
+ if (v[current_idx] <= 0xbf)
+ {
+ if (v[current_idx] <= 0x7f) // positive fixint
+ {
+ return v[current_idx];
+ }
+ else if (v[current_idx] <= 0x8f) // fixmap
+ {
+ basic_json result = value_t::object;
+ const size_t len = v[current_idx] & 0x0f;
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+ else if (v[current_idx] <= 0x9f) // fixarray
+ {
+ basic_json result = value_t::array;
+ const size_t len = v[current_idx] & 0x0f;
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+ else // fixstr
+ {
+ const size_t len = v[current_idx] & 0x1f;
+ const size_t offset = current_idx + 1;
+ idx += len; // skip content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+ }
+ else if (v[current_idx] >= 0xe0) // negative fixint
+ {
+ return static_cast<int8_t>(v[current_idx]);
+ }
+ else
+ {
+ switch (v[current_idx])
+ {
+ case 0xc0: // nil
+ {
+ return value_t::null;
+ }
+
+ case 0xc2: // false
+ {
+ return false;
+ }
+
+ case 0xc3: // true
+ {
+ return true;
+ }
+
+ case 0xca: // float 32
+ {
+ // copy bytes in reverse order into the double variable
+ float res;
+ for (size_t byte = 0; byte < sizeof(float); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(float); // skip content bytes
+ return res;
+ }
+
+ case 0xcb: // float 64
+ {
+ // copy bytes in reverse order into the double variable
+ double res;
+ for (size_t byte = 0; byte < sizeof(double); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(double); // skip content bytes
+ return res;
+ }
+
+ case 0xcc: // uint 8
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0xcd: // uint 16
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0xce: // uint 32
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0xcf: // uint 64
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<uint64_t>(v, current_idx);
+ }
+
+ case 0xd0: // int 8
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<int8_t>(v, current_idx);
+ }
+
+ case 0xd1: // int 16
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<int16_t>(v, current_idx);
+ }
+
+ case 0xd2: // int 32
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<int32_t>(v, current_idx);
+ }
+
+ case 0xd3: // int 64
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<int64_t>(v, current_idx);
+ }
+
+ case 0xd9: // str 8
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ const size_t offset = current_idx + 2;
+ idx += len + 1; // skip size byte + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xda: // str 16
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ const size_t offset = current_idx + 3;
+ idx += len + 2; // skip 2 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xdb: // str 32
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ const size_t offset = current_idx + 5;
+ idx += len + 4; // skip 4 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xdc: // array 16
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0xdd: // array 32
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0xde: // map 16
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xdf: // map 32
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+
+ default:
+ {
+ throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+ }
+ }
+ }
+ }
+
+ /*!
+ @brief create a JSON value from a given CBOR vector
+
+ @param[in] v CBOR serialization
+ @param[in] idx byte index to start reading from @a v
+
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from CBOR were used in
+ the given vector @a v or if the input is not valid CBOR
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @sa https://tools.ietf.org/html/rfc7049
+ */
+ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
+ {
+ // store and increment index
+ const size_t current_idx = idx++;
+
+ switch (v[current_idx])
+ {
+ // Integer 0x00..0x17 (0..23)
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ {
+ return v[current_idx];
+ }
+
+ case 0x18: // Unsigned integer (one-byte uint8_t follows)
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0x19: // Unsigned integer (two-byte uint16_t follows)
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0x1a: // Unsigned integer (four-byte uint32_t follows)
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<uint64_t>(v, current_idx);
+ }
+
+ // Negative integer -1-0x00..-1-0x17 (-1..-24)
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ {
+ return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
+ }
+
+ case 0x38: // Negative integer (one-byte uint8_t follows)
+ {
+ idx += 1; // skip content byte
+ // must be uint8_t !
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+ {
+ idx += 2; // skip 2 content bytes
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
+ {
+ idx += 4; // skip 4 content bytes
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
+ {
+ idx += 8; // skip 8 content bytes
+ return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
+ }
+
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ {
+ const auto len = static_cast<size_t>(v[current_idx] - 0x60);
+ const size_t offset = current_idx + 1;
+ idx += len; // skip content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ const size_t offset = current_idx + 2;
+ idx += len + 1; // skip size byte + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ const size_t offset = current_idx + 3;
+ idx += len + 2; // skip 2 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ const size_t offset = current_idx + 5;
+ idx += len + 4; // skip 4 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ const size_t offset = current_idx + 9;
+ idx += len + 8; // skip 8 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7f: // UTF-8 string (indefinite length)
+ {
+ std::string result;
+ while (v[idx] != 0xff)
+ {
+ string_t s = from_cbor_internal(v, idx);
+ result += s;
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ // array (0x00..0x17 data items follow)
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f:
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(v[current_idx] - 0x80);
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x98: // array (one-byte uint8_t for n follows)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ idx += 1; // skip 1 size byte
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x99: // array (two-byte uint16_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9a: // array (four-byte uint32_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9b: // array (eight-byte uint64_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ idx += 8; // skip 8 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9f: // array (indefinite length)
+ {
+ basic_json result = value_t::array;
+ while (v[idx] != 0xff)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ // map (0x00..0x17 pairs of data items follow)
+ case 0xa0:
+ case 0xa1:
+ case 0xa2:
+ case 0xa3:
+ case 0xa4:
+ case 0xa5:
+ case 0xa6:
+ case 0xa7:
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf:
+ case 0xb0:
+ case 0xb1:
+ case 0xb2:
+ case 0xb3:
+ case 0xb4:
+ case 0xb5:
+ case 0xb6:
+ case 0xb7:
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xb8: // map (one-byte uint8_t for n follows)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ idx += 1; // skip 1 size byte
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xb9: // map (two-byte uint16_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xba: // map (four-byte uint32_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xbb: // map (eight-byte uint64_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ idx += 8; // skip 8 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xbf: // map (indefinite length)
+ {
+ basic_json result = value_t::object;
+ while (v[idx] != 0xff)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ case 0xf4: // false
+ {
+ return false;
+ }
+
+ case 0xf5: // true
+ {
+ return true;
+ }
+
+ case 0xf6: // null
+ {
+ return value_t::null;
+ }
+
+ case 0xf9: // Half-Precision Float (two-byte IEEE 754)
+ {
+ idx += 2; // skip two content bytes
+
+ // code from RFC 7049, Appendix D, Figure 3:
+ // As half-precision floating-point numbers were only added to
+ // IEEE 754 in 2008, today's programming platforms often still
+ // only have limited support for them. It is very easy to
+ // include at least decoding support for them even without such
+ // support. An example of a small decoder for half-precision
+ // floating-point numbers in the C language is shown in Fig. 3.
+ const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
+ const int exp = (half >> 10) & 0x1f;
+ const int mant = half & 0x3ff;
+ double val;
+ if (exp == 0)
+ {
+ val = std::ldexp(mant, -24);
+ }
+ else if (exp != 31)
+ {
+ val = std::ldexp(mant + 1024, exp - 25);
+ }
+ else
+ {
+ val = mant == 0 ? INFINITY : NAN;
+ }
+ return half & 0x8000 ? -val : val;
+ }
+
+ case 0xfa: // Single-Precision Float (four-byte IEEE 754)
+ {
+ // copy bytes in reverse order into the float variable
+ float res;
+ for (size_t byte = 0; byte < sizeof(float); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(float); // skip content bytes
+ return res;
+ }
+
+ case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
+ {
+ // copy bytes in reverse order into the double variable
+ double res;
+ for (size_t byte = 0; byte < sizeof(double); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(double); // skip content bytes
+ return res;
+ }
+
+ default: // anything else (0xFF is handled inside the other types)
+ {
+ throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+ }
+ }
+ }
+
+ public:
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the MessagePack
+ serialization format. MessagePack is a binary serialization format which
+ aims to be more compact than JSON itself, yet more efficient to parse.
+
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in MessagePack format.,to_msgpack}
+
+ @sa http://msgpack.org
+ @sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
+ deserialization
+ @sa @ref to_cbor(const basic_json& for the related CBOR format
+ */
+ static std::vector<uint8_t> to_msgpack(const basic_json& j)
+ {
+ std::vector<uint8_t> result;
+ to_msgpack_internal(j, result);
+ return result;
+ }
+
+ /*!
+ @brief create a JSON value from a byte vector in MessagePack format
+
+ Deserializes a given byte vector @a v to a JSON value using the MessagePack
+ serialization format.
+
+ @param[in] v a byte vector in MessagePack format
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from MessagePack were
+ used in the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @complexity Linear in the size of the byte vector @a v.
+
+ @liveexample{The example shows the deserialization of a byte vector in
+ MessagePack format to a JSON value.,from_msgpack}
+
+ @sa http://msgpack.org
+ @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+ @sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
+ */
+ static basic_json from_msgpack(const std::vector<uint8_t>& v)
+ {
+ size_t i = 0;
+ return from_msgpack_internal(v, i);
+ }
+
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+ Binary Object Representation) serialization format. CBOR is a binary
+ serialization format which aims to be more compact than JSON itself, yet
+ more efficient to parse.
+
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in CBOR format.,to_cbor}
+
+ @sa http://cbor.io
+ @sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
+ deserialization
+ @sa @ref to_msgpack(const basic_json& for the related MessagePack format
+ */
+ static std::vector<uint8_t> to_cbor(const basic_json& j)
+ {
+ std::vector<uint8_t> result;
+ to_cbor_internal(j, result);
+ return result;
+ }
+
+ /*!
+ @brief create a JSON value from a byte vector in CBOR format
+
+ Deserializes a given byte vector @a v to a JSON value using the CBOR
+ (Concise Binary Object Representation) serialization format.
+
+ @param[in] v a byte vector in CBOR format
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from CBOR were used in
+ the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @complexity Linear in the size of the byte vector @a v.
+
+ @liveexample{The example shows the deserialization of a byte vector in CBOR
+ format to a JSON value.,from_cbor}
+
+ @sa http://cbor.io
+ @sa @ref to_cbor(const basic_json&) for the analogous serialization
+ @sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
+ MessagePack format
+ */
+ static basic_json from_cbor(const std::vector<uint8_t>& v)
+ {
+ size_t i = 0;
+ return from_cbor_internal(v, i);
+ }
+
+ /// @}
private:
///////////////////////////
@@ -6769,10 +8205,10 @@
public:
/*!
- @brief a const random access iterator for the @ref basic_json class
+ @brief a template for a random access iterator for the @ref basic_json class
- This class implements a const iterator for the @ref basic_json class. From
- this class, the @ref iterator class is derived.
+ This class implements a both iterators (iterator and const_iterator) for the
+ @ref basic_json class.
@note An iterator is called *initialized* when a pointer to a JSON value
has been set (e.g., by a constructor or a copy assignment). If the
@@ -6785,27 +8221,37 @@
The iterator that can be moved to point (forward and backward) to any
element in constant time.
- @since version 1.0.0
+ @since version 1.0.0, simplified in version 2.0.9
*/
- class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
+ template<typename U>
+ class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
{
/// allow basic_json to access private members
friend class basic_json;
+ // make sure U is basic_json or const basic_json
+ static_assert(std::is_same<U, basic_json>::value
+ or std::is_same<U, const basic_json>::value,
+ "iter_impl only accepts (const) basic_json");
+
public:
/// the type of the values when the iterator is dereferenced
using value_type = typename basic_json::value_type;
/// a type to represent differences between iterators
using difference_type = typename basic_json::difference_type;
/// defines a pointer to the type iterated over (value_type)
- using pointer = typename basic_json::const_pointer;
+ using pointer = typename std::conditional<std::is_const<U>::value,
+ typename basic_json::const_pointer,
+ typename basic_json::pointer>::type;
/// defines a reference to the type iterated over (value_type)
- using reference = typename basic_json::const_reference;
+ using reference = typename std::conditional<std::is_const<U>::value,
+ typename basic_json::const_reference,
+ typename basic_json::reference>::type;
/// the category of the iterator
using iterator_category = std::bidirectional_iterator_tag;
/// default constructor
- const_iterator() = default;
+ iter_impl() = default;
/*!
@brief constructor for a given JSON instance
@@ -6813,7 +8259,7 @@
@pre object != nullptr
@post The iterator is initialized; i.e. `m_object != nullptr`.
*/
- explicit const_iterator(pointer object) noexcept
+ explicit iter_impl(pointer object) noexcept
: m_object(object)
{
assert(m_object != nullptr);
@@ -6840,37 +8286,25 @@
}
}
- /*!
- @brief copy constructor given a non-const iterator
- @param[in] other iterator to copy from
- @note It is not checked whether @a other is initialized.
+ /*
+ Use operator `const_iterator` instead of `const_iterator(const iterator&
+ other) noexcept` to avoid two class definitions for @ref iterator and
+ @ref const_iterator.
+
+ This function is only called if this class is an @ref iterator. If this
+ class is a @ref const_iterator this function is not called.
*/
- explicit const_iterator(const iterator& other) noexcept
- : m_object(other.m_object)
+ operator const_iterator() const
{
- if (m_object != nullptr)
+ const_iterator ret;
+
+ if (m_object)
{
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- m_it.object_iterator = other.m_it.object_iterator;
- break;
- }
-
- case basic_json::value_t::array:
- {
- m_it.array_iterator = other.m_it.array_iterator;
- break;
- }
-
- default:
- {
- m_it.primitive_iterator = other.m_it.primitive_iterator;
- break;
- }
- }
+ ret.m_object = m_object;
+ ret.m_it = m_it;
}
+
+ return ret;
}
/*!
@@ -6878,7 +8312,7 @@
@param[in] other iterator to copy from
@note It is not checked whether @a other is initialized.
*/
- const_iterator(const const_iterator& other) noexcept
+ iter_impl(const iter_impl& other) noexcept
: m_object(other.m_object), m_it(other.m_it)
{}
@@ -6887,7 +8321,7 @@
@param[in,out] other iterator to copy from
@note It is not checked whether @a other is initialized.
*/
- const_iterator& operator=(const_iterator other) noexcept(
+ iter_impl& operator=(iter_impl other) noexcept(
std::is_nothrow_move_constructible<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
@@ -7049,7 +8483,7 @@
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator++(int)
+ iter_impl operator++(int)
{
auto result = *this;
++(*this);
@@ -7060,7 +8494,7 @@
@brief pre-increment (++it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator++()
+ iter_impl& operator++()
{
assert(m_object != nullptr);
@@ -7092,7 +8526,7 @@
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator--(int)
+ iter_impl operator--(int)
{
auto result = *this;
--(*this);
@@ -7103,7 +8537,7 @@
@brief pre-decrement (--it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator--()
+ iter_impl& operator--()
{
assert(m_object != nullptr);
@@ -7135,7 +8569,7 @@
@brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator==(const const_iterator& other) const
+ bool operator==(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (m_object != other.m_object)
@@ -7168,7 +8602,7 @@
@brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator!=(const const_iterator& other) const
+ bool operator!=(const iter_impl& other) const
{
return not operator==(other);
}
@@ -7177,7 +8611,7 @@
@brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator<(const const_iterator& other) const
+ bool operator<(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (m_object != other.m_object)
@@ -7210,7 +8644,7 @@
@brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator<=(const const_iterator& other) const
+ bool operator<=(const iter_impl& other) const
{
return not other.operator < (*this);
}
@@ -7219,7 +8653,7 @@
@brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator>(const const_iterator& other) const
+ bool operator>(const iter_impl& other) const
{
return not operator<=(other);
}
@@ -7228,7 +8662,7 @@
@brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator>=(const const_iterator& other) const
+ bool operator>=(const iter_impl& other) const
{
return not operator<(other);
}
@@ -7237,7 +8671,7 @@
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator+=(difference_type i)
+ iter_impl& operator+=(difference_type i)
{
assert(m_object != nullptr);
@@ -7268,7 +8702,7 @@
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator-=(difference_type i)
+ iter_impl& operator-=(difference_type i)
{
return operator+=(-i);
}
@@ -7277,7 +8711,7 @@
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator+(difference_type i)
+ iter_impl operator+(difference_type i)
{
auto result = *this;
result += i;
@@ -7288,7 +8722,7 @@
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator-(difference_type i)
+ iter_impl operator-(difference_type i)
{
auto result = *this;
result -= i;
@@ -7299,7 +8733,7 @@
@brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- difference_type operator-(const const_iterator& other) const
+ difference_type operator-(const iter_impl& other) const
{
assert(m_object != nullptr);
@@ -7396,141 +8830,6 @@
};
/*!
- @brief a mutable random access iterator for the @ref basic_json class
-
- @requirement The class satisfies the following concept requirements:
- - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
- The iterator that can be moved to point (forward and backward) to any
- element in constant time.
- - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
- It is possible to write to the pointed-to element.
-
- @since version 1.0.0
- */
- class iterator : public const_iterator
- {
- public:
- using base_iterator = const_iterator;
- using pointer = typename basic_json::pointer;
- using reference = typename basic_json::reference;
-
- /// default constructor
- iterator() = default;
-
- /// constructor for a given JSON instance
- explicit iterator(pointer object) noexcept
- : base_iterator(object)
- {}
-
- /// copy constructor
- iterator(const iterator& other) noexcept
- : base_iterator(other)
- {}
-
- /// copy assignment
- iterator& operator=(iterator other) noexcept(
- std::is_nothrow_move_constructible<pointer>::value and
- std::is_nothrow_move_assignable<pointer>::value and
- std::is_nothrow_move_constructible<internal_iterator>::value and
- std::is_nothrow_move_assignable<internal_iterator>::value
- )
- {
- base_iterator::operator=(other);
- return *this;
- }
-
- /// return a reference to the value pointed to by the iterator
- reference operator*() const
- {
- return const_cast<reference>(base_iterator::operator*());
- }
-
- /// dereference the iterator
- pointer operator->() const
- {
- return const_cast<pointer>(base_iterator::operator->());
- }
-
- /// post-increment (it++)
- iterator operator++(int)
- {
- iterator result = *this;
- base_iterator::operator++();
- return result;
- }
-
- /// pre-increment (++it)
- iterator& operator++()
- {
- base_iterator::operator++();
- return *this;
- }
-
- /// post-decrement (it--)
- iterator operator--(int)
- {
- iterator result = *this;
- base_iterator::operator--();
- return result;
- }
-
- /// pre-decrement (--it)
- iterator& operator--()
- {
- base_iterator::operator--();
- return *this;
- }
-
- /// add to iterator
- iterator& operator+=(difference_type i)
- {
- base_iterator::operator+=(i);
- return *this;
- }
-
- /// subtract from iterator
- iterator& operator-=(difference_type i)
- {
- base_iterator::operator-=(i);
- return *this;
- }
-
- /// add to iterator
- iterator operator+(difference_type i)
- {
- auto result = *this;
- result += i;
- return result;
- }
-
- /// subtract from iterator
- iterator operator-(difference_type i)
- {
- auto result = *this;
- result -= i;
- return result;
- }
-
- /// return difference
- difference_type operator-(const iterator& other) const
- {
- return base_iterator::operator-(other);
- }
-
- /// access to successor
- reference operator[](difference_type n) const
- {
- return const_cast<reference>(base_iterator::operator[](n));
- }
-
- /// return the value of an iterator
- reference value() const
- {
- return const_cast<reference>(base_iterator::value());
- }
- };
-
- /*!
@brief a template for a reverse iterator class
@tparam Base the base iterator type to reverse. Valid types are @ref
@@ -9068,8 +10367,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -9088,8 +10385,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -9108,8 +10403,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -9190,19 +10483,19 @@
// skip if definitely not an integer
if (type != value_t::number_float)
{
- // multiply last value by ten and add the new digit
- auto temp = value * 10 + *curptr - '0';
+ auto digit = static_cast<number_unsigned_t>(*curptr - '0');
- // test for overflow
- if (temp < value || temp > max)
+ // overflow if value * 10 + digit > max, move terms around
+ // to avoid overflow in intermediate values
+ if (value > (max - digit) / 10)
{
// overflow
type = value_t::number_float;
}
else
{
- // no overflow - save it
- value = temp;
+ // no overflow
+ value = value * 10 + digit;
}
}
}
@@ -9214,7 +10507,22 @@
}
else if (type == value_t::number_integer)
{
- result.m_value.number_integer = -static_cast<number_integer_t>(value);
+ // invariant: if we parsed a '-', the absolute value is between
+ // 0 (we allow -0) and max == -INT64_MIN
+ assert(value >= 0);
+ assert(value <= max);
+
+ if (value == max)
+ {
+ // we cannot simply negate value (== max == -INT64_MIN),
+ // see https://github.com/nlohmann/json/issues/389
+ result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
+ }
+ else
+ {
+ // all other values can be negated safely
+ result.m_value.number_integer = -static_cast<number_integer_t>(value);
+ }
}
else
{
@@ -9997,13 +11305,11 @@
/*!
@brief replace all occurrences of a substring by another string
- @param[in,out] s the string to manipulate
+ @param[in,out] s the string to manipulate; changed so that all
+ occurrences of @a f are replaced with @a t
@param[in] f the substring to replace with @a t
@param[in] t the string to replace @a f
- @return The string @a s where all occurrences of @a f are replaced
- with @a t.
-
@pre The search string @a f must not be empty.
@since version 2.0.0
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index c6a99b8..ac9a331 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -34,7 +34,7 @@
#include <cassert> // assert
#include <cctype> // isdigit
#include <ciso646> // and, not, or
-#include <cmath> // isfinite, signbit
+#include <cmath> // isfinite, ldexp, signbit
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
#include <cstdint> // int64_t, uint64_t
#include <cstdlib> // strtod, strtof, strtold, strtoul
@@ -75,6 +75,12 @@
#pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
+// disable documentation warnings on clang
+#if defined(__clang__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdocumentation"
+#endif
+
// allow for portable deprecation warnings
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define JSON_DEPRECATED __attribute__((deprecated))
@@ -222,6 +228,7 @@
public:
// forward declarations
+ template<typename U> class iter_impl;
template<typename Base> class json_reverse_iterator;
class json_pointer;
@@ -256,9 +263,9 @@
using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
/// an iterator for a basic_json container
- class iterator;
+ using iterator = iter_impl<basic_json>;
/// a const iterator for a basic_json container
- class const_iterator;
+ using const_iterator = iter_impl<const basic_json>;
/// a reverse iterator for a basic_json container
using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
/// a const reverse iterator for a basic_json container
@@ -944,7 +951,7 @@
With a parser callback function, the result of parsing a JSON text can be
influenced. When passed to @ref parse(std::istream&, const
- parser_callback_t) or @ref parse(const char*, const parser_callback_t),
+ parser_callback_t) or @ref parse(const CharT, const parser_callback_t),
it is called on certain events (passed as @ref parse_event_t via parameter
@a event) with a set recursion depth @a depth and context JSON value
@a parsed. The return value of the callback function is a boolean
@@ -987,7 +994,7 @@
skipped completely or replaced by an empty discarded object.
@sa @ref parse(std::istream&, parser_callback_t) or
- @ref parse(const char*, parser_callback_t) for examples
+ @ref parse(const CharT, const parser_callback_t) for examples
@since version 1.0.0
*/
@@ -6003,11 +6010,11 @@
@since version 1.0.0 (originally for @ref string_t)
*/
- template<typename CharPT, typename std::enable_if<
- std::is_pointer<CharPT>::value and
- std::is_integral<typename std::remove_pointer<CharPT>::type>::value and
- sizeof(typename std::remove_pointer<CharPT>::type) == 1, int>::type = 0>
- static basic_json parse(const CharPT s,
+ template<typename CharT, typename std::enable_if<
+ std::is_pointer<CharT>::value and
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value and
+ sizeof(typename std::remove_pointer<CharT>::type) == 1, int>::type = 0>
+ static basic_json parse(const CharT s,
const parser_callback_t cb = nullptr)
{
return parser(reinterpret_cast<const char*>(s), cb).parse();
@@ -6032,7 +6039,7 @@
@liveexample{The example below demonstrates the `parse()` function with
and without callback function.,parse__istream__parser_callback_t}
- @sa @ref parse(const char*, const parser_callback_t) for a version
+ @sa @ref parse(const CharT, const parser_callback_t) for a version
that reads from a string
@since version 1.0.0
@@ -6217,6 +6224,1435 @@
/// @}
+ //////////////////////////////////////////
+ // binary serialization/deserialization //
+ //////////////////////////////////////////
+
+ /// @name binary serialization/deserialization support
+ /// @{
+
+ private:
+ template<typename T>
+ static void add_to_vector(std::vector<uint8_t>& vec, size_t bytes, const T number)
+ {
+ assert(bytes == 1 or bytes == 2 or bytes == 4 or bytes == 8);
+
+ switch (bytes)
+ {
+ case 8:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 070) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 060) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 050) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 040) & 0xff));
+ // intentional fall-through
+ }
+
+ case 4:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 030) & 0xff));
+ vec.push_back(static_cast<uint8_t>((number >> 020) & 0xff));
+ // intentional fall-through
+ }
+
+ case 2:
+ {
+ vec.push_back(static_cast<uint8_t>((number >> 010) & 0xff));
+ // intentional fall-through
+ }
+
+ case 1:
+ {
+ vec.push_back(static_cast<uint8_t>(number & 0xff));
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief take sufficient bytes from a vector to fill an integer variable
+
+ In the context of binary serialization formats, we need to read several
+ bytes from a byte vector and combine them to multi-byte integral data
+ types.
+
+ @param[in] vec byte vector to read from
+ @param[in] current_index the position in the vector after which to read
+
+ @return the next sizeof(T) bytes from @a vec, in reverse order as T
+
+ @tparam T the integral return type
+
+ @throw std::out_of_range if there are less than sizeof(T)+1 bytes in the
+ vector @a vec to read
+
+ In the for loop, the bytes from the vector are copied in reverse order into
+ the return value. In the figures below, let sizeof(T)=4 and `i` be the loop
+ variable.
+
+ Precondition:
+
+ vec: | | | a | b | c | d | T: | | | | |
+ ^ ^ ^ ^
+ current_index i ptr sizeof(T)
+
+ Postcondition:
+
+ vec: | | | a | b | c | d | T: | d | c | b | a |
+ ^ ^ ^
+ | i ptr
+ current_index
+
+ @sa Code adapted from <http://stackoverflow.com/a/41031865/266378>.
+ */
+ template<typename T>
+ static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
+ {
+ if (current_index + sizeof(T) + 1 > vec.size())
+ {
+ throw std::out_of_range("cannot read " + std::to_string(sizeof(T)) + " bytes from vector");
+ }
+
+ T result;
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(&result);
+ for (size_t i = 0; i < sizeof(T); ++i)
+ {
+ *ptr++ = vec[current_index + sizeof(T) - i];
+ }
+ return result;
+ }
+
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ This is a straightforward implementation of the MessagePack specification.
+
+ @param[in] j JSON value to serialize
+ @param[in,out] v byte vector to write the serialization to
+
+ @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+ */
+ static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ // nil
+ v.push_back(0xc0);
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ // true and false
+ v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // MessagePack does not differentiate between positive
+ // signed integers and unsigned integers. Therefore, we used
+ // the code from the value_t::number_unsigned case here.
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT8_MAX)
+ {
+ // uint 8
+ v.push_back(0xcc);
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT16_MAX)
+ {
+ // uint 16
+ v.push_back(0xcd);
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT32_MAX)
+ {
+ // uint 32
+ v.push_back(0xce);
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT64_MAX)
+ {
+ // uint 64
+ v.push_back(0xcf);
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ }
+ else
+ {
+ if (j.m_value.number_integer >= -32)
+ {
+ // negative fixnum
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
+ {
+ // int 8
+ v.push_back(0xd0);
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
+ {
+ // int 16
+ v.push_back(0xd1);
+ add_to_vector(v, 2, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
+ {
+ // int 32
+ v.push_back(0xd2);
+ add_to_vector(v, 4, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
+ {
+ // int 64
+ v.push_back(0xd3);
+ add_to_vector(v, 8, j.m_value.number_integer);
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT8_MAX)
+ {
+ // uint 8
+ v.push_back(0xcc);
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT16_MAX)
+ {
+ // uint 16
+ v.push_back(0xcd);
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT32_MAX)
+ {
+ // uint 32
+ v.push_back(0xce);
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= UINT64_MAX)
+ {
+ // uint 64
+ v.push_back(0xcf);
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ // float 64
+ v.push_back(0xcb);
+ const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+ for (size_t i = 0; i < 8; ++i)
+ {
+ v.push_back(helper[7 - i]);
+ }
+ break;
+ }
+
+ case value_t::string:
+ {
+ const auto N = j.m_value.string->size();
+ if (N <= 31)
+ {
+ // fixstr
+ v.push_back(static_cast<uint8_t>(0xa0 | N));
+ }
+ else if (N <= 255)
+ {
+ // str 8
+ v.push_back(0xd9);
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 65535)
+ {
+ // str 16
+ v.push_back(0xda);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 4294967295)
+ {
+ // str 32
+ v.push_back(0xdb);
+ add_to_vector(v, 4, N);
+ }
+
+ // append string
+ std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+ std::back_inserter(v));
+ break;
+ }
+
+ case value_t::array:
+ {
+ const auto N = j.m_value.array->size();
+ if (N <= 15)
+ {
+ // fixarray
+ v.push_back(static_cast<uint8_t>(0x90 | N));
+ }
+ else if (N <= 0xffff)
+ {
+ // array 16
+ v.push_back(0xdc);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ // array 32
+ v.push_back(0xdd);
+ add_to_vector(v, 4, N);
+ }
+
+ // append each element
+ for (const auto& el : *j.m_value.array)
+ {
+ to_msgpack_internal(el, v);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ const auto N = j.m_value.object->size();
+ if (N <= 15)
+ {
+ // fixmap
+ v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
+ }
+ else if (N <= 65535)
+ {
+ // map 16
+ v.push_back(0xde);
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 4294967295)
+ {
+ // map 32
+ v.push_back(0xdf);
+ add_to_vector(v, 4, N);
+ }
+
+ // append each element
+ for (const auto& el : *j.m_value.object)
+ {
+ to_msgpack_internal(el.first, v);
+ to_msgpack_internal(el.second, v);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief create a CBOR serialization of a given JSON value
+
+ This is a straightforward implementation of the CBOR specification.
+
+ @param[in] j JSON value to serialize
+ @param[in,out] v byte vector to write the serialization to
+
+ @sa https://tools.ietf.org/html/rfc7049
+ */
+ static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ v.push_back(0xf6);
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ v.push_back(j.m_value.boolean ? 0xf5 : 0xf4);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // CBOR does not differentiate between positive signed
+ // integers and unsigned integers. Therefore, we used the
+ // code from the value_t::number_unsigned case here.
+ if (j.m_value.number_integer <= 0x17)
+ {
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT8_MAX)
+ {
+ v.push_back(0x18);
+ // one-byte uint8_t
+ add_to_vector(v, 1, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT16_MAX)
+ {
+ v.push_back(0x19);
+ // two-byte uint16_t
+ add_to_vector(v, 2, j.m_value.number_integer);
+ }
+ else if (j.m_value.number_integer <= UINT32_MAX)
+ {
+ v.push_back(0x1a);
+ // four-byte uint32_t
+ add_to_vector(v, 4, j.m_value.number_integer);
+ }
+ else
+ {
+ v.push_back(0x1b);
+ // eight-byte uint64_t
+ add_to_vector(v, 8, j.m_value.number_integer);
+ }
+ }
+ else
+ {
+ // The conversions below encode the sign in the first byte,
+ // and the value is converted to a positive number.
+ const auto positive_number = -1 - j.m_value.number_integer;
+ if (j.m_value.number_integer >= -24)
+ {
+ v.push_back(static_cast<uint8_t>(0x20 + positive_number));
+ }
+ else if (positive_number <= UINT8_MAX)
+ {
+ // int 8
+ v.push_back(0x38);
+ add_to_vector(v, 1, positive_number);
+ }
+ else if (positive_number <= UINT16_MAX)
+ {
+ // int 16
+ v.push_back(0x39);
+ add_to_vector(v, 2, positive_number);
+ }
+ else if (positive_number <= UINT32_MAX)
+ {
+ // int 32
+ v.push_back(0x3a);
+ add_to_vector(v, 4, positive_number);
+ }
+ else
+ {
+ // int 64
+ v.push_back(0x3b);
+ add_to_vector(v, 8, positive_number);
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned <= 0x17)
+ {
+ v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= 0xff)
+ {
+ v.push_back(0x18);
+ // one-byte uint8_t
+ add_to_vector(v, 1, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffff)
+ {
+ v.push_back(0x19);
+ // two-byte uint16_t
+ add_to_vector(v, 2, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffffffff)
+ {
+ v.push_back(0x1a);
+ // four-byte uint32_t
+ add_to_vector(v, 4, j.m_value.number_unsigned);
+ }
+ else if (j.m_value.number_unsigned <= 0xffffffffffffffff)
+ {
+ v.push_back(0x1b);
+ // eight-byte uint64_t
+ add_to_vector(v, 8, j.m_value.number_unsigned);
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ // Double-Precision Float
+ v.push_back(0xfb);
+ const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
+ for (size_t i = 0; i < 8; ++i)
+ {
+ v.push_back(helper[7 - i]);
+ }
+ break;
+ }
+
+ case value_t::string:
+ {
+ const auto N = j.m_value.string->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0x60 + N); // 1 byte for string + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0x78); // one-byte uint8_t for N
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0x79); // two-byte uint16_t for N
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0x7a); // four-byte uint32_t for N
+ add_to_vector(v, 4, N);
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0x7b); // eight-byte uint64_t for N
+ add_to_vector(v, 8, N);
+ }
+ // LCOV_EXCL_STOP
+
+ // append string
+ std::copy(j.m_value.string->begin(), j.m_value.string->end(),
+ std::back_inserter(v));
+ break;
+ }
+
+ case value_t::array:
+ {
+ const auto N = j.m_value.array->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0x80 + N); // 1 byte for array + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0x98); // one-byte uint8_t for N
+ add_to_vector(v, 1, N);
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0x99); // two-byte uint16_t for N
+ add_to_vector(v, 2, N);
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0x9a); // four-byte uint32_t for N
+ add_to_vector(v, 4, N);
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0x9b); // eight-byte uint64_t for N
+ add_to_vector(v, 8, N);
+ }
+ // LCOV_EXCL_STOP
+
+ // append each element
+ for (const auto& el : *j.m_value.array)
+ {
+ to_cbor_internal(el, v);
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ const auto N = j.m_value.object->size();
+ if (N <= 0x17)
+ {
+ v.push_back(0xa0 + N); // 1 byte for object + size
+ }
+ else if (N <= 0xff)
+ {
+ v.push_back(0xb8);
+ add_to_vector(v, 1, N); // one-byte uint8_t for N
+ }
+ else if (N <= 0xffff)
+ {
+ v.push_back(0xb9);
+ add_to_vector(v, 2, N); // two-byte uint16_t for N
+ }
+ else if (N <= 0xffffffff)
+ {
+ v.push_back(0xba);
+ add_to_vector(v, 4, N); // four-byte uint32_t for N
+ }
+ // LCOV_EXCL_START
+ else if (N <= 0xffffffffffffffff)
+ {
+ v.push_back(0xbb);
+ add_to_vector(v, 8, N); // eight-byte uint64_t for N
+ }
+ // LCOV_EXCL_STOP
+
+ // append each element
+ for (const auto& el : *j.m_value.object)
+ {
+ to_cbor_internal(el.first, v);
+ to_cbor_internal(el.second, v);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief create a JSON value from a given MessagePack vector
+
+ @param[in] v MessagePack serialization
+ @param[in] idx byte index to start reading from @a v
+
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from MessagePack were
+ used in the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @sa https://github.com/msgpack/msgpack/blob/master/spec.md
+ */
+ static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
+ {
+ // store and increment index
+ const size_t current_idx = idx++;
+
+ if (v[current_idx] <= 0xbf)
+ {
+ if (v[current_idx] <= 0x7f) // positive fixint
+ {
+ return v[current_idx];
+ }
+ else if (v[current_idx] <= 0x8f) // fixmap
+ {
+ basic_json result = value_t::object;
+ const size_t len = v[current_idx] & 0x0f;
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+ else if (v[current_idx] <= 0x9f) // fixarray
+ {
+ basic_json result = value_t::array;
+ const size_t len = v[current_idx] & 0x0f;
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+ else // fixstr
+ {
+ const size_t len = v[current_idx] & 0x1f;
+ const size_t offset = current_idx + 1;
+ idx += len; // skip content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+ }
+ else if (v[current_idx] >= 0xe0) // negative fixint
+ {
+ return static_cast<int8_t>(v[current_idx]);
+ }
+ else
+ {
+ switch (v[current_idx])
+ {
+ case 0xc0: // nil
+ {
+ return value_t::null;
+ }
+
+ case 0xc2: // false
+ {
+ return false;
+ }
+
+ case 0xc3: // true
+ {
+ return true;
+ }
+
+ case 0xca: // float 32
+ {
+ // copy bytes in reverse order into the double variable
+ float res;
+ for (size_t byte = 0; byte < sizeof(float); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(float); // skip content bytes
+ return res;
+ }
+
+ case 0xcb: // float 64
+ {
+ // copy bytes in reverse order into the double variable
+ double res;
+ for (size_t byte = 0; byte < sizeof(double); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(double); // skip content bytes
+ return res;
+ }
+
+ case 0xcc: // uint 8
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0xcd: // uint 16
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0xce: // uint 32
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0xcf: // uint 64
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<uint64_t>(v, current_idx);
+ }
+
+ case 0xd0: // int 8
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<int8_t>(v, current_idx);
+ }
+
+ case 0xd1: // int 16
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<int16_t>(v, current_idx);
+ }
+
+ case 0xd2: // int 32
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<int32_t>(v, current_idx);
+ }
+
+ case 0xd3: // int 64
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<int64_t>(v, current_idx);
+ }
+
+ case 0xd9: // str 8
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ const size_t offset = current_idx + 2;
+ idx += len + 1; // skip size byte + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xda: // str 16
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ const size_t offset = current_idx + 3;
+ idx += len + 2; // skip 2 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xdb: // str 32
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ const size_t offset = current_idx + 5;
+ idx += len + 4; // skip 4 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0xdc: // array 16
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0xdd: // array 32
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_msgpack_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0xde: // map 16
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xdf: // map 32
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_msgpack_internal(v, idx);
+ result[key] = from_msgpack_internal(v, idx);
+ }
+ return result;
+ }
+
+ default:
+ {
+ throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+ }
+ }
+ }
+ }
+
+ /*!
+ @brief create a JSON value from a given CBOR vector
+
+ @param[in] v CBOR serialization
+ @param[in] idx byte index to start reading from @a v
+
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from CBOR were used in
+ the given vector @a v or if the input is not valid CBOR
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @sa https://tools.ietf.org/html/rfc7049
+ */
+ static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
+ {
+ // store and increment index
+ const size_t current_idx = idx++;
+
+ switch (v[current_idx])
+ {
+ // Integer 0x00..0x17 (0..23)
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ {
+ return v[current_idx];
+ }
+
+ case 0x18: // Unsigned integer (one-byte uint8_t follows)
+ {
+ idx += 1; // skip content byte
+ return get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0x19: // Unsigned integer (two-byte uint16_t follows)
+ {
+ idx += 2; // skip 2 content bytes
+ return get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0x1a: // Unsigned integer (four-byte uint32_t follows)
+ {
+ idx += 4; // skip 4 content bytes
+ return get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
+ {
+ idx += 8; // skip 8 content bytes
+ return get_from_vector<uint64_t>(v, current_idx);
+ }
+
+ // Negative integer -1-0x00..-1-0x17 (-1..-24)
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ {
+ return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
+ }
+
+ case 0x38: // Negative integer (one-byte uint8_t follows)
+ {
+ idx += 1; // skip content byte
+ // must be uint8_t !
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
+ }
+
+ case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+ {
+ idx += 2; // skip 2 content bytes
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
+ }
+
+ case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
+ {
+ idx += 4; // skip 4 content bytes
+ return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
+ }
+
+ case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
+ {
+ idx += 8; // skip 8 content bytes
+ return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
+ }
+
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ {
+ const auto len = static_cast<size_t>(v[current_idx] - 0x60);
+ const size_t offset = current_idx + 1;
+ idx += len; // skip content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ const size_t offset = current_idx + 2;
+ idx += len + 1; // skip size byte + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ const size_t offset = current_idx + 3;
+ idx += len + 2; // skip 2 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ const size_t offset = current_idx + 5;
+ idx += len + 4; // skip 4 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
+ {
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ const size_t offset = current_idx + 9;
+ idx += len + 8; // skip 8 size bytes + content bytes
+ return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
+ }
+
+ case 0x7f: // UTF-8 string (indefinite length)
+ {
+ std::string result;
+ while (v[idx] != 0xff)
+ {
+ string_t s = from_cbor_internal(v, idx);
+ result += s;
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ // array (0x00..0x17 data items follow)
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f:
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(v[current_idx] - 0x80);
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x98: // array (one-byte uint8_t for n follows)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ idx += 1; // skip 1 size byte
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x99: // array (two-byte uint16_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9a: // array (four-byte uint32_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9b: // array (eight-byte uint64_t for n follow)
+ {
+ basic_json result = value_t::array;
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ idx += 8; // skip 8 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ return result;
+ }
+
+ case 0x9f: // array (indefinite length)
+ {
+ basic_json result = value_t::array;
+ while (v[idx] != 0xff)
+ {
+ result.push_back(from_cbor_internal(v, idx));
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ // map (0x00..0x17 pairs of data items follow)
+ case 0xa0:
+ case 0xa1:
+ case 0xa2:
+ case 0xa3:
+ case 0xa4:
+ case 0xa5:
+ case 0xa6:
+ case 0xa7:
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf:
+ case 0xb0:
+ case 0xb1:
+ case 0xb2:
+ case 0xb3:
+ case 0xb4:
+ case 0xb5:
+ case 0xb6:
+ case 0xb7:
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xb8: // map (one-byte uint8_t for n follows)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
+ idx += 1; // skip 1 size byte
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xb9: // map (two-byte uint16_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
+ idx += 2; // skip 2 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xba: // map (four-byte uint32_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
+ idx += 4; // skip 4 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xbb: // map (eight-byte uint64_t for n follow)
+ {
+ basic_json result = value_t::object;
+ const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
+ idx += 8; // skip 8 size bytes
+ for (size_t i = 0; i < len; ++i)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ return result;
+ }
+
+ case 0xbf: // map (indefinite length)
+ {
+ basic_json result = value_t::object;
+ while (v[idx] != 0xff)
+ {
+ std::string key = from_cbor_internal(v, idx);
+ result[key] = from_cbor_internal(v, idx);
+ }
+ // skip break byte (0xFF)
+ idx += 1;
+ return result;
+ }
+
+ case 0xf4: // false
+ {
+ return false;
+ }
+
+ case 0xf5: // true
+ {
+ return true;
+ }
+
+ case 0xf6: // null
+ {
+ return value_t::null;
+ }
+
+ case 0xf9: // Half-Precision Float (two-byte IEEE 754)
+ {
+ idx += 2; // skip two content bytes
+
+ // code from RFC 7049, Appendix D, Figure 3:
+ // As half-precision floating-point numbers were only added to
+ // IEEE 754 in 2008, today's programming platforms often still
+ // only have limited support for them. It is very easy to
+ // include at least decoding support for them even without such
+ // support. An example of a small decoder for half-precision
+ // floating-point numbers in the C language is shown in Fig. 3.
+ const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
+ const int exp = (half >> 10) & 0x1f;
+ const int mant = half & 0x3ff;
+ double val;
+ if (exp == 0)
+ {
+ val = std::ldexp(mant, -24);
+ }
+ else if (exp != 31)
+ {
+ val = std::ldexp(mant + 1024, exp - 25);
+ }
+ else
+ {
+ val = mant == 0 ? INFINITY : NAN;
+ }
+ return half & 0x8000 ? -val : val;
+ }
+
+ case 0xfa: // Single-Precision Float (four-byte IEEE 754)
+ {
+ // copy bytes in reverse order into the float variable
+ float res;
+ for (size_t byte = 0; byte < sizeof(float); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(float); // skip content bytes
+ return res;
+ }
+
+ case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
+ {
+ // copy bytes in reverse order into the double variable
+ double res;
+ for (size_t byte = 0; byte < sizeof(double); ++byte)
+ {
+ reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
+ }
+ idx += sizeof(double); // skip content bytes
+ return res;
+ }
+
+ default: // anything else (0xFF is handled inside the other types)
+ {
+ throw std::invalid_argument("error parsing a CBOR @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx])));
+ }
+ }
+ }
+
+ public:
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the MessagePack
+ serialization format. MessagePack is a binary serialization format which
+ aims to be more compact than JSON itself, yet more efficient to parse.
+
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in MessagePack format.,to_msgpack}
+
+ @sa http://msgpack.org
+ @sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
+ deserialization
+ @sa @ref to_cbor(const basic_json& for the related CBOR format
+ */
+ static std::vector<uint8_t> to_msgpack(const basic_json& j)
+ {
+ std::vector<uint8_t> result;
+ to_msgpack_internal(j, result);
+ return result;
+ }
+
+ /*!
+ @brief create a JSON value from a byte vector in MessagePack format
+
+ Deserializes a given byte vector @a v to a JSON value using the MessagePack
+ serialization format.
+
+ @param[in] v a byte vector in MessagePack format
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from MessagePack were
+ used in the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @complexity Linear in the size of the byte vector @a v.
+
+ @liveexample{The example shows the deserialization of a byte vector in
+ MessagePack format to a JSON value.,from_msgpack}
+
+ @sa http://msgpack.org
+ @sa @ref to_msgpack(const basic_json&) for the analogous serialization
+ @sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
+ */
+ static basic_json from_msgpack(const std::vector<uint8_t>& v)
+ {
+ size_t i = 0;
+ return from_msgpack_internal(v, i);
+ }
+
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+ Binary Object Representation) serialization format. CBOR is a binary
+ serialization format which aims to be more compact than JSON itself, yet
+ more efficient to parse.
+
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in CBOR format.,to_cbor}
+
+ @sa http://cbor.io
+ @sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
+ deserialization
+ @sa @ref to_msgpack(const basic_json& for the related MessagePack format
+ */
+ static std::vector<uint8_t> to_cbor(const basic_json& j)
+ {
+ std::vector<uint8_t> result;
+ to_cbor_internal(j, result);
+ return result;
+ }
+
+ /*!
+ @brief create a JSON value from a byte vector in CBOR format
+
+ Deserializes a given byte vector @a v to a JSON value using the CBOR
+ (Concise Binary Object Representation) serialization format.
+
+ @param[in] v a byte vector in CBOR format
+ @return deserialized JSON value
+
+ @throw std::invalid_argument if unsupported features from CBOR were used in
+ the given vector @a v or if the input is not valid MessagePack
+ @throw std::out_of_range if the given vector ends prematurely
+
+ @complexity Linear in the size of the byte vector @a v.
+
+ @liveexample{The example shows the deserialization of a byte vector in CBOR
+ format to a JSON value.,from_cbor}
+
+ @sa http://cbor.io
+ @sa @ref to_cbor(const basic_json&) for the analogous serialization
+ @sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
+ MessagePack format
+ */
+ static basic_json from_cbor(const std::vector<uint8_t>& v)
+ {
+ size_t i = 0;
+ return from_cbor_internal(v, i);
+ }
+
+ /// @}
private:
///////////////////////////
@@ -6769,10 +8205,10 @@
public:
/*!
- @brief a const random access iterator for the @ref basic_json class
+ @brief a template for a random access iterator for the @ref basic_json class
- This class implements a const iterator for the @ref basic_json class. From
- this class, the @ref iterator class is derived.
+ This class implements a both iterators (iterator and const_iterator) for the
+ @ref basic_json class.
@note An iterator is called *initialized* when a pointer to a JSON value
has been set (e.g., by a constructor or a copy assignment). If the
@@ -6785,27 +8221,37 @@
The iterator that can be moved to point (forward and backward) to any
element in constant time.
- @since version 1.0.0
+ @since version 1.0.0, simplified in version 2.0.9
*/
- class const_iterator : public std::iterator<std::random_access_iterator_tag, const basic_json>
+ template<typename U>
+ class iter_impl : public std::iterator<std::random_access_iterator_tag, U>
{
/// allow basic_json to access private members
friend class basic_json;
+ // make sure U is basic_json or const basic_json
+ static_assert(std::is_same<U, basic_json>::value
+ or std::is_same<U, const basic_json>::value,
+ "iter_impl only accepts (const) basic_json");
+
public:
/// the type of the values when the iterator is dereferenced
using value_type = typename basic_json::value_type;
/// a type to represent differences between iterators
using difference_type = typename basic_json::difference_type;
/// defines a pointer to the type iterated over (value_type)
- using pointer = typename basic_json::const_pointer;
+ using pointer = typename std::conditional<std::is_const<U>::value,
+ typename basic_json::const_pointer,
+ typename basic_json::pointer>::type;
/// defines a reference to the type iterated over (value_type)
- using reference = typename basic_json::const_reference;
+ using reference = typename std::conditional<std::is_const<U>::value,
+ typename basic_json::const_reference,
+ typename basic_json::reference>::type;
/// the category of the iterator
using iterator_category = std::bidirectional_iterator_tag;
/// default constructor
- const_iterator() = default;
+ iter_impl() = default;
/*!
@brief constructor for a given JSON instance
@@ -6813,7 +8259,7 @@
@pre object != nullptr
@post The iterator is initialized; i.e. `m_object != nullptr`.
*/
- explicit const_iterator(pointer object) noexcept
+ explicit iter_impl(pointer object) noexcept
: m_object(object)
{
assert(m_object != nullptr);
@@ -6840,37 +8286,25 @@
}
}
- /*!
- @brief copy constructor given a non-const iterator
- @param[in] other iterator to copy from
- @note It is not checked whether @a other is initialized.
+ /*
+ Use operator `const_iterator` instead of `const_iterator(const iterator&
+ other) noexcept` to avoid two class definitions for @ref iterator and
+ @ref const_iterator.
+
+ This function is only called if this class is an @ref iterator. If this
+ class is a @ref const_iterator this function is not called.
*/
- explicit const_iterator(const iterator& other) noexcept
- : m_object(other.m_object)
+ operator const_iterator() const
{
- if (m_object != nullptr)
+ const_iterator ret;
+
+ if (m_object)
{
- switch (m_object->m_type)
- {
- case basic_json::value_t::object:
- {
- m_it.object_iterator = other.m_it.object_iterator;
- break;
- }
-
- case basic_json::value_t::array:
- {
- m_it.array_iterator = other.m_it.array_iterator;
- break;
- }
-
- default:
- {
- m_it.primitive_iterator = other.m_it.primitive_iterator;
- break;
- }
- }
+ ret.m_object = m_object;
+ ret.m_it = m_it;
}
+
+ return ret;
}
/*!
@@ -6878,7 +8312,7 @@
@param[in] other iterator to copy from
@note It is not checked whether @a other is initialized.
*/
- const_iterator(const const_iterator& other) noexcept
+ iter_impl(const iter_impl& other) noexcept
: m_object(other.m_object), m_it(other.m_it)
{}
@@ -6887,7 +8321,7 @@
@param[in,out] other iterator to copy from
@note It is not checked whether @a other is initialized.
*/
- const_iterator& operator=(const_iterator other) noexcept(
+ iter_impl& operator=(iter_impl other) noexcept(
std::is_nothrow_move_constructible<pointer>::value and
std::is_nothrow_move_assignable<pointer>::value and
std::is_nothrow_move_constructible<internal_iterator>::value and
@@ -7049,7 +8483,7 @@
@brief post-increment (it++)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator++(int)
+ iter_impl operator++(int)
{
auto result = *this;
++(*this);
@@ -7060,7 +8494,7 @@
@brief pre-increment (++it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator++()
+ iter_impl& operator++()
{
assert(m_object != nullptr);
@@ -7092,7 +8526,7 @@
@brief post-decrement (it--)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator--(int)
+ iter_impl operator--(int)
{
auto result = *this;
--(*this);
@@ -7103,7 +8537,7 @@
@brief pre-decrement (--it)
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator--()
+ iter_impl& operator--()
{
assert(m_object != nullptr);
@@ -7135,7 +8569,7 @@
@brief comparison: equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator==(const const_iterator& other) const
+ bool operator==(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (m_object != other.m_object)
@@ -7168,7 +8602,7 @@
@brief comparison: not equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator!=(const const_iterator& other) const
+ bool operator!=(const iter_impl& other) const
{
return not operator==(other);
}
@@ -7177,7 +8611,7 @@
@brief comparison: smaller
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator<(const const_iterator& other) const
+ bool operator<(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (m_object != other.m_object)
@@ -7210,7 +8644,7 @@
@brief comparison: less than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator<=(const const_iterator& other) const
+ bool operator<=(const iter_impl& other) const
{
return not other.operator < (*this);
}
@@ -7219,7 +8653,7 @@
@brief comparison: greater than
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator>(const const_iterator& other) const
+ bool operator>(const iter_impl& other) const
{
return not operator<=(other);
}
@@ -7228,7 +8662,7 @@
@brief comparison: greater than or equal
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- bool operator>=(const const_iterator& other) const
+ bool operator>=(const iter_impl& other) const
{
return not operator<(other);
}
@@ -7237,7 +8671,7 @@
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator+=(difference_type i)
+ iter_impl& operator+=(difference_type i)
{
assert(m_object != nullptr);
@@ -7268,7 +8702,7 @@
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator& operator-=(difference_type i)
+ iter_impl& operator-=(difference_type i)
{
return operator+=(-i);
}
@@ -7277,7 +8711,7 @@
@brief add to iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator+(difference_type i)
+ iter_impl operator+(difference_type i)
{
auto result = *this;
result += i;
@@ -7288,7 +8722,7 @@
@brief subtract from iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- const_iterator operator-(difference_type i)
+ iter_impl operator-(difference_type i)
{
auto result = *this;
result -= i;
@@ -7299,7 +8733,7 @@
@brief return difference
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- difference_type operator-(const const_iterator& other) const
+ difference_type operator-(const iter_impl& other) const
{
assert(m_object != nullptr);
@@ -7396,141 +8830,6 @@
};
/*!
- @brief a mutable random access iterator for the @ref basic_json class
-
- @requirement The class satisfies the following concept requirements:
- - [RandomAccessIterator](http://en.cppreference.com/w/cpp/concept/RandomAccessIterator):
- The iterator that can be moved to point (forward and backward) to any
- element in constant time.
- - [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
- It is possible to write to the pointed-to element.
-
- @since version 1.0.0
- */
- class iterator : public const_iterator
- {
- public:
- using base_iterator = const_iterator;
- using pointer = typename basic_json::pointer;
- using reference = typename basic_json::reference;
-
- /// default constructor
- iterator() = default;
-
- /// constructor for a given JSON instance
- explicit iterator(pointer object) noexcept
- : base_iterator(object)
- {}
-
- /// copy constructor
- iterator(const iterator& other) noexcept
- : base_iterator(other)
- {}
-
- /// copy assignment
- iterator& operator=(iterator other) noexcept(
- std::is_nothrow_move_constructible<pointer>::value and
- std::is_nothrow_move_assignable<pointer>::value and
- std::is_nothrow_move_constructible<internal_iterator>::value and
- std::is_nothrow_move_assignable<internal_iterator>::value
- )
- {
- base_iterator::operator=(other);
- return *this;
- }
-
- /// return a reference to the value pointed to by the iterator
- reference operator*() const
- {
- return const_cast<reference>(base_iterator::operator*());
- }
-
- /// dereference the iterator
- pointer operator->() const
- {
- return const_cast<pointer>(base_iterator::operator->());
- }
-
- /// post-increment (it++)
- iterator operator++(int)
- {
- iterator result = *this;
- base_iterator::operator++();
- return result;
- }
-
- /// pre-increment (++it)
- iterator& operator++()
- {
- base_iterator::operator++();
- return *this;
- }
-
- /// post-decrement (it--)
- iterator operator--(int)
- {
- iterator result = *this;
- base_iterator::operator--();
- return result;
- }
-
- /// pre-decrement (--it)
- iterator& operator--()
- {
- base_iterator::operator--();
- return *this;
- }
-
- /// add to iterator
- iterator& operator+=(difference_type i)
- {
- base_iterator::operator+=(i);
- return *this;
- }
-
- /// subtract from iterator
- iterator& operator-=(difference_type i)
- {
- base_iterator::operator-=(i);
- return *this;
- }
-
- /// add to iterator
- iterator operator+(difference_type i)
- {
- auto result = *this;
- result += i;
- return result;
- }
-
- /// subtract from iterator
- iterator operator-(difference_type i)
- {
- auto result = *this;
- result -= i;
- return result;
- }
-
- /// return difference
- difference_type operator-(const iterator& other) const
- {
- return base_iterator::operator-(other);
- }
-
- /// access to successor
- reference operator[](difference_type n) const
- {
- return const_cast<reference>(base_iterator::operator[](n));
- }
-
- /// return the value of an iterator
- reference value() const
- {
- return const_cast<reference>(base_iterator::value());
- }
- };
-
- /*!
@brief a template for a reverse iterator class
@tparam Base the base iterator type to reverse. Valid types are @ref
@@ -7883,6 +9182,7 @@
re2c:define:YYMARKER = m_marker;
re2c:define:YYFILL = "fill_line_buffer(@@); // LCOV_EXCL_LINE";
re2c:define:YYFILL:naked = 1;
+ re2c:yyfill:enable = 1;
re2c:indent:string = " ";
re2c:indent:top = 1;
re2c:labelprefix = "basic_json_parser_";
@@ -8217,8 +9517,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -8237,8 +9535,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -8257,8 +9553,6 @@
supplied via the first parameter. Set this to @a
static_cast<number_float_t*>(nullptr).
- @param[in] type the @ref number_float_t in use
-
@param[in,out] endptr recieves a pointer to the first character after
the number
@@ -8339,19 +9633,19 @@
// skip if definitely not an integer
if (type != value_t::number_float)
{
- // multiply last value by ten and add the new digit
- auto temp = value * 10 + *curptr - '0';
+ auto digit = static_cast<number_unsigned_t>(*curptr - '0');
- // test for overflow
- if (temp < value || temp > max)
+ // overflow if value * 10 + digit > max, move terms around
+ // to avoid overflow in intermediate values
+ if (value > (max - digit) / 10)
{
// overflow
type = value_t::number_float;
}
else
{
- // no overflow - save it
- value = temp;
+ // no overflow
+ value = value * 10 + digit;
}
}
}
@@ -8363,7 +9657,22 @@
}
else if (type == value_t::number_integer)
{
- result.m_value.number_integer = -static_cast<number_integer_t>(value);
+ // invariant: if we parsed a '-', the absolute value is between
+ // 0 (we allow -0) and max == -INT64_MIN
+ assert(value >= 0);
+ assert(value <= max);
+
+ if (value == max)
+ {
+ // we cannot simply negate value (== max == -INT64_MIN),
+ // see https://github.com/nlohmann/json/issues/389
+ result.m_value.number_integer = static_cast<number_integer_t>(INT64_MIN);
+ }
+ else
+ {
+ // all other values can be negated safely
+ result.m_value.number_integer = -static_cast<number_integer_t>(value);
+ }
}
else
{
@@ -9146,13 +10455,11 @@
/*!
@brief replace all occurrences of a substring by another string
- @param[in,out] s the string to manipulate
+ @param[in,out] s the string to manipulate; changed so that all
+ occurrences of @a f are replaced with @a t
@param[in] f the substring to replace with @a t
@param[in] t the string to replace @a f
- @return The string @a s where all occurrences of @a f are replaced
- with @a t.
-
@pre The search string @a f must not be empty.
@since version 2.0.0
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 782d5b5..f57ddf7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -6,6 +6,7 @@
"src/unit-algorithms.cpp"
"src/unit-allocator.cpp"
"src/unit-capacity.cpp"
+ "src/unit-cbor.cpp"
"src/unit-class_const_iterator.cpp"
"src/unit-class_iterator.cpp"
"src/unit-class_lexer.cpp"
@@ -26,6 +27,7 @@
"src/unit-json_patch.cpp"
"src/unit-json_pointer.cpp"
"src/unit-modifiers.cpp"
+ "src/unit-msgpack.cpp"
"src/unit-pointer_access.cpp"
"src/unit-readme.cpp"
"src/unit-reference_access.cpp"
diff --git a/test/Makefile b/test/Makefile
index ead1f07..488cec8 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -10,6 +10,7 @@
src/unit-algorithms.cpp \
src/unit-allocator.cpp \
src/unit-capacity.cpp \
+ src/unit-cbor.cpp \
src/unit-class_const_iterator.cpp \
src/unit-class_iterator.cpp \
src/unit-class_lexer.cpp \
@@ -30,6 +31,7 @@
src/unit-json_patch.cpp \
src/unit-json_pointer.cpp \
src/unit-modifiers.cpp \
+ src/unit-msgpack.cpp \
src/unit-pointer_access.cpp \
src/unit-readme.cpp \
src/unit-reference_access.cpp \
@@ -40,7 +42,20 @@
OBJECTS = $(SOURCES:.cpp=.o)
-all: json_unit
+TESTCASES = $(patsubst src/unit-%.cpp,test-%,$(wildcard src/unit-*.cpp))
+
+##############################################################################
+# main rules
+##############################################################################
+
+all: $(TESTCASES)
+
+clean:
+ rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda) $(TESTCASES)
+
+##############################################################################
+# single test file
+##############################################################################
json_unit: $(OBJECTS) ../src/json.hpp src/catch.hpp
@echo "[CXXLD] $@"
@@ -50,5 +65,16 @@
@echo "[CXX] $@"
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@
-clean:
- rm -fr json_unit $(OBJECTS) $(SOURCES:.cpp=.gcno) $(SOURCES:.cpp=.gcda)
+
+##############################################################################
+# individual test cases
+##############################################################################
+
+test-%: src/unit-%.cpp ../src/json.hpp src/catch.hpp
+ @echo "[CXXLD] $@"
+ @$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -DCATCH_CONFIG_MAIN $< -o $@
+
+TEST_PATTERN = "*"
+TEST_PREFIX = ""
+check: $(TESTCASES)
+ @cd .. ; for testcase in $(TESTCASES); do echo "Executing $$testcase..."; $(TEST_PREFIX)test/$$testcase $(TEST_PATTERN) || exit 1; done
diff --git a/test/data/json.org/1.json.cbor b/test/data/json.org/1.json.cbor
new file mode 100644
index 0000000..e31034c
--- /dev/null
+++ b/test/data/json.org/1.json.cbor
@@ -0,0 +1 @@
+¡hglossary¢hGlossDiv¢iGlossList¡jGlossEntry§hGlossDef¢lGlossSeeAlsocGMLcXMLdparaxHA meta-markup language, used to create markup languages such as DocBook.hGlossSeefmarkupgAcronymdSGMLiGlossTermx$Standard Generalized Markup LanguagefAbbrevmISO 8879:1986fSortAsdSGMLbIDdSGMLetitleaSetitlepexample glossary
\ No newline at end of file
diff --git a/test/data/json.org/1.json.msgpack b/test/data/json.org/1.json.msgpack
new file mode 100644
index 0000000..726875c
--- /dev/null
+++ b/test/data/json.org/1.json.msgpack
Binary files differ
diff --git a/test/data/json.org/2.json.cbor b/test/data/json.org/2.json.cbor
new file mode 100644
index 0000000..ddce516
--- /dev/null
+++ b/test/data/json.org/2.json.cbor
@@ -0,0 +1 @@
+¡dmenu£epopup¡hmenuitem¢gonclicknCreateNewDoc()evaluecNew¢gonclickiOpenDoc()evaluedOpen¢gonclickjCloseDoc()evalueeClosebiddfileevaluedFile
\ No newline at end of file
diff --git a/test/data/json.org/2.json.msgpack b/test/data/json.org/2.json.msgpack
new file mode 100644
index 0000000..3321e1e
--- /dev/null
+++ b/test/data/json.org/2.json.msgpack
@@ -0,0 +1 @@
+¤menu¥popup¨menuitem§onclick®CreateNewDoc()¥value£New§onclick©OpenDoc()¥value¤Open§onclickªCloseDoc()¥value¥Close¢id¤file¥value¤File
\ No newline at end of file
diff --git a/test/data/json.org/3.json.cbor b/test/data/json.org/3.json.cbor
new file mode 100644
index 0000000..6bd57bf
--- /dev/null
+++ b/test/data/json.org/3.json.cbor
@@ -0,0 +1 @@
+¡fwidget¤edebugbondtext¨gvOffsetdestyledbolddnameetext1ghOffsetúionMouseUpx)sun1.opacity = (sun1.opacity / 100) * 90;ddatajClick Hereialignmentfcenterdsize$fwindow¤ewidthôfheightôdnamekmain_windowetitlexSample Konfabulator Widgeteimage¥gvOffsetúcsrcnImages/Sun.pngialignmentfcenterdnamedsun1ghOffsetú
\ No newline at end of file
diff --git a/test/data/json.org/3.json.msgpack b/test/data/json.org/3.json.msgpack
new file mode 100644
index 0000000..e261cd5
--- /dev/null
+++ b/test/data/json.org/3.json.msgpack
Binary files differ
diff --git a/test/data/json.org/4.json.cbor b/test/data/json.org/4.json.cbor
new file mode 100644
index 0000000..e994dee
--- /dev/null
+++ b/test/data/json.org/4.json.cbor
@@ -0,0 +1,4 @@
+¡gweb-app£oservlet-mapping¥jcofaxToolsh/tools/*hcofaxCDSa/kfileServleti/static/*jcofaxAdminh/admin/*jcofaxEmails/cofaxutil/aemail/*ftaglib¢otaglib-locationw/WEB-INF/tlds/cofax.tldjtaglib-uriicofax.tldgservlet
£lservlet-namehcofaxCDSjinit-param¸*ocachePagesStoredxsearchEngineListTemplatexforSearchEnginesList.htmxconfigGlossary:adminEmailmksm@pobox.comlmaxUrlLengthôrdataStoreTestQueryx"SET NOCOUNT ON;select test='test';sdefaultFileTemplatesarticleTemplate.htmpdataStoreLogFilex$/usr/local/tomcat/logs/datastore.logstemplateLoaderClassxorg.cofax.FilesTemplateLoaderndataStoreClassvorg.cofax.SqlDataStorepredirectionClassxorg.cofax.SqlRedirectionttemplateOverridePath`scacheTemplatesStore2ldataStoreUrlx;jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goonxsearchEngineFileTemplatetforSearchEngines.htmocachePagesTrackÈucachePackageTagsStoreÈmdataStoreNameecofaxqdataStorePasswordrdataStoreTestQueryfuseJSPôsdefaultListTemplateplistTemplate.htmxconfigGlossary:poweredByeCofaxmdataStoreUserbsaojspListTemplateplistTemplate.jspojspFileTemplatesarticleTemplate.jspqdataStoreMaxConnsdscachePagesDirtyRead
+qcachePagesRefresh
+scacheTemplatesTrackdwdataStoreConnUsageLimitdxconfigGlossary:installationAtpPhiladelphia, PAtsearchEngineRobotsDbqWEB-INF/robots.dbvtemplateProcessorClassxorg.cofax.WysiwygTemplatewcachePackageTagsRefresh<xconfigGlossary:staticPatho/content/staticltemplatePathitemplatesluseDataStoreõucacheTemplatesRefreshodataStoreDriverx,com.microsoft.jdbc.sqlserver.SQLServerDriverxconfigGlossary:poweredByIconq/images/cofax.gifucachePackageTagsTrackÈqdataStoreLogLeveledebugrdataStoreInitConns
+mservlet-classxorg.cofax.cds.CDSServlet£lservlet-namejcofaxEmailjinit-param¢pmailHostOverrideemail2hmailHostemail1mservlet-classxorg.cofax.cds.EmailServlet¢lservlet-namejcofaxAdminmservlet-classxorg.cofax.cds.AdminServlet¢lservlet-namekfileServletmservlet-classxorg.cofax.cds.FileServlet£lservlet-namejcofaxToolsjinit-paramklogLocationx%/usr/local/tomcat/logs/CofaxTools.logrfileTransferFolderx4/usr/local/tomcat/webapps/content/fileTransferFoldercloggdataLogodataLogLocationx"/usr/local/tomcat/logs/dataLog.logladminGroupIDmlookInContextoremovePageCachex%/content/admin/remove?cache=pages&id=sremoveTemplateCachex)/content/admin/remove?cache=templates&id=jlogMaxSize`ndataLogMaxSize`jbetaServerõltemplatePathotoolstemplates/mservlet-classxorg.cofax.cms.CofaxToolsServlet
\ No newline at end of file
diff --git a/test/data/json.org/4.json.msgpack b/test/data/json.org/4.json.msgpack
new file mode 100644
index 0000000..587c0af
--- /dev/null
+++ b/test/data/json.org/4.json.msgpack
Binary files differ
diff --git a/test/data/json.org/5.json.cbor b/test/data/json.org/5.json.cbor
new file mode 100644
index 0000000..41f7ba5
--- /dev/null
+++ b/test/data/json.org/5.json.cbor
@@ -0,0 +1 @@
+¡dmenu¢fheaderjSVG Viewereitems¡biddOpen¢bidgOpenNewelabelhOpen Newö¢bidfZoomInelabelgZoom In¢bidgZoomOutelabelhZoom Out¢bidlOriginalViewelabelmOriginal Viewö¡bidgQuality¡bidePause¡biddMuteö¢biddFindelabelgFind...¢bidiFindAgainelabeljFind Again¡biddCopy¢bidiCopyAgainelabeljCopy Again¢bidgCopySVGelabelhCopy SVG¢bidgViewSVGelabelhView SVG¢bidjViewSourceelabelkView Source¢bidfSaveAselabelgSave Asö¡biddHelp¢bideAboutelabelxAbout Adobe CVG Viewer...
\ No newline at end of file
diff --git a/test/data/json.org/5.json.msgpack b/test/data/json.org/5.json.msgpack
new file mode 100644
index 0000000..cc70155
--- /dev/null
+++ b/test/data/json.org/5.json.msgpack
Binary files differ
diff --git a/test/data/json_nlohmann_tests/all_unicode.json.cbor b/test/data/json_nlohmann_tests/all_unicode.json.cbor
new file mode 100644
index 0000000..208f3cb
--- /dev/null
+++ b/test/data/json_nlohmann_tests/all_unicode.json.cbor
Binary files differ
diff --git a/test/data/json_nlohmann_tests/all_unicode.json.msgpack b/test/data/json_nlohmann_tests/all_unicode.json.msgpack
new file mode 100644
index 0000000..b024316
--- /dev/null
+++ b/test/data/json_nlohmann_tests/all_unicode.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip01.json.cbor b/test/data/json_roundtrip/roundtrip01.json.cbor
new file mode 100644
index 0000000..6977b91
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip01.json.cbor
@@ -0,0 +1 @@
+ö
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip01.json.msgpack b/test/data/json_roundtrip/roundtrip01.json.msgpack
new file mode 100644
index 0000000..37932df
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip01.json.msgpack
@@ -0,0 +1 @@
+À
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip02.json.cbor b/test/data/json_roundtrip/roundtrip02.json.cbor
new file mode 100644
index 0000000..6a7b9cf
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip02.json.cbor
@@ -0,0 +1 @@
+õ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip02.json.msgpack b/test/data/json_roundtrip/roundtrip02.json.msgpack
new file mode 100644
index 0000000..52b4164
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip02.json.msgpack
@@ -0,0 +1 @@
+Ã
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip03.json.cbor b/test/data/json_roundtrip/roundtrip03.json.cbor
new file mode 100644
index 0000000..c14c133
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip03.json.cbor
@@ -0,0 +1 @@
+ô
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip03.json.msgpack b/test/data/json_roundtrip/roundtrip03.json.msgpack
new file mode 100644
index 0000000..ea59298
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip03.json.msgpack
@@ -0,0 +1 @@
+Â
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip04.json.cbor b/test/data/json_roundtrip/roundtrip04.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip04.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip04.json.msgpack b/test/data/json_roundtrip/roundtrip04.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip04.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip05.json.cbor b/test/data/json_roundtrip/roundtrip05.json.cbor
new file mode 100644
index 0000000..bb4b1a5
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip05.json.cbor
@@ -0,0 +1 @@
+cfoo
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip05.json.msgpack b/test/data/json_roundtrip/roundtrip05.json.msgpack
new file mode 100644
index 0000000..fed9247
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip05.json.msgpack
@@ -0,0 +1 @@
+£foo
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip06.json.cbor b/test/data/json_roundtrip/roundtrip06.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip06.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip06.json.msgpack b/test/data/json_roundtrip/roundtrip06.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip06.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip07.json.cbor b/test/data/json_roundtrip/roundtrip07.json.cbor
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip07.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip07.json.msgpack b/test/data/json_roundtrip/roundtrip07.json.msgpack
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip07.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip08.json.cbor b/test/data/json_roundtrip/roundtrip08.json.cbor
new file mode 100644
index 0000000..e1707ae
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip08.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip08.json.msgpack b/test/data/json_roundtrip/roundtrip08.json.msgpack
new file mode 100644
index 0000000..b361f80
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip08.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip09.json.cbor b/test/data/json_roundtrip/roundtrip09.json.cbor
new file mode 100644
index 0000000..1f39c42
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip09.json.cbor
@@ -0,0 +1 @@
+¡cfoocbar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip09.json.msgpack b/test/data/json_roundtrip/roundtrip09.json.msgpack
new file mode 100644
index 0000000..5ace8ec
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip09.json.msgpack
@@ -0,0 +1 @@
+£foo£bar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip10.json.cbor b/test/data/json_roundtrip/roundtrip10.json.cbor
new file mode 100644
index 0000000..68a615c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip10.json.cbor
@@ -0,0 +1 @@
+¢aaöcfoocbar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip10.json.msgpack b/test/data/json_roundtrip/roundtrip10.json.msgpack
new file mode 100644
index 0000000..f9791c1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip10.json.msgpack
@@ -0,0 +1 @@
+¡aÀ£foo£bar
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip11.json.cbor b/test/data/json_roundtrip/roundtrip11.json.cbor
new file mode 100644
index 0000000..0949b11
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip11.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip11.json.msgpack b/test/data/json_roundtrip/roundtrip11.json.msgpack
new file mode 100644
index 0000000..97689a4
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip11.json.msgpack
@@ -0,0 +1 @@
+ÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip12.json.cbor b/test/data/json_roundtrip/roundtrip12.json.cbor
new file mode 100644
index 0000000..3636a1e
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip12.json.cbor
@@ -0,0 +1 @@
+:ÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip12.json.msgpack b/test/data/json_roundtrip/roundtrip12.json.msgpack
new file mode 100644
index 0000000..d523c4a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip12.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip13.json.cbor b/test/data/json_roundtrip/roundtrip13.json.cbor
new file mode 100644
index 0000000..3948e5f
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip13.json.cbor
@@ -0,0 +1 @@
+;"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip13.json.msgpack b/test/data/json_roundtrip/roundtrip13.json.msgpack
new file mode 100644
index 0000000..5b19d3e
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip13.json.msgpack
@@ -0,0 +1 @@
+ÓîÝï~ë
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip14.json.cbor b/test/data/json_roundtrip/roundtrip14.json.cbor
new file mode 100644
index 0000000..ea2a38b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip14.json.cbor
@@ -0,0 +1 @@
+;ÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip14.json.msgpack b/test/data/json_roundtrip/roundtrip14.json.msgpack
new file mode 100644
index 0000000..4b87c84
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip14.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip15.json.cbor b/test/data/json_roundtrip/roundtrip15.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip15.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip15.json.msgpack b/test/data/json_roundtrip/roundtrip15.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip15.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip16.json.cbor b/test/data/json_roundtrip/roundtrip16.json.cbor
new file mode 100644
index 0000000..c051d45
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip16.json.cbor
@@ -0,0 +1 @@
+ÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip16.json.msgpack b/test/data/json_roundtrip/roundtrip16.json.msgpack
new file mode 100644
index 0000000..199e499
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip16.json.msgpack
@@ -0,0 +1 @@
+Îÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip17.json.cbor b/test/data/json_roundtrip/roundtrip17.json.cbor
new file mode 100644
index 0000000..413dbd2
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip17.json.cbor
@@ -0,0 +1 @@
+ÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip17.json.msgpack b/test/data/json_roundtrip/roundtrip17.json.msgpack
new file mode 100644
index 0000000..7e2a955
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip17.json.msgpack
@@ -0,0 +1 @@
+Îÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip18.json.cbor b/test/data/json_roundtrip/roundtrip18.json.cbor
new file mode 100644
index 0000000..17a08f1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip18.json.cbor
@@ -0,0 +1 @@
+"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip18.json.msgpack b/test/data/json_roundtrip/roundtrip18.json.msgpack
new file mode 100644
index 0000000..a24c12b
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip18.json.msgpack
@@ -0,0 +1 @@
+Ï"ô}é
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip19.json.cbor b/test/data/json_roundtrip/roundtrip19.json.cbor
new file mode 100644
index 0000000..a8ff265
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip19.json.cbor
@@ -0,0 +1 @@
+ÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip19.json.msgpack b/test/data/json_roundtrip/roundtrip19.json.msgpack
new file mode 100644
index 0000000..670c193
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip19.json.msgpack
@@ -0,0 +1 @@
+Ïÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip20.json.cbor b/test/data/json_roundtrip/roundtrip20.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip20.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip20.json.msgpack b/test/data/json_roundtrip/roundtrip20.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip20.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip21.json.cbor b/test/data/json_roundtrip/roundtrip21.json.cbor
new file mode 100644
index 0000000..90e1bef
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip21.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip21.json.msgpack b/test/data/json_roundtrip/roundtrip21.json.msgpack
new file mode 100644
index 0000000..ebe72a0
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip21.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip22.json.cbor b/test/data/json_roundtrip/roundtrip22.json.cbor
new file mode 100644
index 0000000..1af4e2c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip22.json.cbor
@@ -0,0 +1 @@
+û?óÀn
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip22.json.msgpack b/test/data/json_roundtrip/roundtrip22.json.msgpack
new file mode 100644
index 0000000..bb8b079
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip22.json.msgpack
@@ -0,0 +1 @@
+Ë?óÀn
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip23.json.cbor b/test/data/json_roundtrip/roundtrip23.json.cbor
new file mode 100644
index 0000000..80a2fa1
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip23.json.cbor
@@ -0,0 +1 @@
+û¿óÀn
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip23.json.msgpack b/test/data/json_roundtrip/roundtrip23.json.msgpack
new file mode 100644
index 0000000..76ac419
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip23.json.msgpack
@@ -0,0 +1 @@
+Ë¿óÀn
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip24.json.cbor b/test/data/json_roundtrip/roundtrip24.json.cbor
new file mode 100644
index 0000000..86aea39
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip24.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip24.json.msgpack b/test/data/json_roundtrip/roundtrip24.json.msgpack
new file mode 100644
index 0000000..f5bf071
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip24.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip25.json.cbor b/test/data/json_roundtrip/roundtrip25.json.cbor
new file mode 100644
index 0000000..4a361ca
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip25.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip25.json.msgpack b/test/data/json_roundtrip/roundtrip25.json.msgpack
new file mode 100644
index 0000000..c45fb04
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip25.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip26.json.cbor b/test/data/json_roundtrip/roundtrip26.json.cbor
new file mode 100644
index 0000000..c5de720
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip26.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip26.json.msgpack b/test/data/json_roundtrip/roundtrip26.json.msgpack
new file mode 100644
index 0000000..0a6b037
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip26.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip27.json.cbor b/test/data/json_roundtrip/roundtrip27.json.cbor
new file mode 100644
index 0000000..e1fcb16
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip27.json.cbor
@@ -0,0 +1 @@
+ûïÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip27.json.msgpack b/test/data/json_roundtrip/roundtrip27.json.msgpack
new file mode 100644
index 0000000..5f03c19
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip27.json.msgpack
@@ -0,0 +1 @@
+Ëïÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip28.json.cbor b/test/data/json_roundtrip/roundtrip28.json.cbor
new file mode 100644
index 0000000..86aea39
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip28.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip28.json.msgpack b/test/data/json_roundtrip/roundtrip28.json.msgpack
new file mode 100644
index 0000000..f5bf071
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip28.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip29.json.cbor b/test/data/json_roundtrip/roundtrip29.json.cbor
new file mode 100644
index 0000000..85c00ac
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip29.json.cbor
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip29.json.msgpack b/test/data/json_roundtrip/roundtrip29.json.msgpack
new file mode 100644
index 0000000..b1ef60a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip29.json.msgpack
Binary files differ
diff --git a/test/data/json_roundtrip/roundtrip30.json.cbor b/test/data/json_roundtrip/roundtrip30.json.cbor
new file mode 100644
index 0000000..f8cdaac
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip30.json.cbor
@@ -0,0 +1 @@
+û9¹ ãõöÂ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip30.json.msgpack b/test/data/json_roundtrip/roundtrip30.json.msgpack
new file mode 100644
index 0000000..4362c4c
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip30.json.msgpack
@@ -0,0 +1 @@
+Ë9¹ ãõöÂ
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip31.json.cbor b/test/data/json_roundtrip/roundtrip31.json.cbor
new file mode 100644
index 0000000..cb47b07
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip31.json.cbor
@@ -0,0 +1 @@
+ûF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip31.json.msgpack b/test/data/json_roundtrip/roundtrip31.json.msgpack
new file mode 100644
index 0000000..e4d9e9a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip31.json.msgpack
@@ -0,0 +1 @@
+ËF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip32.json.cbor b/test/data/json_roundtrip/roundtrip32.json.cbor
new file mode 100644
index 0000000..cb47b07
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip32.json.cbor
@@ -0,0 +1 @@
+ûF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_roundtrip/roundtrip32.json.msgpack b/test/data/json_roundtrip/roundtrip32.json.msgpack
new file mode 100644
index 0000000..e4d9e9a
--- /dev/null
+++ b/test/data/json_roundtrip/roundtrip32.json.msgpack
@@ -0,0 +1 @@
+ËF/)Äî±Uå
\ No newline at end of file
diff --git a/test/data/json_tests/pass1.json.cbor b/test/data/json_tests/pass1.json.cbor
new file mode 100644
index 0000000..063bf93
--- /dev/null
+++ b/test/data/json_tests/pass1.json.cbor
Binary files differ
diff --git a/test/data/json_tests/pass1.json.msgpack b/test/data/json_tests/pass1.json.msgpack
new file mode 100644
index 0000000..6b1e731
--- /dev/null
+++ b/test/data/json_tests/pass1.json.msgpack
Binary files differ
diff --git a/test/data/json_tests/pass2.json.cbor b/test/data/json_tests/pass2.json.cbor
new file mode 100644
index 0000000..fe3a096
--- /dev/null
+++ b/test/data/json_tests/pass2.json.cbor
@@ -0,0 +1 @@
+lNot too deep
\ No newline at end of file
diff --git a/test/data/json_tests/pass2.json.msgpack b/test/data/json_tests/pass2.json.msgpack
new file mode 100644
index 0000000..336ce90
--- /dev/null
+++ b/test/data/json_tests/pass2.json.msgpack
@@ -0,0 +1 @@
+¬Not too deep
\ No newline at end of file
diff --git a/test/data/json_tests/pass3.json.cbor b/test/data/json_tests/pass3.json.cbor
new file mode 100644
index 0000000..d29b43d
--- /dev/null
+++ b/test/data/json_tests/pass3.json.cbor
@@ -0,0 +1 @@
+¡wJSON Test Pattern pass3¢lIn this testpIt is an object.sThe outermost valuexmust be an object or array.
\ No newline at end of file
diff --git a/test/data/json_tests/pass3.json.msgpack b/test/data/json_tests/pass3.json.msgpack
new file mode 100644
index 0000000..aee4236
--- /dev/null
+++ b/test/data/json_tests/pass3.json.msgpack
@@ -0,0 +1 @@
+·JSON Test Pattern pass3¬In this test°It is an object.³The outermost value»must be an object or array.
\ No newline at end of file
diff --git a/test/data/json_testsuite/sample.json.cbor b/test/data/json_testsuite/sample.json.cbor
new file mode 100644
index 0000000..3f1d8dd
--- /dev/null
+++ b/test/data/json_testsuite/sample.json.cbor
Binary files differ
diff --git a/test/data/json_testsuite/sample.json.msgpack b/test/data/json_testsuite/sample.json.msgpack
new file mode 100644
index 0000000..e1338dd
--- /dev/null
+++ b/test/data/json_testsuite/sample.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor
new file mode 100644
index 0000000..ca9d0c9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack
new file mode 100644
index 0000000..df3dff5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor
new file mode 100644
index 0000000..2a24392
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.cbor
@@ -0,0 +1 @@
+`
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack
new file mode 100644
index 0000000..f8569fa
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_empty.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor
new file mode 100644
index 0000000..bc7cf32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.cbor
@@ -0,0 +1 @@
+aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack
new file mode 100644
index 0000000..42f2686
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json.msgpack
@@ -0,0 +1 @@
+¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor
new file mode 100644
index 0000000..c14c133
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.cbor
@@ -0,0 +1 @@
+ô
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack
new file mode 100644
index 0000000..ea59298
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_false.json.msgpack
@@ -0,0 +1 @@
+Â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor
new file mode 100644
index 0000000..e1c3c73
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.cbor
@@ -0,0 +1 @@
+öa1
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack
new file mode 100644
index 0000000..ef5e47a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json.msgpack
@@ -0,0 +1 @@
+À¡1
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor
new file mode 100644
index 0000000..6977b91
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.cbor
@@ -0,0 +1 @@
+ö
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack
new file mode 100644
index 0000000..37932df
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_null.json.msgpack
@@ -0,0 +1 @@
+À
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor
new file mode 100644
index 0000000..17bb347
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack
new file mode 100644
index 0000000..0ad68ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor
new file mode 100644
index 0000000..f7d666b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.cbor
@@ -0,0 +1 @@
+
ööö
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack
new file mode 100644
index 0000000..dd22b5c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json.msgpack
@@ -0,0 +1 @@
+ÀÀÀ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor
new file mode 100644
index 0000000..02b41ff
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack
new file mode 100644
index 0000000..9dee29f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor
new file mode 100644
index 0000000..42ad655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number.json.cbor
@@ -0,0 +1 @@
+ûMÝ2é2¬X¾
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack
new file mode 100644
index 0000000..d8016f8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number.json.msgpack
@@ -0,0 +1 @@
+ËMÝ2é2¬X¾
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_0e1.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor
new file mode 100644
index 0000000..e8a0edf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack
new file mode 100644
index 0000000..4919983
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_after_space.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor
new file mode 100644
index 0000000..ae8b39c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.cbor
@@ -0,0 +1 @@
+û¯½¤ähçÇ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack
new file mode 100644
index 0000000..22b7026
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json.msgpack
@@ -0,0 +1 @@
+˯½¤ähçÇ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor
new file mode 100644
index 0000000..362d407
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack
new file mode 100644
index 0000000..59db48b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor
new file mode 100644
index 0000000..eb4b0a6
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack
new file mode 100644
index 0000000..6560b32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor
new file mode 100644
index 0000000..346ebfb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.cbor
@@ -0,0 +1 @@
+8z
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack
new file mode 100644
index 0000000..8da6fb9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json.msgpack
@@ -0,0 +1 @@
+Ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor
new file mode 100644
index 0000000..0949b11
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack
new file mode 100644
index 0000000..97689a4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json.msgpack
@@ -0,0 +1 @@
+ÿ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor
new file mode 100644
index 0000000..8b040ea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack
new file mode 100644
index 0000000..5b8551b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor
new file mode 100644
index 0000000..a8dcf21
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.cbor
@@ -0,0 +1 @@
+ûDðÏMÕ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack
new file mode 100644
index 0000000..579cf7d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json.msgpack
@@ -0,0 +1 @@
+ËDðÏMÕ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor
new file mode 100644
index 0000000..d9f391b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.cbor
@@ -0,0 +1 @@
+û?záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack
new file mode 100644
index 0000000..3ac2971
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json.msgpack
@@ -0,0 +1 @@
+Ë?záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor
new file mode 100644
index 0000000..1f64a67
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack
new file mode 100644
index 0000000..34ba122
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor
new file mode 100644
index 0000000..cc16a23
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack
new file mode 100644
index 0000000..7c1cc37
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor
new file mode 100644
index 0000000..92ec4de
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.cbor
@@ -0,0 +1 @@
+ûP¨¿O§
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack
new file mode 100644
index 0000000..ec7fe04
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json.msgpack
@@ -0,0 +1 @@
+ËP¨¿O§
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor
new file mode 100644
index 0000000..d9f391b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.cbor
@@ -0,0 +1 @@
+û?záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack
new file mode 100644
index 0000000..3ac2971
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json.msgpack
@@ -0,0 +1 @@
+Ë?záG®{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor
new file mode 100644
index 0000000..5d2e2a4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack
new file mode 100644
index 0000000..1398605
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor
new file mode 100644
index 0000000..1f64a67
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack
new file mode 100644
index 0000000..34ba122
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor
new file mode 100644
index 0000000..362d407
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack
new file mode 100644
index 0000000..59db48b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor
new file mode 100644
index 0000000..75bd6d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack
new file mode 100644
index 0000000..c4b7acf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor
new file mode 100644
index 0000000..35fe6ad
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.cbor
@@ -0,0 +1 @@
+{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack
new file mode 100644
index 0000000..d3ae4d8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json.msgpack
@@ -0,0 +1 @@
+{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor
new file mode 100644
index 0000000..6776a12
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.cbor
@@ -0,0 +1 @@
+û@^Ý<î
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack
new file mode 100644
index 0000000..09dcbc6
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json.msgpack
@@ -0,0 +1 @@
+Ë@^Ý<î
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor
new file mode 100644
index 0000000..e7a5832
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor
new file mode 100644
index 0000000..13593c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object.json.cbor
@@ -0,0 +1 @@
+¢cdfgcfghcasdcsdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack
new file mode 100644
index 0000000..e902e95
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object.json.msgpack
@@ -0,0 +1 @@
+£dfg£fgh£asd£sdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor
new file mode 100644
index 0000000..b233b30
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.cbor
@@ -0,0 +1 @@
+¡casdcsdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack
new file mode 100644
index 0000000..8c89ddb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_basic.json.msgpack
@@ -0,0 +1 @@
+£asd£sdf
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor
new file mode 100644
index 0000000..94a640e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.cbor
@@ -0,0 +1 @@
+¡aaac
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack
new file mode 100644
index 0000000..e82b938
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json.msgpack
@@ -0,0 +1 @@
+¡a¡c
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor
new file mode 100644
index 0000000..7799d3b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.cbor
@@ -0,0 +1 @@
+¡aaab
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack
new file mode 100644
index 0000000..12507c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json.msgpack
@@ -0,0 +1 @@
+¡a¡b
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor
new file mode 100644
index 0000000..9563c4d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack
new file mode 100644
index 0000000..c89d18f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor
new file mode 100644
index 0000000..c76791c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack
new file mode 100644
index 0000000..0106921
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor
new file mode 100644
index 0000000..6d145dd
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.cbor
@@ -0,0 +1 @@
+¢cmaxûEÀ'ç/cminûÅÀ'ç/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack
new file mode 100644
index 0000000..5f9299b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json.msgpack
@@ -0,0 +1 @@
+£maxËEÀ'ç/£minËÅÀ'ç/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor
new file mode 100644
index 0000000..f6d3858
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.cbor
@@ -0,0 +1 @@
+¢ax¡bidx(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxbidx(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack
new file mode 100644
index 0000000..6c99095
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor
new file mode 100644
index 0000000..59c63ac
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.cbor
@@ -0,0 +1 @@
+¡aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack
new file mode 100644
index 0000000..704d8df
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_simple.json.msgpack
@@ -0,0 +1 @@
+¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor
new file mode 100644
index 0000000..4e47941
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.cbor
@@ -0,0 +1 @@
+¡etitlex!ÐолÑоÑа Ðемлекопа
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack
new file mode 100644
index 0000000..540f238
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor
new file mode 100644
index 0000000..7799d3b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.cbor
@@ -0,0 +1 @@
+¡aaab
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack
new file mode 100644
index 0000000..12507c1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json.msgpack
@@ -0,0 +1 @@
+¡a¡b
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor
new file mode 100644
index 0000000..0d6409b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.cbor
@@ -0,0 +1 @@
+f`Īá«
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack
new file mode 100644
index 0000000..612152f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json.msgpack
@@ -0,0 +1 @@
+¦`Īá«
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor
new file mode 100644
index 0000000..78091ec
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.cbor
@@ -0,0 +1 @@
+dð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack
new file mode 100644
index 0000000..a8d174a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json.msgpack
@@ -0,0 +1 @@
+¤ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor
new file mode 100644
index 0000000..63af665
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.cbor
@@ -0,0 +1 @@
+dð·
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack
new file mode 100644
index 0000000..7d0b6e4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json.msgpack
@@ -0,0 +1 @@
+¤ð·
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor
new file mode 100644
index 0000000..6d0d25b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.cbor
@@ -0,0 +1 @@
+hð¹ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack
new file mode 100644
index 0000000..72009e8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json.msgpack
@@ -0,0 +1 @@
+¨ð¹ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor
new file mode 100644
index 0000000..8cbf174
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack
new file mode 100644
index 0000000..017114b
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor
new file mode 100644
index 0000000..906aaaa
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.cbor
@@ -0,0 +1 @@
+f\u0000
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack
new file mode 100644
index 0000000..c4bab43
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json.msgpack
@@ -0,0 +1 @@
+¦\u0000
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor
new file mode 100644
index 0000000..217272c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.cbor
@@ -0,0 +1 @@
+a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack
new file mode 100644
index 0000000..daab159
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json.msgpack
@@ -0,0 +1 @@
+¡"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor
new file mode 100644
index 0000000..30687cc
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.cbor
@@ -0,0 +1 @@
+ma/*b*/c/*d//e
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack
new file mode 100644
index 0000000..5364f2c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_comments.json.msgpack
@@ -0,0 +1 @@
+a/*b*/c/*d//e
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor
new file mode 100644
index 0000000..75e194f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.cbor
@@ -0,0 +1 @@
+b\a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack
new file mode 100644
index 0000000..ea41d05
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json.msgpack
@@ -0,0 +1 @@
+¢\a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor
new file mode 100644
index 0000000..3425cfc
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.cbor
@@ -0,0 +1 @@
+b\n
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack
new file mode 100644
index 0000000..327cf1f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json.msgpack
@@ -0,0 +1 @@
+¢\n
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor
new file mode 100644
index 0000000..3eb5fc1
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.cbor
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack
new file mode 100644
index 0000000..8954efe
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json.msgpack
@@ -0,0 +1 @@
+¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor
new file mode 100644
index 0000000..3406655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.cbor
@@ -0,0 +1 @@
+cï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack
new file mode 100644
index 0000000..80e7452
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json.msgpack
@@ -0,0 +1 @@
+£ï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor
new file mode 100644
index 0000000..0705ec8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack
new file mode 100644
index 0000000..1788db3
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array.json.msgpack
@@ -0,0 +1 @@
+£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor
new file mode 100644
index 0000000..0705ec8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack
new file mode 100644
index 0000000..1788db3
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json.msgpack
@@ -0,0 +1 @@
+£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor
new file mode 100644
index 0000000..a74256d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.cbor
@@ -0,0 +1 @@
+dô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack
new file mode 100644
index 0000000..39a157e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json.msgpack
@@ -0,0 +1 @@
+¤ô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor
new file mode 100644
index 0000000..0a32b32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.cbor
@@ -0,0 +1 @@
+inew line
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack
new file mode 100644
index 0000000..84ccc51
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json.msgpack
@@ -0,0 +1 @@
+©new line
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor
new file mode 100644
index 0000000..a74256d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.cbor
@@ -0,0 +1 @@
+dô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack
new file mode 100644
index 0000000..39a157e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json.msgpack
@@ -0,0 +1 @@
+¤ô¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor
new file mode 100644
index 0000000..977d892
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.cbor
@@ -0,0 +1 @@
+dð¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack
new file mode 100644
index 0000000..19b98bd
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json.msgpack
@@ -0,0 +1 @@
+¤ð¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor
new file mode 100644
index 0000000..3406655
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.cbor
@@ -0,0 +1 @@
+cï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack
new file mode 100644
index 0000000..80e7452
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json.msgpack
@@ -0,0 +1 @@
+£ï¿¿
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor
new file mode 100644
index 0000000..aa34c41
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.cbor
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack
new file mode 100644
index 0000000..3c8ba66
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json.msgpack
Binary files differ
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor
new file mode 100644
index 0000000..ef1fa66
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+a,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..3d07f7f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+¡,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor
new file mode 100644
index 0000000..1405cf9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.cbor
@@ -0,0 +1 @@
+bÏ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack
new file mode 100644
index 0000000..d9738e2
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_pi.json.msgpack
@@ -0,0 +1 @@
+¢Ï
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor
new file mode 100644
index 0000000..1674aea
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.cbor
@@ -0,0 +1 @@
+dasd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack
new file mode 100644
index 0000000..d33b64d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json.msgpack
@@ -0,0 +1 @@
+¤asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor
new file mode 100644
index 0000000..a19cbb9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.cbor
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack
new file mode 100644
index 0000000..ad19734
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_space.json.msgpack
@@ -0,0 +1 @@
+¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor
new file mode 100644
index 0000000..77815d9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+cà ¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..1d94ad0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+£à ¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor
new file mode 100644
index 0000000..2cb1c8d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.cbor
@@ -0,0 +1 @@
+bģ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack
new file mode 100644
index 0000000..e100f62
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json.msgpack
@@ -0,0 +1 @@
+¢Ä£
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor
new file mode 100644
index 0000000..4f74251
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.cbor
@@ -0,0 +1 @@
+câ¨
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack
new file mode 100644
index 0000000..00866ae
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json.msgpack
@@ -0,0 +1 @@
+£â¨
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor
new file mode 100644
index 0000000..d35b667
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.cbor
@@ -0,0 +1 @@
+câ©
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack
new file mode 100644
index 0000000..b8f541d
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json.msgpack
@@ -0,0 +1 @@
+£â©
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor
new file mode 100644
index 0000000..7c90b15
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.cbor
@@ -0,0 +1 @@
+jaã¯ãªã¹
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack
new file mode 100644
index 0000000..9dd9e30
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json.msgpack
@@ -0,0 +1 @@
+ªaã¯ãªã¹
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor
new file mode 100644
index 0000000..a5d8eef
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.cbor
@@ -0,0 +1 @@
+a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack
new file mode 100644
index 0000000..b2827c9
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json.msgpack
@@ -0,0 +1 @@
+¡
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor
new file mode 100644
index 0000000..9eeef8e
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.cbor
@@ -0,0 +1 @@
+cê
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack
new file mode 100644
index 0000000..cfdc561
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode.json.msgpack
@@ -0,0 +1 @@
+£ê
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor
new file mode 100644
index 0000000..c8d5c77
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.cbor
@@ -0,0 +1 @@
+a\
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack
new file mode 100644
index 0000000..2083b69
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json.msgpack
@@ -0,0 +1 @@
+¡\
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor
new file mode 100644
index 0000000..e46815f
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.cbor
@@ -0,0 +1 @@
+iâã´â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack
new file mode 100644
index 0000000..8451f4a
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json.msgpack
@@ -0,0 +1 @@
+©âã´â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor
new file mode 100644
index 0000000..2c33ac2
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.cbor
@@ -0,0 +1 @@
+câ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack
new file mode 100644
index 0000000..b175034
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json.msgpack
@@ -0,0 +1 @@
+£â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor
new file mode 100644
index 0000000..ca6cae4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.cbor
@@ -0,0 +1 @@
+câ¤
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack
new file mode 100644
index 0000000..febc5e0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json.msgpack
@@ -0,0 +1 @@
+£â¤
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor
new file mode 100644
index 0000000..217272c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.cbor
@@ -0,0 +1 @@
+a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack
new file mode 100644
index 0000000..daab159
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json.msgpack
@@ -0,0 +1 @@
+¡"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor
new file mode 100644
index 0000000..41f5884
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.cbor
@@ -0,0 +1 @@
+gâ¬ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack
new file mode 100644
index 0000000..c0089d8
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_utf8.json.msgpack
@@ -0,0 +1 @@
+§â¬ð
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor
new file mode 100644
index 0000000..ec51b86
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.cbor
@@ -0,0 +1 @@
+caa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack
new file mode 100644
index 0000000..e0a87ec
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json.msgpack
@@ -0,0 +1 @@
+£aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor
new file mode 100644
index 0000000..3a6e607
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.cbor
@@ -0,0 +1 @@
+ô
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack
new file mode 100644
index 0000000..5277188
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json.msgpack
@@ -0,0 +1 @@
+Â
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor
new file mode 100644
index 0000000..d9ba731
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.cbor
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack
new file mode 100644
index 0000000..f59ec20
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json.msgpack
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor
new file mode 100644
index 0000000..8a0eb60
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.cbor
@@ -0,0 +1 @@
+û¿¹
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack
new file mode 100644
index 0000000..8d624e4
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json.msgpack
@@ -0,0 +1 @@
+Ë¿¹
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor
new file mode 100644
index 0000000..f7a8cad
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.cbor
@@ -0,0 +1 @@
+ö
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack
new file mode 100644
index 0000000..e7754ca
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json.msgpack
@@ -0,0 +1 @@
+À
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor
new file mode 100644
index 0000000..4616cca
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.cbor
@@ -0,0 +1 @@
+casd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack
new file mode 100644
index 0000000..ac624bf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json.msgpack
@@ -0,0 +1 @@
+£asd
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor
new file mode 100644
index 0000000..bb7d13c
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.cbor
@@ -0,0 +1 @@
+õ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack
new file mode 100644
index 0000000..6b10f95
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json.msgpack
@@ -0,0 +1 @@
+Ã
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor
new file mode 100644
index 0000000..64845fb
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.cbor
@@ -0,0 +1 @@
+`
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack
new file mode 100644
index 0000000..eea1bf0
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor
new file mode 100644
index 0000000..bc7cf32
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.cbor
@@ -0,0 +1 @@
+aa
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack
new file mode 100644
index 0000000..42f2686
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json.msgpack
@@ -0,0 +1 @@
+¡a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor
new file mode 100644
index 0000000..6a7b9cf
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.cbor
@@ -0,0 +1 @@
+õ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack
new file mode 100644
index 0000000..52b4164
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json.msgpack
@@ -0,0 +1 @@
+Ã
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor
new file mode 100644
index 0000000..5416677
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.cbor
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack
new file mode 100644
index 0000000..9e99dd5
--- /dev/null
+++ b/test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json.msgpack
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/regression/floats.json.cbor b/test/data/regression/floats.json.cbor
new file mode 100644
index 0000000..9fe6a82
--- /dev/null
+++ b/test/data/regression/floats.json.cbor
Binary files differ
diff --git a/test/data/regression/floats.json.msgpack b/test/data/regression/floats.json.msgpack
new file mode 100644
index 0000000..e54198c
--- /dev/null
+++ b/test/data/regression/floats.json.msgpack
Binary files differ
diff --git a/test/data/regression/signed_ints.json.cbor b/test/data/regression/signed_ints.json.cbor
new file mode 100644
index 0000000..2124691
--- /dev/null
+++ b/test/data/regression/signed_ints.json.cbor
Binary files differ
diff --git a/test/data/regression/signed_ints.json.msgpack b/test/data/regression/signed_ints.json.msgpack
new file mode 100644
index 0000000..d1daa46
--- /dev/null
+++ b/test/data/regression/signed_ints.json.msgpack
Binary files differ
diff --git a/test/data/regression/unsigned_ints.json.cbor b/test/data/regression/unsigned_ints.json.cbor
new file mode 100644
index 0000000..63b7f93
--- /dev/null
+++ b/test/data/regression/unsigned_ints.json.cbor
Binary files differ
diff --git a/test/data/regression/unsigned_ints.json.msgpack b/test/data/regression/unsigned_ints.json.msgpack
new file mode 100644
index 0000000..c995381
--- /dev/null
+++ b/test/data/regression/unsigned_ints.json.msgpack
Binary files differ
diff --git a/test/data/regression/working_file.json.cbor b/test/data/regression/working_file.json.cbor
new file mode 100644
index 0000000..db5befa
--- /dev/null
+++ b/test/data/regression/working_file.json.cbor
@@ -0,0 +1 @@
+©jFullScreenõcFOVZpAmbientOcclusionônRenderDistancejWindowResXjWindowResY8kMipmapLeveleVSyncõtAnisotropicFiltering
\ No newline at end of file
diff --git a/test/data/regression/working_file.json.msgpack b/test/data/regression/working_file.json.msgpack
new file mode 100644
index 0000000..3abaa15
--- /dev/null
+++ b/test/data/regression/working_file.json.msgpack
@@ -0,0 +1 @@
+ªFullScreenãFOVZ°AmbientOcclusion®RenderDistanceªWindowResXͪWindowResYÍ8«MipmapLevel¥VSyncôAnisotropicFiltering
\ No newline at end of file
diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp
index 880dc1c..ef403ea 100644
--- a/test/src/fuzz.cpp
+++ b/test/src/fuzz.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Run "make fuzz_testing" and follow the instructions.
diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp
index 5197f80..31be655 100644
--- a/test/src/unit-algorithms.cpp
+++ b/test/src/unit-algorithms.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp
index f6cecc8..25fd334 100644
--- a/test/src/unit-allocator.cpp
+++ b/test/src/unit-allocator.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp
index 97c19cf..7fc3d49 100644
--- a/test/src/unit-capacity.cpp
+++ b/test/src/unit-capacity.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
new file mode 100644
index 0000000..14944cf
--- /dev/null
+++ b/test/src/unit-cbor.cpp
@@ -0,0 +1,1548 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++ (test suite)
+| | |__ | | | | | | version 2.0.9
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+Copyright (c) 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:
+
+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 "catch.hpp"
+
+#include "json.hpp"
+using nlohmann::json;
+
+#include <fstream>
+
+TEST_CASE("CBOR")
+{
+ SECTION("individual values")
+ {
+ SECTION("discarded")
+ {
+ // discarded values are not serialized
+ json j = json::value_t::discarded;
+ const auto result = json::to_cbor(j);
+ CHECK(result.empty());
+ }
+
+ SECTION("null")
+ {
+ json j = nullptr;
+ std::vector<uint8_t> expected = {0xf6};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("boolean")
+ {
+ SECTION("true")
+ {
+ json j = true;
+ std::vector<uint8_t> expected = {0xf5};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("false")
+ {
+ json j = false;
+ std::vector<uint8_t> expected = {0xf4};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("number")
+ {
+ SECTION("signed")
+ {
+ SECTION("-9223372036854775808..-4294967297")
+ {
+ std::vector<int64_t> numbers;
+ numbers.push_back(INT64_MIN);
+ numbers.push_back(-1000000000000000000);
+ numbers.push_back(-100000000000000000);
+ numbers.push_back(-10000000000000000);
+ numbers.push_back(-1000000000000000);
+ numbers.push_back(-100000000000000);
+ numbers.push_back(-10000000000000);
+ numbers.push_back(-1000000000000);
+ numbers.push_back(-100000000000);
+ numbers.push_back(-10000000000);
+ numbers.push_back(-4294967297);
+ for (auto i : numbers)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x3b));
+ uint64_t positive = static_cast<uint64_t>(-1 - i);
+ expected.push_back(static_cast<uint8_t>((positive >> 56) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 48) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 40) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 32) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0x3b);
+ uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+ (static_cast<uint64_t>(result[2]) << 060) +
+ (static_cast<uint64_t>(result[3]) << 050) +
+ (static_cast<uint64_t>(result[4]) << 040) +
+ (static_cast<uint64_t>(result[5]) << 030) +
+ (static_cast<uint64_t>(result[6]) << 020) +
+ (static_cast<uint64_t>(result[7]) << 010) +
+ static_cast<uint64_t>(result[8]));
+ CHECK(restored == positive);
+ CHECK(-1 - static_cast<int64_t>(restored) == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("-4294967296..-65537")
+ {
+ std::vector<int64_t> numbers;
+ numbers.push_back(-65537);
+ numbers.push_back(-100000);
+ numbers.push_back(-1000000);
+ numbers.push_back(-10000000);
+ numbers.push_back(-100000000);
+ numbers.push_back(-1000000000);
+ numbers.push_back(-4294967296);
+ for (auto i : numbers)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x3a));
+ uint32_t positive = static_cast<uint32_t>(static_cast<uint64_t>(-1 - i) & 0x00000000ffffffff);
+ expected.push_back(static_cast<uint8_t>((positive >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0x3a);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == positive);
+ CHECK(-1ll - restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("-65536..-257")
+ {
+ for (int32_t i = -65536; i <= -257; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x39));
+ uint16_t positive = static_cast<uint16_t>(-1 - i);
+ expected.push_back(static_cast<uint8_t>((positive >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(positive & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0x39);
+ uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+ CHECK(restored == positive);
+ CHECK(-1 - restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("-9263 (int 16)")
+ {
+ json j = -9263;
+ std::vector<uint8_t> expected = {0x39, 0x24, 0x2e};
+
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ int16_t restored = -1 - ((result[1] << 8) + result[2]);
+ CHECK(restored == -9263);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("-256..-24")
+ {
+ for (auto i = -256; i < -24; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x38);
+ expected.push_back(static_cast<uint8_t>(-1 - i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0x38);
+ CHECK(static_cast<int16_t>(-1 - result[1]) == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("-24..-1")
+ {
+ for (auto i = -24; i <= -1; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x20 - 1 - static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(static_cast<int8_t>(0x20 - 1 - result[0]) == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("0..23")
+ {
+ for (size_t i = 0; i <= 23; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(result[0] == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("24..255")
+ {
+ for (size_t i = 24; i <= 255; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x18));
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0x18);
+ CHECK(result[1] == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("256..65535")
+ {
+ for (size_t i = 256; i <= 65535; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x19));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0x19);
+ uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("65536..4294967295")
+ {
+ for (uint32_t i :
+ {
+ 65536u, 77777u, 1048576u
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x1a);
+ expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0x1a);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("4294967296..4611686018427387903")
+ {
+ for (uint64_t i :
+ {
+ 4294967296ul, 4611686018427387903ul
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x1b);
+ expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0x1b);
+ uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+ (static_cast<uint64_t>(result[2]) << 060) +
+ (static_cast<uint64_t>(result[3]) << 050) +
+ (static_cast<uint64_t>(result[4]) << 040) +
+ (static_cast<uint64_t>(result[5]) << 030) +
+ (static_cast<uint64_t>(result[6]) << 020) +
+ (static_cast<uint64_t>(result[7]) << 010) +
+ static_cast<uint64_t>(result[8]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ /*
+ SECTION("-32768..-129 (int 16)")
+ {
+ for (int16_t i = -32768; i <= -129; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd1);
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0xd1);
+ int16_t restored = (result[1] << 8) + result[2];
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ */
+ }
+
+ SECTION("unsigned")
+ {
+ SECTION("0..23 (Integer)")
+ {
+ for (size_t i = 0; i <= 23; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(result[0] == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("24..255 (one-byte uint8_t)")
+ {
+ for (size_t i = 24; i <= 255; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x18);
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0x18);
+ uint8_t restored = static_cast<uint8_t>(result[1]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("256..65535 (two-byte uint16_t)")
+ {
+ for (size_t i = 256; i <= 65535; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x19);
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0x19);
+ uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("65536..4294967295 (four-byte uint32_t)")
+ {
+ for (uint32_t i :
+ {
+ 65536u, 77777u, 1048576u
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x1a);
+ expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0x1a);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("4294967296..4611686018427387903 (eight-byte uint64_t)")
+ {
+ for (uint64_t i :
+ {
+ 4294967296ul, 4611686018427387903ul
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x1b);
+ expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0x1b);
+ uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+ (static_cast<uint64_t>(result[2]) << 060) +
+ (static_cast<uint64_t>(result[3]) << 050) +
+ (static_cast<uint64_t>(result[4]) << 040) +
+ (static_cast<uint64_t>(result[5]) << 030) +
+ (static_cast<uint64_t>(result[6]) << 020) +
+ (static_cast<uint64_t>(result[7]) << 010) +
+ static_cast<uint64_t>(result[8]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+ }
+
+ SECTION("float")
+ {
+ SECTION("3.1415925")
+ {
+ double v = 3.1415925;
+ json j = v;
+ std::vector<uint8_t> expected =
+ {
+ 0xfb, 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
+ };
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // restore value (reverse array for endianess)
+ double restored;
+ std::reverse(expected.begin(), expected.end());
+ memcpy(&restored, expected.data(), sizeof(double));
+ CHECK(restored == v);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("half-precision float (edge cases)")
+ {
+ SECTION("infinity")
+ {
+ json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x00}));
+ CHECK(j == nullptr);
+ }
+
+ SECTION("NaN")
+ {
+ json j = json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c, 0x01}));
+ CHECK(j == nullptr);
+ }
+ }
+ }
+
+ SECTION("string")
+ {
+ SECTION("N = 0..23")
+ {
+ for (size_t N = 0; N <= 0x17; ++N)
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(0x60 + N));
+ for (size_t i = 0; i < N; ++i)
+ {
+ expected.push_back('x');
+ }
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 1);
+ // check that no null byte is appended
+ if (N > 0)
+ {
+ CHECK(result.back() != '\x00');
+ }
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("N = 24..255")
+ {
+ for (size_t N = 24; N <= 255; ++N)
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0x78);
+ expected.push_back(static_cast<uint8_t>(N));
+ for (size_t i = 0; i < N; ++i)
+ {
+ expected.push_back('x');
+ }
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 2);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("N = 256..65535")
+ {
+ for (size_t N :
+ {
+ 256u, 999u, 1025u, 3333u, 2048u, 65535u
+ })
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector (hack: create string first)
+ std::vector<uint8_t> expected(N, 'x');
+ // reverse order of commands, because we insert at begin()
+ expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+ expected.insert(expected.begin(), 0x79);
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 3);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+
+ SECTION("N = 65536..4294967295")
+ {
+ for (size_t N :
+ {
+ 65536u, 77777u, 1048576u
+ })
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector (hack: create string first)
+ std::vector<uint8_t> expected(N, 'x');
+ // reverse order of commands, because we insert at begin()
+ expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
+ expected.insert(expected.begin(), 0x7a);
+
+ // compare result + size
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 5);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+ }
+
+ SECTION("array")
+ {
+ SECTION("empty")
+ {
+ json j = json::array();
+ std::vector<uint8_t> expected = {0x80};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("[null]")
+ {
+ json j = {nullptr};
+ std::vector<uint8_t> expected = {0x81, 0xf6};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("[1,2,3,4,5]")
+ {
+ json j = json::parse("[1,2,3,4,5]");
+ std::vector<uint8_t> expected = {0x85, 0x01, 0x02, 0x03, 0x04, 0x05};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("[[[[]]]]")
+ {
+ json j = json::parse("[[[[]]]]");
+ std::vector<uint8_t> expected = {0x81, 0x81, 0x81, 0x80};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("array with uint16_t elements")
+ {
+ json j(257, nullptr);
+ std::vector<uint8_t> expected(j.size() + 3, 0xf6); // all null
+ expected[0] = 0x99; // array 16 bit
+ expected[1] = 0x01; // size (0x0101), byte 0
+ expected[2] = 0x01; // size (0x0101), byte 1
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("array with uint32_t elements")
+ {
+ json j(65793, nullptr);
+ std::vector<uint8_t> expected(j.size() + 5, 0xf6); // all null
+ expected[0] = 0x9a; // array 32 bit
+ expected[1] = 0x00; // size (0x00010101), byte 0
+ expected[2] = 0x01; // size (0x00010101), byte 1
+ expected[3] = 0x01; // size (0x00010101), byte 2
+ expected[4] = 0x01; // size (0x00010101), byte 3
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ /*
+ SECTION("array with uint64_t elements")
+ {
+ json j(4294967296, nullptr);
+ std::vector<uint8_t> expected(j.size() + 9, 0xf6); // all null
+ expected[0] = 0x9b; // array 64 bit
+ expected[1] = 0x00; // size (0x0000000100000000), byte 0
+ expected[2] = 0x00; // size (0x0000000100000000), byte 1
+ expected[3] = 0x00; // size (0x0000000100000000), byte 2
+ expected[4] = 0x01; // size (0x0000000100000000), byte 3
+ expected[5] = 0x00; // size (0x0000000100000000), byte 4
+ expected[6] = 0x00; // size (0x0000000100000000), byte 5
+ expected[7] = 0x00; // size (0x0000000100000000), byte 6
+ expected[8] = 0x00; // size (0x0000000100000000), byte 7
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ */
+ }
+
+ SECTION("object")
+ {
+ SECTION("empty")
+ {
+ json j = json::object();
+ std::vector<uint8_t> expected = {0xa0};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("{\"\":null}")
+ {
+ json j = {{"", nullptr}};
+ std::vector<uint8_t> expected = {0xa1, 0x60, 0xf6};
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
+ {
+ json j = json::parse("{\"a\": {\"b\": {\"c\": {}}}}");
+ std::vector<uint8_t> expected =
+ {
+ 0xa1, 0x61, 0x61, 0xa1, 0x61, 0x62, 0xa1, 0x61, 0x63, 0xa0
+ };
+ const auto result = json::to_cbor(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("object with uint8_t elements")
+ {
+ json j;
+ for (auto i = 0; i < 255; ++i)
+ {
+ // format i to a fixed width of 5
+ // each entry will need 7 bytes: 6 for string, 1 for null
+ std::stringstream ss;
+ ss << std::setw(5) << std::setfill('0') << i;
+ j.emplace(ss.str(), nullptr);
+ }
+
+ const auto result = json::to_cbor(j);
+
+ // Checking against an expected vector byte by byte is
+ // difficult, because no assumption on the order of key/value
+ // pairs are made. We therefore only check the prefix (type and
+ // size and the overall size. The rest is then handled in the
+ // roundtrip check.
+ CHECK(result.size() == 1787); // 1 type, 1 size, 255*7 content
+ CHECK(result[0] == 0xb8); // map 8 bit
+ CHECK(result[1] == 0xff); // size byte (0xff)
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("object with uint16_t elements")
+ {
+ json j;
+ for (auto i = 0; i < 256; ++i)
+ {
+ // format i to a fixed width of 5
+ // each entry will need 7 bytes: 6 for string, 1 for null
+ std::stringstream ss;
+ ss << std::setw(5) << std::setfill('0') << i;
+ j.emplace(ss.str(), nullptr);
+ }
+
+ const auto result = json::to_cbor(j);
+
+ // Checking against an expected vector byte by byte is
+ // difficult, because no assumption on the order of key/value
+ // pairs are made. We therefore only check the prefix (type and
+ // size and the overall size. The rest is then handled in the
+ // roundtrip check.
+ CHECK(result.size() == 1795); // 1 type, 2 size, 256*7 content
+ CHECK(result[0] == 0xb9); // map 16 bit
+ CHECK(result[1] == 0x01); // byte 0 of size (0x0100)
+ CHECK(result[2] == 0x00); // byte 1 of size (0x0100)
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+
+ SECTION("object with uint32_t elements")
+ {
+ json j;
+ for (auto i = 0; i < 65536; ++i)
+ {
+ // format i to a fixed width of 5
+ // each entry will need 7 bytes: 6 for string, 1 for null
+ std::stringstream ss;
+ ss << std::setw(5) << std::setfill('0') << i;
+ j.emplace(ss.str(), nullptr);
+ }
+
+ const auto result = json::to_cbor(j);
+
+ // Checking against an expected vector byte by byte is
+ // difficult, because no assumption on the order of key/value
+ // pairs are made. We therefore only check the prefix (type and
+ // size and the overall size. The rest is then handled in the
+ // roundtrip check.
+ CHECK(result.size() == 458757); // 1 type, 4 size, 65536*7 content
+ CHECK(result[0] == 0xba); // map 32 bit
+ CHECK(result[1] == 0x00); // byte 0 of size (0x00010000)
+ CHECK(result[2] == 0x01); // byte 1 of size (0x00010000)
+ CHECK(result[3] == 0x00); // byte 2 of size (0x00010000)
+ CHECK(result[4] == 0x00); // byte 3 of size (0x00010000)
+
+ // roundtrip
+ CHECK(json::from_cbor(result) == j);
+ }
+ }
+ }
+
+ SECTION("additonal deserialization")
+ {
+ SECTION("0x7b (string)")
+ {
+ std::vector<uint8_t> given = {0x7b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x61
+ };
+ json j = json::from_cbor(given);
+ CHECK(j == "a");
+ }
+
+ SECTION("0x9b (array)")
+ {
+ std::vector<uint8_t> given = {0x9b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0xf4
+ };
+ json j = json::from_cbor(given);
+ CHECK(j == json::parse("[false]"));
+ }
+
+ SECTION("0xbb (map)")
+ {
+ std::vector<uint8_t> given = {0xbb, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x60, 0xf4
+ };
+ json j = json::from_cbor(given);
+ CHECK(j == json::parse("{\"\": false}"));
+ }
+ }
+
+ SECTION("errors")
+ {
+ SECTION("too short byte vector")
+ {
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x18})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x19, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), std::out_of_range);
+ }
+ }
+}
+
+// use this testcase outside [hide] to run it with Valgrind
+TEST_CASE("single CBOR roundtrip")
+{
+ SECTION("sample.json")
+ {
+ std::string filename = "test/data/json_testsuite/sample.json";
+
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
+ // parse MessagePack file
+ std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+ std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_cbor)),
+ std::istreambuf_iterator<char>());
+ json j2;
+ CHECK_NOTHROW(j2 = json::from_cbor(packed));
+
+ // compare parsed JSON values
+ CHECK(j1 == j2);
+ }
+}
+
+TEST_CASE("CBOR roundtrips", "[hide]")
+{
+ SECTION("input from flynn")
+ {
+ for (std::string filename :
+ {
+ "test/data/json_nlohmann_tests/all_unicode.json",
+ "test/data/json.org/1.json",
+ "test/data/json.org/2.json",
+ "test/data/json.org/3.json",
+ "test/data/json.org/4.json",
+ "test/data/json.org/5.json",
+ "test/data/json_roundtrip/roundtrip01.json",
+ "test/data/json_roundtrip/roundtrip02.json",
+ "test/data/json_roundtrip/roundtrip03.json",
+ "test/data/json_roundtrip/roundtrip04.json",
+ "test/data/json_roundtrip/roundtrip05.json",
+ "test/data/json_roundtrip/roundtrip06.json",
+ "test/data/json_roundtrip/roundtrip07.json",
+ "test/data/json_roundtrip/roundtrip08.json",
+ "test/data/json_roundtrip/roundtrip09.json",
+ "test/data/json_roundtrip/roundtrip10.json",
+ "test/data/json_roundtrip/roundtrip11.json",
+ "test/data/json_roundtrip/roundtrip12.json",
+ "test/data/json_roundtrip/roundtrip13.json",
+ "test/data/json_roundtrip/roundtrip14.json",
+ "test/data/json_roundtrip/roundtrip15.json",
+ "test/data/json_roundtrip/roundtrip16.json",
+ "test/data/json_roundtrip/roundtrip17.json",
+ "test/data/json_roundtrip/roundtrip18.json",
+ "test/data/json_roundtrip/roundtrip19.json",
+ "test/data/json_roundtrip/roundtrip20.json",
+ "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/roundtrip29.json",
+ "test/data/json_roundtrip/roundtrip30.json",
+ "test/data/json_roundtrip/roundtrip31.json",
+ "test/data/json_roundtrip/roundtrip32.json",
+ "test/data/json_testsuite/sample.json", // kills AppVeyor
+ "test/data/json_tests/pass1.json",
+ "test/data/json_tests/pass2.json",
+ "test/data/json_tests/pass3.json",
+ "test/data/regression/floats.json",
+ "test/data/regression/signed_ints.json",
+ "test/data/regression/unsigned_ints.json",
+ "test/data/regression/working_file.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_false.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_0e1.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_after_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_pos_int.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_very_big_negative_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_basic.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_simple.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_comments.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_in_array.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_pi.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json",
+ // "test/data/nst_json_testsuite/test_parsing/y_string_utf16.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_utf8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json"
+ })
+ {
+ CAPTURE(filename);
+
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
+ // parse CBOR file
+ std::ifstream f_cbor(filename + ".cbor", std::ios::binary);
+ std::vector<uint8_t> packed(
+ (std::istreambuf_iterator<char>(f_cbor)),
+ std::istreambuf_iterator<char>());
+ json j2;
+ CHECK_NOTHROW(j2 = json::from_cbor(packed));
+
+ // compare parsed JSON values
+ CHECK(j1 == j2);
+ }
+ }
+}
+
+TEST_CASE("examples from RFC 7049 Appendix A")
+{
+ SECTION("numbers")
+ {
+ CHECK(json::to_cbor(json::parse("0")) == std::vector<uint8_t>({0x00}));
+ CHECK(json::parse("0") == json::from_cbor(std::vector<uint8_t>({0x00})));
+
+ CHECK(json::to_cbor(json::parse("1")) == std::vector<uint8_t>({0x01}));
+ CHECK(json::parse("1") == json::from_cbor(std::vector<uint8_t>({0x01})));
+
+ CHECK(json::to_cbor(json::parse("10")) == std::vector<uint8_t>({0x0a}));
+ CHECK(json::parse("10") == json::from_cbor(std::vector<uint8_t>({0x0a})));
+
+ CHECK(json::to_cbor(json::parse("23")) == std::vector<uint8_t>({0x17}));
+ CHECK(json::parse("23") == json::from_cbor(std::vector<uint8_t>({0x17})));
+
+ CHECK(json::to_cbor(json::parse("24")) == std::vector<uint8_t>({0x18, 0x18}));
+ CHECK(json::parse("24") == json::from_cbor(std::vector<uint8_t>({0x18, 0x18})));
+
+ CHECK(json::to_cbor(json::parse("25")) == std::vector<uint8_t>({0x18, 0x19}));
+ CHECK(json::parse("25") == json::from_cbor(std::vector<uint8_t>({0x18, 0x19})));
+
+ CHECK(json::to_cbor(json::parse("100")) == std::vector<uint8_t>({0x18, 0x64}));
+ CHECK(json::parse("100") == json::from_cbor(std::vector<uint8_t>({0x18, 0x64})));
+
+ CHECK(json::to_cbor(json::parse("1000")) == std::vector<uint8_t>({0x19, 0x03, 0xe8}));
+ CHECK(json::parse("1000") == json::from_cbor(std::vector<uint8_t>({0x19, 0x03, 0xe8})));
+
+ CHECK(json::to_cbor(json::parse("1000000")) == std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40}));
+ CHECK(json::parse("1000000") == json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x0f, 0x42, 0x40})));
+
+ CHECK(json::to_cbor(json::parse("1000000000000")) == std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00}));
+ CHECK(json::parse("1000000000000") == json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0xe8, 0xd4, 0xa5, 0x10, 0x00})));
+
+ CHECK(json::to_cbor(json::parse("18446744073709551615")) == std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
+ CHECK(json::parse("18446744073709551615") == json::from_cbor(std::vector<uint8_t>({0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
+
+ // positive bignum is not supported
+ //CHECK(json::to_cbor(json::parse("18446744073709551616")) == std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
+ //CHECK(json::parse("18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0xc2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
+
+ //CHECK(json::to_cbor(json::parse("-18446744073709551616")) == std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}));
+ //CHECK(json::parse("-18446744073709551616") == json::from_cbor(std::vector<uint8_t>({0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})));
+
+ // negative bignum is not supported
+ //CHECK(json::to_cbor(json::parse("-18446744073709551617")) == std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
+ //CHECK(json::parse("-18446744073709551617") == json::from_cbor(std::vector<uint8_t>({0xc3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})));
+
+ CHECK(json::to_cbor(json::parse("-1")) == std::vector<uint8_t>({0x20}));
+ CHECK(json::parse("-1") == json::from_cbor(std::vector<uint8_t>({0x20})));
+
+ CHECK(json::to_cbor(json::parse("-10")) == std::vector<uint8_t>({0x29}));
+ CHECK(json::parse("-10") == json::from_cbor(std::vector<uint8_t>({0x29})));
+
+ CHECK(json::to_cbor(json::parse("-100")) == std::vector<uint8_t>({0x38, 0x63}));
+ CHECK(json::parse("-100") == json::from_cbor(std::vector<uint8_t>({0x38, 0x63})));
+
+ CHECK(json::to_cbor(json::parse("-1000")) == std::vector<uint8_t>({0x39, 0x03, 0xe7}));
+ CHECK(json::parse("-1000") == json::from_cbor(std::vector<uint8_t>({0x39, 0x03, 0xe7})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("0.0")) == std::vector<uint8_t>({0xf9, 0x00, 0x00}));
+ CHECK(json::parse("0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("-0.0")) == std::vector<uint8_t>({0xf9, 0x80, 0x00}));
+ CHECK(json::parse("-0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("1.0")) == std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
+ CHECK(json::parse("1.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00})));
+
+ CHECK(json::to_cbor(json::parse("1.1")) == std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a}));
+ CHECK(json::parse("1.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("1.5")) == std::vector<uint8_t>({0xf9, 0x3e, 0x00}));
+ CHECK(json::parse("1.5") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3e, 0x00})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("65504.0")) == std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
+ CHECK(json::parse("65504.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff})));
+
+ //CHECK(json::to_cbor(json::parse("100000.0")) == std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00}));
+ CHECK(json::parse("100000.0") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00})));
+
+ //CHECK(json::to_cbor(json::parse("3.4028234663852886e+38")) == std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff}));
+ CHECK(json::parse("3.4028234663852886e+38") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x7f, 0x7f, 0xff, 0xff})));
+
+ CHECK(json::to_cbor(json::parse("1.0e+300")) == std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c}));
+ CHECK(json::parse("1.0e+300") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("5.960464477539063e-8")) == std::vector<uint8_t>({0xf9, 0x00, 0x01}));
+ CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("0.00006103515625")) == std::vector<uint8_t>({0xf9, 0x04, 0x00}));
+ CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+ // half-precision float
+ //CHECK(json::to_cbor(json::parse("-4.0")) == std::vector<uint8_t>({0xf9, 0xc4, 0x00}));
+ CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
+
+ CHECK(json::to_cbor(json::parse("-4.1")) == std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}));
+ CHECK(json::parse("-4.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})));
+ }
+
+ SECTION("simple values")
+ {
+ CHECK(json::to_cbor(json::parse("false")) == std::vector<uint8_t>({0xf4}));
+ CHECK(json::parse("false") == json::from_cbor(std::vector<uint8_t>({0xf4})));
+
+ CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
+ CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
+
+ CHECK(json::to_cbor(json::parse("true")) == std::vector<uint8_t>({0xf5}));
+ CHECK(json::parse("true") == json::from_cbor(std::vector<uint8_t>({0xf5})));
+ }
+
+ SECTION("strings")
+ {
+ CHECK(json::to_cbor(json::parse("\"\"")) == std::vector<uint8_t>({0x60}));
+ CHECK(json::parse("\"\"") == json::from_cbor(std::vector<uint8_t>({0x60})));
+
+ CHECK(json::to_cbor(json::parse("\"a\"")) == std::vector<uint8_t>({0x61, 0x61}));
+ CHECK(json::parse("\"a\"") == json::from_cbor(std::vector<uint8_t>({0x61, 0x61})));
+
+ CHECK(json::to_cbor(json::parse("\"IETF\"")) == std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46}));
+ CHECK(json::parse("\"IETF\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0x49, 0x45, 0x54, 0x46})));
+
+ CHECK(json::to_cbor(json::parse("\"\\u00fc\"")) == std::vector<uint8_t>({0x62, 0xc3, 0xbc}));
+ CHECK(json::parse("\"\\u00fc\"") == json::from_cbor(std::vector<uint8_t>({0x62, 0xc3, 0xbc})));
+
+ CHECK(json::to_cbor(json::parse("\"\\u6c34\"")) == std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4}));
+ CHECK(json::parse("\"\\u6c34\"") == json::from_cbor(std::vector<uint8_t>({0x63, 0xe6, 0xb0, 0xb4})));
+
+ CHECK(json::to_cbor(json::parse("\"\\ud800\\udd51\"")) == std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91}));
+ CHECK(json::parse("\"\\ud800\\udd51\"") == json::from_cbor(std::vector<uint8_t>({0x64, 0xf0, 0x90, 0x85, 0x91})));
+
+ // indefinite length strings
+ CHECK(json::parse("\"streaming\"") == json::from_cbor(std::vector<uint8_t>({0x7f, 0x65, 0x73, 0x74, 0x72, 0x65, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x67, 0xff})));
+ }
+
+ SECTION("arrays")
+ {
+ CHECK(json::to_cbor(json::parse("[]")) == std::vector<uint8_t>({0x80}));
+ CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x80})));
+
+ CHECK(json::to_cbor(json::parse("[1, 2, 3]")) == std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03}));
+ CHECK(json::parse("[1, 2, 3]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x02, 0x03})));
+
+ CHECK(json::to_cbor(json::parse("[1, [2, 3], [4, 5]]")) == std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05}));
+ CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05})));
+
+ CHECK(json::to_cbor(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]")) == std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19}));
+ CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19})));
+
+ // indefinite length arrays
+ CHECK(json::parse("[]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0xff})));
+ CHECK(json::parse("[1, [2, 3], [4, 5]] ") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff, 0xff})));
+ CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x82, 0x02, 0x03, 0x82, 0x04, 0x05, 0xff})));
+ CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x82, 0x02, 0x03, 0x9f, 0x04, 0x05, 0xff})));
+ CHECK(json::parse("[1, [2, 3], [4, 5]]") == json::from_cbor(std::vector<uint8_t>({0x83, 0x01, 0x9f, 0x02, 0x03, 0xff, 0x82, 0x04, 0x05})));
+ CHECK(json::parse("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]") == json::from_cbor(std::vector<uint8_t>({0x9f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, 0xff})));
+ }
+
+ SECTION("objects")
+ {
+ CHECK(json::to_cbor(json::parse("{}")) == std::vector<uint8_t>({0xa0}));
+ CHECK(json::parse("{}") == json::from_cbor(std::vector<uint8_t>({0xa0})));
+
+ CHECK(json::to_cbor(json::parse("{\"a\": 1, \"b\": [2, 3]}")) == std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03}));
+ CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xa2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03})));
+
+ CHECK(json::to_cbor(json::parse("[\"a\", {\"b\": \"c\"}]")) == std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63}));
+ CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xa1, 0x61, 0x62, 0x61, 0x63})));
+
+ CHECK(json::to_cbor(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}")) == std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45}));
+ CHECK(json::parse("{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\", \"d\": \"D\", \"e\": \"E\"}") == json::from_cbor(std::vector<uint8_t>({0xa5, 0x61, 0x61, 0x61, 0x41, 0x61, 0x62, 0x61, 0x42, 0x61, 0x63, 0x61, 0x43, 0x61, 0x64, 0x61, 0x44, 0x61, 0x65, 0x61, 0x45})));
+
+ // indefinite length objects
+ CHECK(json::parse("{\"a\": 1, \"b\": [2, 3]}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x61, 0x61, 0x01, 0x61, 0x62, 0x9f, 0x02, 0x03, 0xff, 0xff})));
+ CHECK(json::parse("[\"a\", {\"b\": \"c\"}]") == json::from_cbor(std::vector<uint8_t>({0x82, 0x61, 0x61, 0xbf, 0x61, 0x62, 0x61, 0x63, 0xff})));
+ CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
+ }
+}
diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp
index 2ef6244..2970b86 100644
--- a/test/src/unit-class_const_iterator.cpp
+++ b/test/src/unit-class_const_iterator.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp
index 3d82fce..14c6828 100644
--- a/test/src/unit-class_iterator.cpp
+++ b/test/src/unit-class_iterator.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp
index 22a04b0..6dec3f8 100644
--- a/test/src/unit-class_lexer.cpp
+++ b/test/src/unit-class_lexer.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp
index dad6b1e..7bf23d5 100644
--- a/test/src/unit-class_parser.cpp
+++ b/test/src/unit-class_parser.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp
index 582146a..73c31ab 100644
--- a/test/src/unit-comparison.cpp
+++ b/test/src/unit-comparison.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp
index 002ccdf..dea6b51 100644
--- a/test/src/unit-concepts.cpp
+++ b/test/src/unit-concepts.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp
index 6804a3a..23c0db3 100644
--- a/test/src/unit-constructor1.cpp
+++ b/test/src/unit-constructor1.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp
index 1edad6a..0bbd13c 100644
--- a/test/src/unit-constructor2.cpp
+++ b/test/src/unit-constructor2.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp
index 8791caf..94341be 100644
--- a/test/src/unit-convenience.cpp
+++ b/test/src/unit-convenience.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp
index 1c49a93..72c3bf6 100644
--- a/test/src/unit-conversions.cpp
+++ b/test/src/unit-conversions.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 969a775..605c596 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp
index d3b9ed4..0a1715e 100644
--- a/test/src/unit-element_access1.cpp
+++ b/test/src/unit-element_access1.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp
index ed1348f..29be17a 100644
--- a/test/src/unit-element_access2.cpp
+++ b/test/src/unit-element_access2.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp
index d373c10..1660c71 100644
--- a/test/src/unit-inspection.cpp
+++ b/test/src/unit-inspection.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterator_wrapper.cpp b/test/src/unit-iterator_wrapper.cpp
index af1fa08..96928eb 100644
--- a/test/src/unit-iterator_wrapper.cpp
+++ b/test/src/unit-iterator_wrapper.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp
index d51c454..60f7c2f 100644
--- a/test/src/unit-iterators1.cpp
+++ b/test/src/unit-iterators1.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp
index f231c8e..da0fc93 100644
--- a/test/src/unit-iterators2.cpp
+++ b/test/src/unit-iterators2.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp
index 9a40ce7..880bc46 100644
--- a/test/src/unit-json_patch.cpp
+++ b/test/src/unit-json_patch.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index 35558d2..91d003a 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp
index 08a6dd3..02ffa6a 100644
--- a/test/src/unit-modifiers.cpp
+++ b/test/src/unit-modifiers.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp
new file mode 100644
index 0000000..46997e2
--- /dev/null
+++ b/test/src/unit-msgpack.cpp
@@ -0,0 +1,1216 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++ (test suite)
+| | |__ | | | | | | version 2.0.9
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+Copyright (c) 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:
+
+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 "catch.hpp"
+
+#include "json.hpp"
+using nlohmann::json;
+
+#include <fstream>
+
+TEST_CASE("MessagePack")
+{
+ SECTION("individual values")
+ {
+ SECTION("discarded")
+ {
+ // discarded values are not serialized
+ json j = json::value_t::discarded;
+ const auto result = json::to_msgpack(j);
+ CHECK(result.empty());
+ }
+
+ SECTION("null")
+ {
+ json j = nullptr;
+ std::vector<uint8_t> expected = {0xc0};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("boolean")
+ {
+ SECTION("true")
+ {
+ json j = true;
+ std::vector<uint8_t> expected = {0xc3};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("false")
+ {
+ json j = false;
+ std::vector<uint8_t> expected = {0xc2};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("number")
+ {
+ SECTION("signed")
+ {
+ SECTION("-32..-1 (negative fixnum)")
+ {
+ for (auto i = -32; i <= -1; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(static_cast<int8_t>(result[0]) == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("0..127 (positive fixnum)")
+ {
+ for (size_t i = 0; i <= 127; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(result[0] == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("128..255 (int 8)")
+ {
+ for (size_t i = 128; i <= 255; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcc);
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcc);
+ uint8_t restored = static_cast<uint8_t>(result[1]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("256..65535 (int 16)")
+ {
+ for (size_t i = 256; i <= 65535; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcd);
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcd);
+ uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("65536..4294967295 (int 32)")
+ {
+ for (uint32_t i :
+ {
+ 65536u, 77777u, 1048576u, 4294967295u
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xce);
+ expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0xce);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("4294967296..9223372036854775807 (int 64)")
+ {
+ for (uint64_t i :
+ {
+ 4294967296lu, 9223372036854775807lu
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = -1;
+ j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcf);
+ expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcf);
+ uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+ (static_cast<uint64_t>(result[2]) << 060) +
+ (static_cast<uint64_t>(result[3]) << 050) +
+ (static_cast<uint64_t>(result[4]) << 040) +
+ (static_cast<uint64_t>(result[5]) << 030) +
+ (static_cast<uint64_t>(result[6]) << 020) +
+ (static_cast<uint64_t>(result[7]) << 010) +
+ static_cast<uint64_t>(result[8]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("-128..-33 (int 8)")
+ {
+ for (auto i = -128; i <= -33; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd0);
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0xd0);
+ CHECK(static_cast<int8_t>(result[1]) == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("-9263 (int 16)")
+ {
+ json j = -9263;
+ std::vector<uint8_t> expected = {0xd1, 0xdb, 0xd1};
+
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ int16_t restored = (result[1] << 8) + result[2];
+ CHECK(restored == -9263);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("-32768..-129 (int 16)")
+ {
+ for (int16_t i = -32768; i <= -129; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd1);
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0xd1);
+ int16_t restored = (result[1] << 8) + result[2];
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("-32769..-2147483648")
+ {
+ std::vector<int32_t> numbers;
+ numbers.push_back(-32769);
+ numbers.push_back(-65536);
+ numbers.push_back(-77777);
+ numbers.push_back(-1048576);
+ numbers.push_back(-2147483648);
+ for (auto i : numbers)
+ {
+ CAPTURE(i);
+
+ // create JSON value with integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd2);
+ expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0xd2);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("-9223372036854775808..-2147483649 (int 64)")
+ {
+ std::vector<int64_t> numbers;
+ numbers.push_back(INT64_MIN);
+ numbers.push_back(-2147483649ll);
+ for (auto i : numbers)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_integer());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd3);
+ expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0xd3);
+ int64_t restored = static_cast<int64_t>((static_cast<int64_t>(result[1]) << 070) +
+ (static_cast<int64_t>(result[2]) << 060) +
+ (static_cast<int64_t>(result[3]) << 050) +
+ (static_cast<int64_t>(result[4]) << 040) +
+ (static_cast<int64_t>(result[5]) << 030) +
+ (static_cast<int64_t>(result[6]) << 020) +
+ (static_cast<int64_t>(result[7]) << 010) +
+ static_cast<int64_t>(result[8]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ }
+
+ SECTION("unsigned")
+ {
+ SECTION("0..127 (positive fixnum)")
+ {
+ for (size_t i = 0; i <= 127; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 1);
+
+ // check individual bytes
+ CHECK(result[0] == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("128..255 (uint 8)")
+ {
+ for (size_t i = 128; i <= 255; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcc);
+ expected.push_back(static_cast<uint8_t>(i));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 2);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcc);
+ uint8_t restored = static_cast<uint8_t>(result[1]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("256..65535 (uint 16)")
+ {
+ for (size_t i = 256; i <= 65535; ++i)
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcd);
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 3);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcd);
+ uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("65536..4294967295 (uint 32)")
+ {
+ for (uint32_t i :
+ {
+ 65536u, 77777u, 1048576u, 4294967295u
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xce);
+ expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 5);
+
+ // check individual bytes
+ CHECK(result[0] == 0xce);
+ uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
+ (static_cast<uint32_t>(result[2]) << 020) +
+ (static_cast<uint32_t>(result[3]) << 010) +
+ static_cast<uint32_t>(result[4]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("4294967296..18446744073709551615 (uint 64)")
+ {
+ for (uint64_t i :
+ {
+ 4294967296lu, 18446744073709551615lu
+ })
+ {
+ CAPTURE(i);
+
+ // create JSON value with unsigned integer number
+ json j = i;
+
+ // check type
+ CHECK(j.is_number_unsigned());
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xcf);
+ expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
+ expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
+ expected.push_back(static_cast<uint8_t>(i & 0xff));
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == 9);
+
+ // check individual bytes
+ CHECK(result[0] == 0xcf);
+ uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
+ (static_cast<uint64_t>(result[2]) << 060) +
+ (static_cast<uint64_t>(result[3]) << 050) +
+ (static_cast<uint64_t>(result[4]) << 040) +
+ (static_cast<uint64_t>(result[5]) << 030) +
+ (static_cast<uint64_t>(result[6]) << 020) +
+ (static_cast<uint64_t>(result[7]) << 010) +
+ static_cast<uint64_t>(result[8]));
+ CHECK(restored == i);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ }
+
+ SECTION("float")
+ {
+ SECTION("3.1415925")
+ {
+ double v = 3.1415925;
+ json j = v;
+ std::vector<uint8_t> expected =
+ {
+ 0xcb, 0x40, 0x09, 0x21, 0xfb, 0x3f, 0xa6, 0xde, 0xfc
+ };
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // restore value (reverse array for endianess)
+ double restored;
+ std::reverse(expected.begin(), expected.end());
+ memcpy(&restored, expected.data(), sizeof(double));
+ CHECK(restored == v);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ }
+
+ SECTION("string")
+ {
+ SECTION("N = 0..31")
+ {
+ // explicitly enumerate the first byte for all 32 strings
+ const std::vector<uint8_t> first_bytes =
+ {
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+ 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1,
+ 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+ 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
+ };
+
+ for (size_t N = 0; N < first_bytes.size(); ++N)
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(first_bytes[N]);
+ for (size_t i = 0; i < N; ++i)
+ {
+ expected.push_back('x');
+ }
+
+ // check first byte
+ CHECK((first_bytes[N] & 0x1f) == N);
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 1);
+ // check that no null byte is appended
+ if (N > 0)
+ {
+ CHECK(result.back() != '\x00');
+ }
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("N = 32..255")
+ {
+ for (size_t N = 32; N <= 255; ++N)
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector
+ std::vector<uint8_t> expected;
+ expected.push_back(0xd9);
+ expected.push_back(static_cast<uint8_t>(N));
+ for (size_t i = 0; i < N; ++i)
+ {
+ expected.push_back('x');
+ }
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 2);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("N = 256..65535")
+ {
+ for (size_t N :
+ {
+ 256u, 999u, 1025u, 3333u, 2048u, 65535u
+ })
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector (hack: create string first)
+ std::vector<uint8_t> expected(N, 'x');
+ // reverse order of commands, because we insert at begin()
+ expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+ expected.insert(expected.begin(), 0xda);
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 3);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("N = 65536..4294967295")
+ {
+ for (size_t N :
+ {
+ 65536u, 77777u, 1048576u
+ })
+ {
+ CAPTURE(N);
+
+ // create JSON value with string containing of N * 'x'
+ const auto s = std::string(N, 'x');
+ json j = s;
+
+ // create expected byte vector (hack: create string first)
+ std::vector<uint8_t> expected(N, 'x');
+ // reverse order of commands, because we insert at begin()
+ expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff));
+ expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff));
+ expected.insert(expected.begin(), 0xdb);
+
+ // compare result + size
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+ CHECK(result.size() == N + 5);
+ // check that no null byte is appended
+ CHECK(result.back() != '\x00');
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ }
+
+ SECTION("array")
+ {
+ SECTION("empty")
+ {
+ json j = json::array();
+ std::vector<uint8_t> expected = {0x90};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("[null]")
+ {
+ json j = {nullptr};
+ std::vector<uint8_t> expected = {0x91, 0xc0};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("[1,2,3,4,5]")
+ {
+ json j = json::parse("[1,2,3,4,5]");
+ std::vector<uint8_t> expected = {0x95, 0x01, 0x02, 0x03, 0x04, 0x05};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("[[[[]]]]")
+ {
+ json j = json::parse("[[[[]]]]");
+ std::vector<uint8_t> expected = {0x91, 0x91, 0x91, 0x90};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("array 16")
+ {
+ json j(16, nullptr);
+ std::vector<uint8_t> expected(j.size() + 3, 0xc0); // all null
+ expected[0] = 0xdc; // array 16
+ expected[1] = 0x00; // size (0x0010), byte 0
+ expected[2] = 0x10; // size (0x0010), byte 1
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("array 32")
+ {
+ json j(65536, nullptr);
+ std::vector<uint8_t> expected(j.size() + 5, 0xc0); // all null
+ expected[0] = 0xdd; // array 32
+ expected[1] = 0x00; // size (0x00100000), byte 0
+ expected[2] = 0x01; // size (0x00100000), byte 1
+ expected[3] = 0x00; // size (0x00100000), byte 2
+ expected[4] = 0x00; // size (0x00100000), byte 3
+ const auto result = json::to_msgpack(j);
+ //CHECK(result == expected);
+
+ CHECK(result.size() == expected.size());
+ for (size_t i = 0; i < expected.size(); ++i)
+ {
+ CAPTURE(i);
+ CHECK(result[i] == expected[i]);
+ }
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+
+ SECTION("object")
+ {
+ SECTION("empty")
+ {
+ json j = json::object();
+ std::vector<uint8_t> expected = {0x80};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("{\"\":null}")
+ {
+ json j = {{"", nullptr}};
+ std::vector<uint8_t> expected = {0x81, 0xa0, 0xc0};
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
+ {
+ json j = json::parse("{\"a\": {\"b\": {\"c\": {}}}}");
+ std::vector<uint8_t> expected =
+ {
+ 0x81, 0xa1, 0x61, 0x81, 0xa1, 0x62, 0x81, 0xa1, 0x63, 0x80
+ };
+ const auto result = json::to_msgpack(j);
+ CHECK(result == expected);
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("map 16")
+ {
+ json j = R"({"00": null, "01": null, "02": null, "03": null,
+ "04": null, "05": null, "06": null, "07": null,
+ "08": null, "09": null, "10": null, "11": null,
+ "12": null, "13": null, "14": null, "15": null})"_json;
+
+ const auto result = json::to_msgpack(j);
+
+ // Checking against an expected vector byte by byte is
+ // difficult, because no assumption on the order of key/value
+ // pairs are made. We therefore only check the prefix (type and
+ // size and the overall size. The rest is then handled in the
+ // roundtrip check.
+ CHECK(result.size() == 67); // 1 type, 2 size, 16*4 content
+ CHECK(result[0] == 0xde); // map 16
+ CHECK(result[1] == 0x00); // byte 0 of size (0x0010)
+ CHECK(result[2] == 0x10); // byte 1 of size (0x0010)
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+
+ SECTION("map 32")
+ {
+ json j;
+ for (auto i = 0; i < 65536; ++i)
+ {
+ // format i to a fixed width of 5
+ // each entry will need 7 bytes: 6 for fixstr, 1 for null
+ std::stringstream ss;
+ ss << std::setw(5) << std::setfill('0') << i;
+ j.emplace(ss.str(), nullptr);
+ }
+
+ const auto result = json::to_msgpack(j);
+
+ // Checking against an expected vector byte by byte is
+ // difficult, because no assumption on the order of key/value
+ // pairs are made. We therefore only check the prefix (type and
+ // size and the overall size. The rest is then handled in the
+ // roundtrip check.
+ CHECK(result.size() == 458757); // 1 type, 4 size, 65536*7 content
+ CHECK(result[0] == 0xdf); // map 32
+ CHECK(result[1] == 0x00); // byte 0 of size (0x00010000)
+ CHECK(result[2] == 0x01); // byte 1 of size (0x00010000)
+ CHECK(result[3] == 0x00); // byte 2 of size (0x00010000)
+ CHECK(result[4] == 0x00); // byte 3 of size (0x00010000)
+
+ // roundtrip
+ CHECK(json::from_msgpack(result) == j);
+ }
+ }
+ }
+
+ SECTION("from float32")
+ {
+ auto given = std::vector<uint8_t>({0xca, 0x41, 0xc8, 0x00, 0x01});
+ json j = json::from_msgpack(given);
+ CHECK(j.get<double>() == Approx(25.0000019073486));
+ }
+}
+
+
+// use this testcase outside [hide] to run it with Valgrind
+TEST_CASE("single MessagePack roundtrip")
+{
+ SECTION("sample.json")
+ {
+ std::string filename = "test/data/json_testsuite/sample.json";
+
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
+ // parse MessagePack file
+ std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+ std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
+ std::istreambuf_iterator<char>());
+ json j2;
+ CHECK_NOTHROW(j2 = json::from_msgpack(packed));
+
+ // compare parsed JSON values
+ CHECK(j1 == j2);
+ }
+}
+
+
+TEST_CASE("MessagePack roundtrips", "[hide]")
+{
+ SECTION("input from msgpack-python")
+ {
+ for (std::string filename :
+ {
+ "test/data/json_nlohmann_tests/all_unicode.json",
+ "test/data/json.org/1.json",
+ "test/data/json.org/2.json",
+ "test/data/json.org/3.json",
+ "test/data/json.org/4.json",
+ "test/data/json.org/5.json",
+ "test/data/json_roundtrip/roundtrip01.json",
+ "test/data/json_roundtrip/roundtrip02.json",
+ "test/data/json_roundtrip/roundtrip03.json",
+ "test/data/json_roundtrip/roundtrip04.json",
+ "test/data/json_roundtrip/roundtrip05.json",
+ "test/data/json_roundtrip/roundtrip06.json",
+ "test/data/json_roundtrip/roundtrip07.json",
+ "test/data/json_roundtrip/roundtrip08.json",
+ "test/data/json_roundtrip/roundtrip09.json",
+ "test/data/json_roundtrip/roundtrip10.json",
+ "test/data/json_roundtrip/roundtrip11.json",
+ "test/data/json_roundtrip/roundtrip12.json",
+ "test/data/json_roundtrip/roundtrip13.json",
+ "test/data/json_roundtrip/roundtrip14.json",
+ "test/data/json_roundtrip/roundtrip15.json",
+ "test/data/json_roundtrip/roundtrip16.json",
+ "test/data/json_roundtrip/roundtrip17.json",
+ "test/data/json_roundtrip/roundtrip18.json",
+ "test/data/json_roundtrip/roundtrip19.json",
+ "test/data/json_roundtrip/roundtrip20.json",
+ "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/roundtrip29.json",
+ "test/data/json_roundtrip/roundtrip30.json",
+ "test/data/json_roundtrip/roundtrip31.json",
+ "test/data/json_roundtrip/roundtrip32.json",
+ "test/data/json_testsuite/sample.json", // kills AppVeyor
+ "test/data/json_tests/pass1.json",
+ "test/data/json_tests/pass2.json",
+ "test/data/json_tests/pass3.json",
+ "test/data/regression/floats.json",
+ "test/data/regression/signed_ints.json",
+ "test/data/regression/unsigned_ints.json",
+ "test/data/regression/working_file.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_arraysWithSpaces.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_empty-string.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_ending_with_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_false.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_heterogeneous.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_1_and_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_leading_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_several_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_array_with_trailing_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_0e+1.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_0e1.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_after_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_double_close_to_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_double_huge_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_huge_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_int_with_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_minus_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_one.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_negative_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_capital_e_pos_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_fraction_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_exp.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_neg_overflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_exponent.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_pos_overflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_real_underflow.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_simple_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_number_simple_real.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_neg_int.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_too_big_pos_int.json",
+ //"test/data/nst_json_testsuite/test_parsing/y_number_very_big_negative_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_basic.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key_and_value.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_empty_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_escaped_null_in_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_extreme_numbers.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_simple.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_string_unicode.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_with_newlines.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_UTF-16_Surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pair.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_accepted_surrogate_pairs.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_allowed_escapes.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_backslash_and_u_escaped_zero.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_backslash_doublequotes.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_comments.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_a.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_double_escape_n.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_escaped_control_character.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_escaped_noncharacter.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_in_array.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_in_array_with_leading_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_last_surrogates_1_and_2.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_newline_uescaped.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_null_escape.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_one-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_pi.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_simple_ascii.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_space.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_three-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_two-byte-utf-8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_u+2028_line_sep.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_u+2029_par_sep.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_uEscape.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unescaped_char_delete.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicodeEscapedBackslash.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_2.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_unicode_escaped_double_quote.json",
+ // "test/data/nst_json_testsuite/test_parsing/y_string_utf16.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_utf8.json",
+ "test/data/nst_json_testsuite/test_parsing/y_string_with_del_character.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_false.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_int.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_negative_real.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_null.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_string.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_lonely_true.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_string_empty.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_trailing_newline.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_true_in_array.json",
+ "test/data/nst_json_testsuite/test_parsing/y_structure_whitespace_array.json"
+ })
+ {
+ CAPTURE(filename);
+
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
+ // parse MessagePack file
+ std::ifstream f_msgpack(filename + ".msgpack", std::ios::binary);
+ std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_msgpack)),
+ std::istreambuf_iterator<char>());
+ json j2;
+ CHECK_NOTHROW(j2 = json::from_msgpack(packed));
+
+ // compare parsed JSON values
+ CHECK(j1 == j2);
+ }
+ }
+}
diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp
index 5d5eb16..e1c9caa 100644
--- a/test/src/unit-pointer_access.cpp
+++ b/test/src/unit-pointer_access.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp
index 07f3636..92b1322 100644
--- a/test/src/unit-readme.cpp
+++ b/test/src/unit-readme.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp
index a036d2f..4a8047f 100644
--- a/test/src/unit-reference_access.cpp
+++ b/test/src/unit-reference_access.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index e04513c..1e720dd 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -516,4 +516,28 @@
CHECK_THROWS_AS(j << ss, std::invalid_argument);
CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
}
+
+ SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
+ {
+ // original test case
+ json j1 = json::parse("-9223372036854775808");
+ CHECK(j1.is_number_integer());
+ CHECK(j1.get<json::number_integer_t>() == INT64_MIN);
+
+ // edge case (+1; still an integer)
+ json j2 = json::parse("-9223372036854775807");
+ CHECK(j2.is_number_integer());
+ CHECK(j2.get<json::number_integer_t>() == INT64_MIN + 1);
+
+ // edge case (-1; overflow -> floats)
+ json j3 = json::parse("-9223372036854775809");
+ CHECK(j3.is_number_float());
+ }
+
+ SECTION("issue #380 - bug in overflow detection when parsing integers")
+ {
+ json j = json::parse("166020696663385964490");
+ CHECK(j.is_number_float());
+ CHECK(j.dump() == "1.66020696663386e+20");
+ }
}
diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp
index 0c80038..8385a4a 100644
--- a/test/src/unit-serialization.cpp
+++ b/test/src/unit-serialization.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp
index c41c478..92b6e5a 100644
--- a/test/src/unit-testsuites.cpp
+++ b/test/src/unit-testsuites.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp
index 0e49757..4cb51e2 100644
--- a/test/src/unit-unicode.cpp
+++ b/test/src/unit-unicode.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
diff --git a/test/src/unit.cpp b/test/src/unit.cpp
index 7b93c38..1a27886 100644
--- a/test/src/unit.cpp
+++ b/test/src/unit.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 2.0.8
+| | |__ | | | | | | version 2.0.9
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.