Merge branch 'release/3.2.0'
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/Bug_report.md
similarity index 80%
rename from .github/ISSUE_TEMPLATE.md
rename to .github/ISSUE_TEMPLATE/Bug_report.md
index a3140bc..177a4b3 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE/Bug_report.md
@@ -1,22 +1,19 @@
-**Bug Report**
-
-- What is the issue you have?
-
-- Please describe the steps to reproduce the issue. Can you provide a small but working code example?
-
-- What is the expected behavior?
-
-- And what is the actual behavior instead?
-
-- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
-
-- Did you use a released version of the library or the version from the `develop` branch?
-
-- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?
-
-
-**Feature Request**
-
-- Describe the feature in as much detail as possible.
-
-- Include sample usage where appropriate.
+---
+name: Bug report
+about: Create a report to help us improve
+
+---
+
+- What is the issue you have?
+
+- Please describe the steps to reproduce the issue. Can you provide a small but working code example?
+
+- What is the expected behavior?
+
+- And what is the actual behavior instead?
+
+- Which compiler and operating system are you using? Is it a [supported compiler](https://github.com/nlohmann/json#supported-compilers)?
+
+- Did you use a released version of the library or the version from the `develop` branch?
+
+- If you experience a compilation error: can you [compile and run the unit tests](https://github.com/nlohmann/json#execute-unit-tests)?
diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md
new file mode 100644
index 0000000..f5ea57c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Feature_request.md
@@ -0,0 +1,9 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+
+---
+
+- Describe the feature in as much detail as possible.
+
+- Include sample usage where appropriate.
diff --git a/.travis.yml b/.travis.yml
index 8ce38cc..e5f0835 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -155,6 +155,12 @@
- os: osx
osx_image: xcode9.2
+ - os: osx
+ osx_image: xcode9.3
+
+ - os: osx
+ osx_image: xcode9.4
+
# Linux / GCC
- os: linux
@@ -191,13 +197,21 @@
- os: linux
compiler: gcc
+ env: COMPILER=g++-8
+ addons:
+ apt:
+ sources: ['ubuntu-toolchain-r-test']
+ packages: ['g++-8', 'ninja-build']
+
+ - os: linux
+ compiler: gcc
env:
- - COMPILER=g++-7
+ - COMPILER=g++-8
- CXXFLAGS=-std=c++17
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
- packages: ['g++-7', 'ninja-build']
+ packages: ['g++-8', 'ninja-build']
# Linux / Clang
@@ -259,13 +273,21 @@
- os: linux
compiler: clang
+ env: COMPILER=clang++-6.0
+ addons:
+ apt:
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
+ packages: ['g++-6', 'clang-6.0', 'ninja-build']
+
+ - os: linux
+ compiler: clang
env:
- - COMPILER=clang++-5.0
+ - COMPILER=clang++-6.0
- CXXFLAGS=-std=c++1z
addons:
apt:
- sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0']
- packages: ['g++-6', 'clang-5.0', 'ninja-build']
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
+ packages: ['g++-6', 'clang-6.0', 'ninja-build']
################
# build script #
@@ -277,6 +299,7 @@
if [[ (-x $(which brew)) ]]; then
brew update
brew install cmake ninja
+ brew upgrade cmake
cmake --version
fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c0acc75..b345c77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,10 +1,10 @@
-cmake_minimum_required(VERSION 3.0.0)
+cmake_minimum_required(VERSION 3.8)
##
## PROJECT
## name and version
##
-project(nlohmann_json VERSION 3.1.2 LANGUAGES CXX)
+project(nlohmann_json VERSION 3.2.0 LANGUAGES CXX)
##
## INCLUDE
@@ -22,13 +22,15 @@
## CONFIGURATION
##
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
-set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
+set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}"
+ CACHE INTERNAL "")
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include")
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
-set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake_config")
+set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
+set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake")
if (JSON_MultipleHeaders)
set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/")
@@ -43,6 +45,8 @@
## create target and add include path
##
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
+add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
+target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
target_include_directories(
${NLOHMANN_JSON_TARGET_NAME}
@@ -51,8 +55,8 @@
$<INSTALL_INTERFACE:include>
)
-## add debug view defintion file for msvc (natvis) [cmake <= 3.2.2 does not support export of source files]
-if (MSVC AND CMAKE_VERSION VERSION_GREATER "3.2.2")
+## add debug view definition file for msvc (natvis)
+if (MSVC)
set(NLOHMANN_ADD_NATVIS TRUE)
set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis")
target_sources(
@@ -62,7 +66,7 @@
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NLOHMANN_NATVIS_FILE}>
)
endif()
-
+
##
## TESTS
## create and configure the unit test target
@@ -102,6 +106,11 @@
DESTINATION .
)
endif()
+export(
+ TARGETS ${NLOHMANN_JSON_TARGET_NAME}
+ NAMESPACE ${PROJECT_NAME}::
+ FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
+)
install(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
@@ -109,5 +118,6 @@
)
install(
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
+ NAMESPACE ${PROJECT_NAME}::
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)
diff --git a/ChangeLog.md b/ChangeLog.md
index ea48332..0c6cc00 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,186 @@
# Change Log
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
+## [v3.2.0](https://github.com/nlohmann/json/releases/tag/v3.2.0) (2018-08-18)
+[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.2...v3.2.0)
+
+- Am I doing this wrong? Getting an empty string [\#1199](https://github.com/nlohmann/json/issues/1199)
+- Incompatible Pointer Type [\#1196](https://github.com/nlohmann/json/issues/1196)
+- json.exception.type\_error.316 [\#1195](https://github.com/nlohmann/json/issues/1195)
+- Strange warnings in Code::Blocks 17.12, GNU GCC [\#1192](https://github.com/nlohmann/json/issues/1192)
+- \[Question\] Current place in code to change floating point resolution [\#1191](https://github.com/nlohmann/json/issues/1191)
+- Add key name when throwing type error [\#1189](https://github.com/nlohmann/json/issues/1189)
+- Not able to include in visual studio code? [\#1188](https://github.com/nlohmann/json/issues/1188)
+- Get an Index or row number of an element [\#1186](https://github.com/nlohmann/json/issues/1186)
+- reduce repos size [\#1185](https://github.com/nlohmann/json/issues/1185)
+- Difference between `merge\_patch` and `update` [\#1183](https://github.com/nlohmann/json/issues/1183)
+- Is there a way to get an element from a JSON without throwing an exception on failure? [\#1182](https://github.com/nlohmann/json/issues/1182)
+- to\_string? [\#1181](https://github.com/nlohmann/json/issues/1181)
+- How to cache a json object's pointer into a map? [\#1180](https://github.com/nlohmann/json/issues/1180)
+- Can this library work within a Qt project for Android using Qt Creator? [\#1178](https://github.com/nlohmann/json/issues/1178)
+- How to get all keys of one object? [\#1177](https://github.com/nlohmann/json/issues/1177)
+- How can I only parse the first level and get the value as string? [\#1175](https://github.com/nlohmann/json/issues/1175)
+- I have a query regarding nlohmann::basic\_json::basic\_json [\#1174](https://github.com/nlohmann/json/issues/1174)
+- unordered\_map with vectors won't convert to json? [\#1173](https://github.com/nlohmann/json/issues/1173)
+- return json objects from functions [\#1172](https://github.com/nlohmann/json/issues/1172)
+- Problem when exporting to CBOR [\#1171](https://github.com/nlohmann/json/issues/1171)
+- Roundtripping null to nullptr does not work [\#1169](https://github.com/nlohmann/json/issues/1169)
+- MSVC fails to compile std::swap specialization for nlohmann::json [\#1168](https://github.com/nlohmann/json/issues/1168)
+- Unexpected behaviour of is\_null - Part II [\#1167](https://github.com/nlohmann/json/issues/1167)
+- Floating point imprecision [\#1166](https://github.com/nlohmann/json/issues/1166)
+- Combine json objects into one? [\#1165](https://github.com/nlohmann/json/issues/1165)
+- Is there any way to know if the object has changed? [\#1164](https://github.com/nlohmann/json/issues/1164)
+- Value throws on null string [\#1163](https://github.com/nlohmann/json/issues/1163)
+- Weird template issue in large project [\#1162](https://github.com/nlohmann/json/issues/1162)
+- \_json returns a different result vs ::parse [\#1161](https://github.com/nlohmann/json/issues/1161)
+- Showing difference between two json objects [\#1160](https://github.com/nlohmann/json/issues/1160)
+- no instance of overloaded function "std::swap" matches the specified type [\#1159](https://github.com/nlohmann/json/issues/1159)
+- resize\(...\)? [\#1157](https://github.com/nlohmann/json/issues/1157)
+- Issue with struct nested in class' to\_json [\#1155](https://github.com/nlohmann/json/issues/1155)
+- Deserialize std::map with std::nan [\#1154](https://github.com/nlohmann/json/issues/1154)
+- Parse throwing errors [\#1149](https://github.com/nlohmann/json/issues/1149)
+- cocoapod integration [\#1148](https://github.com/nlohmann/json/issues/1148)
+- wstring parsing [\#1147](https://github.com/nlohmann/json/issues/1147)
+- Is it possible to dump a two-dimensional array to "\[\[null\],\[1,2,3\]\]"? [\#1146](https://github.com/nlohmann/json/issues/1146)
+- Want to write a class member variable and a struct variable \( this structure is inside the class\) to the json file [\#1145](https://github.com/nlohmann/json/issues/1145)
+- Does json support converting an instance of a struct into json string? [\#1143](https://github.com/nlohmann/json/issues/1143)
+- \#Most efficient way to search for child parameters \(recursive find?\) [\#1141](https://github.com/nlohmann/json/issues/1141)
+- could not find to\_json\(\) method in T's namespace [\#1140](https://github.com/nlohmann/json/issues/1140)
+- chars get treated as JSON numbers not JSON strings [\#1139](https://github.com/nlohmann/json/issues/1139)
+- How do I count number of objects in array? [\#1137](https://github.com/nlohmann/json/issues/1137)
+- Serializing a vector of classes? [\#1136](https://github.com/nlohmann/json/issues/1136)
+- Compile error. Unable convert form nullptr to nullptr&& [\#1135](https://github.com/nlohmann/json/issues/1135)
+- std::unordered\_map in struct, serialization [\#1133](https://github.com/nlohmann/json/issues/1133)
+- dump\(\) can't handle umlauts [\#1131](https://github.com/nlohmann/json/issues/1131)
+- Add a way to get a key reference from the iterator [\#1127](https://github.com/nlohmann/json/issues/1127)
+- can't not parse "\\“ string [\#1123](https://github.com/nlohmann/json/issues/1123)
+- if json file contain Internationalization chars , get exception [\#1122](https://github.com/nlohmann/json/issues/1122)
+- How to use a json::iterator dereferenced value in code? [\#1120](https://github.com/nlohmann/json/issues/1120)
+- clang compiler: error : unknown type name 'not' [\#1119](https://github.com/nlohmann/json/issues/1119)
+- Disable implicit conversions from json to std::initializer\_list\<T\> for any T [\#1118](https://github.com/nlohmann/json/issues/1118)
+- Implicit conversions to complex types can lead to surprising and confusing errors [\#1116](https://github.com/nlohmann/json/issues/1116)
+- How can I write from\_json for a complex datatype that is not default constructible? [\#1115](https://github.com/nlohmann/json/issues/1115)
+- Compile error in VS2015 when compiling unit-conversions.cpp [\#1114](https://github.com/nlohmann/json/issues/1114)
+- ADL Serializer for std::any / boost::any [\#1113](https://github.com/nlohmann/json/issues/1113)
+- Unexpected behaviour of is\_null [\#1112](https://github.com/nlohmann/json/issues/1112)
+- How to resolve " undefined reference to `std::\_\_throw\_bad\_cast\(\)'" [\#1111](https://github.com/nlohmann/json/issues/1111)
+- cannot compile on ubuntu 18.04 and 16.04 [\#1110](https://github.com/nlohmann/json/issues/1110)
+- JSON representation for floating point values has too many digits [\#1109](https://github.com/nlohmann/json/issues/1109)
+- Not working for classes containing "\_declspec\(dllimport\)" in their declaration [\#1108](https://github.com/nlohmann/json/issues/1108)
+- Get keys from json object [\#1107](https://github.com/nlohmann/json/issues/1107)
+- dump\(\) without alphabetical order [\#1106](https://github.com/nlohmann/json/issues/1106)
+- Cannot deserialize types using std::ratio [\#1105](https://github.com/nlohmann/json/issues/1105)
+- i want to learn json [\#1104](https://github.com/nlohmann/json/issues/1104)
+- Type checking during compile [\#1103](https://github.com/nlohmann/json/issues/1103)
+- Iterate through sub items [\#1102](https://github.com/nlohmann/json/issues/1102)
+- cppcheck failing for version 3.1.2 [\#1101](https://github.com/nlohmann/json/issues/1101)
+- Deserializing std::map [\#1100](https://github.com/nlohmann/json/issues/1100)
+- accessing key by reference [\#1098](https://github.com/nlohmann/json/issues/1098)
+- clang 3.8.0 croaks while trying to compile with debug symbols [\#1097](https://github.com/nlohmann/json/issues/1097)
+- Serialize a list of class objects with json [\#1096](https://github.com/nlohmann/json/issues/1096)
+- Null bytes in files are treated like EOF [\#1095](https://github.com/nlohmann/json/issues/1095)
+- Small question [\#1094](https://github.com/nlohmann/json/issues/1094)
+- Upgrading to 3.x: to\_/from\_json with enum class [\#1093](https://github.com/nlohmann/json/issues/1093)
+- Q: few questions about json construction [\#1092](https://github.com/nlohmann/json/issues/1092)
+- general crayCC compilation failure [\#1091](https://github.com/nlohmann/json/issues/1091)
+- Merge Patch clears original data [\#1090](https://github.com/nlohmann/json/issues/1090)
+- \[Question\] how to use nlohmann/json in c++? [\#1088](https://github.com/nlohmann/json/issues/1088)
+- C++17 decomposition declaration support [\#1087](https://github.com/nlohmann/json/issues/1087)
+- \[Question\] Access multi-level json objects [\#1086](https://github.com/nlohmann/json/issues/1086)
+- Serializing vector [\#1085](https://github.com/nlohmann/json/issues/1085)
+- update nested value in multi hierarchy json object [\#1084](https://github.com/nlohmann/json/issues/1084)
+- Overriding default values? [\#1083](https://github.com/nlohmann/json/issues/1083)
+- detail namespace collision with Cereal? [\#1082](https://github.com/nlohmann/json/issues/1082)
+- Error using json.dump\(\); [\#1081](https://github.com/nlohmann/json/issues/1081)
+- Consuming TCP Stream [\#1080](https://github.com/nlohmann/json/issues/1080)
+- Compilation error with strong typed enums in map in combination with namespaces [\#1079](https://github.com/nlohmann/json/issues/1079)
+- cassert error [\#1076](https://github.com/nlohmann/json/issues/1076)
+- Valid json data not being parsed [\#1075](https://github.com/nlohmann/json/issues/1075)
+- Feature request :: Better testing for key existance without try/catch [\#1074](https://github.com/nlohmann/json/issues/1074)
+- Hi, I have input like a.b.c and want to convert it to \"a\"{\"b\": \"c\"} form. Any suggestions how do I do this? Thanks. [\#1073](https://github.com/nlohmann/json/issues/1073)
+- ADL deserializer not picked up for non default-constructible type [\#1072](https://github.com/nlohmann/json/issues/1072)
+- Deserializing std::array doesn't compiler \(no insert\(\)\) [\#1071](https://github.com/nlohmann/json/issues/1071)
+- Serializing OpenCV Mat problem [\#1070](https://github.com/nlohmann/json/issues/1070)
+- Compilation error with ICPC compiler [\#1068](https://github.com/nlohmann/json/issues/1068)
+- Minimal branch? [\#1066](https://github.com/nlohmann/json/issues/1066)
+- Not existing value, crash [\#1065](https://github.com/nlohmann/json/issues/1065)
+- cyryllic symbols [\#1064](https://github.com/nlohmann/json/issues/1064)
+- newbie usage question [\#1063](https://github.com/nlohmann/json/issues/1063)
+- Trying j\["strTest"\] = "%A" produces "strTest": "-0X1.CCCCCCCCCCCCCP+205" [\#1062](https://github.com/nlohmann/json/issues/1062)
+- convert json value to std::string??? [\#1061](https://github.com/nlohmann/json/issues/1061)
+- Commented out test cases, should they be removed? [\#1060](https://github.com/nlohmann/json/issues/1060)
+- different behaviour between clang and gcc with braced initialization [\#1059](https://github.com/nlohmann/json/issues/1059)
+- json array: initialize with prescribed size and `resize` method. [\#1057](https://github.com/nlohmann/json/issues/1057)
+- Is it possible to use exceptions istead of assertions? [\#1056](https://github.com/nlohmann/json/issues/1056)
+- when using assign operator in with json object a static assertion fails.. [\#1055](https://github.com/nlohmann/json/issues/1055)
+- Iterate over leafs of a JSON data structure: enrich the JSON pointer API [\#1054](https://github.com/nlohmann/json/issues/1054)
+- \[Feature request\] Access by path [\#1053](https://github.com/nlohmann/json/issues/1053)
+- document that implicit js -\> primitive conversion does not work for std::string::value\_type and why [\#1052](https://github.com/nlohmann/json/issues/1052)
+- error: ‘BasicJsonType’ in namespace ‘::’ does not name a type [\#1051](https://github.com/nlohmann/json/issues/1051)
+- Destructor is called when filling object through assignement [\#1050](https://github.com/nlohmann/json/issues/1050)
+- Is this thing thread safe for reads? [\#1049](https://github.com/nlohmann/json/issues/1049)
+- clang-tidy: Call to virtual function during construction [\#1046](https://github.com/nlohmann/json/issues/1046)
+- Using STL algorithms with JSON containers with expected results? [\#1045](https://github.com/nlohmann/json/issues/1045)
+- Usage with gtest/gmock not working as expected [\#1044](https://github.com/nlohmann/json/issues/1044)
+- Consequences of from\_json / to\_json being in namespace of data struct. [\#1042](https://github.com/nlohmann/json/issues/1042)
+- const\_reference operator\[\]\(const typename object\_t::key\_type& key\) const throw instead of assert [\#1039](https://github.com/nlohmann/json/issues/1039)
+- Trying to retrieve data from nested objects [\#1038](https://github.com/nlohmann/json/issues/1038)
+- Direct download link for json\_fwd.hpp? [\#1037](https://github.com/nlohmann/json/issues/1037)
+- I know the library supports UTF-8, but failed to dump the value [\#1036](https://github.com/nlohmann/json/issues/1036)
+- Putting a Vec3-like vector into a json object [\#1035](https://github.com/nlohmann/json/issues/1035)
+- Ternary operator crash [\#1034](https://github.com/nlohmann/json/issues/1034)
+- Issued with Clion Inspection Resolution since 2018.1 [\#1033](https://github.com/nlohmann/json/issues/1033)
+- Some testcases fail and one never finishes [\#1032](https://github.com/nlohmann/json/issues/1032)
+- Can this class work with wchar\_t / std::wstring? [\#1031](https://github.com/nlohmann/json/issues/1031)
+- Makefile: Valgrind flags have no effect [\#1030](https://github.com/nlohmann/json/issues/1030)
+- ใ==ใ Should be ใ\>ใ [\#1029](https://github.com/nlohmann/json/issues/1029)
+- HOCON reader? [\#1027](https://github.com/nlohmann/json/issues/1027)
+- add json string in previous string?? [\#1025](https://github.com/nlohmann/json/issues/1025)
+- RFC: fluent parsing interface [\#1023](https://github.com/nlohmann/json/issues/1023)
+- Does it support chinese character? [\#1022](https://github.com/nlohmann/json/issues/1022)
+- to/from\_msgpack only works with standard typization [\#1021](https://github.com/nlohmann/json/issues/1021)
+- Build failure using latest clang and GCC compilers [\#1020](https://github.com/nlohmann/json/issues/1020)
+- can two json objects be concatenated? [\#1019](https://github.com/nlohmann/json/issues/1019)
+- Erase by integer index [\#1018](https://github.com/nlohmann/json/issues/1018)
+- Function find overload taking a json\_pointer [\#1017](https://github.com/nlohmann/json/issues/1017)
+- I think should implement an parser function [\#1016](https://github.com/nlohmann/json/issues/1016)
+- Readme gif [\#1015](https://github.com/nlohmann/json/issues/1015)
+- Python bindings [\#1014](https://github.com/nlohmann/json/issues/1014)
+- how to add two json string in single object?? [\#1012](https://github.com/nlohmann/json/issues/1012)
+- how to serialize class Object \(convert data in object into json\)?? [\#1011](https://github.com/nlohmann/json/issues/1011)
+- Enable forward declaration of json by making json a class instead of a using declaration [\#997](https://github.com/nlohmann/json/issues/997)
+- compilation error while using intel c++ compiler 2018 [\#994](https://github.com/nlohmann/json/issues/994)
+- How to create a json variable? [\#990](https://github.com/nlohmann/json/issues/990)
+- istream \>\> json --- 1st character skipped in stream [\#976](https://github.com/nlohmann/json/issues/976)
+- Add a SAX parser [\#971](https://github.com/nlohmann/json/issues/971)
+- Add Key name to Exception [\#932](https://github.com/nlohmann/json/issues/932)
+- How to solve large json file? [\#927](https://github.com/nlohmann/json/issues/927)
+- json\_pointer public push\_back, pop\_back [\#837](https://github.com/nlohmann/json/issues/837)
+- Using input\_adapter in a slightly unexpected way [\#834](https://github.com/nlohmann/json/issues/834)
+- Stack-overflow \(OSS-Fuzz 4234\) [\#832](https://github.com/nlohmann/json/issues/832)
+
+- Fix -Wno-sometimes-uninitialized by initializing "result" in parse\_sax [\#1200](https://github.com/nlohmann/json/pull/1200) ([thyu](https://github.com/thyu))
+- \[RFC\] Introduce a new macro function: JSON\_INTERNAL\_CATCH [\#1187](https://github.com/nlohmann/json/pull/1187) ([simnalamburt](https://github.com/simnalamburt))
+- Fix unit tests that were silently skipped or crashed \(depending on the compiler\) [\#1176](https://github.com/nlohmann/json/pull/1176) ([grembo](https://github.com/grembo))
+- Refactor/no virtual sax [\#1153](https://github.com/nlohmann/json/pull/1153) ([theodelrieu](https://github.com/theodelrieu))
+- Fixed compiler error in VS 2015 for debug mode [\#1151](https://github.com/nlohmann/json/pull/1151) ([sonulohani](https://github.com/sonulohani))
+- Fix links to cppreference named requirements \(formerly concepts\) [\#1144](https://github.com/nlohmann/json/pull/1144) ([jrakow](https://github.com/jrakow))
+- meson: fix include directory [\#1142](https://github.com/nlohmann/json/pull/1142) ([jrakow](https://github.com/jrakow))
+- Feature/unordered map conversion [\#1138](https://github.com/nlohmann/json/pull/1138) ([theodelrieu](https://github.com/theodelrieu))
+- fixed compile error for \#1045 [\#1134](https://github.com/nlohmann/json/pull/1134) ([Daniel599](https://github.com/Daniel599))
+- test \(non\)equality for alt\_string implementation [\#1130](https://github.com/nlohmann/json/pull/1130) ([agrianius](https://github.com/agrianius))
+- remove stringstream dependency [\#1117](https://github.com/nlohmann/json/pull/1117) ([TinyTinni](https://github.com/TinyTinni))
+- Provide a from\_json overload for std::map [\#1089](https://github.com/nlohmann/json/pull/1089) ([theodelrieu](https://github.com/theodelrieu))
+- fix typo in README [\#1078](https://github.com/nlohmann/json/pull/1078) ([martin-mfg](https://github.com/martin-mfg))
+- Fix typo [\#1058](https://github.com/nlohmann/json/pull/1058) ([dns13](https://github.com/dns13))
+- Misc cmake packaging enhancements [\#1048](https://github.com/nlohmann/json/pull/1048) ([chuckatkins](https://github.com/chuckatkins))
+- Fixed incorrect LLVM version number in README [\#1047](https://github.com/nlohmann/json/pull/1047) ([jammehcow](https://github.com/jammehcow))
+- Fix trivial typo in comment. [\#1043](https://github.com/nlohmann/json/pull/1043) ([coryan](https://github.com/coryan))
+- Package Manager: Spack [\#1041](https://github.com/nlohmann/json/pull/1041) ([ax3l](https://github.com/ax3l))
+- CMake: 3.8+ is Sufficient [\#1040](https://github.com/nlohmann/json/pull/1040) ([ax3l](https://github.com/ax3l))
+- Added support for string\_view in C++17 [\#1028](https://github.com/nlohmann/json/pull/1028) ([gracicot](https://github.com/gracicot))
+- Added public target\_compile\_features for auto and constexpr [\#1026](https://github.com/nlohmann/json/pull/1026) ([ktonon](https://github.com/ktonon))
+
## [v3.1.2](https://github.com/nlohmann/json/releases/tag/v3.1.2) (2018-03-14)
[Full Changelog](https://github.com/nlohmann/json/compare/v3.1.1...v3.1.2)
@@ -16,7 +196,6 @@
- get\<T\> for types that are not default constructible [\#996](https://github.com/nlohmann/json/issues/996)
- Prevent Null values to appear in .dump\(\) [\#995](https://github.com/nlohmann/json/issues/995)
- number parsing [\#993](https://github.com/nlohmann/json/issues/993)
-- How to create a json variable? [\#990](https://github.com/nlohmann/json/issues/990)
- C2664 \(C++/CLR\) cannot convert 'nullptr' to 'nullptr &&' [\#987](https://github.com/nlohmann/json/issues/987)
- Uniform initialization from another json object differs between gcc and clang. [\#985](https://github.com/nlohmann/json/issues/985)
- Problem with adding the lib as a submodule [\#983](https://github.com/nlohmann/json/issues/983)
diff --git a/Makefile b/Makefile
index a873292..1deb8da 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@
include/nlohmann/detail/exceptions.hpp \
include/nlohmann/detail/input/binary_reader.hpp \
include/nlohmann/detail/input/input_adapters.hpp \
+ include/nlohmann/detail/input/json_sax.hpp \
include/nlohmann/detail/input/lexer.hpp \
include/nlohmann/detail/input/parser.hpp \
include/nlohmann/detail/iterators/internal_iterator.hpp \
@@ -20,7 +21,10 @@
include/nlohmann/detail/json_ref.hpp \
include/nlohmann/detail/macro_scope.hpp \
include/nlohmann/detail/macro_unscope.hpp \
- include/nlohmann/detail/meta.hpp \
+ include/nlohmann/detail/meta/cpp_future.hpp \
+ include/nlohmann/detail/meta/detected.hpp \
+ include/nlohmann/detail/meta/type_traits.hpp \
+ include/nlohmann/detail/meta/void_t.hpp \
include/nlohmann/detail/output/binary_writer.hpp \
include/nlohmann/detail/output/output_adapters.hpp \
include/nlohmann/detail/output/serializer.hpp \
@@ -82,9 +86,9 @@
coverage:
mkdir build_coverage
- cd build_coverage ; CXX=g++-5 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
+ cd build_coverage ; CXX=g++-7 cmake .. -GNinja -DJSON_Coverage=ON -DJSON_MultipleHeaders=ON
cd build_coverage ; ninja
- cd build_coverage ; ctest -j10
+ cd build_coverage ; ctest -E '.*_default' -j10
cd build_coverage ; ninja lcov_html
open build_coverage/test/html/index.html
diff --git a/README.md b/README.md
index 3ed3c18..f3bbf84 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,8 @@
If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `jsonformoderncpp/x.y.z@vthiery/stable` to your `conanfile.py`'s requires, where `x.y.z` is the release version you want to use. Please file issues [here](https://github.com/vthiery/conan-jsonformoderncpp/issues) if you experience problems with the packages.
+If you are using [Spack](https://www.spack.io/) to manage your dependencies, you can use the `nlohmann_json` package. Please see the [spack project](https://github.com/spack/spack) for any issues regarding the packaging.
+
If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json).
@@ -84,6 +86,8 @@
If you are using [cget](http://cget.readthedocs.io/en/latest/), you can install the latest development version with `cget install nlohmann/json`. A specific version can be installed with `cget install nlohmann/json@v3.1.0`. Also, the multiple header version can be installed by adding the `-DJSON_MultipleHeaders=ON` flag (i.e., `cget install nlohmann/json -DJSON_MultipleHeaders=ON`).
+If you are using [CocoaPods](https://cocoapods.org), you can use the library by adding pod `"nlohmann_json", '~>3.1.2'` to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues [here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open).
+
## Examples
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
@@ -169,7 +173,6 @@
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
```
-
### Serialization / Deserialization
#### To/from strings
@@ -235,6 +238,7 @@
[`.dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) always returns the serialized value, and [`.get<std::string>()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a16f9445f7629f634221a42b967cdcd43.html#a16f9445f7629f634221a42b967cdcd43) returns the originally stored string value.
+Note the library only supports UTF-8. When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5adea76fedba9898d404fef8598aa663.html#a5adea76fedba9898d404fef8598aa663) may throw an exception.
#### To/from streams (e.g. files, string streams)
@@ -283,10 +287,53 @@
json j = json::parse(v);
```
+#### SAX interface
+
+The library uses a SAX-like interface with the following functions:
+
+```cpp
+// called when null is parsed
+bool null();
+
+// called when a boolean is parsed; value is passed
+bool boolean(bool val);
+
+// called when a signed or unsigned integer number is parsed; value is passed
+bool number_integer(number_integer_t val);
+bool number_unsigned(number_unsigned_t val);
+
+// called when a floating-point number is parsed; value and original string is passed
+bool number_float(number_float_t val, const string_t& s);
+
+// called when a string is parsed; value is passed and can be safely moved away
+bool string(string_t& val);
+
+// called when an object or array begins or ends, resp. The number of elements is passed (or -1 if not known)
+bool start_object(std::size_t elements);
+bool end_object();
+bool start_array(std::size_t elements);
+bool end_array();
+// called when an object key is parsed; value is passed and can be safely moved away
+bool key(string_t& val);
+
+// called when a parse error occurs; byte position, the last token, and an exception is passed
+bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
+```
+
+The return value of each function determines whether parsing should proceed.
+
+To implement your own SAX handler, proceed as follows:
+
+1. Implement the SAX interface in a class. You can use class `nlohmann::json_sax<json>` as base class, but you can also use any class where the functions described above are implemented and public.
+2. Create an object of your SAX interface class, e.g. `my_sax`.
+3. Call `bool json::sax_parse(input, &my_sax)`; where the first parameter can be any input like a string or an input stream and the second parameter is a pointer to your SAX interface.
+
+Note the `sax_parse` function only returns a `bool` indicating the result of the last executed SAX event. It does not return a `json` value - it is up to you to decide what to do with the SAX events. Furthermore, no exceptions are thrown in case of a parse error - it is up to you what to do with the exception object passed to your `parse_error` implementation. Internally, the SAX interface is used for the DOM parser (class `json_sax_dom_parser`) as well as the acceptor (`json_sax_acceptor`), see file [`json_sax.hpp`](https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/input/json_sax.hpp).
+
### STL-like access
-We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](http://en.cppreference.com/w/cpp/concept/ReversibleContainer) requirement.
+We designed the JSON class to behave just like an STL container. In fact, it satisfies the [**ReversibleContainer**](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) requirement.
```cpp
// create an array using push_back
@@ -523,6 +570,14 @@
// etc.
```
+Note that `char` types are not automatically converted to JSON strings, but to integer numbers. A conversion to a string must be specified explicitly:
+
+```cpp
+char ch = 'A'; // ASCII value 65
+json j_default = ch; // stores integer number 65
+json j_string = std::string(1, ch); // stores string "A"
+```
+
### Arbitrary types conversions
Every type can be serialized in JSON, not just STL containers and scalar types. Usually, you would do something along those lines:
@@ -600,7 +655,8 @@
Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
-* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible). (There is a way to bypass this requirement described later.)
+* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use the implicit conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
+* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get<decltype your_variable>();` instead.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
@@ -612,7 +668,7 @@
This requires a bit more advanced technique. But first, let's see how this conversion mechanism works:
The library uses **JSON Serializers** to convert types to json.
-The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](http://en.cppreference.com/w/cpp/language/adl)).
+The default serializer for `nlohmann::json` is `nlohmann::adl_serializer` (ADL means [Argument-Dependent Lookup](https://en.cppreference.com/w/cpp/language/adl)).
It is implemented like this (simplified):
@@ -661,7 +717,7 @@
#### How can I use `get()` for non-default constructible/non-copyable types?
-There is a way, if your type is [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
+There is a way, if your type is [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible). You will need to specialize the `adl_serializer` as well, but with a special `from_json` overload:
```cpp
struct move_only_type {
@@ -786,8 +842,8 @@
Though it's 2018 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
-- GCC 4.9 - 7.2 (and possibly later)
-- Clang 3.4 - 5.0 (and possibly later)
+- GCC 4.9 - 8.2 (and possibly later)
+- Clang 3.4 - 6.1 (and possibly later)
- Intel C++ Compiler 17.0.2 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
- Microsoft Visual C++ 2017 / Build Tools 15.5.180.51428 (and possibly later)
@@ -809,32 +865,38 @@
- For GCC running on MinGW or Android SDK, the error `'to_string' is not a member of 'std'` (or similarly, for `strtod`) may occur. Note this is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
+- Unsupported versions of GCC and Clang are rejected by `#error` directives. This can be switched off by defining `JSON_SKIP_UNSUPPORTED_COMPILER_CHECK`. Note that you can expect no support in this case.
+
The following compilers are currently used in continuous integration at [Travis](https://travis-ci.org/nlohmann/json) and [AppVeyor](https://ci.appveyor.com/project/nlohmann/json):
| Compiler | Operating System | Version String |
|-----------------|------------------------------|----------------|
-| GCC 4.9.4 | Ubuntu 14.04.5 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 |
-| GCC 5.4.1 | Ubuntu 14.04.5 LTS | g++-5 (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 |
-| GCC 6.3.0 | Ubuntu 14.04.5 LTS | g++-6 (Ubuntu/Linaro 6.3.0-18ubuntu2~14.04) 6.3.0 20170519 |
-| GCC 7.1.0 | Ubuntu 14.04.5 LTS | g++-7 (Ubuntu 7.1.0-5ubuntu2~14.04) 7.1.0
-| Clang 3.5.0 | Ubuntu 14.04.5 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) |
-| Clang 3.6.2 | Ubuntu 14.04.5 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) |
-| Clang 3.7.1 | Ubuntu 14.04.5 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) |
-| Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
-| Clang 3.9.1 | Ubuntu 14.04.5 LTS | clang version 3.9.1-4ubuntu3~14.04.2 (tags/RELEASE_391/rc2) |
-| Clang 4.0.1 | Ubuntu 14.04.5 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
-| Clang 5.0.0 | Ubuntu 14.04.5 LTS | clang version 5.0.0-svn310902-1~exp1 (branches/release_50) |
-| Clang Xcode 6.4 | Darwin Kernel Version 14.3.0 (OSX 10.10.3) | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
-| Clang Xcode 7.3 | Darwin Kernel Version 15.0.0 (OSX 10.10.5) | Apple LLVM version 7.3.0 (clang-703.0.29) |
-| Clang Xcode 8.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) |
-| Clang Xcode 8.1 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
-| Clang Xcode 8.2 | Darwin Kernel Version 16.1.0 (macOS 10.12.1) | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
-| Clang Xcode 8.3 | Darwin Kernel Version 16.5.0 (macOS 10.12.4) | Apple LLVM version 8.1.0 (clang-802.0.38) |
-| Clang Xcode 9.0 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.37) |
-| Clang Xcode 9.1 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 9.0.0 (clang-900.0.38) |
-| Clang Xcode 9.2 | Darwin Kernel Version 16.7.0 (macOS 10.12.6) | Apple LLVM version 8.1.0 (clang-900.0.39.2) |
+| GCC 4.9.4 | Ubuntu 14.04.1 LTS | g++-4.9 (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4 |
+| GCC 5.5.0 | Ubuntu 14.04.1 LTS | g++-5 (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010 |
+| GCC 6.4.0 | Ubuntu 14.04.1 LTS | g++-6 (Ubuntu 6.4.0-17ubuntu1~14.04) 6.4.0 20180424 |
+| GCC 7.3.0 | Ubuntu 14.04.1 LTS | g++-7 (Ubuntu 7.3.0-21ubuntu1~14.04) 7.3.0 |
+| GCC 7.3.0 | Windows Server 2012 R2 (x64) | g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.3.0 |
+| GCC 8.1.0 | Ubuntu 14.04.1 LTS | g++-8 (Ubuntu 8.1.0-5ubuntu1~14.04) 8.1.0 |
+| Clang 3.5.0 | Ubuntu 14.04.1 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0) |
+| Clang 3.6.2 | Ubuntu 14.04.1 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2) |
+| Clang 3.7.1 | Ubuntu 14.04.1 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1) |
+| Clang 3.8.0 | Ubuntu 14.04.1 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
+| Clang 3.9.1 | Ubuntu 14.04.1 LTS | clang version 3.9.1-4ubuntu3~14.04.3 (tags/RELEASE_391/rc2) |
+| Clang 4.0.1 | Ubuntu 14.04.1 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
+| Clang 5.0.2 | Ubuntu 14.04.1 LTS | clang version 5.0.2-svn328729-1~exp1~20180509123505.100 (branches/release_50) |
+| Clang 6.0.1 | Ubuntu 14.04.1 LTS | clang version 6.0.1-svn334776-1~exp1~20180726133705.85 (branches/release_60) |
+| Clang Xcode 6.4 | OSX 10.10.5 | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
+| Clang Xcode 7.3 | OSX 10.11.6 | Apple LLVM version 7.3.0 (clang-703.0.31) |
+| Clang Xcode 8.0 | OSX 10.11.6 | Apple LLVM version 8.0.0 (clang-800.0.38) |
+| Clang Xcode 8.1 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
+| Clang Xcode 8.2 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
+| Clang Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) |
+| Clang Xcode 9.0 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.37) |
+| Clang Xcode 9.1 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.38) |
+| Clang Xcode 9.2 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.1) |
+| Clang Xcode 9.3 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.2) |
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 |
-| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.5.180.51428, MSVC 19.12.25830.2 |
+| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 |
## License
@@ -862,6 +924,9 @@
Only if your request would contain confidential information, please [send me an email](mailto:mail@nlohmann.me). For encrypted messages, please use [this key](https://keybase.io/nlohmann/pgp_keys.asc).
+## Security
+
+[Commits by Niels Lohmann](https://github.com/nlohmann/json/commits) and [releases](https://github.com/nlohmann/json/releases) are signed with this [PGP Key](https://keybase.io/nlohmann/pgp_keys.asc?fingerprint=797167ae41c0a6d9232e48457f3cea63ae251b69).
## Thanks
@@ -916,7 +981,7 @@
- [Vladimir Petrigo](https://github.com/vpetrigo) made a SFINAE hack more readable and added Visual Studio 17 to the build matrix.
- [Denis Andrejew](https://github.com/seeekr) fixed a grammar issue in the README file.
- [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, improved the benchmarking code, and realized locale-independent number parsing and printing.
+- [TurpentineDistillery](https://github.com/TurpentineDistillery) pointed to [`std::locale::classic()`](https://en.cppreference.com/w/cpp/locale/locale/classic) to avoid too much locale joggling, found some nice performance improvements in the parser, improved the benchmarking code, and realized locale-independent number parsing and printing.
- [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.
@@ -975,14 +1040,29 @@
- [Paul Fultz II](https://github.com/pfultz2) added a note on the cget package manager.
- [Wilson Lin](https://github.com/wla80) made the integration section of the README more concise.
- [RalfBielig](https://github.com/ralfbielig) detected and fixed a memory leak in the parser callback.
-- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type
+- [agrianius](https://github.com/agrianius) allowed to dump JSON to an alternative string type.
+- [Kevin Tonon](https://github.com/ktonon) overworked the C++11 compiler checks in CMake.
+- [Axel Huebl](https://github.com/ax3l) simplified a CMake check and added support for the [Spack package manager](https://spack.io).
+- [Carlos O'Ryan](https://github.com/coryan) fixed a typo.
+- [James Upjohn](https://github.com/jammehcow) fixed a version number in the compilers section.
+- [Chuck Atkins](https://github.com/chuckatkins) adjusted the CMake files to the CMake packaging guidelines
+- [Jan Schöppach](https://github.com/dns13) fixed a typo.
+- [martin-mfg](https://github.com/martin-mfg) fixed a typo.
+- [Matthias Möller](https://github.com/TinyTinni) removed the dependency from `std::stringstream`.
+- [agrianius](https://github.com/agrianius) added code to use alternative string implementations.
+- [Daniel599](https://github.com/Daniel599) allowed to use more algorithms with the `items()` function.
+- [Julius Rakow](https://github.com/jrakow) fixed the Meson include directory and fixed the links to [cppreference.com](cppreference.com).
+- [Sonu Lohani](https://github.com/sonulohani) fixed the compilation with MSVC 2015 in debug mode.
+- [grembo](https://github.com/grembo) fixed the test suite and re-enabled several test cases.
+- [Hyeon Kim](https://github.com/simnalamburt) introduced the macro `JSON_INTERNAL_CATCH` to control the exception handling inside the library.
+- [thyu](https://github.com/thyu) fixed a compiler warning.
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
## Used third-party tools
-The library itself contains of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot!
+The library itself consists of a single header file licensed under the MIT license. However, it is built, tested, documented, and whatnot using a lot of third-party tools and services. Thanks a lot!
- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file
- [**American fuzzy lop**](http://lcamtuf.coredump.cx/afl/) for fuzz testing
@@ -1015,7 +1095,7 @@
## Notes
-- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](http://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
+- The code contains numerous debug **assertions** which can be switched off by defining the preprocessor macro `NDEBUG`, see the [documentation of `assert`](https://en.cppreference.com/w/cpp/error/assert). In particular, note [`operator[]`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a2e26bd0b0168abb61f67ad5bcd5b9fa1.html#a2e26bd0b0168abb61f67ad5bcd5b9fa1) implements **unchecked access** for const objects: If the given key is not present, the behavior is undefined (think of a dereferenced null pointer) and yields an [assertion failure](https://github.com/nlohmann/json/issues/289) if assertions are switched on. If you are not sure whether an element in an object exists, use checked access with the [`at()` function](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a674de1ee73e6bf4843fc5dc1351fb726.html#a674de1ee73e6bf4843fc5dc1351fb726).
- As the exact type of a number is not defined in the [JSON specification](http://rfc7159.net/rfc7159), this library tries to choose the best fitting C++ number type automatically. As a result, the type `double` may be used to store numbers which may yield [**floating-point exceptions**](https://github.com/nlohmann/json/issues/181) in certain rare situations if floating-point exceptions have been unmasked in the calling code. These exceptions are not caused by the library and need to be fixed in the calling code, such as by re-masking the exceptions prior to calling library functions.
- The library supports **Unicode input** as follows:
- Only **UTF-8** encoded input is supported which is the default encoding for JSON according to [RFC 7159](http://rfc7159.net/rfc7159#rfc.section.8.1).
diff --git a/appveyor.yml b/appveyor.yml
index da70378..705f53f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,26 +1,58 @@
version: '{build}'
-os:
- - Visual Studio 2015
- - Visual Studio 2017
-
environment:
matrix:
- - additional_flags: ""
- - additional_flags: "/permissive- /std:c++latest /utf-8"
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+ COMPILER: mingw
+ platform: x86
+ FLAGS: ""
+ GENERATOR: Ninja
-matrix:
- exclude:
- - additional_flags: "/permissive- /std:c++latest /utf-8"
- os: Visual Studio 2015
-
-init: []
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+ platform: x86
+ FLAGS: ""
+ GENERATOR: Visual Studio 14 2015
-install: []
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ platform: x86
+ FLAGS: ""
+ GENERATOR: Visual Studio 15 2017
+
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ platform: x86
+ FLAGS: "/permissive- /std:c++latest /utf-8"
+ GENERATOR: Visual Studio 15 2017
+
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
+ platform: x64
+ FLAGS: ""
+ GENERATOR: Visual Studio 14 2015
+
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ platform: x64
+ FLAGS: ""
+ GENERATOR: Visual Studio 15 2017
+
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ platform: x64
+ FLAGS: "/permissive- /std:c++latest /utf-8"
+ GENERATOR: Visual Studio 15 2017
+
+init:
+ - cmake --version
+ - msbuild /version
+
+install:
+ - if "%COMPILER%"=="mingw" appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
+ - if "%COMPILER%"=="mingw" 7z x ninja.zip -oC:\projects\deps\ninja > nul
+ - if "%COMPILER%"=="mingw" set PATH=C:\projects\deps\ninja;%PATH%
+ - if "%COMPILER%"=="mingw" set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
+ - if "%COMPILER%"=="mingw" g++ --version
+
+before_build:
+ - cmake . -G "%GENERATOR%" -DCMAKE_CXX_FLAGS="%FLAGS%" -DCMAKE_IGNORE_PATH="C:/Program Files/Git/usr/bin"
build_script:
- - IF "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" ( SET GEN="Visual Studio 14 2015") ELSE (SET GEN="Visual Studio 15 2017")
- - cmake . -G%GEN% -DCMAKE_CXX_FLAGS="%additional_flags%"
- cmake --build . --config Release
test_script:
diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt
index c10d44e..a53812c 100644
--- a/benchmarks/CMakeLists.txt
+++ b/benchmarks/CMakeLists.txt
@@ -1,9 +1,9 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.8)
project(JSON_Benchmarks LANGUAGES CXX)
# set compiler flags
if((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -flto -DNDEBUG -O3")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -DNDEBUG -O3")
endif()
# configure Google Benchmarks
@@ -23,4 +23,5 @@
# benchmark binary
add_executable(json_benchmarks src/benchmarks.cpp)
+target_compile_features(json_benchmarks PRIVATE cxx_std_11)
target_link_libraries(json_benchmarks benchmark ${CMAKE_THREAD_LIBS_INIT})
diff --git a/cmake/config.cmake.in b/cmake/config.cmake.in
index b4fd29d..8baabf0 100644
--- a/cmake/config.cmake.in
+++ b/cmake/config.cmake.in
@@ -1,3 +1,5 @@
@PACKAGE_INIT@
-include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
+if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@)
+ include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
+endif()
check_required_components("@PROJECT_NAME@")
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 977e419..f951264 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -5,7 +5,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "JSON for Modern C++"
-PROJECT_NUMBER = 3.1.2
+PROJECT_NUMBER = 3.2.0
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = .
diff --git a/doc/avatars.png b/doc/avatars.png
index 0024190..4798d3b 100644
--- a/doc/avatars.png
+++ b/doc/avatars.png
Binary files differ
diff --git a/doc/examples/README.cpp b/doc/examples/README.cpp
index 04b488d..2d641e5 100644
--- a/doc/examples/README.cpp
+++ b/doc/examples/README.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/README.link b/doc/examples/README.link
index 45b4cfb..a9d70c4 100644
--- a/doc/examples/README.link
+++ b/doc/examples/README.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/TarF5pPn9NtHQjhf"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/VexEaSCbbvOOXsPt"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/diff.cpp b/doc/examples/diff.cpp
index a29f14d..71b19be 100644
--- a/doc/examples/diff.cpp
+++ b/doc/examples/diff.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/diff.link b/doc/examples/diff.link
index dfd1772..8873343 100644
--- a/doc/examples/diff.link
+++ b/doc/examples/diff.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/tfI8DuCuZs3VB9VF"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/3OPLSVPyweUyEHaX"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/flatten.cpp b/doc/examples/flatten.cpp
index 2bd7e9e..83f3ff6 100644
--- a/doc/examples/flatten.cpp
+++ b/doc/examples/flatten.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/flatten.link b/doc/examples/flatten.link
index 8eb81a6..d28cafb 100644
--- a/doc/examples/flatten.link
+++ b/doc/examples/flatten.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/E1HQedkl1zo48WW5"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/4bn447WQbTERfBaL"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_cbor.cpp b/doc/examples/from_cbor.cpp
index 633b3e7..e49987e 100644
--- a/doc/examples/from_cbor.cpp
+++ b/doc/examples/from_cbor.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/from_cbor.link b/doc/examples/from_cbor.link
index 6e27db9..a1798c9 100644
--- a/doc/examples/from_cbor.link
+++ b/doc/examples/from_cbor.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/mya8dUDcDDVoUlBZ"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/AHKW5EMQN4YQ68TY"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_msgpack.cpp b/doc/examples/from_msgpack.cpp
index 8a99b3c..67fdc45 100644
--- a/doc/examples/from_msgpack.cpp
+++ b/doc/examples/from_msgpack.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/from_msgpack.link b/doc/examples/from_msgpack.link
index ddfdcb3..4512c13 100644
--- a/doc/examples/from_msgpack.link
+++ b/doc/examples/from_msgpack.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/sMmEKxW5MGOgLC7z"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/J0KoQF8sOpdMg4kN"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/from_ubjson.cpp b/doc/examples/from_ubjson.cpp
index b20999f..a84057e 100644
--- a/doc/examples/from_ubjson.cpp
+++ b/doc/examples/from_ubjson.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/from_ubjson.link b/doc/examples/from_ubjson.link
index 2855f18..390612b 100644
--- a/doc/examples/from_ubjson.link
+++ b/doc/examples/from_ubjson.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/qq29jfETq7nZRrh5"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/uuQK0DAjhbSd96K6"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/meta.cpp b/doc/examples/meta.cpp
index e800b9b..a051575 100644
--- a/doc/examples/meta.cpp
+++ b/doc/examples/meta.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/meta.link b/doc/examples/meta.link
index 4da2b02..f571745 100644
--- a/doc/examples/meta.link
+++ b/doc/examples/meta.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/0zdmfNQCe4TMw0iI"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/eFzRNyod3g4aVkvl"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/meta.output b/doc/examples/meta.output
index 3c4bf32..3683a17 100644
--- a/doc/examples/meta.output
+++ b/doc/examples/meta.output
@@ -2,7 +2,7 @@
"compiler": {
"c++": "201103",
"family": "clang",
- "version": "9.0.0 (clang-900.0.39.2)"
+ "version": "9.1.0 (clang-902.0.39.2)"
},
"copyright": "(C) 2013-2017 Niels Lohmann",
"name": "JSON for Modern C++",
@@ -10,8 +10,8 @@
"url": "https://github.com/nlohmann/json",
"version": {
"major": 3,
- "minor": 1,
- "patch": 2,
- "string": "3.1.2"
+ "minor": 2,
+ "patch": 0,
+ "string": "3.2.0"
}
}
diff --git a/doc/examples/operator__greater.cpp b/doc/examples/operator__greater.cpp
index c632387..65bb9c0 100644
--- a/doc/examples/operator__greater.cpp
+++ b/doc/examples/operator__greater.cpp
@@ -17,8 +17,8 @@
// output values and comparisons
std::cout << std::boolalpha;
- std::cout << array_1 << " == " << array_2 << " " << (array_1 > array_2) << '\n';
- std::cout << object_1 << " == " << object_2 << " " << (object_1 > object_2) << '\n';
- std::cout << number_1 << " == " << number_2 << " " << (number_1 > number_2) << '\n';
- std::cout << string_1 << " == " << string_2 << " " << (string_1 > string_2) << '\n';
+ std::cout << array_1 << " > " << array_2 << " " << (array_1 > array_2) << '\n';
+ std::cout << object_1 << " > " << object_2 << " " << (object_1 > object_2) << '\n';
+ std::cout << number_1 << " > " << number_2 << " " << (number_1 > number_2) << '\n';
+ std::cout << string_1 << " > " << string_2 << " " << (string_1 > string_2) << '\n';
}
diff --git a/doc/examples/operator__greater.link b/doc/examples/operator__greater.link
index 3fc848e..c59a48a 100644
--- a/doc/examples/operator__greater.link
+++ b/doc/examples/operator__greater.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/yiz7oCHVpFHSALB1"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/ntF7DMzC85gbQKHu"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/operator__greater.output b/doc/examples/operator__greater.output
index 045847c..910c48e 100644
--- a/doc/examples/operator__greater.output
+++ b/doc/examples/operator__greater.output
@@ -1,4 +1,4 @@
-[1,2,3] == [1,2,4] false
-{"A":"a","B":"b"} == {"A":"a","B":"b"} false
-17 == 17.0000000000001 false
-"foo" == "bar" true
+[1,2,3] > [1,2,4] false
+{"A":"a","B":"b"} > {"A":"a","B":"b"} false
+17 > 17.0000000000001 false
+"foo" > "bar" true
diff --git a/doc/examples/operator_deserialize.cpp b/doc/examples/operator_deserialize.cpp
index bf21448..8e3d8bd 100644
--- a/doc/examples/operator_deserialize.cpp
+++ b/doc/examples/operator_deserialize.cpp
@@ -1,4 +1,6 @@
#include <iostream>
+#include <iomanip>
+#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/operator_deserialize.link b/doc/examples/operator_deserialize.link
index 72d7350..1d34af2 100644
--- a/doc/examples/operator_deserialize.link
+++ b/doc/examples/operator_deserialize.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/YrUqrUFMD7JHwSQR"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/IvgowYGaX0SgOFIG"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/operator_serialize.cpp b/doc/examples/operator_serialize.cpp
index 0c46f01..3bd4ad5 100644
--- a/doc/examples/operator_serialize.cpp
+++ b/doc/examples/operator_serialize.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/operator_serialize.link b/doc/examples/operator_serialize.link
index 57edc8c..2367d1c 100644
--- a/doc/examples/operator_serialize.link
+++ b/doc/examples/operator_serialize.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/wXcm4ObnoaXw7CRt"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/ckGZIBookDffV00n"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/operatorarray__key_type.cpp b/doc/examples/operatorarray__key_type.cpp
index 8db08d0..f9b7f73 100644
--- a/doc/examples/operatorarray__key_type.cpp
+++ b/doc/examples/operatorarray__key_type.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/operatorarray__key_type.link b/doc/examples/operatorarray__key_type.link
index c1a534b..50fd455 100644
--- a/doc/examples/operatorarray__key_type.link
+++ b/doc/examples/operatorarray__key_type.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/vxt8d8qvYorXS2yq"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/oKnfnFrLHG8H1OAl"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/parse__array__parser_callback_t.cpp b/doc/examples/parse__array__parser_callback_t.cpp
index 6083a95..63f0a0e 100644
--- a/doc/examples/parse__array__parser_callback_t.cpp
+++ b/doc/examples/parse__array__parser_callback_t.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/parse__array__parser_callback_t.link b/doc/examples/parse__array__parser_callback_t.link
index 017f9ff..02a92b8 100644
--- a/doc/examples/parse__array__parser_callback_t.link
+++ b/doc/examples/parse__array__parser_callback_t.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/TSNxHmegVwLW2pXf"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/i3BBhl7Ub5y9b0yp"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp b/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp
index fe51560..14cfa25 100644
--- a/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp
+++ b/doc/examples/parse__contiguouscontainer__parser_callback_t.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/parse__contiguouscontainer__parser_callback_t.link b/doc/examples/parse__contiguouscontainer__parser_callback_t.link
index 2cc9659..8153d5d 100644
--- a/doc/examples/parse__contiguouscontainer__parser_callback_t.link
+++ b/doc/examples/parse__contiguouscontainer__parser_callback_t.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/l3zNo3YKC2X8yAw9"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/sGdJMOaJnFNJBtH7"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/parse__istream__parser_callback_t.cpp b/doc/examples/parse__istream__parser_callback_t.cpp
index 92e62d9..afcaa39 100644
--- a/doc/examples/parse__istream__parser_callback_t.cpp
+++ b/doc/examples/parse__istream__parser_callback_t.cpp
@@ -1,4 +1,6 @@
#include <iostream>
+#include <iomanip>
+#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/parse__istream__parser_callback_t.link b/doc/examples/parse__istream__parser_callback_t.link
index 64b703a..3b51c08 100644
--- a/doc/examples/parse__istream__parser_callback_t.link
+++ b/doc/examples/parse__istream__parser_callback_t.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/Mf7A6JtvqT1Na7Pk"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/UZgRBIeqdZhm6M8F"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/parse__iteratortype__parser_callback_t.cpp b/doc/examples/parse__iteratortype__parser_callback_t.cpp
index b513fe7..1b5e23d 100644
--- a/doc/examples/parse__iteratortype__parser_callback_t.cpp
+++ b/doc/examples/parse__iteratortype__parser_callback_t.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/parse__iteratortype__parser_callback_t.link b/doc/examples/parse__iteratortype__parser_callback_t.link
index 9adda14..4e0174a 100644
--- a/doc/examples/parse__iteratortype__parser_callback_t.link
+++ b/doc/examples/parse__iteratortype__parser_callback_t.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/oa6BVkBXjG8DNkzX"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/VThe0hdMSUdNSOLK"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/parse__string__parser_callback_t.cpp b/doc/examples/parse__string__parser_callback_t.cpp
index 4db82d9..2ae4410 100644
--- a/doc/examples/parse__string__parser_callback_t.cpp
+++ b/doc/examples/parse__string__parser_callback_t.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/parse__string__parser_callback_t.link b/doc/examples/parse__string__parser_callback_t.link
index 8eab4cd..fb6bec0 100644
--- a/doc/examples/parse__string__parser_callback_t.link
+++ b/doc/examples/parse__string__parser_callback_t.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/QXdl4yzts3qPeZ0U"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/QZgjsR0PiAw2Lqpk"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/patch.cpp b/doc/examples/patch.cpp
index a3c64a6..b0896c7 100644
--- a/doc/examples/patch.cpp
+++ b/doc/examples/patch.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/patch.link b/doc/examples/patch.link
index 1997062..1a9d189 100644
--- a/doc/examples/patch.link
+++ b/doc/examples/patch.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/8ObNa6ejw4BXQ5qG"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/hFd1W46W2Hb81sHN"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/sax_parse.cpp b/doc/examples/sax_parse.cpp
new file mode 100644
index 0000000..69e8962
--- /dev/null
+++ b/doc/examples/sax_parse.cpp
@@ -0,0 +1,124 @@
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <nlohmann/json.hpp>
+
+using json = nlohmann::json;
+
+// a simple event consumer that collects string representations of the passed
+// values; not inheriting from json::json_sax_t is not required, but can
+// help not to forget a required function
+class sax_event_consumer : public json::json_sax_t
+{
+ public:
+ std::vector<std::string> events;
+
+ bool null() override
+ {
+ events.push_back("value: null");
+ return true;
+ }
+
+ bool boolean(bool val) override
+ {
+ events.push_back("value: " + std::string(val ? "true" : "false"));
+ return true;
+ }
+
+ bool number_integer(number_integer_t val) override
+ {
+ events.push_back("value: " + std::to_string(val));
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val) override
+ {
+ events.push_back("value: " + std::to_string(val));
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t& s) override
+ {
+ events.push_back("value: " + s);
+ return true;
+ }
+
+ bool string(string_t& val) override
+ {
+ events.push_back("value: " + val);
+ return true;
+ }
+
+ bool start_object(std::size_t elements) override
+ {
+ events.push_back("start: object");
+ return true;
+ }
+
+ bool end_object() override
+ {
+ events.push_back("end: object");
+ return true;
+ }
+
+ bool start_array(std::size_t elements) override
+ {
+ events.push_back("start: array");
+ return true;
+ }
+
+ bool end_array() override
+ {
+ events.push_back("end: array");
+ return true;
+ }
+
+ bool key(string_t& val) override
+ {
+ events.push_back("key: " + val);
+ return true;
+ }
+
+ bool parse_error(std::size_t position, const std::string& last_token, const json::exception& ex) override
+ {
+ events.push_back("error: " + std::string(ex.what()));
+ return false;
+ }
+};
+
+int main()
+{
+ // a JSON text
+ auto text = R"(
+ {
+ "Image": {
+ "Width": 800,
+ "Height": 600,
+ "Title": "View from 15th Floor",
+ "Thumbnail": {
+ "Url": "http://www.example.com/image/481989943",
+ "Height": 125,
+ "Width": 100
+ },
+ "Animated" : false,
+ "IDs": [116, 943, 234, 38793],
+ "Distance": 12.723374634
+ }
+ }
+ )";
+
+ // create a SAX event consumer object
+ sax_event_consumer sec;
+
+ // parse and serialize JSON
+ bool result = json::sax_parse(text, &sec);
+
+ // output the recorded events
+ for (auto& event : sec.events)
+ {
+ std::cout << "(" << event << ") ";
+ }
+
+ // output the result of sax_parse
+ std::cout << "\nresult: " << std::boolalpha << result << std::endl;
+}
diff --git a/doc/examples/sax_parse.link b/doc/examples/sax_parse.link
new file mode 100644
index 0000000..14aa5e3
--- /dev/null
+++ b/doc/examples/sax_parse.link
@@ -0,0 +1 @@
+<a target="_blank" href="https://wandbox.org/permlink/fGkQLWbQn7enKkIG"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/sax_parse.output b/doc/examples/sax_parse.output
new file mode 100644
index 0000000..e16c2c4
--- /dev/null
+++ b/doc/examples/sax_parse.output
@@ -0,0 +1,2 @@
+(start: object) (key: Image) (start: object) (key: Width) (value: 800) (key: Height) (value: 600) (key: Title) (value: View from 15th Floor) (key: Thumbnail) (start: object) (key: Url) (value: http://www.example.com/image/481989943) (key: Height) (value: 125) (key: Width) (value: 100) (end: object) (key: Animated) (value: false) (key: IDs) (start: array) (value: 116) (value: 943) (value: 234) (value: 38793) (end: array) (key: Distance) (value: 12.723374634) (end: object) (end: object)
+result: true
diff --git a/doc/examples/to_cbor.cpp b/doc/examples/to_cbor.cpp
index b4849c1..1237ca8 100644
--- a/doc/examples/to_cbor.cpp
+++ b/doc/examples/to_cbor.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/to_cbor.link b/doc/examples/to_cbor.link
index 31f4809..bc4543a 100644
--- a/doc/examples/to_cbor.link
+++ b/doc/examples/to_cbor.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/4bQSclXeqjVFYVL3"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/LRM37xarSuPJmv92"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_msgpack.cpp b/doc/examples/to_msgpack.cpp
index 8b18a12..99cc9ed 100644
--- a/doc/examples/to_msgpack.cpp
+++ b/doc/examples/to_msgpack.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/to_msgpack.link b/doc/examples/to_msgpack.link
index dfc0d33..9a3a098 100644
--- a/doc/examples/to_msgpack.link
+++ b/doc/examples/to_msgpack.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/WvT2Q0r9vlJYyMM8"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/CaRFhkrefL4miesE"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/to_ubjson.cpp b/doc/examples/to_ubjson.cpp
index 8a25e61..06b2abb 100644
--- a/doc/examples/to_ubjson.cpp
+++ b/doc/examples/to_ubjson.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/to_ubjson.link b/doc/examples/to_ubjson.link
index add6fe4..f565adb 100644
--- a/doc/examples/to_ubjson.link
+++ b/doc/examples/to_ubjson.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/j3HE6cOkCmKbxxAt"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/2luqHy9iADx4UNm7"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/unflatten.cpp b/doc/examples/unflatten.cpp
index 5e3d65e..75fb02d 100644
--- a/doc/examples/unflatten.cpp
+++ b/doc/examples/unflatten.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/unflatten.link b/doc/examples/unflatten.link
index d13f171..1af6853 100644
--- a/doc/examples/unflatten.link
+++ b/doc/examples/unflatten.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/U45AGi5nsDtoDf3u"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/knK4jnD2hIVxQoyk"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/update.cpp b/doc/examples/update.cpp
index b77c0fe..fecdae7 100644
--- a/doc/examples/update.cpp
+++ b/doc/examples/update.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/update.link b/doc/examples/update.link
index 5ad367d..1aa7e60 100644
--- a/doc/examples/update.link
+++ b/doc/examples/update.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/TGvdYyJtstacZxWq"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/kjcoWACW7FMqKRBG"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/examples/update__range.cpp b/doc/examples/update__range.cpp
index 88780fd..9f3e521 100644
--- a/doc/examples/update__range.cpp
+++ b/doc/examples/update__range.cpp
@@ -1,4 +1,5 @@
#include <iostream>
+#include <iomanip>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
diff --git a/doc/examples/update__range.link b/doc/examples/update__range.link
index d2d85a8..222c6e6 100644
--- a/doc/examples/update__range.link
+++ b/doc/examples/update__range.link
@@ -1 +1 @@
-<a target="_blank" href="https://wandbox.org/permlink/BMlas6312rkE4cxz"><b>online</b></a>
\ No newline at end of file
+<a target="_blank" href="https://wandbox.org/permlink/0LBIsEa18IrerWwy"><b>online</b></a>
\ No newline at end of file
diff --git a/doc/index.md b/doc/index.md
index b3d6114..a2ad364 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -39,9 +39,11 @@
- @link nlohmann::basic_json::dump dump @endlink serialize to string
- @link nlohmann::basic_json::operator<<(std::ostream&, const basic_json &) operator<< @endlink serialize to stream
- deserialization / parsing
- - @link nlohmann::basic_json::parse parse @endlink parse from string
+ - @link nlohmann::basic_json::parse parse @endlink parse from input (string, file, etc.) and return JSON value
+ - @link nlohmann::basic_json::sax_parse sax_parse @endlink parse from input (string, file, etc.) and generate SAX events
- @link nlohmann::basic_json::operator>>(std::istream&, basic_json&) operator>> @endlink parse from stream
- @link nlohmann::basic_json::accept accept @endlink check for syntax errors without parsing
+ - @link nlohmann::json_sax SAX interface @endlink define a user-defined SAX event consumer
- [binary formats](binary_formats.md):
- CBOR: @link nlohmann::basic_json::from_cbor from_cbor @endlink / @link nlohmann::basic_json::to_cbor to_cbor @endlink
- MessagePack: @link nlohmann::basic_json::from_msgpack from_msgpack @endlink / @link nlohmann::basic_json::to_msgpack to_msgpack @endlink
@@ -304,4 +306,4 @@
@author [Niels Lohmann](http://nlohmann.me)
@see https://github.com/nlohmann/json to download the source code
-@version 3.1.2
+@version 3.2.0
diff --git a/doc/json.gif b/doc/json.gif
index 7d2d3c7..0c00d9f 100644
--- a/doc/json.gif
+++ b/doc/json.gif
Binary files differ
diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp
index eccc04f..5956352 100644
--- a/include/nlohmann/detail/conversions/from_json.hpp
+++ b/include/nlohmann/detail/conversions/from_json.hpp
@@ -5,21 +5,34 @@
#include <ciso646> // and, not
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
+#include <map> // map
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
-#include <nlohmann/detail/meta.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
+#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
{
namespace detail
{
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+ if (JSON_UNLIKELY(not j.is_null()))
+ {
+ JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
+ }
+ n = nullptr;
+}
+
// overloads for basic_json template parameters
template<typename BasicJsonType, typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
@@ -70,6 +83,23 @@
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
+template <
+ typename BasicJsonType, typename CompatibleStringType,
+ enable_if_t <
+ is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
+ not std::is_same<typename BasicJsonType::string_t,
+ CompatibleStringType>::value,
+ int > = 0 >
+void from_json(const BasicJsonType& j, CompatibleStringType& s)
+{
+ if (JSON_UNLIKELY(not j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
+ }
+
+ s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
@@ -277,6 +307,44 @@
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
}
+template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+ typename = enable_if_t<not std::is_constructible<
+ typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ for (const auto& p : j)
+ {
+ if (JSON_UNLIKELY(not p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
+template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+ typename = enable_if_t<not std::is_constructible<
+ typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ for (const auto& p : j)
+ {
+ if (JSON_UNLIKELY(not p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
struct from_json_fn
{
private:
diff --git a/include/nlohmann/detail/conversions/to_chars.hpp b/include/nlohmann/detail/conversions/to_chars.hpp
index 186b62e..a13d258 100644
--- a/include/nlohmann/detail/conversions/to_chars.hpp
+++ b/include/nlohmann/detail/conversions/to_chars.hpp
@@ -887,7 +887,7 @@
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
// decimal representations are not exactly "short".
//
- // The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars)
+ // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
// does.
diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp
index ce2bc0a..35be5de 100644
--- a/include/nlohmann/detail/conversions/to_json.hpp
+++ b/include/nlohmann/detail/conversions/to_json.hpp
@@ -8,8 +8,10 @@
#include <valarray> // valarray
#include <vector> // vector
-#include <nlohmann/detail/meta.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
+#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
+#include <nlohmann/detail/iterators/iteration_proxy.hpp>
namespace nlohmann
{
@@ -51,6 +53,16 @@
j.m_value = std::move(s);
j.assert_invariant();
}
+
+ template<typename BasicJsonType, typename CompatibleStringType,
+ enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+ int> = 0>
+ static void construct(BasicJsonType& j, const CompatibleStringType& str)
+ {
+ j.m_type = value_t::string;
+ j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+ j.assert_invariant();
+ }
};
template<>
@@ -247,7 +259,7 @@
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
-void to_json(BasicJsonType& j, std::valarray<T> arr)
+void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
@@ -284,6 +296,14 @@
j = {p.first, p.second};
}
+// for https://github.com/nlohmann/json/pull/1134
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+ j = {{b.key(), b.value()}};
+}
+
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
{
diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp
index d4ca38f..05ab36f 100644
--- a/include/nlohmann/detail/input/binary_reader.hpp
+++ b/include/nlohmann/detail/input/binary_reader.hpp
@@ -6,18 +6,18 @@
#include <cmath> // ldexp
#include <cstddef> // size_t
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
#include <cstring> // memcpy
-#include <iomanip> // setw, setfill
-#include <ios> // hex
#include <iterator> // back_inserter
#include <limits> // numeric_limits
-#include <sstream> // stringstream
#include <string> // char_traits, string
#include <utility> // make_pair, move
#include <nlohmann/detail/input/input_adapters.hpp>
+#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
+#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@@ -29,14 +29,16 @@
///////////////////
/*!
-@brief deserialization of CBOR and MessagePack values
+@brief deserialization of CBOR, MessagePack, and UBJSON values
*/
-template<typename BasicJsonType>
+template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
class binary_reader
{
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
+ using json_sax_t = SAX;
public:
/*!
@@ -46,70 +48,63 @@
*/
explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
{
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
assert(ia);
}
/*!
- @brief create a JSON value from CBOR input
-
+ @param[in] format the binary format to parse
+ @param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from CBOR input
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
+ @return
*/
- BasicJsonType parse_cbor(const bool strict)
+ bool sax_parse(const input_format_t format,
+ json_sax_t* sax_,
+ const bool strict = true)
{
- const auto res = parse_cbor_internal();
- if (strict)
+ sax = sax_;
+ bool result = false;
+
+ switch (format)
{
- get();
- expect_eof();
+ case input_format_t::cbor:
+ result = parse_cbor_internal();
+ break;
+
+ case input_format_t::msgpack:
+ result = parse_msgpack_internal();
+ break;
+
+ case input_format_t::ubjson:
+ result = parse_ubjson_internal();
+ break;
+
+ // LCOV_EXCL_START
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
}
- return res;
- }
- /*!
- @brief create a JSON value from MessagePack input
-
- @param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from MessagePack input
-
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
- */
- BasicJsonType parse_msgpack(const bool strict)
- {
- const auto res = parse_msgpack_internal();
- if (strict)
+ // strict mode: next byte must be EOF
+ if (result and strict)
{
- get();
- expect_eof();
+ if (format == input_format_t::ubjson)
+ {
+ get_ignore_noop();
+ }
+ else
+ {
+ get();
+ }
+
+ if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
+ }
}
- return res;
- }
- /*!
- @brief create a JSON value from UBJSON input
-
- @param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from UBJSON input
-
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
- */
- BasicJsonType parse_ubjson(const bool strict)
- {
- const auto res = parse_ubjson_internal();
- if (strict)
- {
- get_ignore_noop();
- expect_eof();
- }
- return res;
+ return result;
}
/*!
@@ -129,14 +124,16 @@
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
+
+ @return whether a valid CBOR value was passed to the SAX parser
*/
- BasicJsonType parse_cbor_internal(const bool get_char = true)
+ bool parse_cbor_internal(const bool get_char = true)
{
switch (get_char ? get() : current)
{
// EOF
case std::char_traits<char>::eof():
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
// Integer 0x00..0x17 (0..23)
case 0x00:
@@ -163,19 +160,31 @@
case 0x15:
case 0x16:
case 0x17:
- return static_cast<number_unsigned_t>(current);
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
case 0x18: // Unsigned integer (one-byte uint8_t follows)
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x19: // Unsigned integer (two-byte uint16_t follows)
- return get_number<uint16_t>();
+ {
+ uint16_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
- return get_number<uint32_t>();
+ {
+ uint32_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
- return get_number<uint64_t>();
+ {
+ uint64_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
// Negative integer -1-0x00..-1-0x17 (-1..-24)
case 0x20:
@@ -202,27 +211,31 @@
case 0x35:
case 0x36:
case 0x37:
- return static_cast<int8_t>(0x20 - 1 - current);
+ return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
case 0x38: // Negative integer (one-byte uint8_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint8_t>();
+ uint8_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint16_t>();
+ uint16_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint32_t>();
+ uint32_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
{
- return static_cast<number_integer_t>(-1) -
- static_cast<number_integer_t>(get_number<uint64_t>());
+ uint64_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1)
+ - static_cast<number_integer_t>(number));
}
// UTF-8 string (0x00..0x17 bytes follow)
@@ -256,7 +269,8 @@
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
case 0x7F: // UTF-8 string (indefinite length)
{
- return get_cbor_string();
+ string_t s;
+ return get_cbor_string(s) and sax->string(s);
}
// array (0x00..0x17 data items follow)
@@ -284,39 +298,34 @@
case 0x95:
case 0x96:
case 0x97:
- {
- return get_cbor_array(current & 0x1F);
- }
+ return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
case 0x98: // array (one-byte uint8_t for n follows)
{
- return get_cbor_array(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x99: // array (two-byte uint16_t for n follow)
{
- return get_cbor_array(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9A: // array (four-byte uint32_t for n follow)
{
- return get_cbor_array(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
- return get_cbor_array(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9F: // array (indefinite length)
- {
- BasicJsonType result = value_t::array;
- while (get() != 0xFF)
- {
- result.push_back(parse_cbor_internal(false));
- }
- return result;
- }
+ return get_cbor_array(std::size_t(-1));
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
@@ -343,62 +352,56 @@
case 0xB5:
case 0xB6:
case 0xB7:
- {
- return get_cbor_object(current & 0x1F);
- }
+ return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
case 0xB8: // map (one-byte uint8_t for n follows)
{
- return get_cbor_object(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xB9: // map (two-byte uint16_t for n follow)
{
- return get_cbor_object(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBA: // map (four-byte uint32_t for n follow)
{
- return get_cbor_object(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
- return get_cbor_object(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBF: // map (indefinite length)
- {
- BasicJsonType result = value_t::object;
- while (get() != 0xFF)
- {
- auto key = get_cbor_string();
- result[key] = parse_cbor_internal();
- }
- return result;
- }
+ return get_cbor_object(std::size_t(-1));
case 0xF4: // false
- {
- return false;
- }
+ return sax->boolean(false);
case 0xF5: // true
- {
- return true;
- }
+ return sax->boolean(true);
case 0xF6: // null
- {
- return value_t::null;
- }
+ return sax->null();
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
{
const int byte1 = get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
const int byte2 = get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
// code from RFC 7049, Appendix D, Figure 3:
// As half-precision floating-point numbers were only added
@@ -409,51 +412,59 @@
// half-precision floating-point numbers in the C language
// is shown in Fig. 3.
const int half = (byte1 << 8) + byte2;
- const int exp = (half >> 10) & 0x1F;
- const int mant = half & 0x3FF;
- double val;
- if (exp == 0)
+ const double val = [&half]
{
- val = std::ldexp(mant, -24);
- }
- else if (exp != 31)
- {
- val = std::ldexp(mant + 1024, exp - 25);
- }
- else
- {
- val = (mant == 0) ? std::numeric_limits<double>::infinity()
- : std::numeric_limits<double>::quiet_NaN();
- }
- return (half & 0x8000) != 0 ? -val : val;
+ const int exp = (half >> 10) & 0x1F;
+ const int mant = half & 0x3FF;
+ assert(0 <= exp and exp <= 32);
+ assert(0 <= mant and mant <= 1024);
+ switch (exp)
+ {
+ case 0:
+ return std::ldexp(mant, -24);
+ case 31:
+ return (mant == 0)
+ ? std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::quiet_NaN();
+ default:
+ return std::ldexp(mant + 1024, exp - 25);
+ }
+ }();
+ return sax->number_float((half & 0x8000) != 0
+ ? static_cast<number_float_t>(-val)
+ : static_cast<number_float_t>(val), "");
}
case 0xFA: // Single-Precision Float (four-byte IEEE 754)
{
- return get_number<float>();
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
}
case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
{
- return get_number<double>();
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
}
default: // anything else (0xFF is handled inside the other types)
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token));
}
}
}
- BasicJsonType parse_msgpack_internal()
+ /*!
+ @return whether a valid MessagePack value was passed to the SAX parser
+ */
+ bool parse_msgpack_internal()
{
switch (get())
{
// EOF
case std::char_traits<char>::eof():
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
// positive fixint
case 0x00:
@@ -584,7 +595,7 @@
case 0x7D:
case 0x7E:
case 0x7F:
- return static_cast<number_unsigned_t>(current);
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
// fixmap
case 0x80:
@@ -603,9 +614,7 @@
case 0x8D:
case 0x8E:
case 0x8F:
- {
- return get_msgpack_object(current & 0x0F);
- }
+ return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
// fixarray
case 0x90:
@@ -624,9 +633,7 @@
case 0x9D:
case 0x9E:
case 0x9F:
- {
- return get_msgpack_array(current & 0x0F);
- }
+ return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
// fixstr
case 0xA0:
@@ -661,73 +668,113 @@
case 0xBD:
case 0xBE:
case 0xBF:
- return get_msgpack_string();
+ {
+ string_t s;
+ return get_msgpack_string(s) and sax->string(s);
+ }
case 0xC0: // nil
- return value_t::null;
+ return sax->null();
case 0xC2: // false
- return false;
+ return sax->boolean(false);
case 0xC3: // true
- return true;
+ return sax->boolean(true);
case 0xCA: // float 32
- return get_number<float>();
+ {
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 0xCB: // float 64
- return get_number<double>();
+ {
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 0xCC: // uint 8
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCD: // uint 16
- return get_number<uint16_t>();
+ {
+ uint16_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCE: // uint 32
- return get_number<uint32_t>();
+ {
+ uint32_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCF: // uint 64
- return get_number<uint64_t>();
+ {
+ uint64_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xD0: // int 8
- return get_number<int8_t>();
+ {
+ int8_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD1: // int 16
- return get_number<int16_t>();
+ {
+ int16_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD2: // int 32
- return get_number<int32_t>();
+ {
+ int32_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD3: // int 64
- return get_number<int64_t>();
+ {
+ int64_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD9: // str 8
case 0xDA: // str 16
case 0xDB: // str 32
- return get_msgpack_string();
+ {
+ string_t s;
+ return get_msgpack_string(s) and sax->string(s);
+ }
case 0xDC: // array 16
{
- return get_msgpack_array(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDD: // array 32
{
- return get_msgpack_array(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDE: // map 16
{
- return get_msgpack_object(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
}
case 0xDF: // map 32
{
- return get_msgpack_object(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
}
- // positive fixint
+ // negative fixint
case 0xE0:
case 0xE1:
case 0xE2:
@@ -760,14 +807,12 @@
case 0xFD:
case 0xFE:
case 0xFF:
- return static_cast<int8_t>(current);
+ return sax->number_integer(static_cast<int8_t>(current));
default: // anything else
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "error reading MessagePack; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token));
}
}
}
@@ -776,8 +821,10 @@
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
+
+ @return whether a valid UBJSON value was passed to the SAX parser
*/
- BasicJsonType parse_ubjson_internal(const bool get_char = true)
+ bool parse_ubjson_internal(const bool get_char = true)
{
return get_ubjson_value(get_char ? get_ignore_noop() : current);
}
@@ -815,23 +862,26 @@
@brief read a number from the input
@tparam NumberType the type of the number
+ @param[out] result number of type @a NumberType
- @return number of type @a NumberType
+ @return whether conversion completed
@note This function needs to respect the system's endianess, because
- bytes in CBOR and MessagePack are stored in network order (big
- endian) and therefore need reordering on little endian systems.
-
- @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
+ bytes in CBOR, MessagePack, and UBJSON are stored in network order
+ (big endian) and therefore need reordering on little endian systems.
*/
- template<typename NumberType> NumberType get_number()
+ template<typename NumberType>
+ bool get_number(NumberType& result)
{
// step 1: read input into array with system's byte order
std::array<uint8_t, sizeof(NumberType)> vec;
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
// reverse byte order prior to conversion if necessary
if (is_little_endian)
@@ -845,35 +895,37 @@
}
// step 2: convert array into number of type T and return
- NumberType result;
std::memcpy(&result, vec.data(), sizeof(NumberType));
- return result;
+ return true;
}
/*!
@brief create a string by reading characters from the input
- @param[in] len number of bytes to read
+ @tparam NumberType the type of the number
+ @param[in] len number of characters to read
+ @param[out] string created by reading @a len bytes
+
+ @return whether string creation completed
@note We can not reserve @a len bytes for the result, because @a len
may be too large. Usually, @ref unexpect_eof() detects the end of
the input before we run out of string memory.
-
- @return string created by reading @a len bytes
-
- @throw parse_error.110 if input has less than @a len bytes
*/
template<typename NumberType>
- string_t get_string(const NumberType len)
+ bool get_string(const NumberType len, string_t& result)
{
- string_t result;
- std::generate_n(std::back_inserter(result), len, [this]()
+ bool success = true;
+ std::generate_n(std::back_inserter(result), len, [this, &success]()
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ success = false;
+ }
return static_cast<char>(current);
});
- return result;
+ return success;
}
/*!
@@ -883,14 +935,16 @@
string length and then copies this number of bytes into a string.
Additionally, CBOR's strings with indefinite lengths are supported.
- @return string
+ @param[out] result created string
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_cbor_string()
+ bool get_cbor_string(string_t& result)
{
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
@@ -920,73 +974,137 @@
case 0x76:
case 0x77:
{
- return get_string(current & 0x1F);
+ return get_string(current & 0x1F, result);
}
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{
- return get_string(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{
- return get_string(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
{
- return get_string(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
{
- return get_string(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7F: // UTF-8 string (indefinite length)
{
- string_t result;
while (get() != 0xFF)
{
- result.append(get_cbor_string());
+ string_t chunk;
+ if (not get_cbor_string(chunk))
+ {
+ return false;
+ }
+ result.append(chunk);
}
- return result;
+ return true;
}
default:
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token));
}
}
}
- template<typename NumberType>
- BasicJsonType get_cbor_array(const NumberType len)
+ /*!
+ @param[in] len the length of the array or std::size_t(-1) for an
+ array of indefinite size
+ @return whether array creation completed
+ */
+ bool get_cbor_array(const std::size_t len)
{
- BasicJsonType result = value_t::array;
- std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ if (JSON_UNLIKELY(not sax->start_array(len)))
{
- return parse_cbor_internal();
- });
- return result;
+ return false;
+ }
+
+ if (len != std::size_t(-1))
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_UNLIKELY(not parse_cbor_internal(false)))
+ {
+ return false;
+ }
+ }
+ }
+
+ return sax->end_array();
}
- template<typename NumberType>
- BasicJsonType get_cbor_object(const NumberType len)
+ /*!
+ @param[in] len the length of the object or std::size_t(-1) for an
+ object of indefinite size
+ @return whether object creation completed
+ */
+ bool get_cbor_object(const std::size_t len)
{
- BasicJsonType result = value_t::object;
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- len, [this]()
+ if (not JSON_UNLIKELY(sax->start_object(len)))
{
- get();
- auto key = get_cbor_string();
- auto val = parse_cbor_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
- return result;
+ return false;
+ }
+
+ string_t key;
+ if (len != std::size_t(-1))
+ {
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ get();
+ if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+
+ return sax->end_object();
}
/*!
@@ -995,14 +1113,16 @@
This function first reads starting bytes to determine the expected
string length and then copies this number of bytes into a string.
- @return string
+ @param[out] result created string
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_msgpack_string()
+ bool get_msgpack_string(string_t& result)
{
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
@@ -1040,59 +1160,85 @@
case 0xBE:
case 0xBF:
{
- return get_string(current & 0x1F);
+ return get_string(current & 0x1F, result);
}
case 0xD9: // str 8
{
- return get_string(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
}
case 0xDA: // str 16
{
- return get_string(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_string(len, result);
}
case 0xDB: // str 32
{
- return get_string(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_string(len, result);
}
default:
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "expected a MessagePack string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token));
}
}
}
- template<typename NumberType>
- BasicJsonType get_msgpack_array(const NumberType len)
+ /*!
+ @param[in] len the length of the array
+ @return whether array creation completed
+ */
+ bool get_msgpack_array(const std::size_t len)
{
- BasicJsonType result = value_t::array;
- std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ if (JSON_UNLIKELY(not sax->start_array(len)))
{
- return parse_msgpack_internal();
- });
- return result;
+ return false;
+ }
+
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_UNLIKELY(not parse_msgpack_internal()))
+ {
+ return false;
+ }
+ }
+
+ return sax->end_array();
}
- template<typename NumberType>
- BasicJsonType get_msgpack_object(const NumberType len)
+ /*!
+ @param[in] len the length of the object
+ @return whether object creation completed
+ */
+ bool get_msgpack_object(const std::size_t len)
{
- BasicJsonType result = value_t::object;
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- len, [this]()
+ if (JSON_UNLIKELY(not sax->start_object(len)))
+ {
+ return false;
+ }
+
+ string_t key;
+ for (std::size_t i = 0; i < len; ++i)
{
get();
- auto key = get_msgpack_string();
- auto val = parse_msgpack_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
- return result;
+ if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_msgpack_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+
+ return sax->end_object();
}
/*!
@@ -1102,41 +1248,131 @@
indicating a string, or in case of an object key where the 'S' byte can be
left out.
+ @param[out] result created string
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
- @return string
-
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_ubjson_string(const bool get_char = true)
+ bool get_ubjson_string(string_t& result, const bool get_char = true)
{
if (get_char)
{
get(); // TODO: may we ignore N here?
}
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
case 'U':
- return get_string(get_number<uint8_t>());
+ {
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'i':
- return get_string(get_number<int8_t>());
+ {
+ int8_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'I':
- return get_string(get_number<int16_t>());
+ {
+ int16_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'l':
- return get_string(get_number<int32_t>());
+ {
+ int32_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'L':
- return get_string(get_number<int64_t>());
+ {
+ int64_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
default:
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "expected a UBJSON string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token));
+ }
+ }
+
+ /*!
+ @param[out] result determined size
+ @return whether size determination completed
+ */
+ bool get_ubjson_size_value(std::size_t& result)
+ {
+ switch (get_ignore_noop())
+ {
+ case 'U':
+ {
+ uint8_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'i':
+ {
+ int8_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'I':
+ {
+ int16_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'l':
+ {
+ int32_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'L':
+ {
+ int64_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token));
+ }
}
}
@@ -1146,84 +1382,127 @@
In the optimized UBJSON format, a type and a size can be provided to allow
for a more compact representation.
- @return pair of the size and the type
+ @param[out] result pair of the size and the type
+
+ @return whether pair creation completed
*/
- std::pair<std::size_t, int> get_ubjson_size_type()
+ bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
{
- std::size_t sz = string_t::npos;
- int tc = 0;
+ result.first = string_t::npos; // size
+ result.second = 0; // type
get_ignore_noop();
if (current == '$')
{
- tc = get(); // must not ignore 'N', because 'N' maybe the type
- unexpect_eof();
+ result.second = get(); // must not ignore 'N', because 'N' maybe the type
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
get_ignore_noop();
- if (current != '#')
+ if (JSON_UNLIKELY(current != '#'))
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "expected '#' after UBJSON type information; last byte: 0x" + ss.str()));
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token));
}
- sz = parse_ubjson_internal();
+
+ return get_ubjson_size_value(result.first);
}
else if (current == '#')
{
- sz = parse_ubjson_internal();
+ return get_ubjson_size_value(result.first);
}
-
- return std::make_pair(sz, tc);
+ return true;
}
- BasicJsonType get_ubjson_value(const int prefix)
+ /*!
+ @param prefix the previously read or set type prefix
+ @return whether value creation completed
+ */
+ bool get_ubjson_value(const int prefix)
{
switch (prefix)
{
case std::char_traits<char>::eof(): // EOF
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
case 'T': // true
- return true;
+ return sax->boolean(true);
case 'F': // false
- return false;
+ return sax->boolean(false);
case 'Z': // null
- return nullptr;
+ return sax->null();
case 'U':
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
+
case 'i':
- return get_number<int8_t>();
+ {
+ int8_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'I':
- return get_number<int16_t>();
+ {
+ int16_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'l':
- return get_number<int32_t>();
+ {
+ int32_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'L':
- return get_number<int64_t>();
+ {
+ int64_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'd':
- return get_number<float>();
+ {
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
case 'D':
- return get_number<double>();
+ {
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 'C': // char
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
if (JSON_UNLIKELY(current > 127))
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token));
}
- return string_t(1, static_cast<char>(current));
+ string_t s(1, static_cast<char>(current));
+ return sax->string(s);
}
case 'S': // string
- return get_ubjson_string();
+ {
+ string_t s;
+ return get_ubjson_string(s) and sax->string(s);
+ }
case '[': // array
return get_ubjson_array();
@@ -1232,129 +1511,170 @@
return get_ubjson_object();
default: // anything else
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "error reading UBJSON; last byte: 0x" + ss.str()));
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token));
+ }
}
}
- BasicJsonType get_ubjson_array()
+ /*!
+ @return whether array creation completed
+ */
+ bool get_ubjson_array()
{
- BasicJsonType result = value_t::array;
- const auto size_and_type = get_ubjson_size_type();
+ std::pair<std::size_t, int> size_and_type;
+ if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
if (size_and_type.first != string_t::npos)
{
- if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
+ if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
{
- JSON_THROW(out_of_range::create(408,
- "excessive array size: " + std::to_string(size_and_type.first)));
+ return false;
}
if (size_and_type.second != 0)
{
if (size_and_type.second != 'N')
{
- std::generate_n(std::back_inserter(*result.m_value.array),
- size_and_type.first, [this, size_and_type]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- return get_ubjson_value(size_and_type.second);
- });
+ if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ }
}
}
else
{
- std::generate_n(std::back_inserter(*result.m_value.array),
- size_and_type.first, [this]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- return parse_ubjson_internal();
- });
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
+ }
}
}
else
{
+ if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
while (current != ']')
{
- result.push_back(parse_ubjson_internal(false));
+ if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
+ {
+ return false;
+ }
get_ignore_noop();
}
}
- return result;
+ return sax->end_array();
}
- BasicJsonType get_ubjson_object()
+ /*!
+ @return whether object creation completed
+ */
+ bool get_ubjson_object()
{
- BasicJsonType result = value_t::object;
- const auto size_and_type = get_ubjson_size_type();
+ std::pair<std::size_t, int> size_and_type;
+ if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
+ string_t key;
if (size_and_type.first != string_t::npos)
{
- if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
+ if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
{
- JSON_THROW(out_of_range::create(408,
- "excessive object size: " + std::to_string(size_and_type.first)));
+ return false;
}
if (size_and_type.second != 0)
{
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- size_and_type.first, [this, size_and_type]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- auto key = get_ubjson_string();
- auto val = get_ubjson_value(size_and_type.second);
- return std::make_pair(std::move(key), std::move(val));
- });
+ if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ key.clear();
+ }
}
else
{
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- size_and_type.first, [this]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- auto key = get_ubjson_string();
- auto val = parse_ubjson_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
+ if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
}
}
else
{
+ if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
+ {
+ return false;
+ }
+
while (current != '}')
{
- auto key = get_ubjson_string(false);
- result[std::move(key)] = parse_ubjson_internal();
+ if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
get_ignore_noop();
+ key.clear();
}
}
- return result;
+ return sax->end_object();
}
/*!
- @brief throw if end of input is not reached
- @throw parse_error.110 if input not ended
+ @return whether the last read character is not EOF
*/
- void expect_eof() const
- {
- if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
- {
- JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
- }
- }
-
- /*!
- @briefthrow if end of input is reached
- @throw parse_error.110 if input ended
- */
- void unexpect_eof() const
+ bool unexpect_eof() const
{
if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
{
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
}
+ return true;
+ }
+
+ /*!
+ @return a string representation of the last read byte
+ */
+ std::string get_token_string() const
+ {
+ char cr[3];
+ snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
+ return std::string{cr};
}
private:
@@ -1369,6 +1689,9 @@
/// whether we can assume little endianess
const bool is_little_endian = little_endianess();
+
+ /// the SAX parser
+ json_sax_t* sax = nullptr;
};
}
}
diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp
index ef66948..01bec74 100644
--- a/include/nlohmann/detail/input/input_adapters.hpp
+++ b/include/nlohmann/detail/input/input_adapters.hpp
@@ -1,11 +1,8 @@
#pragma once
-#include <algorithm> // min
-#include <array> // array
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstring> // strlen
-#include <ios> // streamsize, streamoff, streampos
#include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
@@ -20,6 +17,9 @@
{
namespace detail
{
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson };
+
////////////////////
// input adapters //
////////////////////
@@ -28,19 +28,17 @@
@brief abstract input adapter interface
Produces a stream of std::char_traits<char>::int_type characters from a
-std::istream, a buffer, or some other input type. Accepts the return of exactly
-one non-EOF character for future input. The int_type characters returned
-consist of all valid char values as positive values (typically unsigned char),
-plus an EOF value outside that range, specified by the value of the function
-std::char_traits<char>::eof(). This value is typically -1, but could be any
-arbitrary value which is not a valid char value.
+std::istream, a buffer, or some other input type. Accepts the return of
+exactly one non-EOF character for future input. The int_type characters
+returned consist of all valid char values as positive values (typically
+unsigned char), plus an EOF value outside that range, specified by the value
+of the function std::char_traits<char>::eof(). This value is typically -1, but
+could be any arbitrary value which is not a valid char value.
*/
struct input_adapter_protocol
{
/// get a character [0,255] or std::char_traits<char>::eof().
virtual std::char_traits<char>::int_type get_character() = 0;
- /// restore the last non-eof() character to input
- virtual void unget_character() = 0;
virtual ~input_adapter_protocol() = default;
};
@@ -68,34 +66,7 @@
explicit input_stream_adapter(std::istream& i)
: is(i), sb(*i.rdbuf())
- {
- // skip byte order mark
- std::char_traits<char>::int_type c;
- if ((c = get_character()) == 0xEF)
- {
- if ((c = get_character()) == 0xBB)
- {
- if ((c = get_character()) == 0xBF)
- {
- return; // Ignore BOM
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget();
- }
- is.putback('\xBB');
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget();
- }
- is.putback('\xEF');
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget(); // no byte order mark; process as usual
- }
- }
+ {}
// delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete;
@@ -109,11 +80,6 @@
return sb.sbumpc();
}
- void unget_character() override
- {
- sb.sungetc(); // is.unget() avoided for performance
- }
-
private:
/// the associated input stream
std::istream& is;
@@ -125,14 +91,8 @@
{
public:
input_buffer_adapter(const char* b, const std::size_t l)
- : cursor(b), limit(b + l), start(b)
- {
- // skip byte order mark
- if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
- {
- cursor += 3;
- }
- }
+ : cursor(b), limit(b + l)
+ {}
// delete because of pointer members
input_buffer_adapter(const input_buffer_adapter&) = delete;
@@ -148,21 +108,164 @@
return std::char_traits<char>::eof();
}
- void unget_character() noexcept override
- {
- if (JSON_LIKELY(cursor > start))
- {
- --cursor;
- }
- }
-
private:
/// pointer to the current character
const char* cursor;
/// pointer past the last character
- const char* limit;
- /// pointer to the first character
- const char* start;
+ const char* const limit;
+};
+
+template<typename WideStringType>
+class wide_string_input_adapter : public input_adapter_protocol
+{
+ public:
+ explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
+
+ std::char_traits<char>::int_type get_character() noexcept override
+ {
+ // check if buffer needs to be filled
+ if (utf8_bytes_index == utf8_bytes_filled)
+ {
+ if (sizeof(typename WideStringType::value_type) == 2)
+ {
+ fill_buffer_utf16();
+ }
+ else
+ {
+ fill_buffer_utf32();
+ }
+
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index == 0);
+ }
+
+ // use buffer
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index < utf8_bytes_filled);
+ return utf8_bytes[utf8_bytes_index++];
+ }
+
+ private:
+ void fill_buffer_utf16()
+ {
+ utf8_bytes_index = 0;
+
+ if (current_wchar == str.size())
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const int wc = static_cast<int>(str[current_wchar++]);
+
+ // UTF-16 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = 0xC0 | ((wc >> 6));
+ utf8_bytes[1] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 2;
+ }
+ else if (0xD800 > wc or wc >= 0xE000)
+ {
+ utf8_bytes[0] = 0xE0 | ((wc >> 12));
+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[2] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 3;
+ }
+ else
+ {
+ if (current_wchar < str.size())
+ {
+ const int wc2 = static_cast<int>(str[current_wchar++]);
+ const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
+ utf8_bytes[0] = 0xf0 | (charcode >> 18);
+ utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
+ utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
+ utf8_bytes[3] = 0x80 | (charcode & 0x3F);
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ // unknown character
+ ++current_wchar;
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+ }
+
+ void fill_buffer_utf32()
+ {
+ utf8_bytes_index = 0;
+
+ if (current_wchar == str.size())
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const int wc = static_cast<int>(str[current_wchar++]);
+
+ // UTF-32 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
+ utf8_bytes[1] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 2;
+ }
+ else if (wc <= 0xFFFF)
+ {
+ utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[2] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 3;
+ }
+ else if (wc <= 0x10FFFF)
+ {
+ utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
+ utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
+ utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[3] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ // unknown character
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+
+ private:
+ /// the wstring to process
+ const WideStringType& str;
+
+ /// index of the current wchar in str
+ std::size_t current_wchar = 0;
+
+ /// a buffer for UTF-8 bytes
+ std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+ /// index to the utf8_codes array for the next valid byte
+ std::size_t utf8_bytes_index = 0;
+ /// number of valid bytes in the utf8_codes array
+ std::size_t utf8_bytes_filled = 0;
};
class input_adapter
@@ -178,6 +281,15 @@
input_adapter(std::istream&& i)
: ia(std::make_shared<input_stream_adapter>(i)) {}
+ input_adapter(const std::wstring& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
+
+ input_adapter(const std::u16string& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
+
+ input_adapter(const std::u32string& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
+
/// input adapter for buffer
template<typename CharT,
typename std::enable_if<
diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp
new file mode 100644
index 0000000..1705a86
--- /dev/null
+++ b/include/nlohmann/detail/input/json_sax.hpp
@@ -0,0 +1,702 @@
+#pragma once
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include <nlohmann/detail/input/parser.hpp>
+#include <nlohmann/detail/exceptions.hpp>
+
+namespace nlohmann
+{
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+ /// type for (signed) integers
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ /// type for unsigned integers
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ /// type for floating-point numbers
+ using number_float_t = typename BasicJsonType::number_float_t;
+ /// type for strings
+ using string_t = typename BasicJsonType::string_t;
+
+ /*!
+ @brief a null value was read
+ @return whether parsing should proceed
+ */
+ virtual bool null() = 0;
+
+ /*!
+ @brief a boolean value was read
+ @param[in] val boolean value
+ @return whether parsing should proceed
+ */
+ virtual bool boolean(bool val) = 0;
+
+ /*!
+ @brief an integer number was read
+ @param[in] val integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_integer(number_integer_t val) = 0;
+
+ /*!
+ @brief an unsigned integer number was read
+ @param[in] val unsigned integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+ /*!
+ @brief an floating-point number was read
+ @param[in] val floating-point value
+ @param[in] s raw token value
+ @return whether parsing should proceed
+ */
+ virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+ /*!
+ @brief a string was read
+ @param[in] val string value
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool string(string_t& val) = 0;
+
+ /*!
+ @brief the beginning of an object was read
+ @param[in] elements number of object elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_object(std::size_t elements) = 0;
+
+ /*!
+ @brief an object key was read
+ @param[in] val object key
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool key(string_t& val) = 0;
+
+ /*!
+ @brief the end of an object was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_object() = 0;
+
+ /*!
+ @brief the beginning of an array was read
+ @param[in] elements number of array elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_array(std::size_t elements) = 0;
+
+ /*!
+ @brief the end of an array was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_array() = 0;
+
+ /*!
+ @brief a parse error occurred
+ @param[in] position the position in the input where the error occurs
+ @param[in] last_token the last read token
+ @param[in] error_msg a detailed error message
+ @return whether parsing should proceed (must return false)
+ */
+ virtual bool parse_error(std::size_t position,
+ const std::string& last_token,
+ const detail::exception& ex) = 0;
+
+ virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+
+ /*!
+ @param[in, out] r reference to a JSON value that is manipulated while
+ parsing
+ @param[in] allow_exceptions_ whether parse errors yield exceptions
+ */
+ explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+ : root(r), allow_exceptions(allow_exceptions_)
+ {}
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t&)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive object size: " + std::to_string(len)));
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ // add null at given key and store the reference for later
+ object_element = &(ref_stack.back()->m_value.object->operator[](val));
+ return true;
+ }
+
+ bool end_object()
+ {
+ ref_stack.pop_back();
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive array size: " + std::to_string(len)));
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ ref_stack.pop_back();
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&,
+ const detail::exception& ex)
+ {
+ errored = true;
+ if (allow_exceptions)
+ {
+ // determine the proper exception type from the id
+ switch ((ex.id / 100) % 100)
+ {
+ case 1:
+ JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
+ case 4:
+ JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
+ // LCOV_EXCL_START
+ case 2:
+ JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
+ case 3:
+ JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
+ case 5:
+ JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
+ }
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+ */
+ template<typename Value>
+ BasicJsonType* handle_value(Value&& v)
+ {
+ if (ref_stack.empty())
+ {
+ root = BasicJsonType(std::forward<Value>(v));
+ return &root;
+ }
+ else
+ {
+ assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+ return &(ref_stack.back()->m_value.array->back());
+ }
+ else
+ {
+ assert(object_element);
+ *object_element = BasicJsonType(std::forward<Value>(v));
+ return object_element;
+ }
+ }
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack;
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using parser_callback_t = typename BasicJsonType::parser_callback_t;
+ using parse_event_t = typename BasicJsonType::parse_event_t;
+
+ json_sax_dom_callback_parser(BasicJsonType& r,
+ const parser_callback_t cb,
+ const bool allow_exceptions_ = true)
+ : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+ {
+ keep_stack.push_back(true);
+ }
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t&)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ // check callback for object start
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::object, true);
+ ref_stack.push_back(val.second);
+
+ // check object limit
+ if (ref_stack.back())
+ {
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive object size: " + std::to_string(len)));
+ }
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ BasicJsonType k = BasicJsonType(val);
+
+ // check callback for key
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+ key_keep_stack.push_back(keep);
+
+ // add discarded value at given key and store the reference for later
+ if (keep and ref_stack.back())
+ {
+ object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+ }
+
+ return true;
+ }
+
+ bool end_object()
+ {
+ if (ref_stack.back())
+ {
+ if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+ {
+ // discard object
+ *ref_stack.back() = discarded;
+ }
+ }
+
+ assert(not ref_stack.empty());
+ assert(not keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ if (not ref_stack.empty() and ref_stack.back())
+ {
+ // remove discarded value
+ if (ref_stack.back()->is_object())
+ {
+ for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+ {
+ if (it->is_discarded())
+ {
+ ref_stack.back()->erase(it);
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::array, true);
+ ref_stack.push_back(val.second);
+
+ // check array limit
+ if (ref_stack.back())
+ {
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive array size: " + std::to_string(len)));
+ }
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ bool keep = true;
+
+ if (ref_stack.back())
+ {
+ keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+ if (not keep)
+ {
+ // discard array
+ *ref_stack.back() = discarded;
+ }
+ }
+
+ assert(not ref_stack.empty());
+ assert(not keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ // remove discarded value
+ if (not keep and not ref_stack.empty())
+ {
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->pop_back();
+ }
+ }
+
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&,
+ const detail::exception& ex)
+ {
+ errored = true;
+ if (allow_exceptions)
+ {
+ // determine the proper exception type from the id
+ switch ((ex.id / 100) % 100)
+ {
+ case 1:
+ JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
+ case 4:
+ JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
+ // LCOV_EXCL_START
+ case 2:
+ JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
+ case 3:
+ JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
+ case 5:
+ JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
+ }
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @param[in] v value to add to the JSON value we build during parsing
+ @param[in] skip_callback whether we should skip calling the callback
+ function; this is required after start_array() and
+ start_object() SAX events, because otherwise we would call the
+ callback function with an empty array or object, respectively.
+
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+
+ @return pair of boolean (whether value should be kept) and pointer (to the
+ passed value in the ref_stack hierarchy; nullptr if not kept)
+ */
+ template<typename Value>
+ std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+ {
+ assert(not keep_stack.empty());
+
+ // do not handle this value if we know it would be added to a discarded
+ // container
+ if (not keep_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ // create value
+ auto value = BasicJsonType(std::forward<Value>(v));
+
+ // check callback
+ const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+ // do not handle this value if we just learnt it shall be discarded
+ if (not keep)
+ {
+ return {false, nullptr};
+ }
+
+ if (ref_stack.empty())
+ {
+ root = std::move(value);
+ return {true, &root};
+ }
+ else
+ {
+ // skip this value if we already decided to skip the parent
+ // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+ if (not ref_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->push_back(std::move(value));
+ return {true, &(ref_stack.back()->m_value.array->back())};
+ }
+ else
+ {
+ // check if we should store an element for the current key
+ assert(not key_keep_stack.empty());
+ const bool store_element = key_keep_stack.back();
+ key_keep_stack.pop_back();
+
+ if (not store_element)
+ {
+ return {false, nullptr};
+ }
+
+ assert(object_element);
+ *object_element = std::move(value);
+ return {true, object_element};
+ }
+ }
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack;
+ /// stack to manage which values to keep
+ std::vector<bool> keep_stack;
+ /// stack to manage which object keys to keep
+ std::vector<bool> key_keep_stack;
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// callback function
+ const parser_callback_t callback = nullptr;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+ /// a discarded value for the callback
+ BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+
+ bool null()
+ {
+ return true;
+ }
+
+ bool boolean(bool)
+ {
+ return true;
+ }
+
+ bool number_integer(number_integer_t)
+ {
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t)
+ {
+ return true;
+ }
+
+ bool number_float(number_float_t, const string_t&)
+ {
+ return true;
+ }
+
+ bool string(string_t&)
+ {
+ return true;
+ }
+
+ bool start_object(std::size_t = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool key(string_t&)
+ {
+ return true;
+ }
+
+ bool end_object()
+ {
+ return true;
+ }
+
+ bool start_array(std::size_t = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool end_array()
+ {
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const detail::exception&)
+ {
+ return false;
+ }
+};
+}
+
+}
diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp
index 98cc1b6..44165ff 100644
--- a/include/nlohmann/detail/input/lexer.hpp
+++ b/include/nlohmann/detail/input/lexer.hpp
@@ -3,10 +3,8 @@
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <cstdio> // snprintf
#include <initializer_list> // initializer_list
-#include <ios> // hex, uppercase
-#include <iomanip> // setw, setfill
-#include <sstream> // stringstream
#include <string> // char_traits, string
#include <vector> // vector
@@ -94,12 +92,14 @@
return "end of input";
case token_type::literal_or_value:
return "'[', '{', or a literal";
+ // LCOV_EXCL_START
default: // catch non-enum values
- return "unknown token"; // LCOV_EXCL_LINE
+ return "unknown token";
+ // LCOV_EXCL_STOP
}
}
- explicit lexer(detail::input_adapter_t adapter)
+ explicit lexer(detail::input_adapter_t&& adapter)
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
// delete because of pointer members
@@ -747,11 +747,13 @@
goto scan_number_any1;
}
+ // LCOV_EXCL_START
default:
{
// all other characters are rejected outside scan_number()
- assert(false); // LCOV_EXCL_LINE
+ assert(false);
}
+ // LCOV_EXCL_STOP
}
scan_number_minus:
@@ -1081,7 +1083,16 @@
std::char_traits<char>::int_type get()
{
++chars_read;
- current = ia->get_character();
+ if (next_unget)
+ {
+ // just reset the next_unget variable and work with current
+ next_unget = false;
+ }
+ else
+ {
+ current = ia->get_character();
+ }
+
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
token_string.push_back(std::char_traits<char>::to_char_type(current));
@@ -1089,13 +1100,20 @@
return current;
}
- /// unget current character (return it again on next get)
+ /*!
+ @brief unget current character (read it again on next get)
+
+ We implement unget by setting variable next_unget to true. The input is not
+ changed - we just simulate ungetting by modifying chars_read and
+ token_string. The next call to get() will behave as if the unget character
+ is read again.
+ */
void unget()
{
+ next_unget = true;
--chars_read;
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
- ia->unget_character();
assert(token_string.size() != 0);
token_string.pop_back();
}
@@ -1131,9 +1149,9 @@
}
/// return current string value (implicitly resets the token; useful only once)
- string_t&& move_string()
+ string_t& get_string()
{
- return std::move(token_buffer);
+ return token_buffer;
}
/////////////////////
@@ -1158,10 +1176,9 @@
if ('\x00' <= c and c <= '\x1F')
{
// escape control characters
- std::stringstream ss;
- ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0')
- << std::hex << static_cast<int>(c) << ">";
- result += ss.str();
+ char cs[9];
+ snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
+ result += cs;
}
else
{
@@ -1183,8 +1200,43 @@
// actual scanner
/////////////////////
+ /*!
+ @brief skip the UTF-8 byte order mark
+ @return true iff there is no BOM or the correct BOM has been skipped
+ */
+ bool skip_bom()
+ {
+ if (get() == 0xEF)
+ {
+ if (get() == 0xBB and get() == 0xBF)
+ {
+ // we completely parsed the BOM
+ return true;
+ }
+ else
+ {
+ // after reading 0xEF, an unexpected character followed
+ return false;
+ }
+ }
+ else
+ {
+ // the first character is not the beginning of the BOM; unget it to
+ // process is later
+ unget();
+ return true;
+ }
+ }
+
token_type scan()
{
+ // initially, skip the BOM
+ if (chars_read == 0 and not skip_bom())
+ {
+ error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+ return token_type::parse_error;
+ }
+
// read next character and ignore whitespace
do
{
@@ -1254,6 +1306,9 @@
/// the current character
std::char_traits<char>::int_type current = std::char_traits<char>::eof();
+ /// whether the next get() call should just return current
+ bool next_unget = false;
+
/// the number of characters read
std::size_t chars_read = 0;
diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp
index e58aaaf..70d92a2 100644
--- a/include/nlohmann/detail/input/parser.hpp
+++ b/include/nlohmann/detail/input/parser.hpp
@@ -9,7 +9,9 @@
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
+#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
+#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -57,11 +59,14 @@
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
/// a parser reading from an input adapter
- explicit parser(detail::input_adapter_t adapter,
+ explicit parser(detail::input_adapter_t&& adapter,
const parser_callback_t cb = nullptr,
const bool allow_exceptions_ = true)
- : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
- {}
+ : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
+ {
+ // read first token
+ get_token();
+ }
/*!
@brief public parser interface
@@ -75,31 +80,54 @@
*/
void parse(const bool strict, BasicJsonType& result)
{
- // read first token
- get_token();
-
- parse_internal(true, result);
- result.assert_invariant();
-
- // in strict mode, input must be completely read
- if (strict)
+ if (callback)
{
- get_token();
- expect(token_type::end_of_input);
+ json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+ sax_parse_internal(&sdp);
+ result.assert_invariant();
+
+ // in strict mode, input must be completely read
+ if (strict and (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
+
+ // set top-level value to null if it was discarded by the callback
+ // function
+ if (result.is_discarded())
+ {
+ result = nullptr;
+ }
}
-
- // in case of an error, return discarded value
- if (errored)
+ else
{
- result = value_t::discarded;
- return;
- }
+ json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+ sax_parse_internal(&sdp);
+ result.assert_invariant();
- // set top-level value to null if it was discarded by the callback
- // function
- if (result.is_discarded())
- {
- result = nullptr;
+ // in strict mode, input must be completely read
+ if (strict and (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
}
}
@@ -111,414 +139,311 @@
*/
bool accept(const bool strict = true)
{
- // read first token
- get_token();
+ json_sax_acceptor<BasicJsonType> sax_acceptor;
+ return sax_parse(&sax_acceptor, strict);
+ }
- if (not accept_internal())
+ template <typename SAX>
+ bool sax_parse(SAX* sax, const bool strict = true)
+ {
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+ const bool result = sax_parse_internal(sax);
+
+ // strict mode: next byte must be EOF
+ if (result and strict and (get_token() != token_type::end_of_input))
{
- return false;
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
}
- // strict => last token must be EOF
- return not strict or (get_token() == token_type::end_of_input);
+ return result;
}
private:
- /*!
- @brief the actual parser
- @throw parse_error.101 in case of an unexpected token
- @throw parse_error.102 if to_unicode fails or surrogate error
- @throw parse_error.103 if to_unicode fails
- */
- void parse_internal(bool keep, BasicJsonType& result)
+ template <typename SAX>
+ bool sax_parse_internal(SAX* sax)
{
- // never parse after a parse error was detected
- assert(not errored);
+ // stack to remember the hieararchy of structured values we are parsing
+ // true = array; false = object
+ std::vector<bool> states;
+ // value to avoid a goto (see comment where set to true)
+ bool skip_to_state_evaluation = false;
- // start with a discarded value
- if (not result.is_discarded())
+ while (true)
{
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
-
- switch (last_token)
- {
- case token_type::begin_object:
+ if (not skip_to_state_evaluation)
{
- if (keep)
+ // invariant: get_token() was called before each iteration
+ switch (last_token)
{
- if (callback)
+ case token_type::begin_object:
{
- keep = callback(depth++, parse_event_t::object_start, result);
- }
-
- if (not callback or keep)
- {
- // explicitly set result to object to cope with {}
- result.m_type = value_t::object;
- result.m_value = value_t::object;
- }
- }
-
- // read next token
- get_token();
-
- // closing } -> we are done
- if (last_token == token_type::end_object)
- {
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- // parse values
- string_t key;
- BasicJsonType value;
- while (true)
- {
- // store key
- if (not expect(token_type::value_string))
- {
- return;
- }
- key = m_lexer.move_string();
-
- bool keep_tag = false;
- if (keep)
- {
- if (callback)
+ if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
- BasicJsonType k(key);
- keep_tag = callback(depth, parse_event_t::key, k);
+ return false;
+ }
+
+ // closing } -> we are done
+ if (get_token() == token_type::end_object)
+ {
+ if (JSON_UNLIKELY(not sax->end_object()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // parse key
+ if (JSON_UNLIKELY(last_token != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
- keep_tag = true;
+ if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+ }
+
+ // parse separator (:)
+ if (JSON_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
+ }
+
+ // remember we are now inside an object
+ states.push_back(false);
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ case token_type::begin_array:
+ {
+ if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ // closing ] -> we are done
+ if (get_token() == token_type::end_array)
+ {
+ if (JSON_UNLIKELY(not sax->end_array()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // remember we are now inside an array
+ states.push_back(true);
+
+ // parse values (no need to call get_token)
+ continue;
+ }
+
+ case token_type::value_float:
+ {
+ const auto res = m_lexer.get_number_float();
+
+ if (JSON_UNLIKELY(not std::isfinite(res)))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
+ }
+ else
+ {
+ if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
+ {
+ return false;
+ }
+ break;
}
}
- // parse separator (:)
- get_token();
- if (not expect(token_type::name_separator))
+ case token_type::literal_false:
{
- return;
+ if (JSON_UNLIKELY(not sax->boolean(false)))
+ {
+ return false;
+ }
+ break;
}
- // parse and add value
- get_token();
- value.m_value.destroy(value.m_type);
- value.m_type = value_t::discarded;
- parse_internal(keep, value);
-
- if (JSON_UNLIKELY(errored))
+ case token_type::literal_null:
{
- return;
+ if (JSON_UNLIKELY(not sax->null()))
+ {
+ return false;
+ }
+ break;
}
- if (keep and keep_tag and not value.is_discarded())
+ case token_type::literal_true:
{
- result.m_value.object->emplace(std::move(key), std::move(value));
+ if (JSON_UNLIKELY(not sax->boolean(true)))
+ {
+ return false;
+ }
+ break;
}
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
+ case token_type::value_integer:
{
- get_token();
- continue;
+ if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
+ {
+ return false;
+ }
+ break;
}
- // closing }
- if (not expect(token_type::end_object))
+ case token_type::value_string:
{
- return;
- }
- break;
- }
-
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- case token_type::begin_array:
- {
- if (keep)
- {
- if (callback)
- {
- keep = callback(depth++, parse_event_t::array_start, result);
+ if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
+ {
+ return false;
+ }
+ break;
}
- if (not callback or keep)
+ case token_type::value_unsigned:
{
- // explicitly set result to array to cope with []
- result.m_type = value_t::array;
- result.m_value = value_t::array;
+ if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::parse_error:
+ {
+ // using "uninitialized" to avoid "expected" message
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
+ }
+
+ default: // the last token was unexpected
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
}
}
-
- // read next token
- get_token();
-
- // closing ] -> we are done
- if (last_token == token_type::end_array)
- {
- if (callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- // parse values
- BasicJsonType value;
- while (true)
- {
- // parse value
- value.m_value.destroy(value.m_type);
- value.m_type = value_t::discarded;
- parse_internal(keep, value);
-
- if (JSON_UNLIKELY(errored))
- {
- return;
- }
-
- if (keep and not value.is_discarded())
- {
- result.m_value.array->push_back(std::move(value));
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing ]
- if (not expect(token_type::end_array))
- {
- return;
- }
- break;
- }
-
- if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
}
-
- case token_type::literal_null:
+ else
{
- result.m_type = value_t::null;
- break;
+ skip_to_state_evaluation = false;
}
- case token_type::value_string:
+ // we reached this line after we successfully parsed a value
+ if (states.empty())
{
- result.m_type = value_t::string;
- result.m_value = m_lexer.move_string();
- break;
- }
-
- case token_type::literal_true:
- {
- result.m_type = value_t::boolean;
- result.m_value = true;
- break;
- }
-
- case token_type::literal_false:
- {
- result.m_type = value_t::boolean;
- result.m_value = false;
- break;
- }
-
- case token_type::value_unsigned:
- {
- result.m_type = value_t::number_unsigned;
- result.m_value = m_lexer.get_number_unsigned();
- break;
- }
-
- case token_type::value_integer:
- {
- result.m_type = value_t::number_integer;
- result.m_value = m_lexer.get_number_integer();
- break;
- }
-
- case token_type::value_float:
- {
- result.m_type = value_t::number_float;
- result.m_value = m_lexer.get_number_float();
-
- // throw in case of infinity or NAN
- if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
- {
- if (allow_exceptions)
- {
- JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
- m_lexer.get_token_string() + "'"));
- }
- expect(token_type::uninitialized);
- }
- break;
- }
-
- case token_type::parse_error:
- {
- // using "uninitialized" to avoid "expected" message
- if (not expect(token_type::uninitialized))
- {
- return;
- }
- break; // LCOV_EXCL_LINE
- }
-
- default:
- {
- // the last token was unexpected; we expected a value
- if (not expect(token_type::literal_or_value))
- {
- return;
- }
- break; // LCOV_EXCL_LINE
- }
- }
-
- if (keep and callback and not callback(depth, parse_event_t::value, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- }
-
- /*!
- @brief the actual acceptor
-
- @invariant 1. The last token is not yet processed. Therefore, the caller
- of this function must make sure a token has been read.
- 2. When this function returns, the last token is processed.
- That is, the last read character was already considered.
-
- This invariant makes sure that no token needs to be "unput".
- */
- bool accept_internal()
- {
- switch (last_token)
- {
- case token_type::begin_object:
- {
- // read next token
- get_token();
-
- // closing } -> we are done
- if (last_token == token_type::end_object)
- {
- return true;
- }
-
- // parse values
- while (true)
- {
- // parse key
- if (last_token != token_type::value_string)
- {
- return false;
- }
-
- // parse separator (:)
- get_token();
- if (last_token != token_type::name_separator)
- {
- return false;
- }
-
- // parse value
- get_token();
- if (not accept_internal())
- {
- return false;
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing }
- return (last_token == token_type::end_object);
- }
- }
-
- case token_type::begin_array:
- {
- // read next token
- get_token();
-
- // closing ] -> we are done
- if (last_token == token_type::end_array)
- {
- return true;
- }
-
- // parse values
- while (true)
- {
- // parse value
- if (not accept_internal())
- {
- return false;
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing ]
- return (last_token == token_type::end_array);
- }
- }
-
- case token_type::value_float:
- {
- // reject infinity or NAN
- return std::isfinite(m_lexer.get_number_float());
- }
-
- case token_type::literal_false:
- case token_type::literal_null:
- case token_type::literal_true:
- case token_type::value_integer:
- case token_type::value_string:
- case token_type::value_unsigned:
+ // empty stack: we reached the end of the hieararchy: done
return true;
+ }
+ else
+ {
+ if (states.back()) // array
+ {
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse a new value
+ get_token();
+ continue;
+ }
- default: // the last token was unexpected
- return false;
+ // closing ]
+ if (JSON_LIKELY(last_token == token_type::end_array))
+ {
+ if (JSON_UNLIKELY(not sax->end_array()))
+ {
+ return false;
+ }
+
+ // We are done with this array. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ assert(not states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+ else
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
+ }
+ }
+ else // object
+ {
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse key
+ if (JSON_UNLIKELY(get_token() != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
+ }
+ else
+ {
+ if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+ }
+
+ // parse separator (:)
+ if (JSON_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
+ }
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ // closing }
+ if (JSON_LIKELY(last_token == token_type::end_object))
+ {
+ if (JSON_UNLIKELY(not sax->end_object()))
+ {
+ return false;
+ }
+
+ // We are done with this object. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ assert(not states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+ else
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
+ }
+ }
+ }
}
}
@@ -528,29 +453,7 @@
return (last_token = m_lexer.scan());
}
- /*!
- @throw parse_error.101 if expected token did not occur
- */
- bool expect(token_type t)
- {
- if (JSON_UNLIKELY(t != last_token))
- {
- errored = true;
- expected = t;
- if (allow_exceptions)
- {
- throw_exception();
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- [[noreturn]] void throw_exception() const
+ std::string exception_message(const token_type expected)
{
std::string error_msg = "syntax error - ";
if (last_token == token_type::parse_error)
@@ -568,22 +471,16 @@
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
}
- JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
+ return error_msg;
}
private:
- /// current level of recursion
- int depth = 0;
/// callback function
const parser_callback_t callback = nullptr;
/// the type of the last read token
token_type last_token = token_type::uninitialized;
/// the lexer
lexer_t m_lexer;
- /// whether a syntax error occurred
- bool errored = false;
- /// possible reason for the syntax error
- token_type expected = token_type::uninitialized;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
};
diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp
index 52ede17..adcd8a3 100644
--- a/include/nlohmann/detail/iterators/iter_impl.hpp
+++ b/include/nlohmann/detail/iterators/iter_impl.hpp
@@ -8,7 +8,7 @@
#include <nlohmann/detail/iterators/internal_iterator.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/macro_scope.hpp>
-#include <nlohmann/detail/meta.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@@ -31,7 +31,7 @@
@requirement The class satisfies the following concept requirements:
-
-[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
@@ -583,7 +583,7 @@
@brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- typename object_t::key_type key() const
+ const typename object_t::key_type& key() const
{
assert(m_object != nullptr);
diff --git a/include/nlohmann/detail/iterators/iteration_proxy.hpp b/include/nlohmann/detail/iterators/iteration_proxy.hpp
index 7547d03..f5dbb2c 100644
--- a/include/nlohmann/detail/iterators/iteration_proxy.hpp
+++ b/include/nlohmann/detail/iterators/iteration_proxy.hpp
@@ -2,6 +2,7 @@
#include <cstddef> // size_t
#include <string> // string, to_string
+#include <iterator> // input_iterator_tag
#include <nlohmann/detail/value_t.hpp>
@@ -16,15 +17,31 @@
/// helper class for iteration
class iteration_proxy_internal
{
+ public:
+ using difference_type = std::ptrdiff_t;
+ using value_type = iteration_proxy_internal;
+ using pointer = iteration_proxy_internal*;
+ using reference = iteration_proxy_internal&;
+ using iterator_category = std::input_iterator_tag;
+
private:
/// the iterator
IteratorType anchor;
/// an index for arrays (used to create key names)
std::size_t array_index = 0;
+ /// last stringified array index
+ mutable std::size_t array_index_last = 0;
+ /// a string representation of the array index
+ mutable std::string array_index_str = "0";
+ /// an empty string (to return a reference for primitive values)
+ const std::string empty_str = "";
public:
explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
+ iteration_proxy_internal(const iteration_proxy_internal&) = default;
+ iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
+
/// dereference operator (needed for range-based for)
iteration_proxy_internal& operator*()
{
@@ -40,6 +57,12 @@
return *this;
}
+ /// equality operator (needed for InputIterator)
+ bool operator==(const iteration_proxy_internal& o) const noexcept
+ {
+ return anchor == o.anchor;
+ }
+
/// inequality operator (needed for range-based for)
bool operator!=(const iteration_proxy_internal& o) const noexcept
{
@@ -47,7 +70,7 @@
}
/// return key of the iterator
- std::string key() const
+ const std::string& key() const
{
assert(anchor.m_object != nullptr);
@@ -55,7 +78,14 @@
{
// use integer array index as key
case value_t::array:
- return std::to_string(array_index);
+ {
+ if (array_index != array_index_last)
+ {
+ array_index_str = std::to_string(array_index);
+ array_index_last = array_index;
+ }
+ return array_index_str;
+ }
// use key from the object
case value_t::object:
@@ -63,7 +93,7 @@
// use an empty key for all primitive types
default:
- return "";
+ return empty_str;
}
}
diff --git a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp
index 0644819..2750de4 100644
--- a/include/nlohmann/detail/iterators/json_reverse_iterator.hpp
+++ b/include/nlohmann/detail/iterators/json_reverse_iterator.hpp
@@ -21,10 +21,10 @@
@requirement The class satisfies the following concept requirements:
-
-[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
-- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
It is possible to write to the pointed-to element (only if @a Base is
@ref iterator).
@@ -41,11 +41,11 @@
using reference = typename Base::reference;
/// create reverse iterator from iterator
- json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+ explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it) {}
/// create reverse iterator from base class
- json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+ explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++)
json_reverse_iterator const operator++(int)
diff --git a/include/nlohmann/detail/iterators/primitive_iterator.hpp b/include/nlohmann/detail/iterators/primitive_iterator.hpp
index db0b1e7..db3f897 100644
--- a/include/nlohmann/detail/iterators/primitive_iterator.hpp
+++ b/include/nlohmann/detail/iterators/primitive_iterator.hpp
@@ -87,7 +87,7 @@
primitive_iterator_t const operator++(int) noexcept
{
auto result = *this;
- m_it++;
+ ++m_it;
return result;
}
@@ -100,7 +100,7 @@
primitive_iterator_t const operator--(int) noexcept
{
auto result = *this;
- m_it--;
+ --m_it;
return result;
}
diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp
index e675221..a5b6101 100644
--- a/include/nlohmann/detail/macro_scope.hpp
+++ b/include/nlohmann/detail/macro_scope.hpp
@@ -4,13 +4,15 @@
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
// exclude unsupported compilers
-#if defined(__clang__)
- #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
- #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
- #endif
-#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
- #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
- #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+ #if defined(__clang__)
+ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+ #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
#endif
#endif
@@ -40,10 +42,12 @@
#define JSON_THROW(exception) throw exception
#define JSON_TRY try
#define JSON_CATCH(exception) catch(exception)
+ #define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#define JSON_THROW(exception) std::abort()
#define JSON_TRY if(true)
#define JSON_CATCH(exception) if(false)
+ #define JSON_INTERNAL_CATCH(exception) if(false)
#endif
// override exception macros
@@ -58,6 +62,11 @@
#if defined(JSON_CATCH_USER)
#undef JSON_CATCH
#define JSON_CATCH JSON_CATCH_USER
+ #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+ #undef JSON_INTERNAL_CATCH
+ #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
#endif
// manual branch prediction
diff --git a/include/nlohmann/detail/macro_unscope.hpp b/include/nlohmann/detail/macro_unscope.hpp
index 99a0abd..032b121 100644
--- a/include/nlohmann/detail/macro_unscope.hpp
+++ b/include/nlohmann/detail/macro_unscope.hpp
@@ -9,6 +9,7 @@
#endif
// clean up
+#undef JSON_INTERNAL_CATCH
#undef JSON_CATCH
#undef JSON_THROW
#undef JSON_TRY
diff --git a/include/nlohmann/detail/meta/cpp_future.hpp b/include/nlohmann/detail/meta/cpp_future.hpp
new file mode 100644
index 0000000..d12d6bd
--- /dev/null
+++ b/include/nlohmann/detail/meta/cpp_future.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <ciso646> // not
+#include <cstddef> // size_t
+#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+
+namespace nlohmann
+{
+namespace detail
+{
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+// implementation of C++14 index_sequence and affiliates
+// source: https://stackoverflow.com/a/32223343
+template<std::size_t... Ints>
+struct index_sequence
+{
+ using type = index_sequence;
+ using value_type = std::size_t;
+ static constexpr std::size_t size() noexcept
+ {
+ return sizeof...(Ints);
+ }
+};
+
+template<class Sequence1, class Sequence2>
+struct merge_and_renumber;
+
+template<std::size_t... I1, std::size_t... I2>
+struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
+ : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
+
+template<std::size_t N>
+struct make_index_sequence
+ : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
+ typename make_index_sequence < N - N / 2 >::type > {};
+
+template<> struct make_index_sequence<0> : index_sequence<> {};
+template<> struct make_index_sequence<1> : index_sequence<0> {};
+
+template<typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+/*
+Implementation of two C++17 constructs: conjunction, negation. This is needed
+to avoid evaluating all the traits in a condition
+
+For example: not std::is_same<void, T>::value and has_value_type<T>::value
+will not compile when T = void (on MSVC at least). Whereas
+conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
+stop evaluating if negation<...>::value == false
+
+Please note that those constructs must be used with caution, since symbols can
+become very long quickly (which can slow down compilation and cause MSVC
+internal compiler errors). Only use it when you have to (see example ahead).
+*/
+template<class...> struct conjunction : std::true_type {};
+template<class B1> struct conjunction<B1> : B1 {};
+template<class B1, class... Bn>
+struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+template<class B> struct negation : std::integral_constant<bool, not B::value> {};
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+ static constexpr T value{};
+};
+
+template<typename T>
+constexpr T static_const<T>::value;
+}
+}
diff --git a/include/nlohmann/detail/meta/detected.hpp b/include/nlohmann/detail/meta/detected.hpp
new file mode 100644
index 0000000..ed1d6ac
--- /dev/null
+++ b/include/nlohmann/detail/meta/detected.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <type_traits>
+
+#include <nlohmann/detail/meta/void_t.hpp>
+
+// http://en.cppreference.com/w/cpp/experimental/is_detected
+namespace nlohmann
+{
+namespace detail
+{
+struct nonesuch
+{
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ void operator=(nonesuch const&) = delete;
+};
+
+template <class Default,
+ class AlwaysVoid,
+ template <class...> class Op,
+ class... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
+
+template <class Default, template <class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
+
+template <template <class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template <template <class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template <class Expected, template <class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template <class To, template <class...> class Op, class... Args>
+using is_detected_convertible =
+ std::is_convertible<detected_t<Op, Args...>, To>;
+}
+}
diff --git a/include/nlohmann/detail/meta/is_sax.hpp b/include/nlohmann/detail/meta/is_sax.hpp
new file mode 100644
index 0000000..b4e1f3f
--- /dev/null
+++ b/include/nlohmann/detail/meta/is_sax.hpp
@@ -0,0 +1,141 @@
+#pragma once
+
+#include <cstdint> // size_t
+#include <utility> // declval
+
+#include <nlohmann/detail/meta/detected.hpp>
+#include <nlohmann/detail/meta/type_traits.hpp>
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template <typename T>
+using boolean_function_t =
+ decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template <typename T, typename Integer>
+using number_integer_function_t =
+ decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template <typename T, typename Unsigned>
+using number_unsigned_function_t =
+ decltype(std::declval<T &>().number_unsigned(std::declval<Unsigned>()));
+
+template <typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T &>().number_float(
+ std::declval<Float>(), std::declval<const String &>()));
+
+template <typename T, typename String>
+using string_function_t =
+ decltype(std::declval<T &>().string(std::declval<String &>()));
+
+template <typename T>
+using start_object_function_t =
+ decltype(std::declval<T &>().start_object(std::declval<std::size_t>()));
+
+template <typename T, typename String>
+using key_function_t =
+ decltype(std::declval<T &>().key(std::declval<String &>()));
+
+template <typename T>
+using end_object_function_t = decltype(std::declval<T &>().end_object());
+
+template <typename T>
+using start_array_function_t =
+ decltype(std::declval<T &>().start_array(std::declval<std::size_t>()));
+
+template <typename T>
+using end_array_function_t = decltype(std::declval<T &>().end_array());
+
+template <typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T &>().parse_error(
+ std::declval<std::size_t>(), std::declval<const std::string &>(),
+ std::declval<const Exception &>()));
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax
+{
+private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using exception_t = typename BasicJsonType::exception;
+
+public:
+ static constexpr bool value =
+ is_detected_exact<bool, null_function_t, SAX>::value &&
+ is_detected_exact<bool, boolean_function_t, SAX>::value &&
+ is_detected_exact<bool, number_integer_function_t, SAX,
+ number_integer_t>::value &&
+ is_detected_exact<bool, number_unsigned_function_t, SAX,
+ number_unsigned_t>::value &&
+ is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
+ string_t>::value &&
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, start_object_function_t, SAX>::value &&
+ is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, end_object_function_t, SAX>::value &&
+ is_detected_exact<bool, start_array_function_t, SAX>::value &&
+ is_detected_exact<bool, end_array_function_t, SAX>::value &&
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using exception_t = typename BasicJsonType::exception;
+
+public:
+ static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+ "Missing/invalid function: bool null()");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(
+ is_detected_exact<bool, number_integer_function_t, SAX,
+ number_integer_t>::value,
+ "Missing/invalid function: bool number_integer(number_integer_t)");
+ static_assert(
+ is_detected_exact<bool, number_unsigned_function_t, SAX,
+ number_unsigned_t>::value,
+ "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+ static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+ number_float_t, string_t>::value,
+ "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+ static_assert(
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool string(string_t&)");
+ static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+ "Missing/invalid function: bool start_object(std::size_t)");
+ static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool key(string_t&)");
+ static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+ "Missing/invalid function: bool end_object()");
+ static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+ "Missing/invalid function: bool start_array(std::size_t)");
+ static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+ "Missing/invalid function: bool end_array()");
+ static_assert(
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+ "Missing/invalid function: bool parse_error(std::size_t, const "
+ "std::string&, const exception&)");
+};
+}
+}
diff --git a/include/nlohmann/detail/meta.hpp b/include/nlohmann/detail/meta/type_traits.hpp
similarity index 71%
rename from include/nlohmann/detail/meta.hpp
rename to include/nlohmann/detail/meta/type_traits.hpp
index b251afb..caf8122 100644
--- a/include/nlohmann/detail/meta.hpp
+++ b/include/nlohmann/detail/meta/type_traits.hpp
@@ -1,12 +1,12 @@
#pragma once
#include <ciso646> // not
-#include <cstddef> // size_t
#include <limits> // numeric_limits
-#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
@@ -30,68 +30,6 @@
NLOHMANN_BASIC_JSON_TPL_DECLARATION
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
-// alias templates to reduce boilerplate
-template<bool B, typename T = void>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-template<typename T>
-using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-
-// implementation of C++14 index_sequence and affiliates
-// source: https://stackoverflow.com/a/32223343
-template<std::size_t... Ints>
-struct index_sequence
-{
- using type = index_sequence;
- using value_type = std::size_t;
- static constexpr std::size_t size() noexcept
- {
- return sizeof...(Ints);
- }
-};
-
-template<class Sequence1, class Sequence2>
-struct merge_and_renumber;
-
-template<std::size_t... I1, std::size_t... I2>
-struct merge_and_renumber<index_sequence<I1...>, index_sequence<I2...>>
- : index_sequence < I1..., (sizeof...(I1) + I2)... > {};
-
-template<std::size_t N>
-struct make_index_sequence
- : merge_and_renumber < typename make_index_sequence < N / 2 >::type,
- typename make_index_sequence < N - N / 2 >::type > {};
-
-template<> struct make_index_sequence<0> : index_sequence<> {};
-template<> struct make_index_sequence<1> : index_sequence<0> {};
-
-template<typename... Ts>
-using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
-
-/*
-Implementation of two C++17 constructs: conjunction, negation. This is needed
-to avoid evaluating all the traits in a condition
-
-For example: not std::is_same<void, T>::value and has_value_type<T>::value
-will not compile when T = void (on MSVC at least). Whereas
-conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
-stop evaluating if negation<...>::value == false
-
-Please note that those constructs must be used with caution, since symbols can
-become very long quickly (which can slow down compilation and cause MSVC
-internal compiler errors). Only use it when you have to (see example ahead).
-*/
-template<class...> struct conjunction : std::true_type {};
-template<class B1> struct conjunction<B1> : B1 {};
-template<class B1, class... Bn>
-struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
-
-template<class B> struct negation : std::integral_constant<bool, not B::value> {};
-
-// dispatch utility (taken from ranges-v3)
-template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
-template<> struct priority_tag<0> {};
-
////////////////////////
// has_/is_ functions //
////////////////////////
@@ -120,6 +58,17 @@
std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
};
+template<bool B, class RealType, class CompatibleStringType>
+struct is_compatible_string_type_impl : std::false_type {};
+
+template<class RealType, class CompatibleStringType>
+struct is_compatible_string_type_impl<true, RealType, CompatibleStringType>
+{
+ static constexpr auto value =
+ std::is_same<typename RealType::value_type, typename CompatibleStringType::value_type>::value and
+ std::is_constructible<RealType, CompatibleStringType>::value;
+};
+
template<class BasicJsonType, class CompatibleObjectType>
struct is_compatible_object_type
{
@@ -130,6 +79,15 @@
typename BasicJsonType::object_t, CompatibleObjectType >::value;
};
+template<class BasicJsonType, class CompatibleStringType>
+struct is_compatible_string_type
+{
+ static auto constexpr value = is_compatible_string_type_impl <
+ conjunction<negation<std::is_same<void, CompatibleStringType>>,
+ has_value_type<CompatibleStringType>>::value,
+ typename BasicJsonType::string_t, CompatibleStringType >::value;
+};
+
template<typename BasicJsonType, typename T>
struct is_basic_json_nested_type
{
@@ -244,15 +202,5 @@
is_compatible_complete_type<BasicJsonType, CompatibleType>>
{
};
-
-// taken from ranges-v3
-template<typename T>
-struct static_const
-{
- static constexpr T value{};
-};
-
-template<typename T>
-constexpr T static_const<T>::value;
}
}
diff --git a/include/nlohmann/detail/meta/void_t.hpp b/include/nlohmann/detail/meta/void_t.hpp
new file mode 100644
index 0000000..66c4a35
--- /dev/null
+++ b/include/nlohmann/detail/meta/void_t.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename...>
+using void_t = void;
+}
+}
diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp
index 1b15bda..71e5ec8 100644
--- a/include/nlohmann/detail/output/binary_writer.hpp
+++ b/include/nlohmann/detail/output/binary_writer.hpp
@@ -149,9 +149,9 @@
break;
}
- case value_t::number_float: // Double-Precision Float
+ case value_t::number_float:
{
- oa->write_character(static_cast<CharType>(0xFB));
+ oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -409,9 +409,9 @@
break;
}
- case value_t::number_float: // float 64
+ case value_t::number_float:
{
- oa->write_character(static_cast<CharType>(0xCB));
+ oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -588,7 +588,7 @@
if (use_type and not j.m_value.array->empty())
{
assert(use_count);
- const char first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -599,7 +599,7 @@
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
- oa->write_character(static_cast<CharType>(first_prefix));
+ oa->write_character(first_prefix);
}
}
@@ -633,7 +633,7 @@
if (use_type and not j.m_value.object->empty())
{
assert(use_count);
- const char first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -644,7 +644,7 @@
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
- oa->write_character(static_cast<CharType>(first_prefix));
+ oa->write_character(first_prefix);
}
}
@@ -712,7 +712,7 @@
{
if (add_prefix)
{
- oa->write_character(static_cast<CharType>('D')); // float64
+ oa->write_character(get_ubjson_float_prefix(n));
}
write_number(n);
}
@@ -833,7 +833,7 @@
write_number_with_ubjson_prefix. Therefore, we return 'L' for any
value that does not fit the previous limits.
*/
- char ubjson_prefix(const BasicJsonType& j) const noexcept
+ CharType ubjson_prefix(const BasicJsonType& j) const noexcept
{
switch (j.type())
{
@@ -892,7 +892,7 @@
}
case value_t::number_float:
- return 'D';
+ return get_ubjson_float_prefix(j.m_value.number_float);
case value_t::string:
return 'S';
@@ -908,6 +908,36 @@
}
}
+ static constexpr CharType get_cbor_float_prefix(float)
+ {
+ return static_cast<CharType>(0xFA); // Single-Precision Float
+ }
+
+ static constexpr CharType get_cbor_float_prefix(double)
+ {
+ return static_cast<CharType>(0xFB); // Double-Precision Float
+ }
+
+ static constexpr CharType get_msgpack_float_prefix(float)
+ {
+ return static_cast<CharType>(0xCA); // float 32
+ }
+
+ static constexpr CharType get_msgpack_float_prefix(double)
+ {
+ return static_cast<CharType>(0xCB); // float 64
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(float)
+ {
+ return 'd'; // float 32
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(double)
+ {
+ return 'D'; // float 64
+ }
+
private:
/// whether we can assume little endianess
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp
index a644264..de3676a 100644
--- a/include/nlohmann/detail/output/serializer.hpp
+++ b/include/nlohmann/detail/output/serializer.hpp
@@ -9,17 +9,14 @@
#include <cstddef> // size_t, ptrdiff_t
#include <cstdint> // uint8_t
#include <cstdio> // snprintf
-#include <iomanip> // setfill
-#include <iterator> // next
#include <limits> // numeric_limits
#include <string> // string
-#include <sstream> // stringstream
#include <type_traits> // is_same
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/macro_scope.hpp>
-#include <nlohmann/detail/meta.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
#include <nlohmann/detail/value_t.hpp>
@@ -389,9 +386,9 @@
case UTF8_REJECT: // decode found invalid UTF-8 byte
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte);
- JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str()));
+ std::string sn(3, '\0');
+ snprintf(&sn[0], sn.size(), "%.2X", byte);
+ JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
}
default: // decode found yet incomplete multi-byte code point
@@ -417,9 +414,9 @@
else
{
// we finish reading, but do not accept: string was incomplete
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(s.back()));
- JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str()));
+ std::string sn(3, '\0');
+ snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
+ JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
}
}
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index 7ecf631..1f39e3e 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -30,8 +31,8 @@
#define NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_VERSION_MAJOR 3
-#define NLOHMANN_JSON_VERSION_MINOR 1
-#define NLOHMANN_JSON_VERSION_PATCH 2
+#define NLOHMANN_JSON_VERSION_MINOR 2
+#define NLOHMANN_JSON_VERSION_PATCH 0
#include <algorithm> // all_of, find, for_each
#include <cassert> // assert
@@ -47,7 +48,8 @@
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/macro_scope.hpp>
-#include <nlohmann/detail/meta.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
+#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/conversions/from_json.hpp>
@@ -100,42 +102,42 @@
@requirement The class satisfies the following concept requirements:
- Basic
- - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
+ - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
JSON values can be default constructed. The result will be a JSON null
value.
- - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
+ - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
A JSON value can be constructed from an rvalue argument.
- - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
+ - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
A JSON value can be copy-constructed from an lvalue expression.
- - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
+ - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
A JSON value van be assigned from an rvalue argument.
- - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
+ - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
A JSON value can be copy-assigned from an lvalue expression.
- - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
+ - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
JSON values can be destructed.
- Layout
- - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
+ - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
JSON values have
- [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+ [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
All non-static data members are private and standard layout types, the
class has no virtual functions or (virtual) base classes.
- Library-wide
- - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
+ - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
JSON values can be compared with `==`, see @ref
operator==(const_reference,const_reference).
- - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
+ - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
JSON values can be compared with `<`, see @ref
operator<(const_reference,const_reference).
- - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
+ - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
other compatible types, using unqualified function call @ref swap().
- - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
+ - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
JSON values can be compared against `std::nullptr_t` objects which are used
to model the `null` value.
- Container
- - [Container](http://en.cppreference.com/w/cpp/concept/Container):
+ - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
JSON values can be used like STL containers and provide iterator access.
- - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
+ - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
JSON values can be used like STL containers and provide reverse iterator
access.
@@ -169,8 +171,12 @@
friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer;
- template<typename BasicJsonType>
+ template<typename BasicJsonType, typename SAX>
friend class ::nlohmann::detail::binary_reader;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_parser;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_callback_parser;
/// workaround type for MSVC
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
@@ -198,13 +204,17 @@
public:
using value_t = detail::value_t;
- /// @copydoc nlohmann::json_pointer
+ /// JSON Pointer, see @ref nlohmann::json_pointer
using json_pointer = ::nlohmann::json_pointer<basic_json>;
template<typename T, typename SFINAE>
using json_serializer = JSONSerializer<T, SFINAE>;
/// helper type for initializer lists of basic_json values
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+ using input_format_t = detail::input_format_t;
+ /// SAX interface type, see @ref nlohmann::json_sax
+ using json_sax_t = json_sax<basic_json>;
+
////////////////
// exceptions //
////////////////
@@ -937,7 +947,7 @@
object = nullptr; // silence warning, see #821
if (JSON_UNLIKELY(t == value_t::null))
{
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.1.2")); // LCOV_EXCL_LINE
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
}
break;
}
@@ -1105,7 +1115,6 @@
*/
using parser_callback_t = typename parser::parser_callback_t;
-
//////////////////
// constructors //
//////////////////
@@ -1267,7 +1276,7 @@
was provided), strong guarantee holds: if an exception is thrown, there are
no changes to any JSON value.
- @since version 3.1.2
+ @since version 3.2.0
*/
template <typename BasicJsonType,
detail::enable_if_t<
@@ -1587,7 +1596,7 @@
@warning A precondition is enforced with a runtime assertion that will
result in calling `std::abort` if this precondition is not met.
Assertions can be disabled by defining `NDEBUG` at compile time.
- See http://en.cppreference.com/w/cpp/error/assert for more
+ See https://en.cppreference.com/w/cpp/error/assert for more
information.
@throw invalid_iterator.201 if iterators @a first and @a last are not
@@ -1727,7 +1736,7 @@
changes to any JSON value.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
- As postcondition, it holds: `other == basic_json(other)`.
@@ -1812,7 +1821,7 @@
exceptions.
@requirement This function helps `basic_json` satisfying the
- [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible)
+ [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
requirements.
@liveexample{The code below shows the move constructor explicitly called
@@ -1846,7 +1855,7 @@
@complexity Linear.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
@@ -1883,7 +1892,7 @@
@complexity Linear.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
- All stored elements are destroyed and all memory is freed.
@@ -2500,7 +2509,7 @@
@complexity Depending on the implementation of the called `from_json()`
method.
- @since version 3.1.2
+ @since version 3.2.0
*/
template<typename BasicJsonType, detail::enable_if_t<
not std::is_same<BasicJsonType, basic_json>::value and
@@ -2514,8 +2523,8 @@
@brief get a value (explicit)
Explicit type conversion between the JSON value and a compatible value
- which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
- and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
The value is converted by calling the @ref json_serializer<ValueType>
`from_json()` method.
@@ -2575,8 +2584,8 @@
@brief get a value (explicit); special case
Explicit type conversion between the JSON value and a compatible value
- which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
- and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
The value is converted by calling the @ref json_serializer<ValueType>
`from_json()` method.
@@ -2821,10 +2830,10 @@
not detail::is_basic_json<ValueType>::value
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
-#endif
-#if defined(JSON_HAS_CPP_17)
+#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
and not std::is_same<ValueType, typename std::string_view>::value
#endif
+#endif
, int >::type = 0 >
operator ValueType() const
{
@@ -3405,7 +3414,7 @@
@return copy of the element at key @a key or @a default_value if @a key
is not found
- @throw type_error.306 if the JSON value is not an objec; in that case,
+ @throw type_error.306 if the JSON value is not an object; in that case,
using `value()` with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -3429,7 +3438,7 @@
{
return ptr.get_checked(this);
}
- JSON_CATCH (out_of_range&)
+ JSON_INTERNAL_CATCH (out_of_range&)
{
return default_value;
}
@@ -3940,7 +3949,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
@@ -3979,7 +3988,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
@@ -4011,7 +4020,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
@@ -4050,7 +4059,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).end()`.
@@ -4080,7 +4089,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `reverse_iterator(end())`.
@@ -4117,7 +4126,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `reverse_iterator(begin())`.
@@ -4154,7 +4163,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
@@ -4183,7 +4192,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
@@ -4324,7 +4333,7 @@
@complexity Constant.
- @since version 3.x.x.
+ @since version 3.1.0.
*/
iteration_proxy<iterator> items() noexcept
{
@@ -4381,7 +4390,7 @@
false in the case of a string.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `begin() == end()`.
@@ -4452,7 +4461,7 @@
the case of a string.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `std::distance(begin(), end())`.
@@ -4522,7 +4531,7 @@
@exceptionsafety No-throw guarantee: this function never throws exceptions.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of returning `b.size()` where `b` is the largest
@@ -5991,7 +6000,7 @@
@since version 2.0.3 (contiguous containers)
*/
- static basic_json parse(detail::input_adapter i,
+ static basic_json parse(detail::input_adapter&& i,
const parser_callback_t cb = nullptr,
const bool allow_exceptions = true)
{
@@ -6000,26 +6009,80 @@
return result;
}
+ static bool accept(detail::input_adapter&& i)
+ {
+ return parser(i).accept(true);
+ }
+
/*!
- @copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
+ @brief generate SAX events
+
+ The SAX event lister must follow the interface of @ref json_sax.
+
+ This function reads from a compatible input. Examples are:
+ - an array of 1-byte values
+ - strings with character/literal type with size of 1 byte
+ - input streams
+ - container with contiguous storage of 1-byte values. Compatible container
+ types include `std::vector`, `std::string`, `std::array`,
+ `std::valarray`, and `std::initializer_list`. Furthermore, C-style
+ arrays can be used with `std::begin()`/`std::end()`. User-defined
+ containers can be used as long as they implement random-access iterators
+ and a contiguous storage.
+
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @pre The container storage is contiguous. Violating this precondition
+ yields undefined behavior. **This precondition is enforced with an
+ assertion.**
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with a noncompliant container and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @param[in] i input to read from
+ @param[in,out] sax SAX event listener
+ @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
+ @param[in] strict whether the input has to be consumed completely
+
+ @return return value of the last processed SAX event
+
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
+ a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `sax_parse()` function
+ reading from string and processing the events with a user-defined SAX
+ event consumer.,sax_parse}
+
+ @since version 3.2.0
*/
- static basic_json parse(detail::input_adapter& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true)
+ template <typename SAX>
+ static bool sax_parse(detail::input_adapter&& i, SAX* sax,
+ input_format_t format = input_format_t::json,
+ const bool strict = true)
{
- basic_json result;
- parser(i, cb, allow_exceptions).parse(true, result);
- return result;
- }
-
- static bool accept(detail::input_adapter i)
- {
- return parser(i).accept(true);
- }
-
- static bool accept(detail::input_adapter& i)
- {
- return parser(i).accept(true);
+ assert(sax);
+ switch (format)
+ {
+ case input_format_t::json:
+ return parser(std::move(i)).sax_parse(sax, strict);
+ default:
+ return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
+ }
}
/*!
@@ -6091,6 +6154,15 @@
return parser(detail::input_adapter(first, last)).accept(true);
}
+ template<class IteratorType, class SAX, typename std::enable_if<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+ static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
+ {
+ return parser(detail::input_adapter(first, last)).sax_parse(sax);
+ }
+
/*!
@brief deserialize from stream
@deprecated This stream operator is deprecated and will be removed in
@@ -6587,6 +6659,9 @@
@param[in] i an input in CBOR format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
@return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
@@ -6602,29 +6677,39 @@
@sa http://cbor.io
@sa @ref to_cbor(const basic_json&) for the analogous serialization
- @sa @ref from_msgpack(detail::input_adapter, const bool) for the
+ @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the
related MessagePack format
- @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
- UBJSON format
+ @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the
+ related UBJSON format
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added
- @a strict parameter since 3.0.0
+ @a strict parameter since 3.0.0; added @allow_exceptions parameter
+ since 3.2.0
*/
- static basic_json from_cbor(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_cbor(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_cbor(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
- @copydoc from_cbor(detail::input_adapter, const bool)
+ @copydoc from_cbor(detail::input_adapter, const bool, const bool)
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_cbor(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
@@ -6677,6 +6762,10 @@
adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true
@@ -6691,29 +6780,39 @@
@sa http://msgpack.org
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
- @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
- format
- @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
- UBJSON format
+ @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
+ related CBOR format
+ @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for
+ the related UBJSON format
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added
- @a strict parameter since 3.0.0
+ @a strict parameter since 3.0.0; added @allow_exceptions parameter
+ since 3.2.0
*/
- static basic_json from_msgpack(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_msgpack(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_msgpack(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
- @copydoc from_msgpack(detail::input_adapter, const bool)
+ @copydoc from_msgpack(detail::input_adapter, const bool, const bool)
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_msgpack(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
@@ -6748,6 +6847,10 @@
@param[in] i an input in UBJSON format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true
@@ -6762,24 +6865,36 @@
@sa http://ubjson.org
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
analogous serialization
- @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
- format
- @sa @ref from_msgpack(detail::input_adapter, const bool) for the related
- MessagePack format
+ @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
+ related CBOR format
+ @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for
+ the related MessagePack format
- @since version 3.1.0
+ @since version 3.1.0; added @allow_exceptions parameter since 3.2.0
*/
- static basic_json from_ubjson(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_ubjson(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_ubjson(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
+ /*!
+ @copydoc from_ubjson(detail::input_adapter, const bool, const bool)
+ */
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_ubjson(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/// @}
@@ -7156,11 +7271,13 @@
break;
}
+ // LCOV_EXCL_START
default:
{
// if there exists a parent it cannot be primitive
- assert(false); // LCOV_EXCL_LINE
+ assert(false);
}
+ // LCOV_EXCL_STOP
}
}
};
@@ -7302,7 +7419,7 @@
// the "path" location must exist - use at()
success = (result.at(ptr) == get_value("test", "value", false));
}
- JSON_CATCH (out_of_range&)
+ JSON_INTERNAL_CATCH (out_of_range&)
{
// ignore out of range errors: success remains false
}
@@ -7580,11 +7697,10 @@
@since version 1.0.0
*/
template<>
-inline void swap(nlohmann::json& j1,
- nlohmann::json& j2) noexcept(
- is_nothrow_move_constructible<nlohmann::json>::value and
- is_nothrow_move_assignable<nlohmann::json>::value
- )
+inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
+ is_nothrow_move_constructible<nlohmann::json>::value and
+ is_nothrow_move_assignable<nlohmann::json>::value
+)
{
j1.swap(j2);
}
diff --git a/include/nlohmann/json_fwd.hpp b/include/nlohmann/json_fwd.hpp
index 750adb6..5ff0d75 100644
--- a/include/nlohmann/json_fwd.hpp
+++ b/include/nlohmann/json_fwd.hpp
@@ -18,10 +18,10 @@
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
-([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
-template<typename = void, typename = void>
+template<typename T = void, typename SFINAE = void>
struct adl_serializer;
template<template<typename U, typename V, typename... Args> class ObjectType =
diff --git a/meson.build b/meson.build
index cdbaad9..c79dcd3 100644
--- a/meson.build
+++ b/meson.build
@@ -1,7 +1,9 @@
project('nlohmann_json', 'cpp')
-nlohmann_json_inc = include_directories('single_include/nlohmann')
-
nlohmann_json_dep = declare_dependency(
- include_directories : nlohmann_json_inc
+ include_directories: include_directories('single_include')
+)
+
+nlohmann_json_multiple_headers = declare_dependency(
+ include_directories: include_directories('include')
)
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 6b6655a..b80386f 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -30,8 +31,8 @@
#define NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_VERSION_MAJOR 3
-#define NLOHMANN_JSON_VERSION_MINOR 1
-#define NLOHMANN_JSON_VERSION_PATCH 2
+#define NLOHMANN_JSON_VERSION_MINOR 2
+#define NLOHMANN_JSON_VERSION_PATCH 0
#include <algorithm> // all_of, find, for_each
#include <cassert> // assert
@@ -66,10 +67,10 @@
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
-([argument-dependent lookup](http://en.cppreference.com/w/cpp/language/adl))
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
-template<typename = void, typename = void>
+template<typename T = void, typename SFINAE = void>
struct adl_serializer;
template<template<typename U, typename V, typename... Args> class ObjectType =
@@ -118,13 +119,15 @@
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
// exclude unsupported compilers
-#if defined(__clang__)
- #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
- #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
- #endif
-#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
- #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
- #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+ #if defined(__clang__)
+ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+ #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
#endif
#endif
@@ -154,10 +157,12 @@
#define JSON_THROW(exception) throw exception
#define JSON_TRY try
#define JSON_CATCH(exception) catch(exception)
+ #define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#define JSON_THROW(exception) std::abort()
#define JSON_TRY if(true)
#define JSON_CATCH(exception) if(false)
+ #define JSON_INTERNAL_CATCH(exception) if(false)
#endif
// override exception macros
@@ -172,6 +177,11 @@
#if defined(JSON_CATCH_USER)
#undef JSON_CATCH
#define JSON_CATCH JSON_CATCH_USER
+ #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+ #undef JSON_INTERNAL_CATCH
+ #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
#endif
// manual branch prediction
@@ -228,41 +238,17 @@
std::is_integral<decltype(detect(std::declval<T>()))>::value; \
}
-// #include <nlohmann/detail/meta.hpp>
+// #include <nlohmann/detail/meta/cpp_future.hpp>
#include <ciso646> // not
#include <cstddef> // size_t
-#include <limits> // numeric_limits
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
-#include <utility> // declval
-
-// #include <nlohmann/json_fwd.hpp>
-
-// #include <nlohmann/detail/macro_scope.hpp>
-
namespace nlohmann
{
-/*!
-@brief detail namespace with internal helper functions
-
-This namespace collects functions that should not be exposed,
-implementations of some @ref basic_json methods, and meta-programming helpers.
-
-@since version 2.1.0
-*/
namespace detail
{
-/////////////
-// helpers //
-/////////////
-
-template<typename> struct is_basic_json : std::false_type {};
-
-NLOHMANN_BASIC_JSON_TPL_DECLARATION
-struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
-
// alias templates to reduce boilerplate
template<bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
@@ -325,6 +311,54 @@
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+ static constexpr T value{};
+};
+
+template<typename T>
+constexpr T static_const<T>::value;
+}
+}
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+#include <ciso646> // not
+#include <limits> // numeric_limits
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
+#include <utility> // declval
+
+// #include <nlohmann/json_fwd.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+/*!
+@brief detail namespace with internal helper functions
+
+This namespace collects functions that should not be exposed,
+implementations of some @ref basic_json methods, and meta-programming helpers.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+/////////////
+// helpers //
+/////////////
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
////////////////////////
// has_/is_ functions //
////////////////////////
@@ -353,6 +387,17 @@
std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
};
+template<bool B, class RealType, class CompatibleStringType>
+struct is_compatible_string_type_impl : std::false_type {};
+
+template<class RealType, class CompatibleStringType>
+struct is_compatible_string_type_impl<true, RealType, CompatibleStringType>
+{
+ static constexpr auto value =
+ std::is_same<typename RealType::value_type, typename CompatibleStringType::value_type>::value and
+ std::is_constructible<RealType, CompatibleStringType>::value;
+};
+
template<class BasicJsonType, class CompatibleObjectType>
struct is_compatible_object_type
{
@@ -363,6 +408,15 @@
typename BasicJsonType::object_t, CompatibleObjectType >::value;
};
+template<class BasicJsonType, class CompatibleStringType>
+struct is_compatible_string_type
+{
+ static auto constexpr value = is_compatible_string_type_impl <
+ conjunction<negation<std::is_same<void, CompatibleStringType>>,
+ has_value_type<CompatibleStringType>>::value,
+ typename BasicJsonType::string_t, CompatibleStringType >::value;
+};
+
template<typename BasicJsonType, typename T>
struct is_basic_json_nested_type
{
@@ -477,16 +531,6 @@
is_compatible_complete_type<BasicJsonType, CompatibleType>>
{
};
-
-// taken from ranges-v3
-template<typename T>
-struct static_const
-{
- static constexpr T value{};
-};
-
-template<typename T>
-constexpr T static_const<T>::value;
}
}
@@ -908,9 +952,11 @@
#include <ciso646> // and, not
#include <forward_list> // forward_list
#include <iterator> // inserter, front_inserter, end
+#include <map> // map
#include <string> // string
#include <tuple> // tuple, make_tuple
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
#include <utility> // pair, declval
#include <valarray> // valarray
@@ -918,7 +964,9 @@
// #include <nlohmann/detail/macro_scope.hpp>
-// #include <nlohmann/detail/meta.hpp>
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
@@ -927,6 +975,16 @@
{
namespace detail
{
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+ if (JSON_UNLIKELY(not j.is_null()))
+ {
+ JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
+ }
+ n = nullptr;
+}
+
// overloads for basic_json template parameters
template<typename BasicJsonType, typename ArithmeticType,
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
@@ -977,6 +1035,23 @@
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
}
+template <
+ typename BasicJsonType, typename CompatibleStringType,
+ enable_if_t <
+ is_compatible_string_type<BasicJsonType, CompatibleStringType>::value and
+ not std::is_same<typename BasicJsonType::string_t,
+ CompatibleStringType>::value,
+ int > = 0 >
+void from_json(const BasicJsonType& j, CompatibleStringType& s)
+{
+ if (JSON_UNLIKELY(not j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
+ }
+
+ s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
{
@@ -1184,6 +1259,44 @@
from_json_tuple_impl(j, t, index_sequence_for<Args...> {});
}
+template <typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+ typename = enable_if_t<not std::is_constructible<
+ typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ for (const auto& p : j)
+ {
+ if (JSON_UNLIKELY(not p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
+template <typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+ typename = enable_if_t<not std::is_constructible<
+ typename BasicJsonType::string_t, Key>::value>>
+void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+ if (JSON_UNLIKELY(not j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
+ }
+ for (const auto& p : j)
+ {
+ if (JSON_UNLIKELY(not p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
struct from_json_fn
{
private:
@@ -1238,10 +1351,143 @@
#include <valarray> // valarray
#include <vector> // vector
-// #include <nlohmann/detail/meta.hpp>
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
// #include <nlohmann/detail/value_t.hpp>
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+
+#include <cstddef> // size_t
+#include <string> // string, to_string
+#include <iterator> // input_iterator_tag
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// proxy class for the items() function
+template<typename IteratorType> class iteration_proxy
+{
+ private:
+ /// helper class for iteration
+ class iteration_proxy_internal
+ {
+ public:
+ using difference_type = std::ptrdiff_t;
+ using value_type = iteration_proxy_internal;
+ using pointer = iteration_proxy_internal*;
+ using reference = iteration_proxy_internal&;
+ using iterator_category = std::input_iterator_tag;
+
+ private:
+ /// the iterator
+ IteratorType anchor;
+ /// an index for arrays (used to create key names)
+ std::size_t array_index = 0;
+ /// last stringified array index
+ mutable std::size_t array_index_last = 0;
+ /// a string representation of the array index
+ mutable std::string array_index_str = "0";
+ /// an empty string (to return a reference for primitive values)
+ const std::string empty_str = "";
+
+ public:
+ explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
+
+ iteration_proxy_internal(const iteration_proxy_internal&) = default;
+ iteration_proxy_internal& operator=(const iteration_proxy_internal&) = default;
+
+ /// dereference operator (needed for range-based for)
+ iteration_proxy_internal& operator*()
+ {
+ return *this;
+ }
+
+ /// increment operator (needed for range-based for)
+ iteration_proxy_internal& operator++()
+ {
+ ++anchor;
+ ++array_index;
+
+ return *this;
+ }
+
+ /// equality operator (needed for InputIterator)
+ bool operator==(const iteration_proxy_internal& o) const noexcept
+ {
+ return anchor == o.anchor;
+ }
+
+ /// inequality operator (needed for range-based for)
+ bool operator!=(const iteration_proxy_internal& o) const noexcept
+ {
+ return anchor != o.anchor;
+ }
+
+ /// return key of the iterator
+ const std::string& key() const
+ {
+ assert(anchor.m_object != nullptr);
+
+ switch (anchor.m_object->type())
+ {
+ // use integer array index as key
+ case value_t::array:
+ {
+ if (array_index != array_index_last)
+ {
+ array_index_str = std::to_string(array_index);
+ array_index_last = array_index;
+ }
+ return array_index_str;
+ }
+
+ // use key from the object
+ case value_t::object:
+ return anchor.key();
+
+ // use an empty key for all primitive types
+ default:
+ return empty_str;
+ }
+ }
+
+ /// return value of the iterator
+ typename IteratorType::reference value() const
+ {
+ return anchor.value();
+ }
+ };
+
+ /// the container to iterate
+ typename IteratorType::reference container;
+
+ public:
+ /// construct iteration proxy from a container
+ explicit iteration_proxy(typename IteratorType::reference cont) noexcept
+ : container(cont) {}
+
+ /// return iterator begin (needed for range-based for)
+ iteration_proxy_internal begin() noexcept
+ {
+ return iteration_proxy_internal(container.begin());
+ }
+
+ /// return iterator end (needed for range-based for)
+ iteration_proxy_internal end() noexcept
+ {
+ return iteration_proxy_internal(container.end());
+ }
+};
+}
+}
+
namespace nlohmann
{
@@ -1283,6 +1529,16 @@
j.m_value = std::move(s);
j.assert_invariant();
}
+
+ template<typename BasicJsonType, typename CompatibleStringType,
+ enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+ int> = 0>
+ static void construct(BasicJsonType& j, const CompatibleStringType& str)
+ {
+ j.m_type = value_t::string;
+ j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+ j.assert_invariant();
+ }
};
template<>
@@ -1479,7 +1735,7 @@
template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
-void to_json(BasicJsonType& j, std::valarray<T> arr)
+void to_json(BasicJsonType& j, const std::valarray<T>& arr)
{
external_constructor<value_t::array>::construct(j, std::move(arr));
}
@@ -1516,6 +1772,14 @@
j = {p.first, p.second};
}
+// for https://github.com/nlohmann/json/pull/1134
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_same<T, typename iteration_proxy<typename BasicJsonType::iterator>::iteration_proxy_internal>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+ j = {{b.key(), b.value()}};
+}
+
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>)
{
@@ -1572,12 +1836,9 @@
// #include <nlohmann/detail/input/input_adapters.hpp>
-#include <algorithm> // min
-#include <array> // array
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstring> // strlen
-#include <ios> // streamsize, streamoff, streampos
#include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
#include <memory> // shared_ptr, make_shared, addressof
@@ -1593,6 +1854,9 @@
{
namespace detail
{
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson };
+
////////////////////
// input adapters //
////////////////////
@@ -1601,19 +1865,17 @@
@brief abstract input adapter interface
Produces a stream of std::char_traits<char>::int_type characters from a
-std::istream, a buffer, or some other input type. Accepts the return of exactly
-one non-EOF character for future input. The int_type characters returned
-consist of all valid char values as positive values (typically unsigned char),
-plus an EOF value outside that range, specified by the value of the function
-std::char_traits<char>::eof(). This value is typically -1, but could be any
-arbitrary value which is not a valid char value.
+std::istream, a buffer, or some other input type. Accepts the return of
+exactly one non-EOF character for future input. The int_type characters
+returned consist of all valid char values as positive values (typically
+unsigned char), plus an EOF value outside that range, specified by the value
+of the function std::char_traits<char>::eof(). This value is typically -1, but
+could be any arbitrary value which is not a valid char value.
*/
struct input_adapter_protocol
{
/// get a character [0,255] or std::char_traits<char>::eof().
virtual std::char_traits<char>::int_type get_character() = 0;
- /// restore the last non-eof() character to input
- virtual void unget_character() = 0;
virtual ~input_adapter_protocol() = default;
};
@@ -1641,34 +1903,7 @@
explicit input_stream_adapter(std::istream& i)
: is(i), sb(*i.rdbuf())
- {
- // skip byte order mark
- std::char_traits<char>::int_type c;
- if ((c = get_character()) == 0xEF)
- {
- if ((c = get_character()) == 0xBB)
- {
- if ((c = get_character()) == 0xBF)
- {
- return; // Ignore BOM
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget();
- }
- is.putback('\xBB');
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget();
- }
- is.putback('\xEF');
- }
- else if (c != std::char_traits<char>::eof())
- {
- is.unget(); // no byte order mark; process as usual
- }
- }
+ {}
// delete because of pointer members
input_stream_adapter(const input_stream_adapter&) = delete;
@@ -1682,11 +1917,6 @@
return sb.sbumpc();
}
- void unget_character() override
- {
- sb.sungetc(); // is.unget() avoided for performance
- }
-
private:
/// the associated input stream
std::istream& is;
@@ -1698,14 +1928,8 @@
{
public:
input_buffer_adapter(const char* b, const std::size_t l)
- : cursor(b), limit(b + l), start(b)
- {
- // skip byte order mark
- if (l >= 3 and b[0] == '\xEF' and b[1] == '\xBB' and b[2] == '\xBF')
- {
- cursor += 3;
- }
- }
+ : cursor(b), limit(b + l)
+ {}
// delete because of pointer members
input_buffer_adapter(const input_buffer_adapter&) = delete;
@@ -1721,21 +1945,164 @@
return std::char_traits<char>::eof();
}
- void unget_character() noexcept override
- {
- if (JSON_LIKELY(cursor > start))
- {
- --cursor;
- }
- }
-
private:
/// pointer to the current character
const char* cursor;
/// pointer past the last character
- const char* limit;
- /// pointer to the first character
- const char* start;
+ const char* const limit;
+};
+
+template<typename WideStringType>
+class wide_string_input_adapter : public input_adapter_protocol
+{
+ public:
+ explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
+
+ std::char_traits<char>::int_type get_character() noexcept override
+ {
+ // check if buffer needs to be filled
+ if (utf8_bytes_index == utf8_bytes_filled)
+ {
+ if (sizeof(typename WideStringType::value_type) == 2)
+ {
+ fill_buffer_utf16();
+ }
+ else
+ {
+ fill_buffer_utf32();
+ }
+
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index == 0);
+ }
+
+ // use buffer
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index < utf8_bytes_filled);
+ return utf8_bytes[utf8_bytes_index++];
+ }
+
+ private:
+ void fill_buffer_utf16()
+ {
+ utf8_bytes_index = 0;
+
+ if (current_wchar == str.size())
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const int wc = static_cast<int>(str[current_wchar++]);
+
+ // UTF-16 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = 0xC0 | ((wc >> 6));
+ utf8_bytes[1] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 2;
+ }
+ else if (0xD800 > wc or wc >= 0xE000)
+ {
+ utf8_bytes[0] = 0xE0 | ((wc >> 12));
+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[2] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 3;
+ }
+ else
+ {
+ if (current_wchar < str.size())
+ {
+ const int wc2 = static_cast<int>(str[current_wchar++]);
+ const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
+ utf8_bytes[0] = 0xf0 | (charcode >> 18);
+ utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
+ utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
+ utf8_bytes[3] = 0x80 | (charcode & 0x3F);
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ // unknown character
+ ++current_wchar;
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+ }
+
+ void fill_buffer_utf32()
+ {
+ utf8_bytes_index = 0;
+
+ if (current_wchar == str.size())
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const int wc = static_cast<int>(str[current_wchar++]);
+
+ // UTF-32 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
+ utf8_bytes[1] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 2;
+ }
+ else if (wc <= 0xFFFF)
+ {
+ utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[2] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 3;
+ }
+ else if (wc <= 0x10FFFF)
+ {
+ utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
+ utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
+ utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[3] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ // unknown character
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+
+ private:
+ /// the wstring to process
+ const WideStringType& str;
+
+ /// index of the current wchar in str
+ std::size_t current_wchar = 0;
+
+ /// a buffer for UTF-8 bytes
+ std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+ /// index to the utf8_codes array for the next valid byte
+ std::size_t utf8_bytes_index = 0;
+ /// number of valid bytes in the utf8_codes array
+ std::size_t utf8_bytes_filled = 0;
};
class input_adapter
@@ -1751,6 +2118,15 @@
input_adapter(std::istream&& i)
: ia(std::make_shared<input_stream_adapter>(i)) {}
+ input_adapter(const std::wstring& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::wstring>>(ws)) {}
+
+ input_adapter(const std::u16string& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::u16string>>(ws)) {}
+
+ input_adapter(const std::u32string& ws)
+ : ia(std::make_shared<wide_string_input_adapter<std::u32string>>(ws)) {}
+
/// input adapter for buffer
template<typename CharT,
typename std::enable_if<
@@ -1840,10 +2216,8 @@
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <cstdio> // snprintf
#include <initializer_list> // initializer_list
-#include <ios> // hex, uppercase
-#include <iomanip> // setw, setfill
-#include <sstream> // stringstream
#include <string> // char_traits, string
#include <vector> // vector
@@ -1933,12 +2307,14 @@
return "end of input";
case token_type::literal_or_value:
return "'[', '{', or a literal";
+ // LCOV_EXCL_START
default: // catch non-enum values
- return "unknown token"; // LCOV_EXCL_LINE
+ return "unknown token";
+ // LCOV_EXCL_STOP
}
}
- explicit lexer(detail::input_adapter_t adapter)
+ explicit lexer(detail::input_adapter_t&& adapter)
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
// delete because of pointer members
@@ -2586,11 +2962,13 @@
goto scan_number_any1;
}
+ // LCOV_EXCL_START
default:
{
// all other characters are rejected outside scan_number()
- assert(false); // LCOV_EXCL_LINE
+ assert(false);
}
+ // LCOV_EXCL_STOP
}
scan_number_minus:
@@ -2920,7 +3298,16 @@
std::char_traits<char>::int_type get()
{
++chars_read;
- current = ia->get_character();
+ if (next_unget)
+ {
+ // just reset the next_unget variable and work with current
+ next_unget = false;
+ }
+ else
+ {
+ current = ia->get_character();
+ }
+
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
token_string.push_back(std::char_traits<char>::to_char_type(current));
@@ -2928,13 +3315,20 @@
return current;
}
- /// unget current character (return it again on next get)
+ /*!
+ @brief unget current character (read it again on next get)
+
+ We implement unget by setting variable next_unget to true. The input is not
+ changed - we just simulate ungetting by modifying chars_read and
+ token_string. The next call to get() will behave as if the unget character
+ is read again.
+ */
void unget()
{
+ next_unget = true;
--chars_read;
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
- ia->unget_character();
assert(token_string.size() != 0);
token_string.pop_back();
}
@@ -2970,9 +3364,9 @@
}
/// return current string value (implicitly resets the token; useful only once)
- string_t&& move_string()
+ string_t& get_string()
{
- return std::move(token_buffer);
+ return token_buffer;
}
/////////////////////
@@ -2997,10 +3391,9 @@
if ('\x00' <= c and c <= '\x1F')
{
// escape control characters
- std::stringstream ss;
- ss << "<U+" << std::setw(4) << std::uppercase << std::setfill('0')
- << std::hex << static_cast<int>(c) << ">";
- result += ss.str();
+ char cs[9];
+ snprintf(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
+ result += cs;
}
else
{
@@ -3022,8 +3415,43 @@
// actual scanner
/////////////////////
+ /*!
+ @brief skip the UTF-8 byte order mark
+ @return true iff there is no BOM or the correct BOM has been skipped
+ */
+ bool skip_bom()
+ {
+ if (get() == 0xEF)
+ {
+ if (get() == 0xBB and get() == 0xBF)
+ {
+ // we completely parsed the BOM
+ return true;
+ }
+ else
+ {
+ // after reading 0xEF, an unexpected character followed
+ return false;
+ }
+ }
+ else
+ {
+ // the first character is not the beginning of the BOM; unget it to
+ // process is later
+ unget();
+ return true;
+ }
+ }
+
token_type scan()
{
+ // initially, skip the BOM
+ if (chars_read == 0 and not skip_bom())
+ {
+ error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+ return token_type::parse_error;
+ }
+
// read next character and ignore whitespace
do
{
@@ -3093,6 +3521,9 @@
/// the current character
std::char_traits<char>::int_type current = std::char_traits<char>::eof();
+ /// whether the next get() call should just return current
+ bool next_unget = false;
+
/// the number of characters read
std::size_t chars_read = 0;
@@ -3130,8 +3561,926 @@
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+
+#include <cstdint> // size_t
+#include <utility> // declval
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename...>
+using void_t = void;
+}
+}
+
+
+// http://en.cppreference.com/w/cpp/experimental/is_detected
+namespace nlohmann
+{
+namespace detail
+{
+struct nonesuch
+{
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ void operator=(nonesuch const&) = delete;
+};
+
+template <class Default,
+ class AlwaysVoid,
+ template <class...> class Op,
+ class... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
+
+template <class Default, template <class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
+
+template <template <class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template <template <class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template <class Default, template <class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template <class Expected, template <class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template <class To, template <class...> class Op, class... Args>
+using is_detected_convertible =
+ std::is_convertible<detected_t<Op, Args...>, To>;
+}
+}
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template <typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template <typename T>
+using boolean_function_t =
+ decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template <typename T, typename Integer>
+using number_integer_function_t =
+ decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template <typename T, typename Unsigned>
+using number_unsigned_function_t =
+ decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
+
+template <typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T&>().number_float(
+ std::declval<Float>(), std::declval<const String&>()));
+
+template <typename T, typename String>
+using string_function_t =
+ decltype(std::declval<T&>().string(std::declval<String&>()));
+
+template <typename T>
+using start_object_function_t =
+ decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
+
+template <typename T, typename String>
+using key_function_t =
+ decltype(std::declval<T&>().key(std::declval<String&>()));
+
+template <typename T>
+using end_object_function_t = decltype(std::declval<T&>().end_object());
+
+template <typename T>
+using start_array_function_t =
+ decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
+
+template <typename T>
+using end_array_function_t = decltype(std::declval<T&>().end_array());
+
+template <typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T&>().parse_error(
+ std::declval<std::size_t>(), std::declval<const std::string&>(),
+ std::declval<const Exception&>()));
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax
+{
+ private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using exception_t = typename BasicJsonType::exception;
+
+ public:
+ static constexpr bool value =
+ is_detected_exact<bool, null_function_t, SAX>::value &&
+ is_detected_exact<bool, boolean_function_t, SAX>::value &&
+ is_detected_exact<bool, number_integer_function_t, SAX,
+ number_integer_t>::value &&
+ is_detected_exact<bool, number_unsigned_function_t, SAX,
+ number_unsigned_t>::value &&
+ is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
+ string_t>::value &&
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, start_object_function_t, SAX>::value &&
+ is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, end_object_function_t, SAX>::value &&
+ is_detected_exact<bool, start_array_function_t, SAX>::value &&
+ is_detected_exact<bool, end_array_function_t, SAX>::value &&
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template <typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+ private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using exception_t = typename BasicJsonType::exception;
+
+ public:
+ static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+ "Missing/invalid function: bool null()");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(
+ is_detected_exact<bool, number_integer_function_t, SAX,
+ number_integer_t>::value,
+ "Missing/invalid function: bool number_integer(number_integer_t)");
+ static_assert(
+ is_detected_exact<bool, number_unsigned_function_t, SAX,
+ number_unsigned_t>::value,
+ "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+ static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+ number_float_t, string_t>::value,
+ "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+ static_assert(
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool string(string_t&)");
+ static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+ "Missing/invalid function: bool start_object(std::size_t)");
+ static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool key(string_t&)");
+ static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+ "Missing/invalid function: bool end_object()");
+ static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+ "Missing/invalid function: bool start_array(std::size_t)");
+ static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+ "Missing/invalid function: bool end_array()");
+ static_assert(
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+ "Missing/invalid function: bool parse_error(std::size_t, const "
+ "std::string&, const exception&)");
+};
+}
+}
+
// #include <nlohmann/detail/input/input_adapters.hpp>
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+// #include <nlohmann/detail/input/parser.hpp>
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+
+namespace nlohmann
+{
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+ /// type for (signed) integers
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ /// type for unsigned integers
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ /// type for floating-point numbers
+ using number_float_t = typename BasicJsonType::number_float_t;
+ /// type for strings
+ using string_t = typename BasicJsonType::string_t;
+
+ /*!
+ @brief a null value was read
+ @return whether parsing should proceed
+ */
+ virtual bool null() = 0;
+
+ /*!
+ @brief a boolean value was read
+ @param[in] val boolean value
+ @return whether parsing should proceed
+ */
+ virtual bool boolean(bool val) = 0;
+
+ /*!
+ @brief an integer number was read
+ @param[in] val integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_integer(number_integer_t val) = 0;
+
+ /*!
+ @brief an unsigned integer number was read
+ @param[in] val unsigned integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+ /*!
+ @brief an floating-point number was read
+ @param[in] val floating-point value
+ @param[in] s raw token value
+ @return whether parsing should proceed
+ */
+ virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+ /*!
+ @brief a string was read
+ @param[in] val string value
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool string(string_t& val) = 0;
+
+ /*!
+ @brief the beginning of an object was read
+ @param[in] elements number of object elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_object(std::size_t elements) = 0;
+
+ /*!
+ @brief an object key was read
+ @param[in] val object key
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool key(string_t& val) = 0;
+
+ /*!
+ @brief the end of an object was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_object() = 0;
+
+ /*!
+ @brief the beginning of an array was read
+ @param[in] elements number of array elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_array(std::size_t elements) = 0;
+
+ /*!
+ @brief the end of an array was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_array() = 0;
+
+ /*!
+ @brief a parse error occurred
+ @param[in] position the position in the input where the error occurs
+ @param[in] last_token the last read token
+ @param[in] error_msg a detailed error message
+ @return whether parsing should proceed (must return false)
+ */
+ virtual bool parse_error(std::size_t position,
+ const std::string& last_token,
+ const detail::exception& ex) = 0;
+
+ virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+
+ /*!
+ @param[in, out] r reference to a JSON value that is manipulated while
+ parsing
+ @param[in] allow_exceptions_ whether parse errors yield exceptions
+ */
+ explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+ : root(r), allow_exceptions(allow_exceptions_)
+ {}
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t&)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive object size: " + std::to_string(len)));
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ // add null at given key and store the reference for later
+ object_element = &(ref_stack.back()->m_value.object->operator[](val));
+ return true;
+ }
+
+ bool end_object()
+ {
+ ref_stack.pop_back();
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive array size: " + std::to_string(len)));
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ ref_stack.pop_back();
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&,
+ const detail::exception& ex)
+ {
+ errored = true;
+ if (allow_exceptions)
+ {
+ // determine the proper exception type from the id
+ switch ((ex.id / 100) % 100)
+ {
+ case 1:
+ JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
+ case 4:
+ JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
+ // LCOV_EXCL_START
+ case 2:
+ JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
+ case 3:
+ JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
+ case 5:
+ JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
+ }
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+ */
+ template<typename Value>
+ BasicJsonType* handle_value(Value&& v)
+ {
+ if (ref_stack.empty())
+ {
+ root = BasicJsonType(std::forward<Value>(v));
+ return &root;
+ }
+ else
+ {
+ assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+ return &(ref_stack.back()->m_value.array->back());
+ }
+ else
+ {
+ assert(object_element);
+ *object_element = BasicJsonType(std::forward<Value>(v));
+ return object_element;
+ }
+ }
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack;
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using parser_callback_t = typename BasicJsonType::parser_callback_t;
+ using parse_event_t = typename BasicJsonType::parse_event_t;
+
+ json_sax_dom_callback_parser(BasicJsonType& r,
+ const parser_callback_t cb,
+ const bool allow_exceptions_ = true)
+ : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+ {
+ keep_stack.push_back(true);
+ }
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t&)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ // check callback for object start
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::object, true);
+ ref_stack.push_back(val.second);
+
+ // check object limit
+ if (ref_stack.back())
+ {
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive object size: " + std::to_string(len)));
+ }
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ BasicJsonType k = BasicJsonType(val);
+
+ // check callback for key
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+ key_keep_stack.push_back(keep);
+
+ // add discarded value at given key and store the reference for later
+ if (keep and ref_stack.back())
+ {
+ object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+ }
+
+ return true;
+ }
+
+ bool end_object()
+ {
+ if (ref_stack.back())
+ {
+ if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+ {
+ // discard object
+ *ref_stack.back() = discarded;
+ }
+ }
+
+ assert(not ref_stack.empty());
+ assert(not keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ if (not ref_stack.empty() and ref_stack.back())
+ {
+ // remove discarded value
+ if (ref_stack.back()->is_object())
+ {
+ for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+ {
+ if (it->is_discarded())
+ {
+ ref_stack.back()->erase(it);
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::array, true);
+ ref_stack.push_back(val.second);
+
+ // check array limit
+ if (ref_stack.back())
+ {
+ if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408,
+ "excessive array size: " + std::to_string(len)));
+ }
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ bool keep = true;
+
+ if (ref_stack.back())
+ {
+ keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+ if (not keep)
+ {
+ // discard array
+ *ref_stack.back() = discarded;
+ }
+ }
+
+ assert(not ref_stack.empty());
+ assert(not keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ // remove discarded value
+ if (not keep and not ref_stack.empty())
+ {
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->pop_back();
+ }
+ }
+
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&,
+ const detail::exception& ex)
+ {
+ errored = true;
+ if (allow_exceptions)
+ {
+ // determine the proper exception type from the id
+ switch ((ex.id / 100) % 100)
+ {
+ case 1:
+ JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
+ case 4:
+ JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
+ // LCOV_EXCL_START
+ case 2:
+ JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
+ case 3:
+ JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
+ case 5:
+ JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
+ }
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @param[in] v value to add to the JSON value we build during parsing
+ @param[in] skip_callback whether we should skip calling the callback
+ function; this is required after start_array() and
+ start_object() SAX events, because otherwise we would call the
+ callback function with an empty array or object, respectively.
+
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+
+ @return pair of boolean (whether value should be kept) and pointer (to the
+ passed value in the ref_stack hierarchy; nullptr if not kept)
+ */
+ template<typename Value>
+ std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+ {
+ assert(not keep_stack.empty());
+
+ // do not handle this value if we know it would be added to a discarded
+ // container
+ if (not keep_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ // create value
+ auto value = BasicJsonType(std::forward<Value>(v));
+
+ // check callback
+ const bool keep = skip_callback or callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+ // do not handle this value if we just learnt it shall be discarded
+ if (not keep)
+ {
+ return {false, nullptr};
+ }
+
+ if (ref_stack.empty())
+ {
+ root = std::move(value);
+ return {true, &root};
+ }
+ else
+ {
+ // skip this value if we already decided to skip the parent
+ // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+ if (not ref_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->push_back(std::move(value));
+ return {true, &(ref_stack.back()->m_value.array->back())};
+ }
+ else
+ {
+ // check if we should store an element for the current key
+ assert(not key_keep_stack.empty());
+ const bool store_element = key_keep_stack.back();
+ key_keep_stack.pop_back();
+
+ if (not store_element)
+ {
+ return {false, nullptr};
+ }
+
+ assert(object_element);
+ *object_element = std::move(value);
+ return {true, object_element};
+ }
+ }
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack;
+ /// stack to manage which values to keep
+ std::vector<bool> keep_stack;
+ /// stack to manage which object keys to keep
+ std::vector<bool> key_keep_stack;
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// callback function
+ const parser_callback_t callback = nullptr;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+ /// a discarded value for the callback
+ BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+
+ bool null()
+ {
+ return true;
+ }
+
+ bool boolean(bool)
+ {
+ return true;
+ }
+
+ bool number_integer(number_integer_t)
+ {
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t)
+ {
+ return true;
+ }
+
+ bool number_float(number_float_t, const string_t&)
+ {
+ return true;
+ }
+
+ bool string(string_t&)
+ {
+ return true;
+ }
+
+ bool start_object(std::size_t = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool key(string_t&)
+ {
+ return true;
+ }
+
+ bool end_object()
+ {
+ return true;
+ }
+
+ bool start_array(std::size_t = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool end_array()
+ {
+ return true;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const detail::exception&)
+ {
+ return false;
+ }
+};
+}
+
+}
+
// #include <nlohmann/detail/input/lexer.hpp>
// #include <nlohmann/detail/value_t.hpp>
@@ -3181,11 +4530,14 @@
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
/// a parser reading from an input adapter
- explicit parser(detail::input_adapter_t adapter,
+ explicit parser(detail::input_adapter_t&& adapter,
const parser_callback_t cb = nullptr,
const bool allow_exceptions_ = true)
- : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
- {}
+ : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
+ {
+ // read first token
+ get_token();
+ }
/*!
@brief public parser interface
@@ -3199,31 +4551,54 @@
*/
void parse(const bool strict, BasicJsonType& result)
{
- // read first token
- get_token();
-
- parse_internal(true, result);
- result.assert_invariant();
-
- // in strict mode, input must be completely read
- if (strict)
+ if (callback)
{
- get_token();
- expect(token_type::end_of_input);
+ json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+ sax_parse_internal(&sdp);
+ result.assert_invariant();
+
+ // in strict mode, input must be completely read
+ if (strict and (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
+
+ // set top-level value to null if it was discarded by the callback
+ // function
+ if (result.is_discarded())
+ {
+ result = nullptr;
+ }
}
-
- // in case of an error, return discarded value
- if (errored)
+ else
{
- result = value_t::discarded;
- return;
- }
+ json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+ sax_parse_internal(&sdp);
+ result.assert_invariant();
- // set top-level value to null if it was discarded by the callback
- // function
- if (result.is_discarded())
- {
- result = nullptr;
+ // in strict mode, input must be completely read
+ if (strict and (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
}
}
@@ -3235,414 +4610,311 @@
*/
bool accept(const bool strict = true)
{
- // read first token
- get_token();
+ json_sax_acceptor<BasicJsonType> sax_acceptor;
+ return sax_parse(&sax_acceptor, strict);
+ }
- if (not accept_internal())
+ template <typename SAX>
+ bool sax_parse(SAX* sax, const bool strict = true)
+ {
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+ const bool result = sax_parse_internal(sax);
+
+ // strict mode: next byte must be EOF
+ if (result and strict and (get_token() != token_type::end_of_input))
{
- return false;
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
}
- // strict => last token must be EOF
- return not strict or (get_token() == token_type::end_of_input);
+ return result;
}
private:
- /*!
- @brief the actual parser
- @throw parse_error.101 in case of an unexpected token
- @throw parse_error.102 if to_unicode fails or surrogate error
- @throw parse_error.103 if to_unicode fails
- */
- void parse_internal(bool keep, BasicJsonType& result)
+ template <typename SAX>
+ bool sax_parse_internal(SAX* sax)
{
- // never parse after a parse error was detected
- assert(not errored);
+ // stack to remember the hieararchy of structured values we are parsing
+ // true = array; false = object
+ std::vector<bool> states;
+ // value to avoid a goto (see comment where set to true)
+ bool skip_to_state_evaluation = false;
- // start with a discarded value
- if (not result.is_discarded())
+ while (true)
{
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
-
- switch (last_token)
- {
- case token_type::begin_object:
+ if (not skip_to_state_evaluation)
{
- if (keep)
+ // invariant: get_token() was called before each iteration
+ switch (last_token)
{
- if (callback)
+ case token_type::begin_object:
{
- keep = callback(depth++, parse_event_t::object_start, result);
- }
-
- if (not callback or keep)
- {
- // explicitly set result to object to cope with {}
- result.m_type = value_t::object;
- result.m_value = value_t::object;
- }
- }
-
- // read next token
- get_token();
-
- // closing } -> we are done
- if (last_token == token_type::end_object)
- {
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- // parse values
- string_t key;
- BasicJsonType value;
- while (true)
- {
- // store key
- if (not expect(token_type::value_string))
- {
- return;
- }
- key = m_lexer.move_string();
-
- bool keep_tag = false;
- if (keep)
- {
- if (callback)
+ if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
- BasicJsonType k(key);
- keep_tag = callback(depth, parse_event_t::key, k);
+ return false;
+ }
+
+ // closing } -> we are done
+ if (get_token() == token_type::end_object)
+ {
+ if (JSON_UNLIKELY(not sax->end_object()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // parse key
+ if (JSON_UNLIKELY(last_token != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
}
else
{
- keep_tag = true;
+ if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+ }
+
+ // parse separator (:)
+ if (JSON_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
+ }
+
+ // remember we are now inside an object
+ states.push_back(false);
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ case token_type::begin_array:
+ {
+ if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ // closing ] -> we are done
+ if (get_token() == token_type::end_array)
+ {
+ if (JSON_UNLIKELY(not sax->end_array()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // remember we are now inside an array
+ states.push_back(true);
+
+ // parse values (no need to call get_token)
+ continue;
+ }
+
+ case token_type::value_float:
+ {
+ const auto res = m_lexer.get_number_float();
+
+ if (JSON_UNLIKELY(not std::isfinite(res)))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
+ }
+ else
+ {
+ if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
+ {
+ return false;
+ }
+ break;
}
}
- // parse separator (:)
- get_token();
- if (not expect(token_type::name_separator))
+ case token_type::literal_false:
{
- return;
+ if (JSON_UNLIKELY(not sax->boolean(false)))
+ {
+ return false;
+ }
+ break;
}
- // parse and add value
- get_token();
- value.m_value.destroy(value.m_type);
- value.m_type = value_t::discarded;
- parse_internal(keep, value);
-
- if (JSON_UNLIKELY(errored))
+ case token_type::literal_null:
{
- return;
+ if (JSON_UNLIKELY(not sax->null()))
+ {
+ return false;
+ }
+ break;
}
- if (keep and keep_tag and not value.is_discarded())
+ case token_type::literal_true:
{
- result.m_value.object->emplace(std::move(key), std::move(value));
+ if (JSON_UNLIKELY(not sax->boolean(true)))
+ {
+ return false;
+ }
+ break;
}
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
+ case token_type::value_integer:
{
- get_token();
- continue;
+ if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
+ {
+ return false;
+ }
+ break;
}
- // closing }
- if (not expect(token_type::end_object))
+ case token_type::value_string:
{
- return;
- }
- break;
- }
-
- if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- case token_type::begin_array:
- {
- if (keep)
- {
- if (callback)
- {
- keep = callback(depth++, parse_event_t::array_start, result);
+ if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
+ {
+ return false;
+ }
+ break;
}
- if (not callback or keep)
+ case token_type::value_unsigned:
{
- // explicitly set result to array to cope with []
- result.m_type = value_t::array;
- result.m_value = value_t::array;
+ if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::parse_error:
+ {
+ // using "uninitialized" to avoid "expected" message
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized)));
+ }
+
+ default: // the last token was unexpected
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value)));
}
}
-
- // read next token
- get_token();
-
- // closing ] -> we are done
- if (last_token == token_type::end_array)
- {
- if (callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
- }
-
- // parse values
- BasicJsonType value;
- while (true)
- {
- // parse value
- value.m_value.destroy(value.m_type);
- value.m_type = value_t::discarded;
- parse_internal(keep, value);
-
- if (JSON_UNLIKELY(errored))
- {
- return;
- }
-
- if (keep and not value.is_discarded())
- {
- result.m_value.array->push_back(std::move(value));
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing ]
- if (not expect(token_type::end_array))
- {
- return;
- }
- break;
- }
-
- if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- break;
}
-
- case token_type::literal_null:
+ else
{
- result.m_type = value_t::null;
- break;
+ skip_to_state_evaluation = false;
}
- case token_type::value_string:
+ // we reached this line after we successfully parsed a value
+ if (states.empty())
{
- result.m_type = value_t::string;
- result.m_value = m_lexer.move_string();
- break;
- }
-
- case token_type::literal_true:
- {
- result.m_type = value_t::boolean;
- result.m_value = true;
- break;
- }
-
- case token_type::literal_false:
- {
- result.m_type = value_t::boolean;
- result.m_value = false;
- break;
- }
-
- case token_type::value_unsigned:
- {
- result.m_type = value_t::number_unsigned;
- result.m_value = m_lexer.get_number_unsigned();
- break;
- }
-
- case token_type::value_integer:
- {
- result.m_type = value_t::number_integer;
- result.m_value = m_lexer.get_number_integer();
- break;
- }
-
- case token_type::value_float:
- {
- result.m_type = value_t::number_float;
- result.m_value = m_lexer.get_number_float();
-
- // throw in case of infinity or NAN
- if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float)))
- {
- if (allow_exceptions)
- {
- JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
- m_lexer.get_token_string() + "'"));
- }
- expect(token_type::uninitialized);
- }
- break;
- }
-
- case token_type::parse_error:
- {
- // using "uninitialized" to avoid "expected" message
- if (not expect(token_type::uninitialized))
- {
- return;
- }
- break; // LCOV_EXCL_LINE
- }
-
- default:
- {
- // the last token was unexpected; we expected a value
- if (not expect(token_type::literal_or_value))
- {
- return;
- }
- break; // LCOV_EXCL_LINE
- }
- }
-
- if (keep and callback and not callback(depth, parse_event_t::value, result))
- {
- result.m_value.destroy(result.m_type);
- result.m_type = value_t::discarded;
- }
- }
-
- /*!
- @brief the actual acceptor
-
- @invariant 1. The last token is not yet processed. Therefore, the caller
- of this function must make sure a token has been read.
- 2. When this function returns, the last token is processed.
- That is, the last read character was already considered.
-
- This invariant makes sure that no token needs to be "unput".
- */
- bool accept_internal()
- {
- switch (last_token)
- {
- case token_type::begin_object:
- {
- // read next token
- get_token();
-
- // closing } -> we are done
- if (last_token == token_type::end_object)
- {
- return true;
- }
-
- // parse values
- while (true)
- {
- // parse key
- if (last_token != token_type::value_string)
- {
- return false;
- }
-
- // parse separator (:)
- get_token();
- if (last_token != token_type::name_separator)
- {
- return false;
- }
-
- // parse value
- get_token();
- if (not accept_internal())
- {
- return false;
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing }
- return (last_token == token_type::end_object);
- }
- }
-
- case token_type::begin_array:
- {
- // read next token
- get_token();
-
- // closing ] -> we are done
- if (last_token == token_type::end_array)
- {
- return true;
- }
-
- // parse values
- while (true)
- {
- // parse value
- if (not accept_internal())
- {
- return false;
- }
-
- // comma -> next value
- get_token();
- if (last_token == token_type::value_separator)
- {
- get_token();
- continue;
- }
-
- // closing ]
- return (last_token == token_type::end_array);
- }
- }
-
- case token_type::value_float:
- {
- // reject infinity or NAN
- return std::isfinite(m_lexer.get_number_float());
- }
-
- case token_type::literal_false:
- case token_type::literal_null:
- case token_type::literal_true:
- case token_type::value_integer:
- case token_type::value_string:
- case token_type::value_unsigned:
+ // empty stack: we reached the end of the hieararchy: done
return true;
+ }
+ else
+ {
+ if (states.back()) // array
+ {
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse a new value
+ get_token();
+ continue;
+ }
- default: // the last token was unexpected
- return false;
+ // closing ]
+ if (JSON_LIKELY(last_token == token_type::end_array))
+ {
+ if (JSON_UNLIKELY(not sax->end_array()))
+ {
+ return false;
+ }
+
+ // We are done with this array. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ assert(not states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+ else
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array)));
+ }
+ }
+ else // object
+ {
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse key
+ if (JSON_UNLIKELY(get_token() != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string)));
+ }
+ else
+ {
+ if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+ }
+
+ // parse separator (:)
+ if (JSON_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
+ }
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ // closing }
+ if (JSON_LIKELY(last_token == token_type::end_object))
+ {
+ if (JSON_UNLIKELY(not sax->end_object()))
+ {
+ return false;
+ }
+
+ // We are done with this object. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ assert(not states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+ else
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object)));
+ }
+ }
+ }
}
}
@@ -3652,29 +4924,7 @@
return (last_token = m_lexer.scan());
}
- /*!
- @throw parse_error.101 if expected token did not occur
- */
- bool expect(token_type t)
- {
- if (JSON_UNLIKELY(t != last_token))
- {
- errored = true;
- expected = t;
- if (allow_exceptions)
- {
- throw_exception();
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- [[noreturn]] void throw_exception() const
+ std::string exception_message(const token_type expected)
{
std::string error_msg = "syntax error - ";
if (last_token == token_type::parse_error)
@@ -3692,22 +4942,16 @@
error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
}
- JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg));
+ return error_msg;
}
private:
- /// current level of recursion
- int depth = 0;
/// callback function
const parser_callback_t callback = nullptr;
/// the type of the last read token
token_type last_token = token_type::uninitialized;
/// the lexer
lexer_t m_lexer;
- /// whether a syntax error occurred
- bool errored = false;
- /// possible reason for the syntax error
- token_type expected = token_type::uninitialized;
/// whether to throw exceptions in case of errors
const bool allow_exceptions = true;
};
@@ -3804,7 +5048,7 @@
primitive_iterator_t const operator++(int) noexcept
{
auto result = *this;
- m_it++;
+ ++m_it;
return result;
}
@@ -3817,7 +5061,7 @@
primitive_iterator_t const operator--(int) noexcept
{
auto result = *this;
- m_it--;
+ --m_it;
return result;
}
@@ -3879,7 +5123,7 @@
// #include <nlohmann/detail/macro_scope.hpp>
-// #include <nlohmann/detail/meta.hpp>
+// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/value_t.hpp>
@@ -3904,7 +5148,7 @@
@requirement The class satisfies the following concept requirements:
-
-[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
@@ -4456,7 +5700,7 @@
@brief return the key of an object iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
*/
- typename object_t::key_type key() const
+ const typename object_t::key_type& key() const
{
assert(m_object != nullptr);
@@ -4488,105 +5732,6 @@
// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
-
-#include <cstddef> // size_t
-#include <string> // string, to_string
-
-// #include <nlohmann/detail/value_t.hpp>
-
-
-namespace nlohmann
-{
-namespace detail
-{
-/// proxy class for the items() function
-template<typename IteratorType> class iteration_proxy
-{
- private:
- /// helper class for iteration
- class iteration_proxy_internal
- {
- private:
- /// the iterator
- IteratorType anchor;
- /// an index for arrays (used to create key names)
- std::size_t array_index = 0;
-
- public:
- explicit iteration_proxy_internal(IteratorType it) noexcept : anchor(it) {}
-
- /// dereference operator (needed for range-based for)
- iteration_proxy_internal& operator*()
- {
- return *this;
- }
-
- /// increment operator (needed for range-based for)
- iteration_proxy_internal& operator++()
- {
- ++anchor;
- ++array_index;
-
- return *this;
- }
-
- /// inequality operator (needed for range-based for)
- bool operator!=(const iteration_proxy_internal& o) const noexcept
- {
- return anchor != o.anchor;
- }
-
- /// return key of the iterator
- std::string key() const
- {
- assert(anchor.m_object != nullptr);
-
- switch (anchor.m_object->type())
- {
- // use integer array index as key
- case value_t::array:
- return std::to_string(array_index);
-
- // use key from the object
- case value_t::object:
- return anchor.key();
-
- // use an empty key for all primitive types
- default:
- return "";
- }
- }
-
- /// return value of the iterator
- typename IteratorType::reference value() const
- {
- return anchor.value();
- }
- };
-
- /// the container to iterate
- typename IteratorType::reference container;
-
- public:
- /// construct iteration proxy from a container
- explicit iteration_proxy(typename IteratorType::reference cont) noexcept
- : container(cont) {}
-
- /// return iterator begin (needed for range-based for)
- iteration_proxy_internal begin() noexcept
- {
- return iteration_proxy_internal(container.begin());
- }
-
- /// return iterator end (needed for range-based for)
- iteration_proxy_internal end() noexcept
- {
- return iteration_proxy_internal(container.end());
- }
-};
-}
-}
-
// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
@@ -4611,10 +5756,10 @@
@requirement The class satisfies the following concept requirements:
-
-[BidirectionalIterator](http://en.cppreference.com/w/cpp/concept/BidirectionalIterator):
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
The iterator that can be moved can be moved in both directions (i.e.
incremented and decremented).
-- [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator):
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
It is possible to write to the pointed-to element (only if @a Base is
@ref iterator).
@@ -4631,11 +5776,11 @@
using reference = typename Base::reference;
/// create reverse iterator from iterator
- json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+ explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
: base_iterator(it) {}
/// create reverse iterator from base class
- json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+ explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
/// post-increment (it++)
json_reverse_iterator const operator++(int)
@@ -4832,21 +5977,23 @@
#include <cmath> // ldexp
#include <cstddef> // size_t
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
#include <cstring> // memcpy
-#include <iomanip> // setw, setfill
-#include <ios> // hex
#include <iterator> // back_inserter
#include <limits> // numeric_limits
-#include <sstream> // stringstream
#include <string> // char_traits, string
#include <utility> // make_pair, move
// #include <nlohmann/detail/input/input_adapters.hpp>
+// #include <nlohmann/detail/input/json_sax.hpp>
+
// #include <nlohmann/detail/exceptions.hpp>
// #include <nlohmann/detail/macro_scope.hpp>
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
// #include <nlohmann/detail/value_t.hpp>
@@ -4859,14 +6006,16 @@
///////////////////
/*!
-@brief deserialization of CBOR and MessagePack values
+@brief deserialization of CBOR, MessagePack, and UBJSON values
*/
-template<typename BasicJsonType>
+template<typename BasicJsonType, typename SAX = json_sax_dom_parser<BasicJsonType>>
class binary_reader
{
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
+ using json_sax_t = SAX;
public:
/*!
@@ -4876,70 +6025,63 @@
*/
explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter))
{
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
assert(ia);
}
/*!
- @brief create a JSON value from CBOR input
-
+ @param[in] format the binary format to parse
+ @param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from CBOR input
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
+ @return
*/
- BasicJsonType parse_cbor(const bool strict)
+ bool sax_parse(const input_format_t format,
+ json_sax_t* sax_,
+ const bool strict = true)
{
- const auto res = parse_cbor_internal();
- if (strict)
+ sax = sax_;
+ bool result = false;
+
+ switch (format)
{
- get();
- expect_eof();
+ case input_format_t::cbor:
+ result = parse_cbor_internal();
+ break;
+
+ case input_format_t::msgpack:
+ result = parse_msgpack_internal();
+ break;
+
+ case input_format_t::ubjson:
+ result = parse_ubjson_internal();
+ break;
+
+ // LCOV_EXCL_START
+ default:
+ assert(false);
+ // LCOV_EXCL_STOP
}
- return res;
- }
- /*!
- @brief create a JSON value from MessagePack input
-
- @param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from MessagePack input
-
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
- */
- BasicJsonType parse_msgpack(const bool strict)
- {
- const auto res = parse_msgpack_internal();
- if (strict)
+ // strict mode: next byte must be EOF
+ if (result and strict)
{
- get();
- expect_eof();
+ if (format == input_format_t::ubjson)
+ {
+ get_ignore_noop();
+ }
+ else
+ {
+ get();
+ }
+
+ if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
+ {
+ return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
+ }
}
- return res;
- }
- /*!
- @brief create a JSON value from UBJSON input
-
- @param[in] strict whether to expect the input to be consumed completed
- @return JSON value created from UBJSON input
-
- @throw parse_error.110 if input ended unexpectedly or the end of file was
- not reached when @a strict was set to true
- @throw parse_error.112 if unsupported byte was read
- */
- BasicJsonType parse_ubjson(const bool strict)
- {
- const auto res = parse_ubjson_internal();
- if (strict)
- {
- get_ignore_noop();
- expect_eof();
- }
- return res;
+ return result;
}
/*!
@@ -4959,14 +6101,16 @@
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
+
+ @return whether a valid CBOR value was passed to the SAX parser
*/
- BasicJsonType parse_cbor_internal(const bool get_char = true)
+ bool parse_cbor_internal(const bool get_char = true)
{
switch (get_char ? get() : current)
{
// EOF
case std::char_traits<char>::eof():
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
// Integer 0x00..0x17 (0..23)
case 0x00:
@@ -4993,19 +6137,31 @@
case 0x15:
case 0x16:
case 0x17:
- return static_cast<number_unsigned_t>(current);
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
case 0x18: // Unsigned integer (one-byte uint8_t follows)
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x19: // Unsigned integer (two-byte uint16_t follows)
- return get_number<uint16_t>();
+ {
+ uint16_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
- return get_number<uint32_t>();
+ {
+ uint32_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
- return get_number<uint64_t>();
+ {
+ uint64_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
// Negative integer -1-0x00..-1-0x17 (-1..-24)
case 0x20:
@@ -5032,27 +6188,31 @@
case 0x35:
case 0x36:
case 0x37:
- return static_cast<int8_t>(0x20 - 1 - current);
+ return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
case 0x38: // Negative integer (one-byte uint8_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint8_t>();
+ uint8_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint16_t>();
+ uint16_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
{
- return static_cast<number_integer_t>(-1) - get_number<uint32_t>();
+ uint32_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
{
- return static_cast<number_integer_t>(-1) -
- static_cast<number_integer_t>(get_number<uint64_t>());
+ uint64_t number;
+ return get_number(number) and sax->number_integer(static_cast<number_integer_t>(-1)
+ - static_cast<number_integer_t>(number));
}
// UTF-8 string (0x00..0x17 bytes follow)
@@ -5086,7 +6246,8 @@
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
case 0x7F: // UTF-8 string (indefinite length)
{
- return get_cbor_string();
+ string_t s;
+ return get_cbor_string(s) and sax->string(s);
}
// array (0x00..0x17 data items follow)
@@ -5114,39 +6275,34 @@
case 0x95:
case 0x96:
case 0x97:
- {
- return get_cbor_array(current & 0x1F);
- }
+ return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
case 0x98: // array (one-byte uint8_t for n follows)
{
- return get_cbor_array(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x99: // array (two-byte uint16_t for n follow)
{
- return get_cbor_array(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9A: // array (four-byte uint32_t for n follow)
{
- return get_cbor_array(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
- return get_cbor_array(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9F: // array (indefinite length)
- {
- BasicJsonType result = value_t::array;
- while (get() != 0xFF)
- {
- result.push_back(parse_cbor_internal(false));
- }
- return result;
- }
+ return get_cbor_array(std::size_t(-1));
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
@@ -5173,62 +6329,56 @@
case 0xB5:
case 0xB6:
case 0xB7:
- {
- return get_cbor_object(current & 0x1F);
- }
+ return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
case 0xB8: // map (one-byte uint8_t for n follows)
{
- return get_cbor_object(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xB9: // map (two-byte uint16_t for n follow)
{
- return get_cbor_object(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBA: // map (four-byte uint32_t for n follow)
{
- return get_cbor_object(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
- return get_cbor_object(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBF: // map (indefinite length)
- {
- BasicJsonType result = value_t::object;
- while (get() != 0xFF)
- {
- auto key = get_cbor_string();
- result[key] = parse_cbor_internal();
- }
- return result;
- }
+ return get_cbor_object(std::size_t(-1));
case 0xF4: // false
- {
- return false;
- }
+ return sax->boolean(false);
case 0xF5: // true
- {
- return true;
- }
+ return sax->boolean(true);
case 0xF6: // null
- {
- return value_t::null;
- }
+ return sax->null();
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
{
const int byte1 = get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
const int byte2 = get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
// code from RFC 7049, Appendix D, Figure 3:
// As half-precision floating-point numbers were only added
@@ -5239,51 +6389,59 @@
// half-precision floating-point numbers in the C language
// is shown in Fig. 3.
const int half = (byte1 << 8) + byte2;
- const int exp = (half >> 10) & 0x1F;
- const int mant = half & 0x3FF;
- double val;
- if (exp == 0)
+ const double val = [&half]
{
- val = std::ldexp(mant, -24);
- }
- else if (exp != 31)
- {
- val = std::ldexp(mant + 1024, exp - 25);
- }
- else
- {
- val = (mant == 0) ? std::numeric_limits<double>::infinity()
- : std::numeric_limits<double>::quiet_NaN();
- }
- return (half & 0x8000) != 0 ? -val : val;
+ const int exp = (half >> 10) & 0x1F;
+ const int mant = half & 0x3FF;
+ assert(0 <= exp and exp <= 32);
+ assert(0 <= mant and mant <= 1024);
+ switch (exp)
+ {
+ case 0:
+ return std::ldexp(mant, -24);
+ case 31:
+ return (mant == 0)
+ ? std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::quiet_NaN();
+ default:
+ return std::ldexp(mant + 1024, exp - 25);
+ }
+ }();
+ return sax->number_float((half & 0x8000) != 0
+ ? static_cast<number_float_t>(-val)
+ : static_cast<number_float_t>(val), "");
}
case 0xFA: // Single-Precision Float (four-byte IEEE 754)
{
- return get_number<float>();
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
}
case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
{
- return get_number<double>();
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
}
default: // anything else (0xFF is handled inside the other types)
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + last_token));
}
}
}
- BasicJsonType parse_msgpack_internal()
+ /*!
+ @return whether a valid MessagePack value was passed to the SAX parser
+ */
+ bool parse_msgpack_internal()
{
switch (get())
{
// EOF
case std::char_traits<char>::eof():
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
// positive fixint
case 0x00:
@@ -5414,7 +6572,7 @@
case 0x7D:
case 0x7E:
case 0x7F:
- return static_cast<number_unsigned_t>(current);
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
// fixmap
case 0x80:
@@ -5433,9 +6591,7 @@
case 0x8D:
case 0x8E:
case 0x8F:
- {
- return get_msgpack_object(current & 0x0F);
- }
+ return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
// fixarray
case 0x90:
@@ -5454,9 +6610,7 @@
case 0x9D:
case 0x9E:
case 0x9F:
- {
- return get_msgpack_array(current & 0x0F);
- }
+ return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
// fixstr
case 0xA0:
@@ -5491,73 +6645,113 @@
case 0xBD:
case 0xBE:
case 0xBF:
- return get_msgpack_string();
+ {
+ string_t s;
+ return get_msgpack_string(s) and sax->string(s);
+ }
case 0xC0: // nil
- return value_t::null;
+ return sax->null();
case 0xC2: // false
- return false;
+ return sax->boolean(false);
case 0xC3: // true
- return true;
+ return sax->boolean(true);
case 0xCA: // float 32
- return get_number<float>();
+ {
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 0xCB: // float 64
- return get_number<double>();
+ {
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 0xCC: // uint 8
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCD: // uint 16
- return get_number<uint16_t>();
+ {
+ uint16_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCE: // uint 32
- return get_number<uint32_t>();
+ {
+ uint32_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xCF: // uint 64
- return get_number<uint64_t>();
+ {
+ uint64_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
case 0xD0: // int 8
- return get_number<int8_t>();
+ {
+ int8_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD1: // int 16
- return get_number<int16_t>();
+ {
+ int16_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD2: // int 32
- return get_number<int32_t>();
+ {
+ int32_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD3: // int 64
- return get_number<int64_t>();
+ {
+ int64_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
case 0xD9: // str 8
case 0xDA: // str 16
case 0xDB: // str 32
- return get_msgpack_string();
+ {
+ string_t s;
+ return get_msgpack_string(s) and sax->string(s);
+ }
case 0xDC: // array 16
{
- return get_msgpack_array(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDD: // array 32
{
- return get_msgpack_array(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDE: // map 16
{
- return get_msgpack_object(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
}
case 0xDF: // map 32
{
- return get_msgpack_object(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_msgpack_object(static_cast<std::size_t>(len));
}
- // positive fixint
+ // negative fixint
case 0xE0:
case 0xE1:
case 0xE2:
@@ -5590,14 +6784,12 @@
case 0xFD:
case 0xFE:
case 0xFF:
- return static_cast<int8_t>(current);
+ return sax->number_integer(static_cast<int8_t>(current));
default: // anything else
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "error reading MessagePack; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading MessagePack; last byte: 0x" + last_token));
}
}
}
@@ -5606,8 +6798,10 @@
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
+
+ @return whether a valid UBJSON value was passed to the SAX parser
*/
- BasicJsonType parse_ubjson_internal(const bool get_char = true)
+ bool parse_ubjson_internal(const bool get_char = true)
{
return get_ubjson_value(get_char ? get_ignore_noop() : current);
}
@@ -5645,23 +6839,26 @@
@brief read a number from the input
@tparam NumberType the type of the number
+ @param[out] result number of type @a NumberType
- @return number of type @a NumberType
+ @return whether conversion completed
@note This function needs to respect the system's endianess, because
- bytes in CBOR and MessagePack are stored in network order (big
- endian) and therefore need reordering on little endian systems.
-
- @throw parse_error.110 if input has less than `sizeof(NumberType)` bytes
+ bytes in CBOR, MessagePack, and UBJSON are stored in network order
+ (big endian) and therefore need reordering on little endian systems.
*/
- template<typename NumberType> NumberType get_number()
+ template<typename NumberType>
+ bool get_number(NumberType& result)
{
// step 1: read input into array with system's byte order
std::array<uint8_t, sizeof(NumberType)> vec;
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
// reverse byte order prior to conversion if necessary
if (is_little_endian)
@@ -5675,35 +6872,37 @@
}
// step 2: convert array into number of type T and return
- NumberType result;
std::memcpy(&result, vec.data(), sizeof(NumberType));
- return result;
+ return true;
}
/*!
@brief create a string by reading characters from the input
- @param[in] len number of bytes to read
+ @tparam NumberType the type of the number
+ @param[in] len number of characters to read
+ @param[out] string created by reading @a len bytes
+
+ @return whether string creation completed
@note We can not reserve @a len bytes for the result, because @a len
may be too large. Usually, @ref unexpect_eof() detects the end of
the input before we run out of string memory.
-
- @return string created by reading @a len bytes
-
- @throw parse_error.110 if input has less than @a len bytes
*/
template<typename NumberType>
- string_t get_string(const NumberType len)
+ bool get_string(const NumberType len, string_t& result)
{
- string_t result;
- std::generate_n(std::back_inserter(result), len, [this]()
+ bool success = true;
+ std::generate_n(std::back_inserter(result), len, [this, &success]()
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ success = false;
+ }
return static_cast<char>(current);
});
- return result;
+ return success;
}
/*!
@@ -5713,14 +6912,16 @@
string length and then copies this number of bytes into a string.
Additionally, CBOR's strings with indefinite lengths are supported.
- @return string
+ @param[out] result created string
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_cbor_string()
+ bool get_cbor_string(string_t& result)
{
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
@@ -5750,73 +6951,137 @@
case 0x76:
case 0x77:
{
- return get_string(current & 0x1F);
+ return get_string(current & 0x1F, result);
}
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{
- return get_string(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{
- return get_string(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
{
- return get_string(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
{
- return get_string(get_number<uint64_t>());
+ uint64_t len;
+ return get_number(len) and get_string(len, result);
}
case 0x7F: // UTF-8 string (indefinite length)
{
- string_t result;
while (get() != 0xFF)
{
- result.append(get_cbor_string());
+ string_t chunk;
+ if (not get_cbor_string(chunk))
+ {
+ return false;
+ }
+ result.append(chunk);
}
- return result;
+ return true;
}
default:
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + last_token));
}
}
}
- template<typename NumberType>
- BasicJsonType get_cbor_array(const NumberType len)
+ /*!
+ @param[in] len the length of the array or std::size_t(-1) for an
+ array of indefinite size
+ @return whether array creation completed
+ */
+ bool get_cbor_array(const std::size_t len)
{
- BasicJsonType result = value_t::array;
- std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ if (JSON_UNLIKELY(not sax->start_array(len)))
{
- return parse_cbor_internal();
- });
- return result;
+ return false;
+ }
+
+ if (len != std::size_t(-1))
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_UNLIKELY(not parse_cbor_internal(false)))
+ {
+ return false;
+ }
+ }
+ }
+
+ return sax->end_array();
}
- template<typename NumberType>
- BasicJsonType get_cbor_object(const NumberType len)
+ /*!
+ @param[in] len the length of the object or std::size_t(-1) for an
+ object of indefinite size
+ @return whether object creation completed
+ */
+ bool get_cbor_object(const std::size_t len)
{
- BasicJsonType result = value_t::object;
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- len, [this]()
+ if (not JSON_UNLIKELY(sax->start_object(len)))
{
- get();
- auto key = get_cbor_string();
- auto val = parse_cbor_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
- return result;
+ return false;
+ }
+
+ string_t key;
+ if (len != std::size_t(-1))
+ {
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ get();
+ if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_cbor_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+
+ return sax->end_object();
}
/*!
@@ -5825,14 +7090,16 @@
This function first reads starting bytes to determine the expected
string length and then copies this number of bytes into a string.
- @return string
+ @param[out] result created string
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_msgpack_string()
+ bool get_msgpack_string(string_t& result)
{
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
@@ -5870,59 +7137,85 @@
case 0xBE:
case 0xBF:
{
- return get_string(current & 0x1F);
+ return get_string(current & 0x1F, result);
}
case 0xD9: // str 8
{
- return get_string(get_number<uint8_t>());
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
}
case 0xDA: // str 16
{
- return get_string(get_number<uint16_t>());
+ uint16_t len;
+ return get_number(len) and get_string(len, result);
}
case 0xDB: // str 32
{
- return get_string(get_number<uint32_t>());
+ uint32_t len;
+ return get_number(len) and get_string(len, result);
}
default:
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "expected a MessagePack string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a MessagePack string; last byte: 0x" + last_token));
}
}
}
- template<typename NumberType>
- BasicJsonType get_msgpack_array(const NumberType len)
+ /*!
+ @param[in] len the length of the array
+ @return whether array creation completed
+ */
+ bool get_msgpack_array(const std::size_t len)
{
- BasicJsonType result = value_t::array;
- std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
+ if (JSON_UNLIKELY(not sax->start_array(len)))
{
- return parse_msgpack_internal();
- });
- return result;
+ return false;
+ }
+
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_UNLIKELY(not parse_msgpack_internal()))
+ {
+ return false;
+ }
+ }
+
+ return sax->end_array();
}
- template<typename NumberType>
- BasicJsonType get_msgpack_object(const NumberType len)
+ /*!
+ @param[in] len the length of the object
+ @return whether object creation completed
+ */
+ bool get_msgpack_object(const std::size_t len)
{
- BasicJsonType result = value_t::object;
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- len, [this]()
+ if (JSON_UNLIKELY(not sax->start_object(len)))
+ {
+ return false;
+ }
+
+ string_t key;
+ for (std::size_t i = 0; i < len; ++i)
{
get();
- auto key = get_msgpack_string();
- auto val = parse_msgpack_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
- return result;
+ if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_UNLIKELY(not parse_msgpack_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+
+ return sax->end_object();
}
/*!
@@ -5932,41 +7225,131 @@
indicating a string, or in case of an object key where the 'S' byte can be
left out.
+ @param[out] result created string
@param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read
character should be considered instead
- @return string
-
- @throw parse_error.110 if input ended
- @throw parse_error.113 if an unexpected byte is read
+ @return whether string creation completed
*/
- string_t get_ubjson_string(const bool get_char = true)
+ bool get_ubjson_string(string_t& result, const bool get_char = true)
{
if (get_char)
{
get(); // TODO: may we ignore N here?
}
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
switch (current)
{
case 'U':
- return get_string(get_number<uint8_t>());
+ {
+ uint8_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'i':
- return get_string(get_number<int8_t>());
+ {
+ int8_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'I':
- return get_string(get_number<int16_t>());
+ {
+ int16_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'l':
- return get_string(get_number<int32_t>());
+ {
+ int32_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
case 'L':
- return get_string(get_number<int64_t>());
+ {
+ int64_t len;
+ return get_number(len) and get_string(len, result);
+ }
+
default:
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "expected a UBJSON string; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "expected a UBJSON string; last byte: 0x" + last_token));
+ }
+ }
+
+ /*!
+ @param[out] result determined size
+ @return whether size determination completed
+ */
+ bool get_ubjson_size_value(std::size_t& result)
+ {
+ switch (get_ignore_noop())
+ {
+ case 'U':
+ {
+ uint8_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'i':
+ {
+ int8_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'I':
+ {
+ int16_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'l':
+ {
+ int32_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'L':
+ {
+ int64_t number;
+ if (JSON_UNLIKELY(not get_number(number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after '#' must denote a number type; last byte: 0x" + last_token));
+ }
}
}
@@ -5976,84 +7359,127 @@
In the optimized UBJSON format, a type and a size can be provided to allow
for a more compact representation.
- @return pair of the size and the type
+ @param[out] result pair of the size and the type
+
+ @return whether pair creation completed
*/
- std::pair<std::size_t, int> get_ubjson_size_type()
+ bool get_ubjson_size_type(std::pair<std::size_t, int>& result)
{
- std::size_t sz = string_t::npos;
- int tc = 0;
+ result.first = string_t::npos; // size
+ result.second = 0; // type
get_ignore_noop();
if (current == '$')
{
- tc = get(); // must not ignore 'N', because 'N' maybe the type
- unexpect_eof();
+ result.second = get(); // must not ignore 'N', because 'N' maybe the type
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
get_ignore_noop();
- if (current != '#')
+ if (JSON_UNLIKELY(current != '#'))
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "expected '#' after UBJSON type information; last byte: 0x" + ss.str()));
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "expected '#' after UBJSON type information; last byte: 0x" + last_token));
}
- sz = parse_ubjson_internal();
+
+ return get_ubjson_size_value(result.first);
}
else if (current == '#')
{
- sz = parse_ubjson_internal();
+ return get_ubjson_size_value(result.first);
}
-
- return std::make_pair(sz, tc);
+ return true;
}
- BasicJsonType get_ubjson_value(const int prefix)
+ /*!
+ @param prefix the previously read or set type prefix
+ @return whether value creation completed
+ */
+ bool get_ubjson_value(const int prefix)
{
switch (prefix)
{
case std::char_traits<char>::eof(): // EOF
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return unexpect_eof();
case 'T': // true
- return true;
+ return sax->boolean(true);
case 'F': // false
- return false;
+ return sax->boolean(false);
case 'Z': // null
- return nullptr;
+ return sax->null();
case 'U':
- return get_number<uint8_t>();
+ {
+ uint8_t number;
+ return get_number(number) and sax->number_unsigned(number);
+ }
+
case 'i':
- return get_number<int8_t>();
+ {
+ int8_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'I':
- return get_number<int16_t>();
+ {
+ int16_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'l':
- return get_number<int32_t>();
+ {
+ int32_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'L':
- return get_number<int64_t>();
+ {
+ int64_t number;
+ return get_number(number) and sax->number_integer(number);
+ }
+
case 'd':
- return get_number<float>();
+ {
+ float number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
case 'D':
- return get_number<double>();
+ {
+ double number;
+ return get_number(number) and sax->number_float(static_cast<number_float_t>(number), "");
+ }
case 'C': // char
{
get();
- unexpect_eof();
+ if (JSON_UNLIKELY(not unexpect_eof()))
+ {
+ return false;
+ }
if (JSON_UNLIKELY(current > 127))
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(113, chars_read,
- "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + ss.str()));
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token));
}
- return string_t(1, static_cast<char>(current));
+ string_t s(1, static_cast<char>(current));
+ return sax->string(s);
}
case 'S': // string
- return get_ubjson_string();
+ {
+ string_t s;
+ return get_ubjson_string(s) and sax->string(s);
+ }
case '[': // array
return get_ubjson_array();
@@ -6062,129 +7488,170 @@
return get_ubjson_object();
default: // anything else
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current;
- JSON_THROW(parse_error::create(112, chars_read,
- "error reading UBJSON; last byte: 0x" + ss.str()));
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, "error reading UBJSON; last byte: 0x" + last_token));
+ }
}
}
- BasicJsonType get_ubjson_array()
+ /*!
+ @return whether array creation completed
+ */
+ bool get_ubjson_array()
{
- BasicJsonType result = value_t::array;
- const auto size_and_type = get_ubjson_size_type();
+ std::pair<std::size_t, int> size_and_type;
+ if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
if (size_and_type.first != string_t::npos)
{
- if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
+ if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
{
- JSON_THROW(out_of_range::create(408,
- "excessive array size: " + std::to_string(size_and_type.first)));
+ return false;
}
if (size_and_type.second != 0)
{
if (size_and_type.second != 'N')
{
- std::generate_n(std::back_inserter(*result.m_value.array),
- size_and_type.first, [this, size_and_type]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- return get_ubjson_value(size_and_type.second);
- });
+ if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ }
}
}
else
{
- std::generate_n(std::back_inserter(*result.m_value.array),
- size_and_type.first, [this]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- return parse_ubjson_internal();
- });
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
+ }
}
}
else
{
+ if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
while (current != ']')
{
- result.push_back(parse_ubjson_internal(false));
+ if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
+ {
+ return false;
+ }
get_ignore_noop();
}
}
- return result;
+ return sax->end_array();
}
- BasicJsonType get_ubjson_object()
+ /*!
+ @return whether object creation completed
+ */
+ bool get_ubjson_object()
{
- BasicJsonType result = value_t::object;
- const auto size_and_type = get_ubjson_size_type();
+ std::pair<std::size_t, int> size_and_type;
+ if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
+ string_t key;
if (size_and_type.first != string_t::npos)
{
- if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
+ if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
{
- JSON_THROW(out_of_range::create(408,
- "excessive object size: " + std::to_string(size_and_type.first)));
+ return false;
}
if (size_and_type.second != 0)
{
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- size_and_type.first, [this, size_and_type]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- auto key = get_ubjson_string();
- auto val = get_ubjson_value(size_and_type.second);
- return std::make_pair(std::move(key), std::move(val));
- });
+ if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ key.clear();
+ }
}
else
{
- std::generate_n(std::inserter(*result.m_value.object,
- result.m_value.object->end()),
- size_and_type.first, [this]()
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
{
- auto key = get_ubjson_string();
- auto val = parse_ubjson_internal();
- return std::make_pair(std::move(key), std::move(val));
- });
+ if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
}
}
else
{
+ if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
+ {
+ return false;
+ }
+
while (current != '}')
{
- auto key = get_ubjson_string(false);
- result[std::move(key)] = parse_ubjson_internal();
+ if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_UNLIKELY(not parse_ubjson_internal()))
+ {
+ return false;
+ }
get_ignore_noop();
+ key.clear();
}
}
- return result;
+ return sax->end_object();
}
/*!
- @brief throw if end of input is not reached
- @throw parse_error.110 if input not ended
+ @return whether the last read character is not EOF
*/
- void expect_eof() const
- {
- if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
- {
- JSON_THROW(parse_error::create(110, chars_read, "expected end of input"));
- }
- }
-
- /*!
- @briefthrow if end of input is reached
- @throw parse_error.110 if input ended
- */
- void unexpect_eof() const
+ bool unexpect_eof() const
{
if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
{
- JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
+ return sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, "unexpected end of input"));
}
+ return true;
+ }
+
+ /*!
+ @return a string representation of the last read byte
+ */
+ std::string get_token_string() const
+ {
+ char cr[3];
+ snprintf(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
+ return std::string{cr};
}
private:
@@ -6199,6 +7666,9 @@
/// whether we can assume little endianess
const bool is_little_endian = little_endianess();
+
+ /// the SAX parser
+ json_sax_t* sax = nullptr;
};
}
}
@@ -6357,9 +7827,9 @@
break;
}
- case value_t::number_float: // Double-Precision Float
+ case value_t::number_float:
{
- oa->write_character(static_cast<CharType>(0xFB));
+ oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -6617,9 +8087,9 @@
break;
}
- case value_t::number_float: // float 64
+ case value_t::number_float:
{
- oa->write_character(static_cast<CharType>(0xCB));
+ oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
write_number(j.m_value.number_float);
break;
}
@@ -6796,7 +8266,7 @@
if (use_type and not j.m_value.array->empty())
{
assert(use_count);
- const char first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -6807,7 +8277,7 @@
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
- oa->write_character(static_cast<CharType>(first_prefix));
+ oa->write_character(first_prefix);
}
}
@@ -6841,7 +8311,7 @@
if (use_type and not j.m_value.object->empty())
{
assert(use_count);
- const char first_prefix = ubjson_prefix(j.front());
+ const CharType first_prefix = ubjson_prefix(j.front());
const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix](const BasicJsonType & v)
{
@@ -6852,7 +8322,7 @@
{
prefix_required = false;
oa->write_character(static_cast<CharType>('$'));
- oa->write_character(static_cast<CharType>(first_prefix));
+ oa->write_character(first_prefix);
}
}
@@ -6920,7 +8390,7 @@
{
if (add_prefix)
{
- oa->write_character(static_cast<CharType>('D')); // float64
+ oa->write_character(get_ubjson_float_prefix(n));
}
write_number(n);
}
@@ -7041,7 +8511,7 @@
write_number_with_ubjson_prefix. Therefore, we return 'L' for any
value that does not fit the previous limits.
*/
- char ubjson_prefix(const BasicJsonType& j) const noexcept
+ CharType ubjson_prefix(const BasicJsonType& j) const noexcept
{
switch (j.type())
{
@@ -7100,7 +8570,7 @@
}
case value_t::number_float:
- return 'D';
+ return get_ubjson_float_prefix(j.m_value.number_float);
case value_t::string:
return 'S';
@@ -7116,6 +8586,36 @@
}
}
+ static constexpr CharType get_cbor_float_prefix(float)
+ {
+ return static_cast<CharType>(0xFA); // Single-Precision Float
+ }
+
+ static constexpr CharType get_cbor_float_prefix(double)
+ {
+ return static_cast<CharType>(0xFB); // Double-Precision Float
+ }
+
+ static constexpr CharType get_msgpack_float_prefix(float)
+ {
+ return static_cast<CharType>(0xCA); // float 32
+ }
+
+ static constexpr CharType get_msgpack_float_prefix(double)
+ {
+ return static_cast<CharType>(0xCB); // float 64
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(float)
+ {
+ return 'd'; // float 32
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(double)
+ {
+ return 'D'; // float 64
+ }
+
private:
/// whether we can assume little endianess
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();
@@ -7138,11 +8638,8 @@
#include <cstddef> // size_t, ptrdiff_t
#include <cstdint> // uint8_t
#include <cstdio> // snprintf
-#include <iomanip> // setfill
-#include <iterator> // next
#include <limits> // numeric_limits
#include <string> // string
-#include <sstream> // stringstream
#include <type_traits> // is_same
// #include <nlohmann/detail/exceptions.hpp>
@@ -8037,7 +9534,7 @@
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
// decimal representations are not exactly "short".
//
- // The documentation for 'std::to_chars' (http://en.cppreference.com/w/cpp/utility/to_chars)
+ // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
// says "value is converted to a string as if by std::sprintf in the default ("C") locale"
// and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
// does.
@@ -8246,7 +9743,7 @@
// #include <nlohmann/detail/macro_scope.hpp>
-// #include <nlohmann/detail/meta.hpp>
+// #include <nlohmann/detail/meta/cpp_future.hpp>
// #include <nlohmann/detail/output/output_adapters.hpp>
@@ -8619,9 +10116,9 @@
case UTF8_REJECT: // decode found invalid UTF-8 byte
{
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(byte);
- JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str()));
+ std::string sn(3, '\0');
+ snprintf(&sn[0], sn.size(), "%.2X", byte);
+ JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn));
}
default: // decode found yet incomplete multi-byte code point
@@ -8647,9 +10144,9 @@
else
{
// we finish reading, but do not accept: string was incomplete
- std::stringstream ss;
- ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast<int>(static_cast<uint8_t>(s.back()));
- JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str()));
+ std::string sn(3, '\0');
+ snprintf(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
+ JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
}
}
@@ -9711,42 +11208,42 @@
@requirement The class satisfies the following concept requirements:
- Basic
- - [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible):
+ - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
JSON values can be default constructed. The result will be a JSON null
value.
- - [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible):
+ - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
A JSON value can be constructed from an rvalue argument.
- - [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible):
+ - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
A JSON value can be copy-constructed from an lvalue expression.
- - [MoveAssignable](http://en.cppreference.com/w/cpp/concept/MoveAssignable):
+ - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
A JSON value van be assigned from an rvalue argument.
- - [CopyAssignable](http://en.cppreference.com/w/cpp/concept/CopyAssignable):
+ - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
A JSON value can be copy-assigned from an lvalue expression.
- - [Destructible](http://en.cppreference.com/w/cpp/concept/Destructible):
+ - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
JSON values can be destructed.
- Layout
- - [StandardLayoutType](http://en.cppreference.com/w/cpp/concept/StandardLayoutType):
+ - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
JSON values have
- [standard layout](http://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+ [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
All non-static data members are private and standard layout types, the
class has no virtual functions or (virtual) base classes.
- Library-wide
- - [EqualityComparable](http://en.cppreference.com/w/cpp/concept/EqualityComparable):
+ - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
JSON values can be compared with `==`, see @ref
operator==(const_reference,const_reference).
- - [LessThanComparable](http://en.cppreference.com/w/cpp/concept/LessThanComparable):
+ - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
JSON values can be compared with `<`, see @ref
operator<(const_reference,const_reference).
- - [Swappable](http://en.cppreference.com/w/cpp/concept/Swappable):
+ - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
other compatible types, using unqualified function call @ref swap().
- - [NullablePointer](http://en.cppreference.com/w/cpp/concept/NullablePointer):
+ - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
JSON values can be compared against `std::nullptr_t` objects which are used
to model the `null` value.
- Container
- - [Container](http://en.cppreference.com/w/cpp/concept/Container):
+ - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
JSON values can be used like STL containers and provide iterator access.
- - [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer);
+ - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
JSON values can be used like STL containers and provide reverse iterator
access.
@@ -9780,8 +11277,12 @@
friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer;
- template<typename BasicJsonType>
+ template<typename BasicJsonType, typename SAX>
friend class ::nlohmann::detail::binary_reader;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_parser;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_callback_parser;
/// workaround type for MSVC
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
@@ -9809,13 +11310,17 @@
public:
using value_t = detail::value_t;
- /// @copydoc nlohmann::json_pointer
+ /// JSON Pointer, see @ref nlohmann::json_pointer
using json_pointer = ::nlohmann::json_pointer<basic_json>;
template<typename T, typename SFINAE>
using json_serializer = JSONSerializer<T, SFINAE>;
/// helper type for initializer lists of basic_json values
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+ using input_format_t = detail::input_format_t;
+ /// SAX interface type, see @ref nlohmann::json_sax
+ using json_sax_t = json_sax<basic_json>;
+
////////////////
// exceptions //
////////////////
@@ -10548,7 +12053,7 @@
object = nullptr; // silence warning, see #821
if (JSON_UNLIKELY(t == value_t::null))
{
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.1.2")); // LCOV_EXCL_LINE
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
}
break;
}
@@ -10716,7 +12221,6 @@
*/
using parser_callback_t = typename parser::parser_callback_t;
-
//////////////////
// constructors //
//////////////////
@@ -10878,7 +12382,7 @@
was provided), strong guarantee holds: if an exception is thrown, there are
no changes to any JSON value.
- @since version 3.1.2
+ @since version 3.2.0
*/
template <typename BasicJsonType,
detail::enable_if_t<
@@ -11198,7 +12702,7 @@
@warning A precondition is enforced with a runtime assertion that will
result in calling `std::abort` if this precondition is not met.
Assertions can be disabled by defining `NDEBUG` at compile time.
- See http://en.cppreference.com/w/cpp/error/assert for more
+ See https://en.cppreference.com/w/cpp/error/assert for more
information.
@throw invalid_iterator.201 if iterators @a first and @a last are not
@@ -11338,7 +12842,7 @@
changes to any JSON value.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
- As postcondition, it holds: `other == basic_json(other)`.
@@ -11423,7 +12927,7 @@
exceptions.
@requirement This function helps `basic_json` satisfying the
- [MoveConstructible](http://en.cppreference.com/w/cpp/concept/MoveConstructible)
+ [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
requirements.
@liveexample{The code below shows the move constructor explicitly called
@@ -11457,7 +12961,7 @@
@complexity Linear.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
@@ -11494,7 +12998,7 @@
@complexity Linear.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is linear.
- All stored elements are destroyed and all memory is freed.
@@ -12111,7 +13615,7 @@
@complexity Depending on the implementation of the called `from_json()`
method.
- @since version 3.1.2
+ @since version 3.2.0
*/
template<typename BasicJsonType, detail::enable_if_t<
not std::is_same<BasicJsonType, basic_json>::value and
@@ -12125,8 +13629,8 @@
@brief get a value (explicit)
Explicit type conversion between the JSON value and a compatible value
- which is [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
- and [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
The value is converted by calling the @ref json_serializer<ValueType>
`from_json()` method.
@@ -12186,8 +13690,8 @@
@brief get a value (explicit); special case
Explicit type conversion between the JSON value and a compatible value
- which is **not** [CopyConstructible](http://en.cppreference.com/w/cpp/concept/CopyConstructible)
- and **not** [DefaultConstructible](http://en.cppreference.com/w/cpp/concept/DefaultConstructible).
+ which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
The value is converted by calling the @ref json_serializer<ValueType>
`from_json()` method.
@@ -12432,10 +13936,10 @@
not detail::is_basic_json<ValueType>::value
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
-#endif
-#if defined(JSON_HAS_CPP_17)
+#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
and not std::is_same<ValueType, typename std::string_view>::value
#endif
+#endif
, int >::type = 0 >
operator ValueType() const
{
@@ -13016,7 +14520,7 @@
@return copy of the element at key @a key or @a default_value if @a key
is not found
- @throw type_error.306 if the JSON value is not an objec; in that case,
+ @throw type_error.306 if the JSON value is not an object; in that case,
using `value()` with a key makes no sense.
@complexity Logarithmic in the size of the container.
@@ -13040,7 +14544,7 @@
{
return ptr.get_checked(this);
}
- JSON_CATCH (out_of_range&)
+ JSON_INTERNAL_CATCH (out_of_range&)
{
return default_value;
}
@@ -13551,7 +15055,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
@@ -13590,7 +15094,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
@@ -13622,7 +15126,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
@@ -13661,7 +15165,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).end()`.
@@ -13691,7 +15195,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `reverse_iterator(end())`.
@@ -13728,7 +15232,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `reverse_iterator(begin())`.
@@ -13765,7 +15269,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
@@ -13794,7 +15298,7 @@
@complexity Constant.
@requirement This function helps `basic_json` satisfying the
- [ReversibleContainer](http://en.cppreference.com/w/cpp/concept/ReversibleContainer)
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
requirements:
- The complexity is constant.
- Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
@@ -13935,7 +15439,7 @@
@complexity Constant.
- @since version 3.x.x.
+ @since version 3.1.0.
*/
iteration_proxy<iterator> items() noexcept
{
@@ -13992,7 +15496,7 @@
false in the case of a string.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `begin() == end()`.
@@ -14063,7 +15567,7 @@
the case of a string.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of `std::distance(begin(), end())`.
@@ -14133,7 +15637,7 @@
@exceptionsafety No-throw guarantee: this function never throws exceptions.
@requirement This function helps `basic_json` satisfying the
- [Container](http://en.cppreference.com/w/cpp/concept/Container)
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
requirements:
- The complexity is constant.
- Has the semantics of returning `b.size()` where `b` is the largest
@@ -15602,7 +17106,7 @@
@since version 2.0.3 (contiguous containers)
*/
- static basic_json parse(detail::input_adapter i,
+ static basic_json parse(detail::input_adapter&& i,
const parser_callback_t cb = nullptr,
const bool allow_exceptions = true)
{
@@ -15611,26 +17115,80 @@
return result;
}
+ static bool accept(detail::input_adapter&& i)
+ {
+ return parser(i).accept(true);
+ }
+
/*!
- @copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
+ @brief generate SAX events
+
+ The SAX event lister must follow the interface of @ref json_sax.
+
+ This function reads from a compatible input. Examples are:
+ - an array of 1-byte values
+ - strings with character/literal type with size of 1 byte
+ - input streams
+ - container with contiguous storage of 1-byte values. Compatible container
+ types include `std::vector`, `std::string`, `std::array`,
+ `std::valarray`, and `std::initializer_list`. Furthermore, C-style
+ arrays can be used with `std::begin()`/`std::end()`. User-defined
+ containers can be used as long as they implement random-access iterators
+ and a contiguous storage.
+
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @pre The container storage is contiguous. Violating this precondition
+ yields undefined behavior. **This precondition is enforced with an
+ assertion.**
+ @pre Each element of the container has a size of 1 byte. Violating this
+ precondition yields undefined behavior. **This precondition is enforced
+ with a static assertion.**
+
+ @warning There is no way to enforce all preconditions at compile-time. If
+ the function is called with a noncompliant container and with
+ assertions switched off, the behavior is undefined and will most
+ likely yield segmentation violation.
+
+ @param[in] i input to read from
+ @param[in,out] sax SAX event listener
+ @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
+ @param[in] strict whether the input has to be consumed completely
+
+ @return return value of the last processed SAX event
+
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
+ a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `sax_parse()` function
+ reading from string and processing the events with a user-defined SAX
+ event consumer.,sax_parse}
+
+ @since version 3.2.0
*/
- static basic_json parse(detail::input_adapter& i,
- const parser_callback_t cb = nullptr,
- const bool allow_exceptions = true)
+ template <typename SAX>
+ static bool sax_parse(detail::input_adapter&& i, SAX* sax,
+ input_format_t format = input_format_t::json,
+ const bool strict = true)
{
- basic_json result;
- parser(i, cb, allow_exceptions).parse(true, result);
- return result;
- }
-
- static bool accept(detail::input_adapter i)
- {
- return parser(i).accept(true);
- }
-
- static bool accept(detail::input_adapter& i)
- {
- return parser(i).accept(true);
+ assert(sax);
+ switch (format)
+ {
+ case input_format_t::json:
+ return parser(std::move(i)).sax_parse(sax, strict);
+ default:
+ return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
+ }
}
/*!
@@ -15702,6 +17260,15 @@
return parser(detail::input_adapter(first, last)).accept(true);
}
+ template<class IteratorType, class SAX, typename std::enable_if<
+ std::is_base_of<
+ std::random_access_iterator_tag,
+ typename std::iterator_traits<IteratorType>::iterator_category>::value, int>::type = 0>
+ static bool sax_parse(IteratorType first, IteratorType last, SAX* sax)
+ {
+ return parser(detail::input_adapter(first, last)).sax_parse(sax);
+ }
+
/*!
@brief deserialize from stream
@deprecated This stream operator is deprecated and will be removed in
@@ -16198,6 +17765,9 @@
@param[in] i an input in CBOR format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
@return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
@@ -16213,29 +17783,39 @@
@sa http://cbor.io
@sa @ref to_cbor(const basic_json&) for the analogous serialization
- @sa @ref from_msgpack(detail::input_adapter, const bool) for the
+ @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the
related MessagePack format
- @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
- UBJSON format
+ @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the
+ related UBJSON format
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added
- @a strict parameter since 3.0.0
+ @a strict parameter since 3.0.0; added @allow_exceptions parameter
+ since 3.2.0
*/
- static basic_json from_cbor(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_cbor(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_cbor(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
- @copydoc from_cbor(detail::input_adapter, const bool)
+ @copydoc from_cbor(detail::input_adapter, const bool, const bool)
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_cbor(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
@@ -16288,6 +17868,10 @@
adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true
@@ -16302,29 +17886,39 @@
@sa http://msgpack.org
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
- @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
- format
- @sa @ref from_ubjson(detail::input_adapter, const bool) for the related
- UBJSON format
+ @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
+ related CBOR format
+ @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for
+ the related UBJSON format
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added
- @a strict parameter since 3.0.0
+ @a strict parameter since 3.0.0; added @allow_exceptions parameter
+ since 3.2.0
*/
- static basic_json from_msgpack(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_msgpack(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_msgpack(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
- @copydoc from_msgpack(detail::input_adapter, const bool)
+ @copydoc from_msgpack(detail::input_adapter, const bool, const bool)
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_msgpack(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/*!
@@ -16359,6 +17953,10 @@
@param[in] i an input in UBJSON format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF
(true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true
@@ -16373,24 +17971,36 @@
@sa http://ubjson.org
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
analogous serialization
- @sa @ref from_cbor(detail::input_adapter, const bool) for the related CBOR
- format
- @sa @ref from_msgpack(detail::input_adapter, const bool) for the related
- MessagePack format
+ @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the
+ related CBOR format
+ @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for
+ the related MessagePack format
- @since version 3.1.0
+ @since version 3.1.0; added @allow_exceptions parameter since 3.2.0
*/
- static basic_json from_ubjson(detail::input_adapter i,
- const bool strict = true)
+ static basic_json from_ubjson(detail::input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(i).parse_ubjson(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
+ /*!
+ @copydoc from_ubjson(detail::input_adapter, const bool, const bool)
+ */
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
- static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true)
+ static basic_json from_ubjson(A1 && a1, A2 && a2,
+ const bool strict = true,
+ const bool allow_exceptions = true)
{
- return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict);
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
}
/// @}
@@ -16767,11 +18377,13 @@
break;
}
+ // LCOV_EXCL_START
default:
{
// if there exists a parent it cannot be primitive
- assert(false); // LCOV_EXCL_LINE
+ assert(false);
}
+ // LCOV_EXCL_STOP
}
}
};
@@ -16913,7 +18525,7 @@
// the "path" location must exist - use at()
success = (result.at(ptr) == get_value("test", "value", false));
}
- JSON_CATCH (out_of_range&)
+ JSON_INTERNAL_CATCH (out_of_range&)
{
// ignore out of range errors: success remains false
}
@@ -17191,11 +18803,10 @@
@since version 1.0.0
*/
template<>
-inline void swap(nlohmann::json& j1,
- nlohmann::json& j2) noexcept(
- is_nothrow_move_constructible<nlohmann::json>::value and
- is_nothrow_move_assignable<nlohmann::json>::value
- )
+inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
+ is_nothrow_move_constructible<nlohmann::json>::value and
+ is_nothrow_move_assignable<nlohmann::json>::value
+)
{
j1.swap(j2);
}
@@ -17284,6 +18895,7 @@
#endif
// clean up
+#undef JSON_INTERNAL_CATCH
#undef JSON_CATCH
#undef JSON_THROW
#undef JSON_TRY
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e5f6dc5..c0f4072 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -6,15 +6,14 @@
if(JSON_Sanitizer)
message(STATUS "Building test suite with Clang sanitizer")
if(NOT MSVC)
- set(CMAKE_CXX_FLAGS "-std=c++11 -g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer")
+ set(CMAKE_CXX_FLAGS "-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer")
endif()
endif()
if(JSON_Valgrind)
find_program(CMAKE_MEMORYCHECK_COMMAND valgrind)
message(STATUS "Executing test suite with Valgrind (${CMAKE_MEMORYCHECK_COMMAND})")
- set(MEMORYCHECK_COMMAND_OPTIONS "--error-exitcode=1 --leak-check=full")
- set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS}")
+ set(memcheck_command "${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS} --error-exitcode=1 --leak-check=full")
separate_arguments(memcheck_command)
endif()
@@ -62,11 +61,10 @@
"src/unit.cpp"
)
set_target_properties(catch_main PROPERTIES
- CXX_STANDARD 11
- CXX_STANDARD_REQUIRED ON
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
+target_compile_features(catch_main PUBLIC cxx_std_11)
target_include_directories(catch_main PRIVATE "thirdparty/catch")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
@@ -83,6 +81,9 @@
# Disable warning C4566: character represented by universal-character-name '\uFF01' cannot be represented in the current code page (1252)
# Disable warning C4996: 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::operator <<': was declared deprecated
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4389 /wd4309 /wd4566 /wd4996")
+
+ # https://github.com/nlohmann/json/issues/1114
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
endif()
#############################################################################
@@ -96,13 +97,12 @@
add_executable(${testcase} $<TARGET_OBJECTS:catch_main> ${file})
set_target_properties(${testcase} PROPERTIES
- CXX_STANDARD 11
- CXX_STANDARD_REQUIRED ON
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
target_compile_definitions(${testcase} PRIVATE CATCH_CONFIG_FAST_COMPILE)
+ target_compile_features(${testcase} PRIVATE cxx_std_11)
target_include_directories(${testcase} PRIVATE "thirdparty/catch")
target_include_directories(${testcase} PRIVATE "thirdparty/fifo_map")
target_include_directories(${testcase} PRIVATE ${NLOHMANN_JSON_INCLUDE_BUILD_DIR})
diff --git a/test/Makefile b/test/Makefile
index f373451..afbb1ba 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -42,7 +42,8 @@
src/unit-serialization.cpp \
src/unit-testsuites.cpp \
src/unit-ubjson.cpp \
- src/unit-unicode.cpp
+ src/unit-unicode.cpp \
+ src/unit-wstring.cpp
OBJECTS = $(SOURCES:.cpp=.o)
diff --git a/test/data/nst_json_testsuite2/LICENSE b/test/data/nst_json_testsuite2/LICENSE
new file mode 100644
index 0000000..c4b3621
--- /dev/null
+++ b/test/data/nst_json_testsuite2/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Nicolas Seriot
+
+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.
diff --git a/test/data/nst_json_testsuite2/README.md b/test/data/nst_json_testsuite2/README.md
new file mode 100644
index 0000000..775ccfd
--- /dev/null
+++ b/test/data/nst_json_testsuite2/README.md
@@ -0,0 +1,55 @@
+# JSON Parsing Test Suite
+A comprehensive test suite for RFC 8259 compliant JSON parsers
+
+This repository was created as an appendix to the article [Parsing JSON is a Minefield ๐ฃ](http://seriot.ch/parsing_json.php).
+
+**/parsers/**
+
+This directory contains several parsers and tiny wrappers to turn the parsers into JSON validators, by returning a specific value.
+
+- `0` the parser did accept the content
+- `1` the parser did reject the content
+- `>1` the process did crash
+- `timeout` happens after 5 seconds
+
+**/test\_parsing/**
+
+The name of these files tell if their contents should be accepted or rejected.
+
+- `y_` content must be accepted by parsers
+- `n_` content must be rejected by parsers
+- `i_` parsers are free to accept or reject content
+
+**/test\_transform/**
+
+These files contain weird structures and characters that parsers may understand differently, eg:
+
+- huge numbers
+- dictionaries with similar keys
+- NULL characters
+- escaped invalid strings
+
+These files were used to produce `results/transform.html`.
+
+**/run_tests.py**
+
+Run all parsers with all files:
+
+ $ python3 run_tests.py
+
+Run all parsers with a specific file:
+
+ $ python3 run_tests.py file.json
+
+Run specific parsers with all files:
+
+ $ echo '["Python 2.7.10", "Python 3.5.2"]' > python_only.json
+ $ python3 run_tests.py --filter=python_only.json
+
+The script writes logs in `results/logs.txt`.
+
+The script then reads `logs.txt` and generates `results/parsing.html`.
+
+**/results/**
+
+<img src="results/pruned_results.png" alt="JSON Parsing Tests" />
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_double_huge_neg_exp.json b/test/data/nst_json_testsuite2/test_parsing/i_number_double_huge_neg_exp.json
new file mode 100644
index 0000000..ae4c7b7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_double_huge_neg_exp.json
@@ -0,0 +1 @@
+[123.456e-789]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_huge_exp.json b/test/data/nst_json_testsuite2/test_parsing/i_number_huge_exp.json
new file mode 100644
index 0000000..9b5efa2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_huge_exp.json
@@ -0,0 +1 @@
+[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_neg_int_huge_exp.json b/test/data/nst_json_testsuite2/test_parsing/i_number_neg_int_huge_exp.json
new file mode 100755
index 0000000..3abd58a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_neg_int_huge_exp.json
@@ -0,0 +1 @@
+[-1e+9999]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_pos_double_huge_exp.json b/test/data/nst_json_testsuite2/test_parsing/i_number_pos_double_huge_exp.json
new file mode 100755
index 0000000..e10a7eb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_pos_double_huge_exp.json
@@ -0,0 +1 @@
+[1.5e+9999]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_real_neg_overflow.json b/test/data/nst_json_testsuite2/test_parsing/i_number_real_neg_overflow.json
new file mode 100644
index 0000000..3d628a9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_real_neg_overflow.json
@@ -0,0 +1 @@
+[-123123e100000]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_real_pos_overflow.json b/test/data/nst_json_testsuite2/test_parsing/i_number_real_pos_overflow.json
new file mode 100644
index 0000000..54d7d3d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_real_pos_overflow.json
@@ -0,0 +1 @@
+[123123e100000]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_real_underflow.json b/test/data/nst_json_testsuite2/test_parsing/i_number_real_underflow.json
new file mode 100644
index 0000000..c5236eb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_real_underflow.json
@@ -0,0 +1 @@
+[123e-10000000]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_neg_int.json b/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_neg_int.json
new file mode 100644
index 0000000..dfa3846
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_neg_int.json
@@ -0,0 +1 @@
+[-123123123123123123123123123123]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_pos_int.json b/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_pos_int.json
new file mode 100644
index 0000000..338a8c3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_too_big_pos_int.json
@@ -0,0 +1 @@
+[100000000000000000000]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_number_very_big_negative_int.json b/test/data/nst_json_testsuite2/test_parsing/i_number_very_big_negative_int.json
new file mode 100755
index 0000000..e2d9738
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_number_very_big_negative_int.json
@@ -0,0 +1 @@
+[-237462374673276894279832749832423479823246327846]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_object_key_lone_2nd_surrogate.json b/test/data/nst_json_testsuite2/test_parsing/i_object_key_lone_2nd_surrogate.json
new file mode 100644
index 0000000..5be7eba
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_object_key_lone_2nd_surrogate.json
@@ -0,0 +1 @@
+{"\uDFAA":0}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_1st_surrogate_but_2nd_missing.json b/test/data/nst_json_testsuite2/test_parsing/i_string_1st_surrogate_but_2nd_missing.json
new file mode 100644
index 0000000..3b9e37c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_1st_surrogate_but_2nd_missing.json
@@ -0,0 +1 @@
+["\uDADA"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json b/test/data/nst_json_testsuite2/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json
new file mode 100644
index 0000000..4875928
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json
@@ -0,0 +1 @@
+["\uD888\u1234"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-16LE_with_BOM.json b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-16LE_with_BOM.json
new file mode 100644
index 0000000..2a79c06
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-16LE_with_BOM.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-8_invalid_sequence.json b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-8_invalid_sequence.json
new file mode 100755
index 0000000..e2a968a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF-8_invalid_sequence.json
@@ -0,0 +1 @@
+["æย¥Ñยú"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_UTF8_surrogate_U+D800.json b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF8_surrogate_U+D800.json
new file mode 100644
index 0000000..916bff9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_UTF8_surrogate_U+D800.json
@@ -0,0 +1 @@
+["í ย"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json
new file mode 100755
index 0000000..3cb11d2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json
@@ -0,0 +1 @@
+["\uD800\n"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_pair.json b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_pair.json
new file mode 100755
index 0000000..38ec23b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_pair.json
@@ -0,0 +1 @@
+["\uDd1ea"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogates_escape_valid.json b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogates_escape_valid.json
new file mode 100755
index 0000000..c9cd6f6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogates_escape_valid.json
@@ -0,0 +1 @@
+["\uD800\uD800\n"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_lonely_surrogate.json b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_lonely_surrogate.json
new file mode 100755
index 0000000..3abbd8d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_lonely_surrogate.json
@@ -0,0 +1 @@
+["\ud800"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_surrogate.json b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_surrogate.json
new file mode 100755
index 0000000..ffddc04
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_surrogate.json
@@ -0,0 +1 @@
+["\ud800abc"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_utf-8.json b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_utf-8.json
new file mode 100644
index 0000000..8e45a7e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_invalid_utf-8.json
@@ -0,0 +1 @@
+["ÿ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_inverted_surrogates_U+1D11E.json b/test/data/nst_json_testsuite2/test_parsing/i_string_inverted_surrogates_U+1D11E.json
new file mode 100755
index 0000000..0d5456c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_inverted_surrogates_U+1D11E.json
@@ -0,0 +1 @@
+["\uDd1e\uD834"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_iso_latin_1.json b/test/data/nst_json_testsuite2/test_parsing/i_string_iso_latin_1.json
new file mode 100644
index 0000000..9389c98
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_iso_latin_1.json
@@ -0,0 +1 @@
+["é"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_lone_second_surrogate.json b/test/data/nst_json_testsuite2/test_parsing/i_string_lone_second_surrogate.json
new file mode 100644
index 0000000..1dbd397
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_lone_second_surrogate.json
@@ -0,0 +1 @@
+["\uDFAA"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_lone_utf8_continuation_byte.json b/test/data/nst_json_testsuite2/test_parsing/i_string_lone_utf8_continuation_byte.json
new file mode 100644
index 0000000..729337c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_lone_utf8_continuation_byte.json
@@ -0,0 +1 @@
+["ย"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_not_in_unicode_range.json b/test/data/nst_json_testsuite2/test_parsing/i_string_not_in_unicode_range.json
new file mode 100644
index 0000000..df90a29
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_not_in_unicode_range.json
@@ -0,0 +1 @@
+["ô¿¿¿"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_2_bytes.json b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_2_bytes.json
new file mode 100644
index 0000000..c8cee5e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_2_bytes.json
@@ -0,0 +1 @@
+["À¯"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes.json b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes.json
new file mode 100755
index 0000000..9a91da7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes.json
@@ -0,0 +1 @@
+["üย¿¿¿¿"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes_null.json b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes_null.json
new file mode 100755
index 0000000..d24fffd
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes_null.json
@@ -0,0 +1 @@
+["üยยยยย"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_truncated-utf-8.json b/test/data/nst_json_testsuite2/test_parsing/i_string_truncated-utf-8.json
new file mode 100644
index 0000000..63c7777
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_truncated-utf-8.json
@@ -0,0 +1 @@
+["àÿ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_utf16BE_no_BOM.json b/test/data/nst_json_testsuite2/test_parsing/i_string_utf16BE_no_BOM.json
new file mode 100644
index 0000000..57e5392
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_utf16BE_no_BOM.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_string_utf16LE_no_BOM.json b/test/data/nst_json_testsuite2/test_parsing/i_string_utf16LE_no_BOM.json
new file mode 100644
index 0000000..c49c1b2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_string_utf16LE_no_BOM.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_structure_500_nested_arrays.json b/test/data/nst_json_testsuite2/test_parsing/i_structure_500_nested_arrays.json
new file mode 100644
index 0000000..7118405
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_structure_500_nested_arrays.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/i_structure_UTF-8_BOM_empty_object.json b/test/data/nst_json_testsuite2/test_parsing/i_structure_UTF-8_BOM_empty_object.json
new file mode 100755
index 0000000..22fdca1
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/i_structure_UTF-8_BOM_empty_object.json
@@ -0,0 +1 @@
+๏ปฟ{}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_1_true_without_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_1_true_without_comma.json
new file mode 100644
index 0000000..c14e3f6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_1_true_without_comma.json
@@ -0,0 +1 @@
+[1 true]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_a_invalid_utf8.json b/test/data/nst_json_testsuite2/test_parsing/n_array_a_invalid_utf8.json
new file mode 100644
index 0000000..38a86e2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_a_invalid_utf8.json
@@ -0,0 +1 @@
+[aå]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_colon_instead_of_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_colon_instead_of_comma.json
new file mode 100644
index 0000000..0d02ad4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_colon_instead_of_comma.json
@@ -0,0 +1 @@
+["": 1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_comma_after_close.json b/test/data/nst_json_testsuite2/test_parsing/n_array_comma_after_close.json
new file mode 100644
index 0000000..2ccba8d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_comma_after_close.json
@@ -0,0 +1 @@
+[""],
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_comma_and_number.json b/test/data/nst_json_testsuite2/test_parsing/n_array_comma_and_number.json
new file mode 100755
index 0000000..d2c84e3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_comma_and_number.json
@@ -0,0 +1 @@
+[,1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_double_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_double_comma.json
new file mode 100755
index 0000000..0431712
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_double_comma.json
@@ -0,0 +1 @@
+[1,,2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_double_extra_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_double_extra_comma.json
new file mode 100644
index 0000000..3f01d31
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_double_extra_comma.json
@@ -0,0 +1 @@
+["x",,]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_extra_close.json b/test/data/nst_json_testsuite2/test_parsing/n_array_extra_close.json
new file mode 100644
index 0000000..c12f9fa
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_extra_close.json
@@ -0,0 +1 @@
+["x"]]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_extra_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_extra_comma.json
new file mode 100644
index 0000000..5f8ce18
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_extra_comma.json
@@ -0,0 +1 @@
+["",]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete.json b/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete.json
new file mode 100644
index 0000000..cc65b0b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete.json
@@ -0,0 +1 @@
+["x"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete_invalid_value.json b/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete_invalid_value.json
new file mode 100644
index 0000000..c21a8f6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_incomplete_invalid_value.json
@@ -0,0 +1 @@
+[x
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_inner_array_no_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_inner_array_no_comma.json
new file mode 100644
index 0000000..c70b716
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_inner_array_no_comma.json
@@ -0,0 +1 @@
+[3[4]]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_invalid_utf8.json b/test/data/nst_json_testsuite2/test_parsing/n_array_invalid_utf8.json
new file mode 100644
index 0000000..6099d34
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_invalid_utf8.json
@@ -0,0 +1 @@
+[ÿ]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_items_separated_by_semicolon.json b/test/data/nst_json_testsuite2/test_parsing/n_array_items_separated_by_semicolon.json
new file mode 100755
index 0000000..d4bd731
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_items_separated_by_semicolon.json
@@ -0,0 +1 @@
+[1:2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_just_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_just_comma.json
new file mode 100755
index 0000000..9d7077c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_just_comma.json
@@ -0,0 +1 @@
+[,]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_just_minus.json b/test/data/nst_json_testsuite2/test_parsing/n_array_just_minus.json
new file mode 100755
index 0000000..29501c6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_just_minus.json
@@ -0,0 +1 @@
+[-]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_missing_value.json b/test/data/nst_json_testsuite2/test_parsing/n_array_missing_value.json
new file mode 100644
index 0000000..3a6ba86
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_missing_value.json
@@ -0,0 +1 @@
+[ , ""]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_newlines_unclosed.json b/test/data/nst_json_testsuite2/test_parsing/n_array_newlines_unclosed.json
new file mode 100644
index 0000000..6466800
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_newlines_unclosed.json
@@ -0,0 +1,3 @@
+["a",
+4
+,1,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_comma.json
new file mode 100755
index 0000000..13f6f1d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_comma.json
@@ -0,0 +1 @@
+[1,]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_several_commas.json b/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_several_commas.json
new file mode 100755
index 0000000..0ac408c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_number_and_several_commas.json
@@ -0,0 +1 @@
+[1,,]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_spaces_vertical_tab_formfeed.json b/test/data/nst_json_testsuite2/test_parsing/n_array_spaces_vertical_tab_formfeed.json
new file mode 100755
index 0000000..6cd7cf5
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_spaces_vertical_tab_formfeed.json
@@ -0,0 +1 @@
+["a"\f]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_star_inside.json b/test/data/nst_json_testsuite2/test_parsing/n_array_star_inside.json
new file mode 100755
index 0000000..5a51946
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_star_inside.json
@@ -0,0 +1 @@
+[*]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed.json b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed.json
new file mode 100644
index 0000000..0607330
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed.json
@@ -0,0 +1 @@
+[""
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_trailing_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_trailing_comma.json
new file mode 100644
index 0000000..6604698
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_trailing_comma.json
@@ -0,0 +1 @@
+[1,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_new_lines.json b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_new_lines.json
new file mode 100644
index 0000000..4f61de3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_new_lines.json
@@ -0,0 +1,3 @@
+[1,
+1
+,1
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_object_inside.json b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_object_inside.json
new file mode 100644
index 0000000..043a87e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_object_inside.json
@@ -0,0 +1 @@
+[{}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_incomplete_false.json b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_false.json
new file mode 100644
index 0000000..eb18c6a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_false.json
@@ -0,0 +1 @@
+[fals]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_incomplete_null.json b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_null.json
new file mode 100644
index 0000000..c18ef53
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_null.json
@@ -0,0 +1 @@
+[nul]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_incomplete_true.json b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_true.json
new file mode 100644
index 0000000..f451ac6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_incomplete_true.json
@@ -0,0 +1 @@
+[tru]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_multidigit_number_then_00.json b/test/data/nst_json_testsuite2/test_parsing/n_multidigit_number_then_00.json
new file mode 100644
index 0000000..c22507b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_multidigit_number_then_00.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_++.json b/test/data/nst_json_testsuite2/test_parsing/n_number_++.json
new file mode 100644
index 0000000..bdb62aa
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_++.json
@@ -0,0 +1 @@
+[++1234]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_+1.json b/test/data/nst_json_testsuite2/test_parsing/n_number_+1.json
new file mode 100755
index 0000000..3cbe58c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_+1.json
@@ -0,0 +1 @@
+[+1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_+Inf.json b/test/data/nst_json_testsuite2/test_parsing/n_number_+Inf.json
new file mode 100755
index 0000000..871ae14
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_+Inf.json
@@ -0,0 +1 @@
+[+Inf]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_-01.json b/test/data/nst_json_testsuite2/test_parsing/n_number_-01.json
new file mode 100755
index 0000000..0df32ba
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_-01.json
@@ -0,0 +1 @@
+[-01]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_-1.0..json b/test/data/nst_json_testsuite2/test_parsing/n_number_-1.0..json
new file mode 100755
index 0000000..7cf55a8
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_-1.0..json
@@ -0,0 +1 @@
+[-1.0.]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_-2..json b/test/data/nst_json_testsuite2/test_parsing/n_number_-2..json
new file mode 100755
index 0000000..9be8436
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_-2..json
@@ -0,0 +1 @@
+[-2.]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_-NaN.json b/test/data/nst_json_testsuite2/test_parsing/n_number_-NaN.json
new file mode 100755
index 0000000..f61615d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_-NaN.json
@@ -0,0 +1 @@
+[-NaN]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_.-1.json b/test/data/nst_json_testsuite2/test_parsing/n_number_.-1.json
new file mode 100644
index 0000000..1c9f2dd
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_.-1.json
@@ -0,0 +1 @@
+[.-1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_.2e-3.json b/test/data/nst_json_testsuite2/test_parsing/n_number_.2e-3.json
new file mode 100755
index 0000000..c6c976f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_.2e-3.json
@@ -0,0 +1 @@
+[.2e-3]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0.1.2.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0.1.2.json
new file mode 100755
index 0000000..c83a256
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0.1.2.json
@@ -0,0 +1 @@
+[0.1.2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e+.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e+.json
new file mode 100644
index 0000000..a55a1bf
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e+.json
@@ -0,0 +1 @@
+[0.3e+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e.json
new file mode 100644
index 0000000..3dd5df4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0.3e.json
@@ -0,0 +1 @@
+[0.3e]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0.e1.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0.e1.json
new file mode 100644
index 0000000..c92c71c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0.e1.json
@@ -0,0 +1 @@
+[0.e1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E+.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E+.json
new file mode 100644
index 0000000..3ba2c7d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E+.json
@@ -0,0 +1 @@
+[0E+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E.json
new file mode 100755
index 0000000..5301840
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E.json
@@ -0,0 +1 @@
+[0E]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0e+.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0e+.json
new file mode 100644
index 0000000..8ab0bc4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0e+.json
@@ -0,0 +1 @@
+[0e+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_0e.json b/test/data/nst_json_testsuite2/test_parsing/n_number_0e.json
new file mode 100644
index 0000000..47ec421
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_0e.json
@@ -0,0 +1 @@
+[0e]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e+.json b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e+.json
new file mode 100755
index 0000000..cd84b9f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e+.json
@@ -0,0 +1 @@
+[1.0e+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e-.json b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e-.json
new file mode 100755
index 0000000..4eb7afa
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e-.json
@@ -0,0 +1 @@
+[1.0e-]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e.json b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e.json
new file mode 100755
index 0000000..21753f4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_1.0e.json
@@ -0,0 +1 @@
+[1.0e]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_1_000.json b/test/data/nst_json_testsuite2/test_parsing/n_number_1_000.json
new file mode 100755
index 0000000..7b18b66
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_1_000.json
@@ -0,0 +1 @@
+[1 000.0]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_1eE2.json b/test/data/nst_json_testsuite2/test_parsing/n_number_1eE2.json
new file mode 100755
index 0000000..4318a34
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_1eE2.json
@@ -0,0 +1 @@
+[1eE2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_2.e+3.json b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e+3.json
new file mode 100755
index 0000000..4442f39
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e+3.json
@@ -0,0 +1 @@
+[2.e+3]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_2.e-3.json b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e-3.json
new file mode 100755
index 0000000..a65060e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e-3.json
@@ -0,0 +1 @@
+[2.e-3]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_2.e3.json b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e3.json
new file mode 100755
index 0000000..66f7cf7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_2.e3.json
@@ -0,0 +1 @@
+[2.e3]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_9.e+.json b/test/data/nst_json_testsuite2/test_parsing/n_number_9.e+.json
new file mode 100644
index 0000000..732a7b1
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_9.e+.json
@@ -0,0 +1 @@
+[9.e+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_Inf.json b/test/data/nst_json_testsuite2/test_parsing/n_number_Inf.json
new file mode 100755
index 0000000..c40c734
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_Inf.json
@@ -0,0 +1 @@
+[Inf]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_NaN.json b/test/data/nst_json_testsuite2/test_parsing/n_number_NaN.json
new file mode 100755
index 0000000..4992317
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_NaN.json
@@ -0,0 +1 @@
+[NaN]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_U+FF11_fullwidth_digit_one.json b/test/data/nst_json_testsuite2/test_parsing/n_number_U+FF11_fullwidth_digit_one.json
new file mode 100644
index 0000000..b14587e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_U+FF11_fullwidth_digit_one.json
@@ -0,0 +1 @@
+[๏ผ]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_expression.json b/test/data/nst_json_testsuite2/test_parsing/n_number_expression.json
new file mode 100644
index 0000000..76fdbc8
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_expression.json
@@ -0,0 +1 @@
+[1+2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_hex_1_digit.json b/test/data/nst_json_testsuite2/test_parsing/n_number_hex_1_digit.json
new file mode 100644
index 0000000..3b21488
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_hex_1_digit.json
@@ -0,0 +1 @@
+[0x1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_hex_2_digits.json b/test/data/nst_json_testsuite2/test_parsing/n_number_hex_2_digits.json
new file mode 100644
index 0000000..83e516a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_hex_2_digits.json
@@ -0,0 +1 @@
+[0x42]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_infinity.json b/test/data/nst_json_testsuite2/test_parsing/n_number_infinity.json
new file mode 100755
index 0000000..8c2baf7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_infinity.json
@@ -0,0 +1 @@
+[Infinity]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_invalid+-.json b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid+-.json
new file mode 100644
index 0000000..1cce602
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid+-.json
@@ -0,0 +1 @@
+[0e+-1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-negative-real.json b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-negative-real.json
new file mode 100644
index 0000000..5fc3c1e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-negative-real.json
@@ -0,0 +1 @@
+[-123.123foo]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-bigger-int.json b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-bigger-int.json
new file mode 100644
index 0000000..3b97e58
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-bigger-int.json
@@ -0,0 +1 @@
+[123å]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-exponent.json b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-exponent.json
new file mode 100644
index 0000000..ea35d72
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-exponent.json
@@ -0,0 +1 @@
+[1e1å]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-int.json b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-int.json
new file mode 100644
index 0000000..371226e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-int.json
@@ -0,0 +1 @@
+[0å]
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_minus_infinity.json b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_infinity.json
new file mode 100755
index 0000000..cf4133d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_infinity.json
@@ -0,0 +1 @@
+[-Infinity]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_minus_sign_with_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_sign_with_trailing_garbage.json
new file mode 100644
index 0000000..a6d8e78
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_sign_with_trailing_garbage.json
@@ -0,0 +1 @@
+[-foo]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_minus_space_1.json b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_space_1.json
new file mode 100644
index 0000000..9a5ebed
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_minus_space_1.json
@@ -0,0 +1 @@
+[- 1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_neg_int_starting_with_zero.json b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_int_starting_with_zero.json
new file mode 100644
index 0000000..67af096
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_int_starting_with_zero.json
@@ -0,0 +1 @@
+[-012]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_neg_real_without_int_part.json b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_real_without_int_part.json
new file mode 100755
index 0000000..1f2a434
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_real_without_int_part.json
@@ -0,0 +1 @@
+[-.123]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_neg_with_garbage_at_end.json b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_with_garbage_at_end.json
new file mode 100644
index 0000000..2aa7311
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_neg_with_garbage_at_end.json
@@ -0,0 +1 @@
+[-1x]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_real_garbage_after_e.json b/test/data/nst_json_testsuite2/test_parsing/n_number_real_garbage_after_e.json
new file mode 100644
index 0000000..9213dfc
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_real_garbage_after_e.json
@@ -0,0 +1 @@
+[1ea]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_real_with_invalid_utf8_after_e.json b/test/data/nst_json_testsuite2/test_parsing/n_number_real_with_invalid_utf8_after_e.json
new file mode 100644
index 0000000..1e52ef9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_real_with_invalid_utf8_after_e.json
@@ -0,0 +1 @@
+[1eå]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_real_without_fractional_part.json b/test/data/nst_json_testsuite2/test_parsing/n_number_real_without_fractional_part.json
new file mode 100755
index 0000000..1de287c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_real_without_fractional_part.json
@@ -0,0 +1 @@
+[1.]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_starting_with_dot.json b/test/data/nst_json_testsuite2/test_parsing/n_number_starting_with_dot.json
new file mode 100755
index 0000000..f682dbd
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_starting_with_dot.json
@@ -0,0 +1 @@
+[.123]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha.json b/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha.json
new file mode 100644
index 0000000..1e42d81
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha.json
@@ -0,0 +1 @@
+[1.2a-3]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha_char.json b/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha_char.json
new file mode 100644
index 0000000..b79dacc
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha_char.json
@@ -0,0 +1 @@
+[1.8011670033376514H-308]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_number_with_leading_zero.json b/test/data/nst_json_testsuite2/test_parsing/n_number_with_leading_zero.json
new file mode 100755
index 0000000..7106da1
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_number_with_leading_zero.json
@@ -0,0 +1 @@
+[012]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_bad_value.json b/test/data/nst_json_testsuite2/test_parsing/n_object_bad_value.json
new file mode 100644
index 0000000..a03a8c0
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_bad_value.json
@@ -0,0 +1 @@
+["x", truth]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_bracket_key.json b/test/data/nst_json_testsuite2/test_parsing/n_object_bracket_key.json
new file mode 100644
index 0000000..cc443b4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_bracket_key.json
@@ -0,0 +1 @@
+{[: "x"}
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_comma_instead_of_colon.json b/test/data/nst_json_testsuite2/test_parsing/n_object_comma_instead_of_colon.json
new file mode 100644
index 0000000..8d56377
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_comma_instead_of_colon.json
@@ -0,0 +1 @@
+{"x", null}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_double_colon.json b/test/data/nst_json_testsuite2/test_parsing/n_object_double_colon.json
new file mode 100644
index 0000000..80e8c7b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_double_colon.json
@@ -0,0 +1 @@
+{"x"::"b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_emoji.json b/test/data/nst_json_testsuite2/test_parsing/n_object_emoji.json
new file mode 100644
index 0000000..cb4078e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_emoji.json
@@ -0,0 +1 @@
+{๐จ๐ญ}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_garbage_at_end.json b/test/data/nst_json_testsuite2/test_parsing/n_object_garbage_at_end.json
new file mode 100644
index 0000000..80c42cb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_garbage_at_end.json
@@ -0,0 +1 @@
+{"a":"a" 123}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_key_with_single_quotes.json b/test/data/nst_json_testsuite2/test_parsing/n_object_key_with_single_quotes.json
new file mode 100755
index 0000000..77c3275
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_key_with_single_quotes.json
@@ -0,0 +1 @@
+{key: 'value'}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json
new file mode 100644
index 0000000..aa2cb63
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json
@@ -0,0 +1 @@
+{"¹":"0",}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_missing_colon.json b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_colon.json
new file mode 100644
index 0000000..b98eff6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_colon.json
@@ -0,0 +1 @@
+{"a" b}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_missing_key.json b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_key.json
new file mode 100755
index 0000000..b4fb0f5
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_key.json
@@ -0,0 +1 @@
+{:"b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_missing_semicolon.json b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_semicolon.json
new file mode 100755
index 0000000..e345138
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_semicolon.json
@@ -0,0 +1 @@
+{"a" "b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_missing_value.json b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_value.json
new file mode 100644
index 0000000..3ef538a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_missing_value.json
@@ -0,0 +1 @@
+{"a":
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_no-colon.json b/test/data/nst_json_testsuite2/test_parsing/n_object_no-colon.json
new file mode 100644
index 0000000..f3797b3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_no-colon.json
@@ -0,0 +1 @@
+{"a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key.json b/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key.json
new file mode 100755
index 0000000..b9945b3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key.json
@@ -0,0 +1 @@
+{1:1}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key_but_huge_number_instead.json b/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key_but_huge_number_instead.json
new file mode 100755
index 0000000..b37fa86
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key_but_huge_number_instead.json
@@ -0,0 +1 @@
+{9999E9999:1}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_repeated_null_null.json b/test/data/nst_json_testsuite2/test_parsing/n_object_repeated_null_null.json
new file mode 100755
index 0000000..f7d2959
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_repeated_null_null.json
@@ -0,0 +1 @@
+{null:null,null:null}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_several_trailing_commas.json b/test/data/nst_json_testsuite2/test_parsing/n_object_several_trailing_commas.json
new file mode 100755
index 0000000..3c9afe8
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_several_trailing_commas.json
@@ -0,0 +1 @@
+{"id":0,,,,,}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_single_quote.json b/test/data/nst_json_testsuite2/test_parsing/n_object_single_quote.json
new file mode 100644
index 0000000..e5cdf97
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_single_quote.json
@@ -0,0 +1 @@
+{'a':0}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comma.json
new file mode 100755
index 0000000..a4b0250
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comma.json
@@ -0,0 +1 @@
+{"id":0,}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment.json b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment.json
new file mode 100644
index 0000000..a372c65
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment.json
@@ -0,0 +1 @@
+{"a":"b"}/**/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_open.json b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_open.json
new file mode 100644
index 0000000..d557f41
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_open.json
@@ -0,0 +1 @@
+{"a":"b"}/**//
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open.json b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open.json
new file mode 100644
index 0000000..e335136
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open.json
@@ -0,0 +1 @@
+{"a":"b"}//
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open_incomplete.json b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open_incomplete.json
new file mode 100644
index 0000000..d892e49
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open_incomplete.json
@@ -0,0 +1 @@
+{"a":"b"}/
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_two_commas_in_a_row.json b/test/data/nst_json_testsuite2/test_parsing/n_object_two_commas_in_a_row.json
new file mode 100755
index 0000000..7c639ae
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_two_commas_in_a_row.json
@@ -0,0 +1 @@
+{"a":"b",,"c":"d"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_unquoted_key.json b/test/data/nst_json_testsuite2/test_parsing/n_object_unquoted_key.json
new file mode 100644
index 0000000..8ba1372
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_unquoted_key.json
@@ -0,0 +1 @@
+{a: "b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_unterminated-value.json b/test/data/nst_json_testsuite2/test_parsing/n_object_unterminated-value.json
new file mode 100644
index 0000000..7fe699a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_unterminated-value.json
@@ -0,0 +1 @@
+{"a":"a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_with_single_string.json b/test/data/nst_json_testsuite2/test_parsing/n_object_with_single_string.json
new file mode 100644
index 0000000..d63f7fb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_with_single_string.json
@@ -0,0 +1 @@
+{ "foo" : "bar", "a" }
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_object_with_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_object_with_trailing_garbage.json
new file mode 100644
index 0000000..787c8f0
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_object_with_trailing_garbage.json
@@ -0,0 +1 @@
+{"a":"b"}#
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_single_space.json b/test/data/nst_json_testsuite2/test_parsing/n_single_space.json
new file mode 100755
index 0000000..0519ecb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_single_space.json
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape.json
new file mode 100644
index 0000000..acec66d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape.json
@@ -0,0 +1 @@
+["\uD800\"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u.json b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u.json
new file mode 100644
index 0000000..e834b05
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u.json
@@ -0,0 +1 @@
+["\uD800\u"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1.json b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1.json
new file mode 100644
index 0000000..a04cd34
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1.json
@@ -0,0 +1 @@
+["\uD800\u1"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1x.json b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1x.json
new file mode 100644
index 0000000..bfbd234
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1x.json
@@ -0,0 +1 @@
+["\uD800\u1x"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_accentuated_char_no_quotes.json b/test/data/nst_json_testsuite2/test_parsing/n_string_accentuated_char_no_quotes.json
new file mode 100644
index 0000000..fd68956
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_accentuated_char_no_quotes.json
@@ -0,0 +1 @@
+[é]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_backslash_00.json b/test/data/nst_json_testsuite2/test_parsing/n_string_backslash_00.json
new file mode 100644
index 0000000..b5bf267
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_backslash_00.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_escape_x.json b/test/data/nst_json_testsuite2/test_parsing/n_string_escape_x.json
new file mode 100644
index 0000000..fae2919
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_escape_x.json
@@ -0,0 +1 @@
+["\x00"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_backslash_bad.json b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_backslash_bad.json
new file mode 100755
index 0000000..016fcb4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_backslash_bad.json
@@ -0,0 +1 @@
+["\\\"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_ctrl_char_tab.json b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_ctrl_char_tab.json
new file mode 100644
index 0000000..f35ea38
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_ctrl_char_tab.json
@@ -0,0 +1 @@
+["\ "]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_emoji.json b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_emoji.json
new file mode 100644
index 0000000..a277754
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_escaped_emoji.json
@@ -0,0 +1 @@
+["\๐"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escape.json
new file mode 100755
index 0000000..3415c33
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escape.json
@@ -0,0 +1 @@
+["\"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escaped_character.json b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escaped_character.json
new file mode 100755
index 0000000..0f2197e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escaped_character.json
@@ -0,0 +1 @@
+["\u00A"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate.json b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate.json
new file mode 100755
index 0000000..75504a6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate.json
@@ -0,0 +1 @@
+["\uD834\uDd"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate_escape_invalid.json b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate_escape_invalid.json
new file mode 100755
index 0000000..bd96560
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate_escape_invalid.json
@@ -0,0 +1 @@
+["\uD800\uD800\x"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_invalid-utf-8-in-escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid-utf-8-in-escape.json
new file mode 100644
index 0000000..0c43006
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid-utf-8-in-escape.json
@@ -0,0 +1 @@
+["\uå"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_backslash_esc.json b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_backslash_esc.json
new file mode 100755
index 0000000..d1eb609
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_backslash_esc.json
@@ -0,0 +1 @@
+["\a"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_unicode_escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_unicode_escape.json
new file mode 100644
index 0000000..7608cb6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_unicode_escape.json
@@ -0,0 +1 @@
+["\uqqqq"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_utf8_after_escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_utf8_after_escape.json
new file mode 100644
index 0000000..2f757a2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_invalid_utf8_after_escape.json
@@ -0,0 +1 @@
+["\å"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_leading_uescaped_thinspace.json b/test/data/nst_json_testsuite2/test_parsing/n_string_leading_uescaped_thinspace.json
new file mode 100755
index 0000000..7b297c6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_leading_uescaped_thinspace.json
@@ -0,0 +1 @@
+[\u0020"asd"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_no_quotes_with_bad_escape.json b/test/data/nst_json_testsuite2/test_parsing/n_string_no_quotes_with_bad_escape.json
new file mode 100644
index 0000000..01bc70a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_no_quotes_with_bad_escape.json
@@ -0,0 +1 @@
+[\n]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_single_doublequote.json b/test/data/nst_json_testsuite2/test_parsing/n_string_single_doublequote.json
new file mode 100755
index 0000000..9d68933
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_single_doublequote.json
@@ -0,0 +1 @@
+"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_single_quote.json b/test/data/nst_json_testsuite2/test_parsing/n_string_single_quote.json
new file mode 100644
index 0000000..caff239
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_single_quote.json
@@ -0,0 +1 @@
+['single quote']
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_single_string_no_double_quotes.json b/test/data/nst_json_testsuite2/test_parsing/n_string_single_string_no_double_quotes.json
new file mode 100755
index 0000000..f2ba8f8
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_single_string_no_double_quotes.json
@@ -0,0 +1 @@
+abc
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_start_escape_unclosed.json b/test/data/nst_json_testsuite2/test_parsing/n_string_start_escape_unclosed.json
new file mode 100644
index 0000000..db62a46
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_start_escape_unclosed.json
@@ -0,0 +1 @@
+["\
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_crtl_char.json b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_crtl_char.json
new file mode 100755
index 0000000..9f21348
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_crtl_char.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_newline.json b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_newline.json
new file mode 100644
index 0000000..700d360
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_newline.json
@@ -0,0 +1,2 @@
+["new
+line"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_tab.json b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_tab.json
new file mode 100644
index 0000000..160264a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_tab.json
@@ -0,0 +1 @@
+[" "]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_unicode_CapitalU.json b/test/data/nst_json_testsuite2/test_parsing/n_string_unicode_CapitalU.json
new file mode 100644
index 0000000..17332bb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_unicode_CapitalU.json
@@ -0,0 +1 @@
+"\UA66D"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_string_with_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_string_with_trailing_garbage.json
new file mode 100644
index 0000000..efe3bd2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_string_with_trailing_garbage.json
@@ -0,0 +1 @@
+""x
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_100000_opening_arrays.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_100000_opening_arrays.json
new file mode 100644
index 0000000..a4823ee
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_100000_opening_arrays.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_U+2060_word_joined.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_U+2060_word_joined.json
new file mode 100644
index 0000000..81156a6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_U+2060_word_joined.json
@@ -0,0 +1 @@
+[โ ]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_UTF8_BOM_no_data.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_UTF8_BOM_no_data.json
new file mode 100755
index 0000000..5f28270
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_UTF8_BOM_no_data.json
@@ -0,0 +1 @@
+๏ปฟ
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_..json b/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_..json
new file mode 100755
index 0000000..a56fef0
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_..json
@@ -0,0 +1 @@
+<.>
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_null.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_null.json
new file mode 100755
index 0000000..617f262
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_null.json
@@ -0,0 +1 @@
+[<null>]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_array_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_trailing_garbage.json
new file mode 100644
index 0000000..5a745e6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_trailing_garbage.json
@@ -0,0 +1 @@
+[1]x
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_extra_array_close.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_extra_array_close.json
new file mode 100755
index 0000000..6cfb139
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_extra_array_close.json
@@ -0,0 +1 @@
+[1]]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_unclosed_string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_unclosed_string.json
new file mode 100755
index 0000000..ba6b178
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_unclosed_string.json
@@ -0,0 +1 @@
+["asd]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_ascii-unicode-identifier.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_ascii-unicode-identifier.json
new file mode 100644
index 0000000..ef2ab62
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_ascii-unicode-identifier.json
@@ -0,0 +1 @@
+aå
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_capitalized_True.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_capitalized_True.json
new file mode 100755
index 0000000..7cd8846
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_capitalized_True.json
@@ -0,0 +1 @@
+[True]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_close_unopened_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_close_unopened_array.json
new file mode 100755
index 0000000..d2af0c6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_close_unopened_array.json
@@ -0,0 +1 @@
+1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_comma_instead_of_closing_brace.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_comma_instead_of_closing_brace.json
new file mode 100644
index 0000000..ac61b82
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_comma_instead_of_closing_brace.json
@@ -0,0 +1 @@
+{"x": true,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_double_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_double_array.json
new file mode 100755
index 0000000..058d162
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_double_array.json
@@ -0,0 +1 @@
+[][]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_end_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_end_array.json
new file mode 100644
index 0000000..54caf60
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_end_array.json
@@ -0,0 +1 @@
+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_incomplete_UTF8_BOM.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_incomplete_UTF8_BOM.json
new file mode 100755
index 0000000..bfcdd51
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_incomplete_UTF8_BOM.json
@@ -0,0 +1 @@
+ï»{}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-invalid-utf-8.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-invalid-utf-8.json
new file mode 100644
index 0000000..8b1296c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-invalid-utf-8.json
@@ -0,0 +1 @@
+å
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-open-bracket.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-open-bracket.json
new file mode 100644
index 0000000..8e2f0be
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_lone-open-bracket.json
@@ -0,0 +1 @@
+[
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_no_data.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_no_data.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_no_data.json
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_null-byte-outside-string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_null-byte-outside-string.json
new file mode 100644
index 0000000..326db14
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_null-byte-outside-string.json
Binary files differ
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_number_with_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_number_with_trailing_garbage.json
new file mode 100644
index 0000000..0746539
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_number_with_trailing_garbage.json
@@ -0,0 +1 @@
+2@
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_object_followed_by_closing_object.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_followed_by_closing_object.json
new file mode 100644
index 0000000..aa9ebae
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_followed_by_closing_object.json
@@ -0,0 +1 @@
+{}}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_object_unclosed_no_value.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_unclosed_no_value.json
new file mode 100644
index 0000000..17d0451
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_unclosed_no_value.json
@@ -0,0 +1 @@
+{"":
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_comment.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_comment.json
new file mode 100644
index 0000000..ed1b569
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_comment.json
@@ -0,0 +1 @@
+{"a":/*comment*/"b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_trailing_garbage.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_trailing_garbage.json
new file mode 100644
index 0000000..9ca2336
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_trailing_garbage.json
@@ -0,0 +1 @@
+{"a": true} "x"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_apostrophe.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_apostrophe.json
new file mode 100644
index 0000000..8bebe3a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_apostrophe.json
@@ -0,0 +1 @@
+['
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_comma.json
new file mode 100644
index 0000000..6295fdc
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_comma.json
@@ -0,0 +1 @@
+[,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_object.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_object.json
new file mode 100644
index 0000000..e870445
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_object.json
@@ -0,0 +1 @@
+[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_object.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_object.json
new file mode 100644
index 0000000..7a63c8c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_object.json
@@ -0,0 +1 @@
+[{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_string.json
new file mode 100644
index 0000000..9822a6b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_string.json
@@ -0,0 +1 @@
+["a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_string.json
new file mode 100644
index 0000000..42a6193
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_string.json
@@ -0,0 +1 @@
+["a"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object.json
new file mode 100644
index 0000000..81750b9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object.json
@@ -0,0 +1 @@
+{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_close_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_close_array.json
new file mode 100755
index 0000000..eebc700
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_close_array.json
@@ -0,0 +1 @@
+{]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_comma.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_comma.json
new file mode 100644
index 0000000..47bc910
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_comma.json
@@ -0,0 +1 @@
+{,
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_array.json
new file mode 100644
index 0000000..381ede5
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_array.json
@@ -0,0 +1 @@
+{[
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_string.json
new file mode 100644
index 0000000..328c30c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_string.json
@@ -0,0 +1 @@
+{"a
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_string_with_apostrophes.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_string_with_apostrophes.json
new file mode 100644
index 0000000..9dba170
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_string_with_apostrophes.json
@@ -0,0 +1 @@
+{'a'
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_open_open.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_open.json
new file mode 100644
index 0000000..841fd5f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_open_open.json
@@ -0,0 +1 @@
+["\{["\{["\{["\{
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_single_eacute.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_single_eacute.json
new file mode 100644
index 0000000..92a39f3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_single_eacute.json
@@ -0,0 +1 @@
+é
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_single_star.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_single_star.json
new file mode 100755
index 0000000..f59ec20
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_single_star.json
@@ -0,0 +1 @@
+*
\ No newline at end of file
diff --git "a/test/data/nst_json_testsuite2/test_parsing/n_structure_trailing_\043.json" "b/test/data/nst_json_testsuite2/test_parsing/n_structure_trailing_\043.json"
new file mode 100644
index 0000000..8986110
--- /dev/null
+++ "b/test/data/nst_json_testsuite2/test_parsing/n_structure_trailing_\043.json"
@@ -0,0 +1 @@
+{"a":"b"}#{}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_uescaped_LF_before_string.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_uescaped_LF_before_string.json
new file mode 100755
index 0000000..df2f0f2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_uescaped_LF_before_string.json
@@ -0,0 +1 @@
+[\u000A""]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array.json
new file mode 100755
index 0000000..1120951
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array.json
@@ -0,0 +1 @@
+[1
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_partial_null.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_partial_null.json
new file mode 100644
index 0000000..0d59176
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_partial_null.json
@@ -0,0 +1 @@
+[ false, nul
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_false.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_false.json
new file mode 100644
index 0000000..a2ff850
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_false.json
@@ -0,0 +1 @@
+[ true, fals
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_true.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_true.json
new file mode 100644
index 0000000..3149e8f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_true.json
@@ -0,0 +1 @@
+[ false, tru
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_object.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_object.json
new file mode 100755
index 0000000..694d69d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_object.json
@@ -0,0 +1 @@
+{"asd":"asd"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_unicode-identifier.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_unicode-identifier.json
new file mode 100644
index 0000000..7284aea
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_unicode-identifier.json
@@ -0,0 +1 @@
+å
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_U+2060_word_joiner.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_U+2060_word_joiner.json
new file mode 100755
index 0000000..81156a6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_U+2060_word_joiner.json
@@ -0,0 +1 @@
+[โ ]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_formfeed.json b/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_formfeed.json
new file mode 100755
index 0000000..a9ea535
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_formfeed.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json b/test/data/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json
new file mode 100755
index 0000000..5822907
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json
@@ -0,0 +1 @@
+[[] ]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_empty-string.json b/test/data/nst_json_testsuite2/test_parsing/y_array_empty-string.json
new file mode 100644
index 0000000..93b6be2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_empty-string.json
@@ -0,0 +1 @@
+[""]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_empty.json b/test/data/nst_json_testsuite2/test_parsing/y_array_empty.json
new file mode 100755
index 0000000..0637a08
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_empty.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json b/test/data/nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json
new file mode 100755
index 0000000..eac5f7b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json
@@ -0,0 +1 @@
+["a"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_false.json b/test/data/nst_json_testsuite2/test_parsing/y_array_false.json
new file mode 100644
index 0000000..67b2f07
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_false.json
@@ -0,0 +1 @@
+[false]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_heterogeneous.json b/test/data/nst_json_testsuite2/test_parsing/y_array_heterogeneous.json
new file mode 100755
index 0000000..d3c1e26
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_heterogeneous.json
@@ -0,0 +1 @@
+[null, 1, "1", {}]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_null.json b/test/data/nst_json_testsuite2/test_parsing/y_array_null.json
new file mode 100644
index 0000000..500db4a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_null.json
@@ -0,0 +1 @@
+[null]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json b/test/data/nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json
new file mode 100644
index 0000000..9948255
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json
@@ -0,0 +1,2 @@
+[1
+]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_with_leading_space.json b/test/data/nst_json_testsuite2/test_parsing/y_array_with_leading_space.json
new file mode 100755
index 0000000..18bfe64
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_with_leading_space.json
@@ -0,0 +1 @@
+ [1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_with_several_null.json b/test/data/nst_json_testsuite2/test_parsing/y_array_with_several_null.json
new file mode 100755
index 0000000..99f6c5d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_with_several_null.json
@@ -0,0 +1 @@
+[1,null,null,null,2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json b/test/data/nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json
new file mode 100755
index 0000000..de9e7a9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json
@@ -0,0 +1 @@
+[2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number.json b/test/data/nst_json_testsuite2/test_parsing/y_number.json
new file mode 100644
index 0000000..e5f5cc3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number.json
@@ -0,0 +1 @@
+[123e65]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_0e+1.json b/test/data/nst_json_testsuite2/test_parsing/y_number_0e+1.json
new file mode 100755
index 0000000..d1d3967
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_0e+1.json
@@ -0,0 +1 @@
+[0e+1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_0e1.json b/test/data/nst_json_testsuite2/test_parsing/y_number_0e1.json
new file mode 100755
index 0000000..3283a79
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_0e1.json
@@ -0,0 +1 @@
+[0e1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_after_space.json b/test/data/nst_json_testsuite2/test_parsing/y_number_after_space.json
new file mode 100644
index 0000000..623570d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_after_space.json
@@ -0,0 +1 @@
+[ 4]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_double_close_to_zero.json b/test/data/nst_json_testsuite2/test_parsing/y_number_double_close_to_zero.json
new file mode 100755
index 0000000..96555ff
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_double_close_to_zero.json
@@ -0,0 +1 @@
+[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_int_with_exp.json b/test/data/nst_json_testsuite2/test_parsing/y_number_int_with_exp.json
new file mode 100755
index 0000000..a4ca9e7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_int_with_exp.json
@@ -0,0 +1 @@
+[20e1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_minus_zero.json b/test/data/nst_json_testsuite2/test_parsing/y_number_minus_zero.json
new file mode 100755
index 0000000..37af131
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_minus_zero.json
@@ -0,0 +1 @@
+[-0]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_negative_int.json b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_int.json
new file mode 100644
index 0000000..8e30f8b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_int.json
@@ -0,0 +1 @@
+[-123]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_negative_one.json b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_one.json
new file mode 100644
index 0000000..99d21a2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_one.json
@@ -0,0 +1 @@
+[-1]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_negative_zero.json b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_zero.json
new file mode 100644
index 0000000..37af131
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_negative_zero.json
@@ -0,0 +1 @@
+[-0]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json
new file mode 100644
index 0000000..6edbdfc
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json
@@ -0,0 +1 @@
+[1E22]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json
new file mode 100644
index 0000000..0a01bd3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json
@@ -0,0 +1 @@
+[1E-2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json
new file mode 100644
index 0000000..5a8fc09
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json
@@ -0,0 +1 @@
+[1E+2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_exponent.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_exponent.json
new file mode 100644
index 0000000..da2522d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_exponent.json
@@ -0,0 +1 @@
+[123e45]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json
new file mode 100644
index 0000000..3944a7a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json
@@ -0,0 +1 @@
+[123.456e78]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json
new file mode 100644
index 0000000..ca40d3c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json
@@ -0,0 +1 @@
+[1e-2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json b/test/data/nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json
new file mode 100644
index 0000000..343601d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json
@@ -0,0 +1 @@
+[1e+2]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_simple_int.json b/test/data/nst_json_testsuite2/test_parsing/y_number_simple_int.json
new file mode 100644
index 0000000..e47f69a
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_simple_int.json
@@ -0,0 +1 @@
+[123]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_number_simple_real.json b/test/data/nst_json_testsuite2/test_parsing/y_number_simple_real.json
new file mode 100644
index 0000000..b02878e
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_number_simple_real.json
@@ -0,0 +1 @@
+[123.456789]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object.json b/test/data/nst_json_testsuite2/test_parsing/y_object.json
new file mode 100755
index 0000000..78262ed
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object.json
@@ -0,0 +1 @@
+{"asd":"sdf", "dfg":"fgh"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_basic.json b/test/data/nst_json_testsuite2/test_parsing/y_object_basic.json
new file mode 100755
index 0000000..646bbe7
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_basic.json
@@ -0,0 +1 @@
+{"asd":"sdf"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json b/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json
new file mode 100755
index 0000000..bbc2e1c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json
@@ -0,0 +1 @@
+{"a":"b","a":"c"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json b/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json
new file mode 100755
index 0000000..211581c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json
@@ -0,0 +1 @@
+{"a":"b","a":"b"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_empty.json b/test/data/nst_json_testsuite2/test_parsing/y_object_empty.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_empty.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_empty_key.json b/test/data/nst_json_testsuite2/test_parsing/y_object_empty_key.json
new file mode 100755
index 0000000..c0013d3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_empty_key.json
@@ -0,0 +1 @@
+{"":0}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_escaped_null_in_key.json b/test/data/nst_json_testsuite2/test_parsing/y_object_escaped_null_in_key.json
new file mode 100644
index 0000000..593f0f6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_escaped_null_in_key.json
@@ -0,0 +1 @@
+{"foo\u0000bar": 42}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_extreme_numbers.json b/test/data/nst_json_testsuite2/test_parsing/y_object_extreme_numbers.json
new file mode 100644
index 0000000..a0d3531
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_extreme_numbers.json
@@ -0,0 +1 @@
+{ "min": -1.0e+28, "max": 1.0e+28 }
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_long_strings.json b/test/data/nst_json_testsuite2/test_parsing/y_object_long_strings.json
new file mode 100644
index 0000000..bdc4a08
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_long_strings.json
@@ -0,0 +1 @@
+{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_simple.json b/test/data/nst_json_testsuite2/test_parsing/y_object_simple.json
new file mode 100644
index 0000000..dacac91
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_simple.json
@@ -0,0 +1 @@
+{"a":[]}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_string_unicode.json b/test/data/nst_json_testsuite2/test_parsing/y_object_string_unicode.json
new file mode 100644
index 0000000..8effdb2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_string_unicode.json
@@ -0,0 +1 @@
+{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_object_with_newlines.json b/test/data/nst_json_testsuite2/test_parsing/y_object_with_newlines.json
new file mode 100644
index 0000000..246ec6b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_object_with_newlines.json
@@ -0,0 +1,3 @@
+{
+"a": "b"
+}
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json b/test/data/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json
new file mode 100755
index 0000000..9967dde
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json
@@ -0,0 +1 @@
+["\u0060\u012a\u12AB"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json b/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json
new file mode 100755
index 0000000..996875c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json
@@ -0,0 +1 @@
+["\uD801\udc37"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json b/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json
new file mode 100755
index 0000000..3401021
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json
@@ -0,0 +1 @@
+["\ud83d\ude39\ud83d\udc8d"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json b/test/data/nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json
new file mode 100644
index 0000000..7f49553
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json
@@ -0,0 +1 @@
+["\"\\\/\b\f\n\r\t"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json b/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json
new file mode 100755
index 0000000..d4439ed
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json
@@ -0,0 +1 @@
+["\\u0000"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json b/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json
new file mode 100644
index 0000000..ae03243
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json
@@ -0,0 +1 @@
+["\""]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_comments.json b/test/data/nst_json_testsuite2/test_parsing/y_string_comments.json
new file mode 100644
index 0000000..2260c20
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_comments.json
@@ -0,0 +1 @@
+["a/*b*/c/*d//e"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_a.json b/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_a.json
new file mode 100644
index 0000000..6715d6f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_a.json
@@ -0,0 +1 @@
+["\\a"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_n.json b/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_n.json
new file mode 100644
index 0000000..44ca56c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_n.json
@@ -0,0 +1 @@
+["\\n"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json b/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json
new file mode 100644
index 0000000..5b014a9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json
@@ -0,0 +1 @@
+["\u0012"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json b/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json
new file mode 100755
index 0000000..2ff52e2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json
@@ -0,0 +1 @@
+["\uFFFF"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_in_array.json b/test/data/nst_json_testsuite2/test_parsing/y_string_in_array.json
new file mode 100755
index 0000000..21d7ae4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_in_array.json
@@ -0,0 +1 @@
+["asd"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json b/test/data/nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json
new file mode 100755
index 0000000..9e1887c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json
@@ -0,0 +1 @@
+[ "asd"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json b/test/data/nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json
new file mode 100644
index 0000000..3919cef
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json
@@ -0,0 +1 @@
+["\uDBFF\uDFFF"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json b/test/data/nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json
new file mode 100644
index 0000000..2085ab1
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json
@@ -0,0 +1 @@
+["new\u00A0line"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json b/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json
new file mode 100755
index 0000000..059e4d9
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json
@@ -0,0 +1 @@
+["๔ฟฟ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json b/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json
new file mode 100755
index 0000000..4c913bd
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json
@@ -0,0 +1 @@
+["๏ฟฟ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_null_escape.json b/test/data/nst_json_testsuite2/test_parsing/y_string_null_escape.json
new file mode 100644
index 0000000..c1ad844
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_null_escape.json
@@ -0,0 +1 @@
+["\u0000"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json b/test/data/nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json
new file mode 100644
index 0000000..1571859
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json
@@ -0,0 +1 @@
+["\u002c"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_pi.json b/test/data/nst_json_testsuite2/test_parsing/y_string_pi.json
new file mode 100644
index 0000000..9df11ae
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_pi.json
@@ -0,0 +1 @@
+["π"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json b/test/data/nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json
new file mode 100755
index 0000000..10a33a1
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json
@@ -0,0 +1 @@
+["๐ฟฟ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_simple_ascii.json b/test/data/nst_json_testsuite2/test_parsing/y_string_simple_ascii.json
new file mode 100644
index 0000000..8cadf7d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_simple_ascii.json
@@ -0,0 +1 @@
+["asd "]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_space.json b/test/data/nst_json_testsuite2/test_parsing/y_string_space.json
new file mode 100644
index 0000000..efd782c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_space.json
@@ -0,0 +1 @@
+" "
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json b/test/data/nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json
new file mode 100755
index 0000000..7620b66
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json
@@ -0,0 +1 @@
+["\uD834\uDd1e"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json b/test/data/nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json
new file mode 100644
index 0000000..108f1d6
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json
@@ -0,0 +1 @@
+["\u0821"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json b/test/data/nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json
new file mode 100644
index 0000000..461503c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json
@@ -0,0 +1 @@
+["\u0123"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json b/test/data/nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json
new file mode 100755
index 0000000..897b602
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json
@@ -0,0 +1 @@
+["โจ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json b/test/data/nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json
new file mode 100755
index 0000000..8cd998c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json
@@ -0,0 +1 @@
+["โฉ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_uEscape.json b/test/data/nst_json_testsuite2/test_parsing/y_string_uEscape.json
new file mode 100755
index 0000000..f7b41a0
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_uEscape.json
@@ -0,0 +1 @@
+["\u0061\u30af\u30EA\u30b9"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json b/test/data/nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json
new file mode 100644
index 0000000..3a5a220
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json
@@ -0,0 +1 @@
+["new\u000Aline"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json
new file mode 100755
index 0000000..7d064f4
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json
@@ -0,0 +1 @@
+[""]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode.json
new file mode 100644
index 0000000..3598095
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode.json
@@ -0,0 +1 @@
+["\uA66D"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json
new file mode 100755
index 0000000..0bb3b51
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json
@@ -0,0 +1 @@
+["\u005C"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_2.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_2.json
new file mode 100644
index 0000000..a7dcb97
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_2.json
@@ -0,0 +1 @@
+["โใดโ"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json
new file mode 100644
index 0000000..9a8370b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json
@@ -0,0 +1 @@
+["\uDBFF\uDFFE"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json
new file mode 100644
index 0000000..c51f8ae
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json
@@ -0,0 +1 @@
+["\uD83F\uDFFE"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json
new file mode 100644
index 0000000..626d5f8
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json
@@ -0,0 +1 @@
+["\u200B"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json
new file mode 100644
index 0000000..1e23972
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json
@@ -0,0 +1 @@
+["\u2064"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json
new file mode 100644
index 0000000..18ef151
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json
@@ -0,0 +1 @@
+["\uFDD0"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json
new file mode 100644
index 0000000..13d261f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json
@@ -0,0 +1 @@
+["\uFFFE"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json
new file mode 100755
index 0000000..4e62578
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json
@@ -0,0 +1 @@
+["\u0022"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_utf8.json b/test/data/nst_json_testsuite2/test_parsing/y_string_utf8.json
new file mode 100644
index 0000000..4087843
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_utf8.json
@@ -0,0 +1 @@
+["€๐"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_string_with_del_character.json b/test/data/nst_json_testsuite2/test_parsing/y_string_with_del_character.json
new file mode 100755
index 0000000..8bd2490
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_string_with_del_character.json
@@ -0,0 +1 @@
+["aa"]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_false.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_false.json
new file mode 100644
index 0000000..02e4a84
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_false.json
@@ -0,0 +1 @@
+false
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_int.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_int.json
new file mode 100755
index 0000000..f70d7bb
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_int.json
@@ -0,0 +1 @@
+42
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_negative_real.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_negative_real.json
new file mode 100755
index 0000000..b5135a2
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_negative_real.json
@@ -0,0 +1 @@
+-0.1
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_null.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_null.json
new file mode 100644
index 0000000..ec747fa
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_null.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_string.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_string.json
new file mode 100755
index 0000000..b6e982c
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_string.json
@@ -0,0 +1 @@
+"asd"
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_true.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_true.json
new file mode 100755
index 0000000..f32a580
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_true.json
@@ -0,0 +1 @@
+true
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_string_empty.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_string_empty.json
new file mode 100644
index 0000000..3cc762b
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_string_empty.json
@@ -0,0 +1 @@
+""
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_trailing_newline.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_trailing_newline.json
new file mode 100644
index 0000000..0c3426d
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_trailing_newline.json
@@ -0,0 +1 @@
+["a"]
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_true_in_array.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_true_in_array.json
new file mode 100644
index 0000000..de601e3
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_true_in_array.json
@@ -0,0 +1 @@
+[true]
\ No newline at end of file
diff --git a/test/data/nst_json_testsuite2/test_parsing/y_structure_whitespace_array.json b/test/data/nst_json_testsuite2/test_parsing/y_structure_whitespace_array.json
new file mode 100644
index 0000000..2bedf7f
--- /dev/null
+++ b/test/data/nst_json_testsuite2/test_parsing/y_structure_whitespace_array.json
@@ -0,0 +1 @@
+ []
\ No newline at end of file
diff --git a/test/src/fuzzer-driver_afl.cpp b/test/src/fuzzer-driver_afl.cpp
index bc8b3e7..dd01b74 100644
--- a/test/src/fuzzer-driver_afl.cpp
+++ b/test/src/fuzzer-driver_afl.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a driver for American Fuzzy Lop (afl-fuzz). It relies on
diff --git a/test/src/fuzzer-parse_cbor.cpp b/test/src/fuzzer-parse_cbor.cpp
index 0520ae7..20050eb 100644
--- a/test/src/fuzzer-parse_cbor.cpp
+++ b/test/src/fuzzer-parse_cbor.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte
@@ -58,6 +58,10 @@
{
// type errors can occur during parsing, too
}
+ catch (const json::out_of_range&)
+ {
+ // out of range errors can occur during parsing, too
+ }
// return 0 - non-zero return values are reserved for future use
return 0;
diff --git a/test/src/fuzzer-parse_json.cpp b/test/src/fuzzer-parse_json.cpp
index 2d13c26..d159a70 100644
--- a/test/src/fuzzer-parse_json.cpp
+++ b/test/src/fuzzer-parse_json.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte
@@ -63,6 +63,10 @@
{
// parse errors are ok, because input may be random bytes
}
+ catch (const json::out_of_range&)
+ {
+ // out of range errors may happen if provided sizes are excessive
+ }
// return 0 - non-zero return values are reserved for future use
return 0;
diff --git a/test/src/fuzzer-parse_msgpack.cpp b/test/src/fuzzer-parse_msgpack.cpp
index 6f98409..0421e13 100644
--- a/test/src/fuzzer-parse_msgpack.cpp
+++ b/test/src/fuzzer-parse_msgpack.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte
@@ -58,6 +58,10 @@
{
// type errors can occur during parsing, too
}
+ catch (const json::out_of_range&)
+ {
+ // out of range errors may happen if provided sizes are excessive
+ }
// return 0 - non-zero return values are reserved for future use
return 0;
diff --git a/test/src/fuzzer-parse_ubjson.cpp b/test/src/fuzzer-parse_ubjson.cpp
index 1d7c936..d20f0fe 100644
--- a/test/src/fuzzer-parse_ubjson.cpp
+++ b/test/src/fuzzer-parse_ubjson.cpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (fuzz test support)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
This file implements a parser test suitable for fuzz testing. Given a byte
diff --git a/test/src/unit-algorithms.cpp b/test/src/unit-algorithms.cpp
index 6579c4a..c525ff1 100644
--- a/test/src/unit-algorithms.cpp
+++ b/test/src/unit-algorithms.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp
index debe69a..8cf5160 100644
--- a/test/src/unit-allocator.cpp
+++ b/test/src/unit-allocator.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -175,29 +176,6 @@
CHECK_THROWS_AS(my_json::json_value(v), std::bad_alloc&);
next_construct_fails = false;
}
-
- /*
- SECTION("json_value(const object_t&)")
- {
- next_construct_fails = false;
- my_json::object_t v {{"foo", "bar"}};
- CHECK_NOTHROW(my_json::json_value j(v));
- next_construct_fails = true;
- CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&);
- next_construct_fails = false;
- }
- */
- /*
- SECTION("json_value(const array_t&)")
- {
- next_construct_fails = false;
- my_json::array_t v = {"foo", "bar", "baz"};
- CHECK_NOTHROW(my_json::json_value j(v));
- next_construct_fails = true;
- CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc&);
- next_construct_fails = false;
- }
- */
}
SECTION("class basic_json")
diff --git a/test/src/unit-alt-string.cpp b/test/src/unit-alt-string.cpp
index 36c8b83..356835c 100644
--- a/test/src/unit-alt-string.cpp
+++ b/test/src/unit-alt-string.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2018 Vitaliy Manushkin <agri@akamo.info>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,6 +33,12 @@
#include <string>
#include <utility>
+
+/* forward declarations */
+class alt_string;
+bool operator<(const char* op1, const alt_string& op2);
+
+
/*
* This is virtually a string class.
* It covers std::string under the hood.
@@ -59,17 +66,27 @@
}
template <typename op_type>
- bool operator==(op_type&& op) const
+ bool operator==(const op_type& op) const
{
return str_impl == op;
}
+ bool operator==(const alt_string& op) const
+ {
+ return str_impl == op.str_impl;
+ }
+
template <typename op_type>
- bool operator!=(op_type&& op) const
+ bool operator!=(const op_type& op) const
{
return str_impl != op;
}
+ bool operator!=(const alt_string& op) const
+ {
+ return str_impl != op.str_impl;
+ }
+
std::size_t size() const noexcept
{
return str_impl.size();
@@ -86,7 +103,7 @@
}
template <typename op_type>
- bool operator<(op_type&& op) const
+ bool operator<(const op_type& op) const
{
return str_impl < op;
}
@@ -133,6 +150,8 @@
private:
std::string str_impl;
+
+ friend bool ::operator<(const char*, const alt_string&);
};
@@ -148,6 +167,12 @@
nlohmann::adl_serializer >;
+bool operator<(const char* op1, const alt_string& op2)
+{
+ return op1 < op2.str_impl;
+}
+
+
TEST_CASE("alternative string type")
{
@@ -209,4 +234,34 @@
alt_string dump = doc.dump();
CHECK(dump == R"({"foo":"bar"})");
}
+
+ SECTION("equality")
+ {
+ alt_json doc;
+ doc["Who are you?"] = "I'm Batman";
+
+ CHECK("I'm Batman" == doc["Who are you?"]);
+ CHECK(doc["Who are you?"] == "I'm Batman");
+ CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
+ CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
+
+ CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
+ CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
+ CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
+ CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
+
+ {
+ const alt_json& const_doc = doc;
+
+ CHECK("I'm Batman" == const_doc["Who are you?"]);
+ CHECK(const_doc["Who are you?"] == "I'm Batman");
+ CHECK_FALSE("I'm Batman" != const_doc["Who are you?"]);
+ CHECK_FALSE(const_doc["Who are you?"] != "I'm Batman");
+
+ CHECK("I'm Bruce Wayne" != const_doc["Who are you?"]);
+ CHECK(const_doc["Who are you?"] != "I'm Bruce Wayne");
+ CHECK_FALSE("I'm Bruce Wayne" == const_doc["Who are you?"]);
+ CHECK_FALSE(const_doc["Who are you?"] == "I'm Bruce Wayne");
+ }
+ }
}
diff --git a/test/src/unit-capacity.cpp b/test/src/unit-capacity.cpp
index 47ac03c..718d102 100644
--- a/test/src/unit-capacity.cpp
+++ b/test/src/unit-capacity.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp
index 6b9eac5..525c763 100644
--- a/test/src/unit-cbor.cpp
+++ b/test/src/unit-cbor.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -33,6 +34,76 @@
#include <fstream>
+class SaxCountdown
+{
+ public:
+ explicit SaxCountdown(const int count) : events_left(count)
+ {}
+
+ bool null()
+ {
+ return events_left-- > 0;
+ }
+
+ bool boolean(bool)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_integer(json::number_integer_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_unsigned(json::number_unsigned_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_float(json::number_float_t, const std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool string(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_object(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool key(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_object()
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_array(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_array()
+ {
+ return events_left-- > 0;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const json::exception&)
+ {
+ return false;
+ }
+
+ private:
+ int events_left = 0;
+};
+
TEST_CASE("CBOR")
{
SECTION("individual values")
@@ -54,6 +125,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("boolean")
@@ -67,6 +139,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("false")
@@ -78,6 +151,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -142,6 +216,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -190,6 +265,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -225,6 +301,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -241,6 +318,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("-256..-24")
@@ -271,6 +349,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -300,6 +379,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -330,6 +410,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -362,6 +443,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -396,6 +478,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -438,6 +521,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -488,10 +572,10 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
- /*
SECTION("-32768..-129 (int 16)")
{
for (int16_t i = -32768; i <= -129; ++i)
@@ -517,14 +601,13 @@
// check individual bytes
CHECK(result[0] == 0xd1);
- int16_t restored = (result[1] << 8) + result[2];
+ int16_t restored = static_cast<int16_t>((result[1] << 8) + result[2]);
CHECK(restored == i);
// roundtrip
CHECK(json::from_msgpack(result) == j);
}
}
- */
}
SECTION("unsigned")
@@ -555,6 +638,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -587,6 +671,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -620,6 +705,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -661,6 +747,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -710,6 +797,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
}
@@ -730,6 +818,8 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
CHECK(json::from_cbor(result) == v);
+
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -742,12 +832,14 @@
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf9})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf9})),
"[json.exception.parse_error.110] parse error at 2: unexpected end of input");
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xf9}), true, false).is_discarded());
}
SECTION("only one byte follows")
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c})),
"[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xf9, 0x7c}), true, false).is_discarded());
}
}
@@ -868,6 +960,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -899,6 +992,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -931,6 +1025,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
@@ -965,6 +1060,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
}
@@ -980,6 +1076,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("[null]")
@@ -991,6 +1088,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("[1,2,3,4,5]")
@@ -1002,6 +1100,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("[[[[]]]]")
@@ -1013,6 +1112,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("array with uint16_t elements")
@@ -1027,6 +1127,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("array with uint32_t elements")
@@ -1043,29 +1144,8 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == 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")
@@ -1079,6 +1159,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("{\"\":null}")
@@ -1090,6 +1171,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
@@ -1104,6 +1186,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("object with uint8_t elements")
@@ -1130,6 +1213,7 @@
CHECK(result[1] == 0xff); // size byte (0xff)
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("object with uint16_t elements")
@@ -1158,6 +1242,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
SECTION("object with uint32_t elements")
@@ -1188,6 +1273,7 @@
// roundtrip
CHECK(json::from_cbor(result) == j);
+ CHECK(json::from_cbor(result, true, false) == j);
}
}
}
@@ -1229,6 +1315,7 @@
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>()),
"[json.exception.parse_error.110] parse error at 1: unexpected end of input");
+ CHECK(json::from_cbor(std::vector<uint8_t>(), true, false).is_discarded());
}
SECTION("too short byte vector")
@@ -1248,6 +1335,15 @@
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x62})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x62, 0x60})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x7F})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x82, 0x01})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0X61})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0X61})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x18})),
"[json.exception.parse_error.110] parse error at 2: unexpected end of input");
@@ -1279,6 +1375,49 @@
"[json.exception.parse_error.110] parse error at 8: unexpected end of input");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 9: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x62})),
+ "[json.exception.parse_error.110] parse error at 2: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x62, 0x60})),
+ "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x7F})),
+ "[json.exception.parse_error.110] parse error at 2: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60})),
+ "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x82, 0x01})),
+ "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01})),
+ "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5})),
+ "[json.exception.parse_error.110] parse error at 5: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0x61})),
+ "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61})),
+ "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x18}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x19}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x19, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1a}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x62}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x62, 0x60}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x7F}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x60}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x82, 0x01}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x9F, 0x01}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61, 0xF5}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xA1, 0x61, 0x61}), true, false).is_discarded());
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xBF, 0x61, 0x61}), true, false).is_discarded());
}
SECTION("unsupported bytes")
@@ -1288,9 +1427,12 @@
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1c})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1c})),
"[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0x1C");
+ CHECK(json::from_cbor(std::vector<uint8_t>({0x1c}), true, false).is_discarded());
+
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xf8})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xf8})),
"[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0xF8");
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xf8}), true, false).is_discarded());
}
SECTION("all unsupported bytes")
@@ -1340,6 +1482,7 @@
})
{
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
+ CHECK(json::from_cbor(std::vector<uint8_t>({static_cast<uint8_t>(byte)}), true, false).is_discarded());
}
}
}
@@ -1349,6 +1492,7 @@
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})),
"[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0xFF");
+ CHECK(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01}), true, false).is_discarded());
}
SECTION("strict mode")
@@ -1358,6 +1502,7 @@
{
const auto result = json::from_cbor(vec, false);
CHECK(result == json());
+ CHECK(not json::from_cbor(vec, false, false).is_discarded());
}
SECTION("strict mode")
@@ -1365,9 +1510,34 @@
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_cbor(vec),
"[json.exception.parse_error.110] parse error at 2: expected end of input");
+ CHECK(json::from_cbor(vec, true, false).is_discarded());
}
}
}
+
+ SECTION("SAX aborts")
+ {
+ SECTION("start_array(len)")
+ {
+ std::vector<uint8_t> v = {0x83, 0x01, 0x02, 0x03};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
+ }
+
+ SECTION("start_object(len)")
+ {
+ std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
+ }
+
+ SECTION("key()")
+ {
+ std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
+ SaxCountdown scp(1);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
+ }
+ }
}
// use this testcase outside [hide] to run it with Valgrind
@@ -1490,6 +1660,22 @@
{
SECTION("input from flynn")
{
+ // most of these are exluded due to differences in key order (not a real problem)
+ auto exclude_packed = std::set<std::string>
+ {
+ "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_testsuite/sample.json", // kills AppVeyor
+ "test/data/json_tests/pass1.json",
+ "test/data/regression/working_file.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_duplicated_key.json",
+ "test/data/nst_json_testsuite/test_parsing/y_object_long_strings.json",
+ };
+
for (std::string filename :
{
"test/data/json_nlohmann_tests/all_unicode.json",
@@ -1641,12 +1827,12 @@
{
CAPTURE(filename);
- // parse JSON file
- std::ifstream f_json(filename);
- json j1 = json::parse(f_json);
-
- SECTION("std::vector<uint8_t>")
+ SECTION(filename + ": std::vector<uint8_t>")
{
+ // 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(
@@ -1659,8 +1845,12 @@
CHECK(j1 == j2);
}
- SECTION("std::ifstream")
+ SECTION(filename + ": std::ifstream")
{
+ // 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);
json j2;
@@ -1670,8 +1860,12 @@
CHECK(j1 == j2);
}
- SECTION("uint8_t* and size")
+ SECTION(filename + ": uint8_t* and size")
{
+ // 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(
@@ -1684,19 +1878,26 @@
CHECK(j1 == j2);
}
- SECTION("output to output adapters")
+ SECTION(filename + ": output to output adapters")
{
+ // 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>());
- SECTION("std::vector<uint8_t>")
+ if (!exclude_packed.count(filename))
{
- std::vector<uint8_t> vec;
- json::to_cbor(j1, vec);
- CHECK(vec == packed);
+ SECTION(filename + ": output adapters: std::vector<uint8_t>")
+ {
+ std::vector<uint8_t> vec;
+ json::to_cbor(j1, vec);
+ CHECK(vec == packed);
+ }
}
}
}
diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp
index 8319fef..783eb04 100644
--- a/test/src/unit-class_const_iterator.cpp
+++ b/test/src/unit-class_const_iterator.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-class_iterator.cpp b/test/src/unit-class_iterator.cpp
index 484a49d..e8d530f 100644
--- a/test/src/unit-class_iterator.cpp
+++ b/test/src/unit-class_iterator.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp
index 164dc67..65859ad 100644
--- a/test/src/unit-class_lexer.cpp
+++ b/test/src/unit-class_lexer.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -173,15 +174,4 @@
s += "\"";
CHECK((scan_string(s.c_str()) == json::lexer::token_type::value_string));
}
-
- /* NOTE: to_unicode function has been removed
- SECTION("to_unicode")
- {
- // lexer to call to_unicode on
- json::lexer dummy_lexer("", 0);
- CHECK(dummy_lexer.to_unicode(0x1F4A9) == "๐ฉ");
- CHECK_THROWS_AS(dummy_lexer.to_unicode(0x200000), json::parse_error);
- CHECK_THROWS_WITH(dummy_lexer.to_unicode(0x200000), "[json.exception.parse_error.103] parse error: code points above 0x10FFFF are invalid");
- }
- */
}
diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp
index 29a948e..f9115f5 100644
--- a/test/src/unit-class_parser.cpp
+++ b/test/src/unit-class_parser.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -34,6 +35,170 @@
#include <valarray>
+class SaxEventLogger
+{
+ public:
+ bool null()
+ {
+ events.push_back("null()");
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ events.push_back(val ? "boolean(true)" : "boolean(false)");
+ return true;
+ }
+
+ bool number_integer(json::number_integer_t val)
+ {
+ events.push_back("number_integer(" + std::to_string(val) + ")");
+ return true;
+ }
+
+ bool number_unsigned(json::number_unsigned_t val)
+ {
+ events.push_back("number_unsigned(" + std::to_string(val) + ")");
+ return true;
+ }
+
+ bool number_float(json::number_float_t, const std::string& s)
+ {
+ events.push_back("number_float(" + s + ")");
+ return true;
+ }
+
+ bool string(std::string& val)
+ {
+ events.push_back("string(" + val + ")");
+ return true;
+ }
+
+ bool start_object(std::size_t elements)
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_object()");
+ }
+ else
+ {
+ events.push_back("start_object(" + std::to_string(elements) + ")");
+ }
+ return true;
+ }
+
+ bool key(std::string& val)
+ {
+ events.push_back("key(" + val + ")");
+ return true;
+ }
+
+ bool end_object()
+ {
+ events.push_back("end_object()");
+ return true;
+ }
+
+ bool start_array(std::size_t elements)
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_array()");
+ }
+ else
+ {
+ events.push_back("start_array(" + std::to_string(elements) + ")");
+ }
+ return true;
+ }
+
+ bool end_array()
+ {
+ events.push_back("end_array()");
+ return true;
+ }
+
+ bool parse_error(std::size_t position, const std::string&, const json::exception&)
+ {
+ errored = true;
+ events.push_back("parse_error(" + std::to_string(position) + ")");
+ return false;
+ }
+
+ std::vector<std::string> events;
+ bool errored = false;
+};
+
+class SaxCountdown : public nlohmann::json::json_sax_t
+{
+ public:
+ explicit SaxCountdown(const int count) : events_left(count)
+ {}
+
+ bool null() override
+ {
+ return events_left-- > 0;
+ }
+
+ bool boolean(bool) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_integer(json::number_integer_t) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_unsigned(json::number_unsigned_t) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_float(json::number_float_t, const std::string&) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool string(std::string&) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_object(std::size_t) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool key(std::string&) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_object() override
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_array(std::size_t) override
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_array() override
+ {
+ return events_left-- > 0;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const json::exception&) override
+ {
+ return false;
+ }
+
+ private:
+ int events_left = 0;
+};
+
json parser_helper(const std::string& s);
bool accept_helper(const std::string& s);
@@ -48,11 +213,18 @@
CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow));
CHECK(j_nothrow == j);
+ json j_sax;
+ nlohmann::detail::json_sax_dom_parser<json> sdp(j_sax);
+ json::sax_parse(s, &sdp);
+ CHECK(j_sax == j);
+
return j;
}
bool accept_helper(const std::string& s)
{
+ CAPTURE(s);
+
// 1. parse s without exceptions
json j;
CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j));
@@ -64,7 +236,23 @@
// 3. check if both approaches come to the same result
CHECK(ok_noexcept == ok_accept);
- // 4. return result
+ // 4. parse with SAX (compare with relaxed accept result)
+ SaxEventLogger el;
+ CHECK_NOTHROW(json::sax_parse(s, &el, json::input_format_t::json, false));
+ CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == not el.errored);
+
+ // 5. parse with simple callback
+ json::parser_callback_t cb = [](int, json::parse_event_t, json&)
+ {
+ return true;
+ };
+ json j_cb = json::parse(s, cb, false);
+ const bool ok_noexcept_cb = not j_cb.is_discarded();
+
+ // 6. check if this approach came to the same result
+ CHECK(ok_noexcept == ok_noexcept_cb);
+
+ // 7. return result
return ok_accept;
}
@@ -1472,4 +1660,100 @@
CHECK(j == json(true));
}
}
+
+ SECTION("improve test coverage")
+ {
+ SECTION("parser with callback")
+ {
+ json::parser_callback_t cb = [](int, json::parse_event_t, json&)
+ {
+ return true;
+ };
+
+ CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded());
+
+ CHECK_THROWS_AS(json::parse("{\"foo\": true:", cb), json::parse_error&);
+ CHECK_THROWS_WITH(json::parse("{\"foo\": true:", cb),
+ "[json.exception.parse_error.101] parse error at 13: syntax error - unexpected ':'; expected '}'");
+
+ CHECK_THROWS_AS(json::parse("1.18973e+4932", cb), json::out_of_range&);
+ CHECK_THROWS_WITH(json::parse("1.18973e+4932", cb),
+ "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'");
+ }
+
+ SECTION("SAX parser")
+ {
+ SECTION("} without value")
+ {
+ SaxCountdown s(1);
+ CHECK(json::sax_parse("{}", &s) == false);
+ }
+
+ SECTION("} with value")
+ {
+ SaxCountdown s(3);
+ CHECK(json::sax_parse("{\"k1\": true}", &s) == false);
+ }
+
+ SECTION("second key")
+ {
+ SaxCountdown s(3);
+ CHECK(json::sax_parse("{\"k1\": true, \"k2\": false}", &s) == false);
+ }
+
+ SECTION("] without value")
+ {
+ SaxCountdown s(1);
+ CHECK(json::sax_parse("[]", &s) == false);
+ }
+
+ SECTION("] with value")
+ {
+ SaxCountdown s(2);
+ CHECK(json::sax_parse("[1]", &s) == false);
+ }
+
+ SECTION("float")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("3.14", &s) == false);
+ }
+
+ SECTION("false")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("false", &s) == false);
+ }
+
+ SECTION("null")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("null", &s) == false);
+ }
+
+ SECTION("true")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("true", &s) == false);
+ }
+
+ SECTION("unsigned")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("12", &s) == false);
+ }
+
+ SECTION("integer")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("-12", &s) == false);
+ }
+
+ SECTION("string")
+ {
+ SaxCountdown s(0);
+ CHECK(json::sax_parse("\"foo\"", &s) == false);
+ }
+ }
+ }
}
diff --git a/test/src/unit-comparison.cpp b/test/src/unit-comparison.cpp
index 0659c1d..3da891b 100644
--- a/test/src/unit-comparison.cpp
+++ b/test/src/unit-comparison.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -32,7 +33,7 @@
using nlohmann::json;
// helper function to check std::less<json::value_t>
-// see http://en.cppreference.com/w/cpp/utility/functional/less
+// see https://en.cppreference.com/w/cpp/utility/functional/less
template <typename A, typename B, typename U = std::less<json::value_t>>
bool f(A a, B b, U u = U())
{
diff --git a/test/src/unit-concepts.cpp b/test/src/unit-concepts.cpp
index e2aac15..95013c6 100644
--- a/test/src/unit-concepts.cpp
+++ b/test/src/unit-concepts.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-constructor1.cpp b/test/src/unit-constructor1.cpp
index 35652bd..d6040fc 100644
--- a/test/src/unit-constructor1.cpp
+++ b/test/src/unit-constructor1.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-constructor2.cpp b/test/src/unit-constructor2.cpp
index e36de92..1473802 100644
--- a/test/src/unit-constructor2.cpp
+++ b/test/src/unit-constructor2.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-convenience.cpp b/test/src/unit-convenience.cpp
index 1559603..08c0b16 100644
--- a/test/src/unit-convenience.cpp
+++ b/test/src/unit-convenience.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp
index d67f5ac..fd09b23 100644
--- a/test/src/unit-conversions.cpp
+++ b/test/src/unit-conversions.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -39,11 +40,28 @@
#include <unordered_set>
#include <valarray>
+#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+ #define JSON_HAS_CPP_17
+ #define JSON_HAS_CPP_14
+#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+ #define JSON_HAS_CPP_14
+#endif
+
+#if defined(JSON_HAS_CPP_17)
+ #include <string_view>
+#endif
+
TEST_CASE("value conversion")
{
SECTION("get an object (explicit)")
{
- json::object_t o_reference = {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
+ json::object_t o_reference = {{"object", json::object()},
+ {"array", {1, 2, 3, 4}},
+ {"number", 42},
+ {"boolean", false},
+ {"null", nullptr},
+ {"string", "Hello world"}
+ };
json j(o_reference);
SECTION("json::object_t")
@@ -54,19 +72,22 @@
SECTION("std::map<json::string_t, json>")
{
- std::map<json::string_t, json> o = j.get<std::map<json::string_t, json>>();
+ std::map<json::string_t, json> o =
+ j.get<std::map<json::string_t, json>>();
CHECK(json(o) == j);
}
SECTION("std::multimap<json::string_t, json>")
{
- std::multimap<json::string_t, json> o = j.get<std::multimap<json::string_t, json>>();
+ std::multimap<json::string_t, json> o =
+ j.get<std::multimap<json::string_t, json>>();
CHECK(json(o) == j);
}
SECTION("std::unordered_map<json::string_t, json>")
{
- std::unordered_map<json::string_t, json> o = j.get<std::unordered_map<json::string_t, json>>();
+ std::unordered_map<json::string_t, json> o =
+ j.get<std::unordered_map<json::string_t, json>>();
CHECK(json(o) == j);
}
@@ -79,34 +100,55 @@
SECTION("exception in case of a non-object type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::array).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::object_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(
+ json(json::value_t::number_unsigned).get<json::object_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is null");
- CHECK_THROWS_WITH(json(json::value_t::array).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is array");
- CHECK_THROWS_WITH(json(json::value_t::string).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is string");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::array).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is array");
+ CHECK_THROWS_WITH(
+ json(json::value_t::string).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is string");
CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is boolean");
- CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::object_t>(),
- "[json.exception.type_error.302] type must be object, but is number");
+ "[json.exception.type_error.302] type must be object, "
+ "but is boolean");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_integer).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_unsigned).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_float).get<json::object_t>(),
+ "[json.exception.type_error.302] type must be object, but is number");
}
}
SECTION("get an object (implicit)")
{
- json::object_t o_reference = {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
+ json::object_t o_reference = {{"object", json::object()},
+ {"array", {1, 2, 3, 4}},
+ {"number", 42},
+ {"boolean", false},
+ {"null", nullptr},
+ {"string", "Hello world"}
+ };
json j(o_reference);
SECTION("json::object_t")
@@ -142,7 +184,8 @@
SECTION("get an array (explicit)")
{
- json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
+ json::array_t a_reference{json(1), json(1u), json(2.2),
+ json(false), json("string"), json()};
json j(a_reference);
SECTION("json::array_t")
@@ -162,9 +205,11 @@
std::forward_list<json> a = j.get<std::forward_list<json>>();
CHECK(json(a) == j);
- CHECK_THROWS_AS(json(json::value_t::null).get<std::forward_list<json>>(), json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<std::forward_list<json>>(),
- "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_AS(json(json::value_t::null).get<std::forward_list<json>>(),
+ json::type_error&);
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<std::forward_list<json>>(),
+ "[json.exception.type_error.302] type must be array, but is null");
}
SECTION("std::vector<json>")
@@ -172,9 +217,11 @@
std::vector<json> a = j.get<std::vector<json>>();
CHECK(json(a) == j);
- CHECK_THROWS_AS(json(json::value_t::null).get<std::vector<json>>(), json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<std::vector<json>>(),
- "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_AS(json(json::value_t::null).get<std::vector<json>>(),
+ json::type_error&);
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<std::vector<json>>(),
+ "[json.exception.type_error.302] type must be array, but is null");
#if not defined(JSON_NOEXCEPTION)
SECTION("reserve is called on containers that supports it")
@@ -213,36 +260,52 @@
SECTION("exception in case of a non-array type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::object).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::object).get<std::vector<int>>(),
- "[json.exception.type_error.302] type must be array, but is object");
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is null");
- CHECK_THROWS_WITH(json(json::value_t::object).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is object");
- CHECK_THROWS_WITH(json(json::value_t::string).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is string");
- CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is boolean");
- CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::array_t>(),
- "[json.exception.type_error.302] type must be array, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::object).get<std::vector<int>>(),
+ "[json.exception.type_error.302] type must be array, but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::object).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::string).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is string");
+ CHECK_THROWS_WITH(
+ json(json::value_t::boolean).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is boolean");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_integer).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_unsigned).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_float).get<json::array_t>(),
+ "[json.exception.type_error.302] type must be array, but is number");
}
}
SECTION("get an array (implicit)")
{
- json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
+ json::array_t a_reference{json(1), json(1u), json(2.2),
+ json(false), json("string"), json()};
json j(a_reference);
SECTION("json::array_t")
@@ -278,7 +341,7 @@
SECTION("get a string (explicit)")
{
- json::string_t s_reference {"Hello world"};
+ json::string_t s_reference{"Hello world"};
json j(s_reference);
SECTION("string_t")
@@ -292,37 +355,120 @@
std::string s = j.get<std::string>();
CHECK(json(s) == j);
}
+#if defined(JSON_HAS_CPP_17)
+ SECTION("std::string_view")
+ {
+ std::string_view s = j.get<std::string_view>();
+ CHECK(json(s) == j);
+ }
+#endif
SECTION("exception in case of a non-string type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::object).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::string_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(
+ json(json::value_t::number_unsigned).get<json::string_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::string_t>(),
- "[json.exception.type_error.302] type must be string, but is null");
- CHECK_THROWS_WITH(json(json::value_t::object).get<json::string_t>(),
- "[json.exception.type_error.302] type must be string, but is object");
- CHECK_THROWS_WITH(json(json::value_t::array).get<json::string_t>(),
- "[json.exception.type_error.302] type must be string, but is array");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::object).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::array).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is array");
CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, "
+ "but is boolean");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_integer).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_unsigned).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_float).get<json::string_t>(),
+ "[json.exception.type_error.302] type must be string, but is number");
+ }
+
+#if defined(JSON_HAS_CPP_17)
+ SECTION("exception in case of a non-string type using string_view")
+ {
+ CHECK_THROWS_AS(json(json::value_t::null).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_integer).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<std::string_view>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<std::string_view>(), json::type_error&);
+
+ CHECK_THROWS_WITH(json(json::value_t::null).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is null");
+ CHECK_THROWS_WITH(json(json::value_t::object).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is object");
+ CHECK_THROWS_WITH(json(json::value_t::array).get<std::string_view>(),
+ "[json.exception.type_error.302] type must be string, but is array");
+ CHECK_THROWS_WITH(json(json::value_t::boolean).get<std::string_view>(),
"[json.exception.type_error.302] type must be string, but is boolean");
- CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::string_t>(),
+ CHECK_THROWS_WITH(json(json::value_t::number_integer).get<std::string_view>(),
"[json.exception.type_error.302] type must be string, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::string_t>(),
+ CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<std::string_view>(),
"[json.exception.type_error.302] type must be string, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::string_t>(),
+ CHECK_THROWS_WITH(json(json::value_t::number_float).get<std::string_view>(),
"[json.exception.type_error.302] type must be string, but is number");
}
+#endif
+ }
+
+ SECTION("get null (explicit)")
+ {
+ std::nullptr_t n = nullptr;
+ json j(n);
+
+ auto n2 = j.get<std::nullptr_t>();
+ CHECK(n2 == n);
+
+ CHECK_THROWS_AS(json(json::value_t::string).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_integer).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<std::nullptr_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<std::nullptr_t>(), json::type_error&);
+
+ CHECK_THROWS_WITH(json(json::value_t::string).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is string");
+ CHECK_THROWS_WITH(json(json::value_t::object).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is object");
+ CHECK_THROWS_WITH(json(json::value_t::array).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is array");
+ CHECK_THROWS_WITH(json(json::value_t::boolean).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is boolean");
+ CHECK_THROWS_WITH(json(json::value_t::number_integer).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number");
+ CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number");
+ CHECK_THROWS_WITH(json(json::value_t::number_float).get<std::nullptr_t>(),
+ "[json.exception.type_error.302] type must be null, but is number");
+
}
SECTION("get a string (implicit)")
{
- json::string_t s_reference {"Hello world"};
+ json::string_t s_reference{"Hello world"};
json j(s_reference);
SECTION("string_t")
@@ -331,6 +477,14 @@
CHECK(json(s) == j);
}
+#if defined(JSON_HAS_CPP_17)
+ SECTION("std::string_view")
+ {
+ std::string_view s = j;
+ CHECK(json(s) == j);
+ }
+#endif
+
SECTION("std::string")
{
std::string s = j;
@@ -340,7 +494,7 @@
SECTION("get a boolean (explicit)")
{
- json::boolean_t b_reference {true};
+ json::boolean_t b_reference{true};
json j(b_reference);
SECTION("boolean_t")
@@ -357,34 +511,53 @@
SECTION("exception in case of a non-string type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::object).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::boolean_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(
+ json(json::value_t::number_integer).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(
+ json(json::value_t::number_unsigned).get<json::boolean_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is null");
CHECK_THROWS_WITH(json(json::value_t::object).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is object");
- CHECK_THROWS_WITH(json(json::value_t::array).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is array");
+ "[json.exception.type_error.302] type must be boolean, "
+ "but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::array).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is array");
CHECK_THROWS_WITH(json(json::value_t::string).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is string");
- CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is number");
- CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::boolean_t>(),
- "[json.exception.type_error.302] type must be boolean, but is number");
+ "[json.exception.type_error.302] type must be boolean, "
+ "but is string");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_integer).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_unsigned).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number");
+ CHECK_THROWS_WITH(
+ json(json::value_t::number_float).get<json::boolean_t>(),
+ "[json.exception.type_error.302] type must be boolean, but is "
+ "number");
}
}
SECTION("get a boolean (implicit)")
{
- json::boolean_t b_reference {true};
+ json::boolean_t b_reference{true};
json j(b_reference);
SECTION("boolean_t")
@@ -402,9 +575,9 @@
SECTION("get an integer number (explicit)")
{
- json::number_integer_t n_reference {42};
+ json::number_integer_t n_reference{42};
json j(n_reference);
- json::number_unsigned_t n_unsigned_reference {42u};
+ json::number_unsigned_t n_unsigned_reference{42u};
json j_unsigned(n_unsigned_reference);
SECTION("number_integer_t")
@@ -613,33 +786,47 @@
SECTION("exception in case of a non-number type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::number_integer_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::object).get<json::number_integer_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::array).get<json::number_integer_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::string).get<json::number_integer_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_integer_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::number_integer_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<json::number_integer_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<json::number_integer_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::string).get<json::number_integer_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(
+ json(json::value_t::boolean).get<json::number_integer_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_integer_t>(),
- "[json.exception.type_error.302] type must be number, but is null");
- CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_integer_t>(),
- "[json.exception.type_error.302] type must be number, but is object");
- CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_integer_t>(),
- "[json.exception.type_error.302] type must be number, but is array");
- CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_integer_t>(),
- "[json.exception.type_error.302] type must be number, but is string");
- CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_integer_t>(),
- "[json.exception.type_error.302] type must be number, but is boolean");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::object).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::array).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is array");
+ CHECK_THROWS_WITH(
+ json(json::value_t::string).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is string");
+ CHECK_THROWS_WITH(
+ json(json::value_t::boolean).get<json::number_integer_t>(),
+ "[json.exception.type_error.302] type must be number, but is "
+ "boolean");
- CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_integer_t>());
- CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_unsigned_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_float).get<json::number_integer_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_float).get<json::number_unsigned_t>());
}
}
SECTION("get an integer number (implicit)")
{
- json::number_integer_t n_reference {42};
+ json::number_integer_t n_reference{42};
json j(n_reference);
- json::number_unsigned_t n_unsigned_reference {42u};
+ json::number_unsigned_t n_unsigned_reference{42u};
json j_unsigned(n_unsigned_reference);
SECTION("number_integer_t")
@@ -849,7 +1036,7 @@
SECTION("get a floating-point number (explicit)")
{
- json::number_float_t n_reference {42.23};
+ json::number_float_t n_reference{42.23};
json j(n_reference);
SECTION("number_float_t")
@@ -872,31 +1059,44 @@
SECTION("exception in case of a non-string type")
{
- CHECK_THROWS_AS(json(json::value_t::null).get<json::number_float_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::object).get<json::number_float_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::array).get<json::number_float_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::string).get<json::number_float_t>(), json::type_error&);
- CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_float_t>(), json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::null).get<json::number_float_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::object).get<json::number_float_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::array).get<json::number_float_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::string).get<json::number_float_t>(),
+ json::type_error&);
+ CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_float_t>(),
+ json::type_error&);
- CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_float_t>(),
- "[json.exception.type_error.302] type must be number, but is null");
- CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_float_t>(),
- "[json.exception.type_error.302] type must be number, but is object");
- CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_float_t>(),
- "[json.exception.type_error.302] type must be number, but is array");
- CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_float_t>(),
- "[json.exception.type_error.302] type must be number, but is string");
- CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_float_t>(),
- "[json.exception.type_error.302] type must be number, but is boolean");
+ CHECK_THROWS_WITH(
+ json(json::value_t::null).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is null");
+ CHECK_THROWS_WITH(
+ json(json::value_t::object).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is object");
+ CHECK_THROWS_WITH(
+ json(json::value_t::array).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is array");
+ CHECK_THROWS_WITH(
+ json(json::value_t::string).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is string");
+ CHECK_THROWS_WITH(
+ json(json::value_t::boolean).get<json::number_float_t>(),
+ "[json.exception.type_error.302] type must be number, but is "
+ "boolean");
- CHECK_NOTHROW(json(json::value_t::number_integer).get<json::number_float_t>());
- CHECK_NOTHROW(json(json::value_t::number_unsigned).get<json::number_float_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_integer).get<json::number_float_t>());
+ CHECK_NOTHROW(
+ json(json::value_t::number_unsigned).get<json::number_float_t>());
}
}
SECTION("get a floating-point number (implicit)")
{
- json::number_float_t n_reference {42.23};
+ json::number_float_t n_reference{42.23};
json j(n_reference);
SECTION("number_float_t")
@@ -953,7 +1153,7 @@
j3.get<std::unordered_map<std::string, double>>();
j4.get<std::unordered_map<std::string, bool>>();
j5.get<std::unordered_map<std::string, std::string>>();
- //CHECK(m5["one"] == "eins");
+ // CHECK(m5["one"] == "eins");
}
SECTION("std::multimap")
@@ -963,7 +1163,7 @@
j3.get<std::multimap<std::string, double>>();
j4.get<std::multimap<std::string, bool>>();
j5.get<std::multimap<std::string, std::string>>();
- //CHECK(m5["one"] == "eins");
+ // CHECK(m5["one"] == "eins");
}
SECTION("std::unordered_multimap")
@@ -973,13 +1173,16 @@
j3.get<std::unordered_multimap<std::string, double>>();
j4.get<std::unordered_multimap<std::string, bool>>();
j5.get<std::unordered_multimap<std::string, std::string>>();
- //CHECK(m5["one"] == "eins");
+ // CHECK(m5["one"] == "eins");
}
SECTION("exception in case of a non-object type")
{
- CHECK_THROWS_AS((json().get<std::map<std::string, int>>()), json::type_error&);
- CHECK_THROWS_WITH((json().get<std::map<std::string, int>>()), "[json.exception.type_error.302] type must be object, but is null");
+ CHECK_THROWS_AS((json().get<std::map<std::string, int>>()),
+ json::type_error&);
+ CHECK_THROWS_WITH(
+ (json().get<std::map<std::string, int>>()),
+ "[json.exception.type_error.302] type must be object, but is null");
}
}
@@ -1021,7 +1224,8 @@
{
std::array<int, 6> arr6 = {{1, 2, 3, 4, 5, 6}};
CHECK_THROWS_AS(arr6 = j1, json::out_of_range&);
- CHECK_THROWS_WITH(arr6 = j1, "[json.exception.out_of_range.401] array index 4 is out of range");
+ CHECK_THROWS_WITH(arr6 = j1, "[json.exception.out_of_range.401] "
+ "array index 4 is out of range");
}
SECTION("std::array is smaller than JSON")
@@ -1078,6 +1282,60 @@
j5.get<std::unordered_set<std::string>>();
}
+ SECTION("std::map (array of pairs)")
+ {
+ std::map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
+ json j6 = m;
+
+ auto m2 = j6.get<std::map<int, int>>();
+ CHECK(m == m2);
+
+ json j7 = {0, 1, 2, 3};
+ json j8 = 2;
+ CHECK_THROWS_AS((j7.get<std::map<int, int>>()), json::type_error&);
+ CHECK_THROWS_AS((j8.get<std::map<int, int>>()), json::type_error&);
+ CHECK_THROWS_WITH((j7.get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number");
+ CHECK_THROWS_WITH((j8.get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number");
+
+ SECTION("superfluous entries")
+ {
+ json j9 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
+ m2 = j9.get<std::map<int, int>>();
+ CHECK(m == m2);
+ }
+ }
+
+ SECTION("std::unordered_map (array of pairs)")
+ {
+ std::unordered_map<int, int> m{{0, 1}, {1, 2}, {2, 3}};
+ json j6 = m;
+
+ auto m2 = j6.get<std::unordered_map<int, int>>();
+ CHECK(m == m2);
+
+ json j7 = {0, 1, 2, 3};
+ json j8 = 2;
+ CHECK_THROWS_AS((j7.get<std::unordered_map<int, int>>()), json::type_error&);
+ CHECK_THROWS_AS((j8.get<std::unordered_map<int, int>>()), json::type_error&);
+ CHECK_THROWS_WITH((j7.get<std::unordered_map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number");
+ CHECK_THROWS_WITH((j8.get<std::unordered_map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, "
+ "but is number");
+
+ SECTION("superfluous entries")
+ {
+ json j9{{0, 1, 2}, {1, 2, 3}, {2, 3, 4}};
+ m2 = j9.get<std::unordered_map<int, int>>();
+ CHECK(m == m2);
+ }
+ }
+
SECTION("exception in case of a non-object type")
{
CHECK_THROWS_AS((json().get<std::list<int>>()), json::type_error&);
@@ -1088,11 +1346,24 @@
// does type really must be an array? or it rather must not be null?
// that's what I thought when other test like this one broke
- CHECK_THROWS_WITH((json().get<std::list<int>>()), "[json.exception.type_error.302] type must be array, but is null");
- CHECK_THROWS_WITH((json().get<std::vector<int>>()), "[json.exception.type_error.302] type must be array, but is null");
- CHECK_THROWS_WITH((json().get<std::vector<json>>()), "[json.exception.type_error.302] type must be array, but is null");
- CHECK_THROWS_WITH((json().get<std::list<json>>()), "[json.exception.type_error.302] type must be array, but is null");
- CHECK_THROWS_WITH((json().get<std::valarray<int>>()), "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::list<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::vector<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::vector<json>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::list<json>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::valarray<int>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
+ CHECK_THROWS_WITH(
+ (json().get<std::map<int, int>>()),
+ "[json.exception.type_error.302] type must be array, but is null");
}
}
}
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 2886f00..4f9970a 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -34,18 +35,162 @@
#include <iostream>
#include <valarray>
+struct SaxEventLogger : public nlohmann::json_sax<json>
+{
+ bool null() override
+ {
+ events.push_back("null()");
+ return true;
+ }
+
+ bool boolean(bool val) override
+ {
+ events.push_back(val ? "boolean(true)" : "boolean(false)");
+ return true;
+ }
+
+ bool number_integer(json::number_integer_t val) override
+ {
+ events.push_back("number_integer(" + std::to_string(val) + ")");
+ return true;
+ }
+
+ bool number_unsigned(json::number_unsigned_t val) override
+ {
+ events.push_back("number_unsigned(" + std::to_string(val) + ")");
+ return true;
+ }
+
+ bool number_float(json::number_float_t, const std::string& s) override
+ {
+ events.push_back("number_float(" + s + ")");
+ return true;
+ }
+
+ bool string(std::string& val) override
+ {
+ events.push_back("string(" + val + ")");
+ return true;
+ }
+
+ bool start_object(std::size_t elements) override
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_object()");
+ }
+ else
+ {
+ events.push_back("start_object(" + std::to_string(elements) + ")");
+ }
+ return true;
+ }
+
+ bool key(std::string& val) override
+ {
+ events.push_back("key(" + val + ")");
+ return true;
+ }
+
+ bool end_object() override
+ {
+ events.push_back("end_object()");
+ return true;
+ }
+
+ bool start_array(std::size_t elements) override
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_array()");
+ }
+ else
+ {
+ events.push_back("start_array(" + std::to_string(elements) + ")");
+ }
+ return true;
+ }
+
+ bool end_array() override
+ {
+ events.push_back("end_array()");
+ return true;
+ }
+
+ bool parse_error(std::size_t position, const std::string&, const json::exception&) override
+ {
+ events.push_back("parse_error(" + std::to_string(position) + ")");
+ return false;
+ }
+
+ std::vector<std::string> events;
+};
+
+struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
+{
+ bool start_object(std::size_t elements) override
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_object()");
+ }
+ else
+ {
+ events.push_back("start_object(" + std::to_string(elements) + ")");
+ }
+ return false;
+ }
+};
+
+struct SaxEventLoggerExitAfterKey : public SaxEventLogger
+{
+ bool key(std::string& val) override
+ {
+ events.push_back("key(" + val + ")");
+ return false;
+ }
+};
+
+struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
+{
+ bool start_array(std::size_t elements) override
+ {
+ if (elements == std::size_t(-1))
+ {
+ events.push_back("start_array()");
+ }
+ else
+ {
+ events.push_back("start_array(" + std::to_string(elements) + ")");
+ }
+ return false;
+ }
+};
+
TEST_CASE("deserialization")
{
SECTION("successful deserialization")
{
SECTION("stream")
{
- std::stringstream ss1, ss2;
+ std::stringstream ss1, ss2, ss3;
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}]";
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}]";
+ ss3 << "[\"foo\",1,2,3,false,{\"one\":1}]";
json j = json::parse(ss1);
CHECK(json::accept(ss2));
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(ss3, &l));
+ CHECK(l.events.size() == 11);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_array()", "string(foo)", "number_unsigned(1)",
+ "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
+ "start_object()", "key(one)", "number_unsigned(1)",
+ "end_object()", "end_array()"
+ }));
}
SECTION("string literal")
@@ -54,6 +199,17 @@
json j = json::parse(s);
CHECK(json::accept(s));
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(s, &l));
+ CHECK(l.events.size() == 11);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_array()", "string(foo)", "number_unsigned(1)",
+ "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
+ "start_object()", "key(one)", "number_unsigned(1)",
+ "end_object()", "end_array()"
+ }));
}
SECTION("string_t")
@@ -62,6 +218,17 @@
json j = json::parse(s);
CHECK(json::accept(s));
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(s, &l));
+ CHECK(l.events.size() == 11);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_array()", "string(foo)", "number_unsigned(1)",
+ "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
+ "start_object()", "key(one)", "number_unsigned(1)",
+ "end_object()", "end_array()"
+ }));
}
SECTION("operator<<")
@@ -92,19 +259,31 @@
{
SECTION("stream")
{
- std::stringstream ss1, ss2, ss3, ss4;
+ std::stringstream ss1, ss2, ss3, ss4, ss5;
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss3 << "[\"foo\",1,2,3,false,{\"one\":1}";
ss4 << "[\"foo\",1,2,3,false,{\"one\":1}";
+ ss5 << "[\"foo\",1,2,3,false,{\"one\":1}";
CHECK_THROWS_AS(json::parse(ss1), json::parse_error&);
CHECK_THROWS_WITH(json::parse(ss2),
"[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'");
CHECK(not json::accept(ss3));
json j_error;
- CHECK_NOTHROW(j_error = json::parse(ss1, nullptr, false));
+ CHECK_NOTHROW(j_error = json::parse(ss4, nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(ss5, &l));
+ CHECK(l.events.size() == 11);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_array()", "string(foo)", "number_unsigned(1)",
+ "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
+ "start_object()", "key(one)", "number_unsigned(1)",
+ "end_object()", "parse_error(29)"
+ }));
}
SECTION("string")
@@ -118,6 +297,17 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(s, nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(s, &l));
+ CHECK(l.events.size() == 11);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_array()", "string(foo)", "number_unsigned(1)",
+ "number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
+ "start_object()", "key(one)", "number_unsigned(1)",
+ "end_object()", "parse_error(29)"
+ }));
}
SECTION("operator<<")
@@ -159,6 +349,11 @@
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from std::array")
@@ -166,6 +361,11 @@
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from array")
@@ -173,6 +373,11 @@
uint8_t v[] = {'t', 'r', 'u', 'e'};
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from chars")
@@ -185,6 +390,12 @@
v[4] = '\0';
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
+
delete[] v;
}
@@ -193,6 +404,11 @@
std::string v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from std::initializer_list")
@@ -200,6 +416,11 @@
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(v) == json(true));
CHECK(json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("empty container")
@@ -207,6 +428,11 @@
std::vector<uint8_t> v;
CHECK_THROWS_AS(json::parse(v), json::parse_error&);
CHECK(not json::accept(v));
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(v, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
}
}
@@ -217,6 +443,12 @@
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
+
}
SECTION("from std::array")
@@ -224,6 +456,11 @@
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from array")
@@ -231,6 +468,11 @@
uint8_t v[] = {'t', 'r', 'u', 'e'};
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from std::string")
@@ -238,6 +480,11 @@
std::string v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from std::initializer_list")
@@ -245,6 +492,11 @@
std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("from std::valarray")
@@ -252,6 +504,11 @@
std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
CHECK(json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
}
SECTION("with empty range")
@@ -259,6 +516,11 @@
std::vector<uint8_t> v;
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&);
CHECK(not json::accept(std::begin(v), std::end(v)));
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
}
}
@@ -274,6 +536,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(10)"}));
}
SECTION("case 2")
@@ -285,6 +552,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(11)"}));
}
SECTION("case 3")
@@ -296,6 +568,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
}
SECTION("case 4")
@@ -307,6 +584,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
}
SECTION("case 5")
@@ -318,6 +600,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(3)"}));
}
SECTION("case 6")
@@ -331,6 +618,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 7")
@@ -342,6 +634,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 8")
@@ -353,6 +650,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 9")
@@ -364,6 +666,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 10")
@@ -375,6 +682,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 11")
@@ -386,6 +698,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 12")
@@ -397,6 +714,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 13")
@@ -408,6 +730,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 14")
@@ -419,6 +746,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 15")
@@ -430,6 +762,11 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
}
SECTION("case 16")
@@ -441,6 +778,15 @@
json j_error;
CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false));
CHECK(j_error.is_discarded());
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(std::begin(v), std::end(v), &l));
+ CHECK(l.events.size() == 4);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "start_object()", "key()", "number_unsigned(11)",
+ "parse_error(7)"
+ }));
}
}
}
@@ -453,39 +799,89 @@
{
CHECK_THROWS_AS(json::parse(bom), json::parse_error&);
CHECK_THROWS_WITH(json::parse(bom),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal");
CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error&);
CHECK_THROWS_WITH(json::parse(std::istringstream(bom)),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal");
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(bom, &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "parse_error(4)"
+ }));
}
SECTION("BOM and content")
{
CHECK(json::parse(bom + "1") == 1);
CHECK(json::parse(std::istringstream(bom + "1")) == 1);
+
+ SaxEventLogger l1, l2;
+ CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
+ CHECK(json::sax_parse(bom + "1", &l2));
+ CHECK(l1.events.size() == 1);
+ CHECK(l1.events == std::vector<std::string>(
+ {
+ "number_unsigned(1)"
+ }));
+ CHECK(l2.events.size() == 1);
+ CHECK(l2.events == std::vector<std::string>(
+ {
+ "number_unsigned(1)"
+ }));
}
SECTION("2 byte of BOM")
{
CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error&);
- CHECK_THROWS_WITH(json::parse(bom),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ CHECK_THROWS_WITH(json::parse(bom.substr(0, 2)),
+ "[json.exception.parse_error.101] parse error at 3: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&);
- CHECK_THROWS_WITH(json::parse(std::istringstream(bom)),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 2))),
+ "[json.exception.parse_error.101] parse error at 3: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'");
+
+ SaxEventLogger l1, l2;
+ CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
+ CHECK(not json::sax_parse(bom.substr(0, 2), &l2));
+ CHECK(l1.events.size() == 1);
+ CHECK(l1.events == std::vector<std::string>(
+ {
+ "parse_error(3)"
+ }));
+ CHECK(l2.events.size() == 1);
+ CHECK(l2.events == std::vector<std::string>(
+ {
+ "parse_error(3)"
+ }));
}
SECTION("1 byte of BOM")
{
CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error&);
- CHECK_THROWS_WITH(json::parse(bom),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ CHECK_THROWS_WITH(json::parse(bom.substr(0, 1)),
+ "[json.exception.parse_error.101] parse error at 2: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&);
- CHECK_THROWS_WITH(json::parse(std::istringstream(bom)),
- "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal");
+ CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 1))),
+ "[json.exception.parse_error.101] parse error at 2: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'");
+
+ SaxEventLogger l1, l2;
+ CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
+ CHECK(not json::sax_parse(bom.substr(0, 1), &l2));
+ CHECK(l1.events.size() == 1);
+ CHECK(l1.events == std::vector<std::string>(
+ {
+ "parse_error(2)"
+ }));
+ CHECK(l2.events.size() == 1);
+ CHECK(l2.events == std::vector<std::string>(
+ {
+ "parse_error(2)"
+ }));
}
SECTION("variations")
@@ -513,12 +909,46 @@
// without any variation, we skip the BOM
CHECK(json::parse(s + "null") == json());
CHECK(json::parse(std::istringstream(s + "null")) == json());
+
+ SaxEventLogger l;
+ CHECK(json::sax_parse(s + "null", &l));
+ CHECK(l.events.size() == 1);
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "null()"
+ }));
}
else
{
// any variation is an error
CHECK_THROWS_AS(json::parse(s + "null"), json::parse_error&);
CHECK_THROWS_AS(json::parse(std::istringstream(s + "null")), json::parse_error&);
+
+ SaxEventLogger l;
+ CHECK(not json::sax_parse(s + "null", &l));
+ CHECK(l.events.size() == 1);
+
+ if (i0 != 0)
+ {
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "parse_error(1)"
+ }));
+ }
+ else if (i1 != 0)
+ {
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "parse_error(2)"
+ }));
+ }
+ else
+ {
+ CHECK(l.events == std::vector<std::string>(
+ {
+ "parse_error(3)"
+ }));
+ }
}
}
}
@@ -535,4 +965,49 @@
CHECK(j == 456);
}
}
+
+ SECTION("SAX and early abort")
+ {
+ std::string s = "[1, [\"string\", 43.12], null, {\"key1\": true, \"key2\": false}]";
+
+ SaxEventLogger default_logger;
+ SaxEventLoggerExitAfterStartObject exit_after_start_object;
+ SaxEventLoggerExitAfterKey exit_after_key;
+ SaxEventLoggerExitAfterStartArray exit_after_start_array;
+
+ json::sax_parse(s, &default_logger);
+ CHECK(default_logger.events.size() == 14);
+ CHECK(default_logger.events == std::vector<std::string>(
+ {
+ "start_array()", "number_unsigned(1)", "start_array()",
+ "string(string)", "number_float(43.12)", "end_array()", "null()",
+ "start_object()", "key(key1)", "boolean(true)", "key(key2)",
+ "boolean(false)", "end_object()", "end_array()"
+ }));
+
+ json::sax_parse(s, &exit_after_start_object);
+ CHECK(exit_after_start_object.events.size() == 8);
+ CHECK(exit_after_start_object.events == std::vector<std::string>(
+ {
+ "start_array()", "number_unsigned(1)", "start_array()",
+ "string(string)", "number_float(43.12)", "end_array()", "null()",
+ "start_object()"
+ }));
+
+ json::sax_parse(s, &exit_after_key);
+ CHECK(exit_after_key.events.size() == 9);
+ CHECK(exit_after_key.events == std::vector<std::string>(
+ {
+ "start_array()", "number_unsigned(1)", "start_array()",
+ "string(string)", "number_float(43.12)", "end_array()", "null()",
+ "start_object()", "key(key1)"
+ }));
+
+ json::sax_parse(s, &exit_after_start_array);
+ CHECK(exit_after_start_array.events.size() == 1);
+ CHECK(exit_after_start_array.events == std::vector<std::string>(
+ {
+ "start_array()"
+ }));
+ }
}
diff --git a/test/src/unit-element_access1.cpp b/test/src/unit-element_access1.cpp
index d06b97c..2954d69 100644
--- a/test/src/unit-element_access1.cpp
+++ b/test/src/unit-element_access1.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-element_access2.cpp b/test/src/unit-element_access2.cpp
index 5ea4b8a..41ec42b 100644
--- a/test/src/unit-element_access2.cpp
+++ b/test/src/unit-element_access2.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp
index 111e6ea..8e42c6e 100644
--- a/test/src/unit-inspection.cpp
+++ b/test/src/unit-inspection.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-items.cpp b/test/src/unit-items.cpp
index 8f18884..69637ee 100644
--- a/test/src/unit-items.cpp
+++ b/test/src/unit-items.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-iterators1.cpp b/test/src/unit-iterators1.cpp
index c8125ce..8c3417d 100644
--- a/test/src/unit-iterators1.cpp
+++ b/test/src/unit-iterators1.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-iterators2.cpp b/test/src/unit-iterators2.cpp
index 2d36988..3d309b3 100644
--- a/test/src/unit-iterators2.cpp
+++ b/test/src/unit-iterators2.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-json_patch.cpp b/test/src/unit-json_patch.cpp
index 1a71621..c7c62fe 100644
--- a/test/src/unit-json_patch.cpp
+++ b/test/src/unit-json_patch.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp
index c630da5..9f39493 100644
--- a/test/src/unit-json_pointer.cpp
+++ b/test/src/unit-json_pointer.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-merge_patch.cpp b/test/src/unit-merge_patch.cpp
index 2daaf00..15997e1 100644
--- a/test/src/unit-merge_patch.cpp
+++ b/test/src/unit-merge_patch.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-meta.cpp b/test/src/unit-meta.cpp
index 6fc8499..1fd21db 100644
--- a/test/src/unit-meta.cpp
+++ b/test/src/unit-meta.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -42,10 +43,10 @@
CHECK(j["url"] == "https://github.com/nlohmann/json");
CHECK(j["version"] == json(
{
- {"string", "3.1.2"},
+ {"string", "3.2.0"},
{"major", 3},
- {"minor", 1},
- {"patch", 2}
+ {"minor", 2},
+ {"patch", 0}
}));
CHECK(j.find("platform") != j.end());
diff --git a/test/src/unit-modifiers.cpp b/test/src/unit-modifiers.cpp
index ada65f2..a73e7cf 100644
--- a/test/src/unit-modifiers.cpp
+++ b/test/src/unit-modifiers.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp
index d8bdb08..6089234 100644
--- a/test/src/unit-msgpack.cpp
+++ b/test/src/unit-msgpack.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -33,6 +34,76 @@
#include <fstream>
+class SaxCountdown
+{
+ public:
+ explicit SaxCountdown(const int count) : events_left(count)
+ {}
+
+ bool null()
+ {
+ return events_left-- > 0;
+ }
+
+ bool boolean(bool)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_integer(json::number_integer_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_unsigned(json::number_unsigned_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_float(json::number_float_t, const std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool string(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_object(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool key(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_object()
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_array(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_array()
+ {
+ return events_left-- > 0;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const json::exception&)
+ {
+ return false;
+ }
+
+ private:
+ int events_left = 0;
+};
+
TEST_CASE("MessagePack")
{
SECTION("individual values")
@@ -54,6 +125,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("boolean")
@@ -67,6 +139,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("false")
@@ -78,6 +151,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -111,6 +185,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -141,6 +216,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -174,6 +250,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -208,6 +285,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -250,6 +328,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -300,6 +379,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -331,6 +411,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -347,6 +428,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("-32768..-129 (int 16)")
@@ -379,6 +461,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -423,6 +506,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -472,6 +556,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
@@ -504,6 +589,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -536,6 +622,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -569,6 +656,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -610,6 +698,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -659,6 +748,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
@@ -679,6 +769,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
CHECK(json::from_msgpack(result) == v);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
@@ -727,6 +818,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -758,6 +850,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -790,6 +883,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -824,6 +918,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
@@ -839,6 +934,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("[null]")
@@ -850,6 +946,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("[1,2,3,4,5]")
@@ -861,6 +958,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("[[[[]]]]")
@@ -872,6 +970,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("array 16")
@@ -886,6 +985,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("array 32")
@@ -909,6 +1009,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
@@ -923,6 +1024,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("{\"\":null}")
@@ -934,6 +1036,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("{\"a\": {\"b\": {\"c\": {}}}}")
@@ -948,6 +1051,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("map 16")
@@ -971,6 +1075,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
SECTION("map 32")
@@ -1001,6 +1106,7 @@
// roundtrip
CHECK(json::from_msgpack(result) == j);
+ CHECK(json::from_msgpack(result, true, false) == j);
}
}
}
@@ -1019,10 +1125,12 @@
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>()), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>()),
"[json.exception.parse_error.110] parse error at 1: unexpected end of input");
+ CHECK(json::from_msgpack(std::vector<uint8_t>(), true, false).is_discarded());
}
SECTION("too short byte vector")
{
+ CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x87})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcc})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})), json::parse_error&);
@@ -1038,7 +1146,12 @@
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})), json::parse_error&);
+ CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x87})),
+ "[json.exception.parse_error.110] parse error at 2: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcc})),
"[json.exception.parse_error.110] parse error at 2: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd})),
@@ -1069,6 +1182,32 @@
"[json.exception.parse_error.110] parse error at 8: unexpected end of input");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 9: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65})),
+ "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x92, 0x01})),
+ "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x81, 0xa1, 0x61})),
+ "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0x87}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcc}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcd}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xce}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xa5, 0x68, 0x65}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0x92, 0x01}), true, false).is_discarded());
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xA1, 0x61}), true, false).is_discarded());
}
SECTION("unsupported bytes")
@@ -1078,9 +1217,12 @@
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc1})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc1})),
"[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC1");
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
+
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xc6})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xc6})),
"[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC6");
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0xc6}), true, false).is_discarded());
}
SECTION("all unsupported bytes")
@@ -1098,6 +1240,7 @@
})
{
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)})), json::parse_error&);
+ CHECK(json::from_msgpack(std::vector<uint8_t>({static_cast<uint8_t>(byte)}), true, false).is_discarded());
}
}
}
@@ -1107,6 +1250,7 @@
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})),
"[json.exception.parse_error.113] parse error at 2: expected a MessagePack string; last byte: 0xFF");
+ CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
}
SECTION("strict mode")
@@ -1123,9 +1267,34 @@
CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&);
CHECK_THROWS_WITH(json::from_msgpack(vec),
"[json.exception.parse_error.110] parse error at 2: expected end of input");
+ CHECK(json::from_msgpack(vec, true, false).is_discarded());
}
}
}
+
+ SECTION("SAX aborts")
+ {
+ SECTION("start_array(len)")
+ {
+ std::vector<uint8_t> v = {0x93, 0x01, 0x02, 0x03};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
+ }
+
+ SECTION("start_object(len)")
+ {
+ std::vector<uint8_t> v = {0x81, 0xa3, 0x66, 0x6F, 0x6F, 0xc2};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
+ }
+
+ SECTION("key()")
+ {
+ std::vector<uint8_t> v = {0x81, 0xa3, 0x66, 0x6F, 0x6F, 0xc2};
+ SaxCountdown scp(1);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
+ }
+ }
}
@@ -1180,6 +1349,25 @@
{
SECTION("input from msgpack-python")
{
+ // most of these are exluded due to differences in key order (not a real problem)
+ auto exclude_packed = std::set<std::string>
+ {
+ "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_testsuite/sample.json", // kills AppVeyor
+ "test/data/json_tests/pass1.json",
+ "test/data/regression/working_file.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_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",
+ };
+
for (std::string filename :
{
"test/data/json_nlohmann_tests/all_unicode.json",
@@ -1331,12 +1519,12 @@
{
CAPTURE(filename);
- // parse JSON file
- std::ifstream f_json(filename);
- json j1 = json::parse(f_json);
-
- SECTION("std::vector<uint8_t>")
+ SECTION(filename + ": std::vector<uint8_t>")
{
+ // 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(
@@ -1349,8 +1537,12 @@
CHECK(j1 == j2);
}
- SECTION("std::ifstream")
+ SECTION(filename + ": std::ifstream")
{
+ // 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);
json j2;
@@ -1360,8 +1552,12 @@
CHECK(j1 == j2);
}
- SECTION("uint8_t* and size")
+ SECTION(filename + ": uint8_t* and size")
{
+ // 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(
@@ -1374,19 +1570,26 @@
CHECK(j1 == j2);
}
- SECTION("output to output adapters")
+ SECTION(filename + ": output to output adapters")
{
+ // 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>());
- SECTION("std::vector<uint8_t>")
+ if (!exclude_packed.count(filename))
{
- std::vector<uint8_t> vec;
- json::to_msgpack(j1, vec);
- CHECK(vec == packed);
+ SECTION(filename + ": output adapters: std::vector<uint8_t>")
+ {
+ std::vector<uint8_t> vec;
+ json::to_msgpack(j1, vec);
+ CHECK(vec == packed);
+ }
}
}
}
diff --git a/test/src/unit-noexcept.cpp b/test/src/unit-noexcept.cpp
index 4b3dcad..72e8926 100644
--- a/test/src/unit-noexcept.cpp
+++ b/test/src/unit-noexcept.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-pointer_access.cpp b/test/src/unit-pointer_access.cpp
index 5670269..f34b0a7 100644
--- a/test/src/unit-pointer_access.cpp
+++ b/test/src/unit-pointer_access.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-readme.cpp b/test/src/unit-readme.cpp
index 4c163af..5e3255c 100644
--- a/test/src/unit-readme.cpp
+++ b/test/src/unit-readme.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-reference_access.cpp b/test/src/unit-reference_access.cpp
index 3c92096..5bd2077 100644
--- a/test/src/unit-reference_access.cpp
+++ b/test/src/unit-reference_access.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp
index c4ca93d..69c0cf2 100644
--- a/test/src/unit-regression.cpp
+++ b/test/src/unit-regression.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -114,6 +115,13 @@
};
}
+/////////////////////////////////////////////////////////////////////
+// for #1021
+/////////////////////////////////////////////////////////////////////
+
+using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;
+
+
TEST_CASE("regression tests")
{
SECTION("issue #60 - Double quotation mark is not parsed correctly")
@@ -129,19 +137,19 @@
SECTION("issue #70 - Handle infinity and NaN cases")
{
- /*
+ // previously, NAN/INFINITY created a null value; now, the values are
+ // properly stored, but are dumped as "null"
SECTION("NAN value")
{
- CHECK(json(NAN) == json());
- CHECK(json(json::number_float_t(NAN)) == json());
+ CHECK(json(NAN).dump() == "null");
+ CHECK(json(json::number_float_t(NAN)).dump() == "null");
}
SECTION("infinity")
{
- CHECK(json(INFINITY) == json());
- CHECK(json(json::number_float_t(INFINITY)) == json());
+ CHECK(json(INFINITY).dump() == "null");
+ CHECK(json(json::number_float_t(INFINITY)).dump() == "null");
}
- */
// With 3.0.0, the semantics of this changed: NAN and infinity are
// stored properly inside the JSON value (no exception or conversion
@@ -1206,41 +1214,6 @@
CHECK(j["bool_vector"].dump() == "[false,true,false,false]");
}
- /* NOTE: m_line_buffer is not used any more
- SECTION("issue #495 - fill_line_buffer incorrectly tests m_stream for eof but not fail or bad bits")
- {
- SECTION("setting failbit")
- {
- std::stringstream ss;
- ss << "[1,2,3\n,4,5]";
-
- json::lexer l(ss);
-
- CHECK(l.m_line_buffer == "[1,2,3\n");
-
- l.m_stream->setstate(std::ios_base::failbit);
-
- CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&);
- CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream");
- }
-
- SECTION("setting badbit")
- {
- std::stringstream ss;
- ss << "[1,2,3\n,4,5]";
-
- json::lexer l(ss);
-
- CHECK(l.m_line_buffer == "[1,2,3\n");
-
- l.m_stream->setstate(std::ios_base::badbit);
-
- CHECK_THROWS_AS(l.fill_line_buffer(), json::parse_error&);
- CHECK_THROWS_WITH(l.fill_line_buffer(), "[json.exception.parse_error.111] parse error: bad input stream");
- }
- }
- */
-
SECTION("issue #504 - assertion error (OSS-Fuzz 856)")
{
std::vector<uint8_t> vec1 = {0xf9, 0xff, 0xff, 0x4a, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x37, 0x02, 0x38};
@@ -1499,6 +1472,46 @@
// "[json.exception.out_of_range.408] excessive object size: 8658170730974374167");
}
+ SECTION("issue #971 - Add a SAX parser - late bug")
+ {
+ // a JSON text
+ auto text = R"(
+ {
+ "Image": {
+ "Width": 800,
+ "Height": 600,
+ "Title": "View from 15th Floor",
+ "Thumbnail": {
+ "Url": "http://www.example.com/image/481989943",
+ "Height": 125,
+ "Width": 100
+ },
+ "Animated" : false,
+ "IDs": [116, 943, 234, 38793]
+ }
+ }
+ )";
+
+ // define parser callback
+ json::parser_callback_t cb = [](int /*depth*/, json::parse_event_t event, json & parsed)
+ {
+ // skip object elements with key "Thumbnail"
+ if (event == json::parse_event_t::key and parsed == json("Thumbnail"))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ };
+
+ // parse (with callback) and serialize JSON
+ json j_filtered = json::parse(text, cb);
+
+ CHECK(j_filtered == R"({"Image":{"Animated":false,"Height":600,"IDs":[116,943,234,38793], "Title":"View from 15th Floor","Width":800}})"_json);
+ }
+
SECTION("issue #972 - Segmentation fault on G++ when trying to assign json string literal to custom json type")
{
my_json foo = R"([1, 2, 3])"_json;
@@ -1563,38 +1576,71 @@
switch (event)
{
case json::parse_event_t::key:
- {
- return true;
- }
+ {
+ return true;
+ }
case json::parse_event_t::value:
- {
- return false;
- }
+ {
+ return false;
+ }
case json::parse_event_t::object_start:
- {
- return true;
- }
+ {
+ return true;
+ }
case json::parse_event_t::object_end:
- {
- return false;
- }
+ {
+ return false;
+ }
case json::parse_event_t::array_start:
- {
- return true;
- }
+ {
+ return true;
+ }
case json::parse_event_t::array_end:
- {
- return false;
- }
+ {
+ return false;
+ }
default:
- {
- return true;
- }
+ {
+ return true;
+ }
}
};
auto j = json::parse(geojsonExample, cb, true);
CHECK(j == json());
}
+
+ SECTION("issue #1021 - to/from_msgpack only works with standard typization")
+ {
+ float_json j = 1000.0;
+ CHECK(float_json::from_cbor(float_json::to_cbor(j)) == j);
+ CHECK(float_json::from_msgpack(float_json::to_msgpack(j)) == j);
+ CHECK(float_json::from_ubjson(float_json::to_ubjson(j)) == j);
+
+ float_json j2 = {1000.0, 2000.0, 3000.0};
+ CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
+ }
+
+ SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
+ {
+ json diffs = nlohmann::json::array();
+ json m1{{"key1", 42}};
+ json m2{{"key2", 42}};
+ auto p1 = m1.items();
+ auto p2 = m2.items();
+
+ using it_type = decltype(p1.begin());
+
+ std::set_difference(
+ p1.begin(), p1.end(),
+ p2.begin(), p2.end(),
+ std::inserter(diffs, diffs.end()), [&](const it_type & e1, const it_type & e2) -> bool
+ {
+ using comper_pair = std::pair<std::string, decltype(e1.value())>; // Trying to avoid unneeded copy
+ return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value()); // Using pair comper
+ });
+
+ CHECK(diffs.size() == 1); // Note the change here, was 2
+ }
}
diff --git a/test/src/unit-serialization.cpp b/test/src/unit-serialization.cpp
index ebe6429..f2861c4 100644
--- a/test/src/unit-serialization.cpp
+++ b/test/src/unit-serialization.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp
index 5f77a73..237eb34 100644
--- a/test/src/unit-testsuites.cpp
+++ b/test/src/unit-testsuites.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -881,6 +882,438 @@
}
}
+TEST_CASE("nst's JSONTestSuite (2)")
+{
+ SECTION("test_parsing")
+ {
+ SECTION("y")
+ {
+ for (auto filename :
+ {
+ "test/data/nst_json_testsuite2/test_parsing/y_array_arraysWithSpaces.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_empty-string.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_empty.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_ending_with_newline.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_false.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_heterogeneous.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_with_1_and_newline.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_with_leading_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_with_several_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_array_with_trailing_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_0e+1.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_0e1.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_after_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_double_close_to_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_int_with_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_minus_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_negative_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_negative_one.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_negative_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_neg_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_capital_e_pos_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_exponent.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_fraction_exponent.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_neg_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_real_pos_exponent.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_simple_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_number_simple_real.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_basic.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_duplicated_key_and_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_empty.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_empty_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_escaped_null_in_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_extreme_numbers.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_long_strings.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_simple.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_string_unicode.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_object_with_newlines.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pair.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_accepted_surrogate_pairs.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_allowed_escapes.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_backslash_and_u_escaped_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_backslash_doublequotes.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_comments.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_a.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_double_escape_n.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_escaped_control_character.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_escaped_noncharacter.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_in_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_in_array_with_leading_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_last_surrogates_1_and_2.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_nbsp_uescaped.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_null_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_one-byte-utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_pi.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_simple_ascii.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_three-byte-utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_two-byte-utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_u+2028_line_sep.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_u+2029_par_sep.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_uEscape.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_uescaped_newline.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unescaped_char_delete.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicodeEscapedBackslash.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_2.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+10FFFE_nonchar.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+1FFFE_nonchar.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+2064_invisible_plus.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FDD0_nonchar.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_U+FFFE_nonchar.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_unicode_escaped_double_quote.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_utf8.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_string_with_del_character.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_false.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_negative_real.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_lonely_true.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_string_empty.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_trailing_newline.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_true_in_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/y_structure_whitespace_array.json"
+ }
+ )
+ {
+ CAPTURE(filename);
+ std::ifstream f(filename);
+ CHECK_NOTHROW(json::parse(f));
+ std::ifstream f2(filename);
+ CHECK(json::accept(f2));
+ }
+ }
+
+ SECTION("n")
+ {
+ for (auto filename :
+ {
+ "test/data/nst_json_testsuite2/test_parsing/n_array_1_true_without_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_a_invalid_utf8.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_colon_instead_of_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_comma_after_close.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_comma_and_number.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_double_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_double_extra_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_extra_close.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_extra_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_incomplete.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_incomplete_invalid_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_inner_array_no_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_invalid_utf8.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_items_separated_by_semicolon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_just_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_just_minus.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_missing_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_newlines_unclosed.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_number_and_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_number_and_several_commas.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_spaces_vertical_tab_formfeed.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_star_inside.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_unclosed.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_trailing_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_new_lines.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_array_unclosed_with_object_inside.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_incomplete_false.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_incomplete_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_incomplete_true.json",
+ //"test/data/nst_json_testsuite2/test_parsing/n_multidigit_number_then_00.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_++.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_+1.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_+Inf.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_-01.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_-1.0..json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_-2..json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_-NaN.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_.-1.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_.2e-3.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0.1.2.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0.3e+.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0.3e.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0.e1.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E+.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0_capital_E.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0e+.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_0e.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_1.0e+.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_1.0e-.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_1.0e.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_1_000.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_1eE2.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_2.e+3.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_2.e-3.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_2.e3.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_9.e+.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_Inf.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_NaN.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_U+FF11_fullwidth_digit_one.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_expression.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_hex_1_digit.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_hex_2_digits.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_infinity.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_invalid+-.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_invalid-negative-real.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-bigger-int.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-exponent.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_invalid-utf-8-in-int.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_minus_infinity.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_minus_sign_with_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_minus_space_1.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_neg_int_starting_with_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_neg_real_without_int_part.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_neg_with_garbage_at_end.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_real_garbage_after_e.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_real_with_invalid_utf8_after_e.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_real_without_fractional_part.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_starting_with_dot.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_with_alpha_char.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_number_with_leading_zero.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_bad_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_bracket_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_comma_instead_of_colon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_double_colon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_emoji.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_garbage_at_end.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_key_with_single_quotes.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_missing_colon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_missing_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_missing_semicolon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_missing_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_no-colon.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_non_string_key_but_huge_number_instead.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_repeated_null_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_several_trailing_commas.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_single_quote.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_open.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_trailing_comment_slash_open_incomplete.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_two_commas_in_a_row.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_unquoted_key.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_unterminated-value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_with_single_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_object_with_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_single_space.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_1_surrogate_then_escape_u1x.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_accentuated_char_no_quotes.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_backslash_00.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_escape_x.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_escaped_backslash_bad.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_escaped_ctrl_char_tab.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_escaped_emoji.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_escaped_character.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_incomplete_surrogate_escape_invalid.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_invalid-utf-8-in-escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_invalid_backslash_esc.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_invalid_unicode_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_invalid_utf8_after_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_leading_uescaped_thinspace.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_no_quotes_with_bad_escape.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_single_doublequote.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_single_quote.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_single_string_no_double_quotes.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_start_escape_unclosed.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_crtl_char.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_newline.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_unescaped_tab.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_unicode_CapitalU.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_string_with_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_U+2060_word_joined.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_UTF8_BOM_no_data.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_..json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_angle_bracket_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_array_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_extra_array_close.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_array_with_unclosed_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_ascii-unicode-identifier.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_capitalized_True.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_close_unopened_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_comma_instead_of_closing_brace.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_double_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_end_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_incomplete_UTF8_BOM.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_lone-invalid-utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_lone-open-bracket.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_no_data.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_null-byte-outside-string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_number_with_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_object_followed_by_closing_object.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_object_unclosed_no_value.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_comment.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_object_with_trailing_garbage.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_apostrophe.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_object.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_open_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_close_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_comma.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_open_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_object_string_with_apostrophes.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_open.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_single_eacute.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_single_star.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_trailing_#.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_uescaped_LF_before_string.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_partial_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_false.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_array_unfinished_true.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unclosed_object.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_unicode-identifier.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_U+2060_word_joiner.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_whitespace_formfeed.json"
+ }
+ )
+ {
+ CAPTURE(filename);
+ std::ifstream f(filename);
+ CHECK_THROWS_AS(json::parse(f), json::parse_error&);
+ std::ifstream f2(filename);
+ CHECK(not json::accept(f2));
+ }
+ }
+
+ SECTION("n (previously overflowed)")
+ {
+ for (auto filename :
+ {
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_100000_opening_arrays.json",
+ "test/data/nst_json_testsuite2/test_parsing/n_structure_open_array_object.json"
+ }
+ )
+ {
+ CAPTURE(filename);
+ std::ifstream f(filename);
+ CHECK(not json::accept(f));
+ }
+ }
+
+ SECTION("i -> y")
+ {
+ for (auto filename :
+ {
+ "test/data/nst_json_testsuite2/test_parsing/i_number_double_huge_neg_exp.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_huge_exp.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_neg_int_huge_exp.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_pos_double_huge_exp.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_real_neg_overflow.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_real_pos_overflow.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_real_underflow.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_too_big_neg_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_too_big_pos_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_very_big_negative_int.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_object_key_lone_2nd_surrogate.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_1st_surrogate_but_2nd_missing.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_UTF-16LE_with_BOM.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_UTF-8_invalid_sequence.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_UTF8_surrogate_U+D800.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_pair.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogates_escape_valid.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_invalid_lonely_surrogate.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_invalid_surrogate.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_invalid_utf-8.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_inverted_surrogates_U+1D11E.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_iso_latin_1.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_lone_second_surrogate.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_lone_utf8_continuation_byte.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_not_in_unicode_range.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_2_bytes.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes_null.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_truncated-utf-8.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_utf16BE_no_BOM.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_string_utf16LE_no_BOM.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_structure_500_nested_arrays.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_structure_UTF-8_BOM_empty_object.json"
+ }
+ )
+ {
+ CAPTURE(filename);
+ std::ifstream f(filename);
+ CHECK_NOTHROW(json::parse(f));
+ std::ifstream f2(filename);
+ CHECK(json::accept(f2));
+ }
+ }
+
+ SECTION("i -> n")
+ {
+ for (auto filename :
+ {
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_double_huge_neg_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_huge_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_neg_int_huge_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_pos_double_huge_exp.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_real_neg_overflow.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_number_real_pos_overflow.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_real_underflow.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_too_big_neg_int.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_too_big_pos_int.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_number_very_big_negative_int.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_object_key_lone_2nd_surrogate.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_1st_surrogate_but_2nd_missing.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_UTF-16LE_with_BOM.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_UTF-8_invalid_sequence.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_UTF8_surrogate_U+D800.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogate_pair.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_incomplete_surrogates_escape_valid.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_invalid_lonely_surrogate.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_invalid_surrogate.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_invalid_utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_inverted_surrogates_U+1D11E.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_iso_latin_1.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_lone_second_surrogate.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_lone_utf8_continuation_byte.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_not_in_unicode_range.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_2_bytes.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_overlong_sequence_6_bytes_null.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_truncated-utf-8.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_utf16BE_no_BOM.json",
+ "test/data/nst_json_testsuite2/test_parsing/i_string_utf16LE_no_BOM.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_structure_500_nested_arrays.json",
+ //"test/data/nst_json_testsuite2/test_parsing/i_structure_UTF-8_BOM_empty_object.json"
+ }
+ )
+ {
+ CAPTURE(filename);
+ std::ifstream f(filename);
+ CHECK_THROWS_AS(json::parse(f), json::exception&); // could be parse_error or out_of_range
+ std::ifstream f2(filename);
+ CHECK(not json::accept(f2));
+ }
+ }
+ }
+}
+
std::string trim(const std::string& str);
// from http://stackoverflow.com/a/25829178/266378
diff --git a/test/src/unit-to_chars.cpp b/test/src/unit-to_chars.cpp
index 841e164..d443176 100644
--- a/test/src/unit-to_chars.cpp
+++ b/test/src/unit-to_chars.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-ubjson.cpp b/test/src/unit-ubjson.cpp
index e2f7723..abae230 100644
--- a/test/src/unit-ubjson.cpp
+++ b/test/src/unit-ubjson.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -33,6 +34,76 @@
#include <fstream>
+class SaxCountdown
+{
+ public:
+ explicit SaxCountdown(const int count) : events_left(count)
+ {}
+
+ bool null()
+ {
+ return events_left-- > 0;
+ }
+
+ bool boolean(bool)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_integer(json::number_integer_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_unsigned(json::number_unsigned_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool number_float(json::number_float_t, const std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool string(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_object(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool key(std::string&)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_object()
+ {
+ return events_left-- > 0;
+ }
+
+ bool start_array(std::size_t)
+ {
+ return events_left-- > 0;
+ }
+
+ bool end_array()
+ {
+ return events_left-- > 0;
+ }
+
+ bool parse_error(std::size_t, const std::string&, const json::exception&)
+ {
+ return false;
+ }
+
+ private:
+ int events_left = 0;
+};
+
TEST_CASE("UBJSON")
{
SECTION("individual values")
@@ -54,6 +125,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("boolean")
@@ -67,6 +139,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("false")
@@ -78,6 +151,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -140,6 +214,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -152,7 +227,7 @@
numbers.push_back(-10000000);
numbers.push_back(-100000000);
numbers.push_back(-1000000000);
- numbers.push_back(-2147483648L);
+ numbers.push_back(-2147483647 - 1); // https://stackoverflow.com/a/29356002/266378
for (auto i : numbers)
{
CAPTURE(i);
@@ -186,6 +261,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -219,6 +295,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -239,6 +316,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("-128..-1 (int8)")
@@ -269,6 +347,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -301,6 +380,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -333,6 +413,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -367,6 +448,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -409,6 +491,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -457,6 +540,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -492,6 +576,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -524,6 +609,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -557,6 +643,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -598,6 +685,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -645,6 +733,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -665,6 +754,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
CHECK(json::from_ubjson(result) == v);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -703,6 +793,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -735,6 +826,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -768,6 +860,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -803,6 +896,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -820,6 +914,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -831,6 +926,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -842,6 +938,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -856,6 +953,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -867,6 +965,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -878,6 +977,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -892,6 +992,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -903,6 +1004,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -914,6 +1016,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -928,6 +1031,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -939,6 +1043,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -950,6 +1055,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -966,6 +1072,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -982,6 +1089,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -993,6 +1101,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -1009,6 +1118,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -1027,6 +1137,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -1038,6 +1149,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -1055,6 +1167,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -1066,6 +1179,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -1077,6 +1191,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -1091,6 +1206,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -1102,6 +1218,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -1113,6 +1230,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
@@ -1130,6 +1248,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=false")
@@ -1144,6 +1263,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
SECTION("size=true type=true")
@@ -1158,6 +1278,7 @@
// roundtrip
CHECK(json::from_ubjson(result) == j);
+ CHECK(json::from_ubjson(result, true, false) == j);
}
}
}
@@ -1189,6 +1310,80 @@
CHECK_THROWS_AS(json::to_ubjson(j), json::out_of_range&);
CHECK_THROWS_WITH(json::to_ubjson(j), "[json.exception.out_of_range.407] number overflow serializing 9223372036854775808");
}
+
+ SECTION("excessive size")
+ {
+ SECTION("array")
+ {
+ std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
+ CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
+
+ json j;
+ nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int, json::parse_event_t, const json&)
+ {
+ return true;
+ });
+ CHECK_THROWS_AS(json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
+ }
+
+ SECTION("object")
+ {
+ std::vector<uint8_t> v_ubjson = {'{', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
+ CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
+
+ json j;
+ nlohmann::detail::json_sax_dom_callback_parser<json> scp(j, [](int, json::parse_event_t, const json&)
+ {
+ return true;
+ });
+ CHECK_THROWS_AS(json::sax_parse(v_ubjson, &scp, json::input_format_t::ubjson), json::out_of_range&);
+ }
+ }
+ }
+
+ SECTION("SAX aborts")
+ {
+ SECTION("start_array()")
+ {
+ std::vector<uint8_t> v = {'[', 'T', 'F', ']'};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
+
+ SECTION("start_object()")
+ {
+ std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
+
+ SECTION("key() in object")
+ {
+ std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
+ SaxCountdown scp(1);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
+
+ SECTION("start_array(len)")
+ {
+ std::vector<uint8_t> v = {'[', '#', 'i', '2', 'T', 'F'};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
+
+ SECTION("start_object(len)")
+ {
+ std::vector<uint8_t> v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'};
+ SaxCountdown scp(0);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
+
+ SECTION("key() in object with length")
+ {
+ std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
+ SaxCountdown scp(1);
+ CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
+ }
}
SECTION("parsing values")
@@ -1239,6 +1434,7 @@
SECTION("optimized version (length only)")
{
// create vector with two elements of the same type
+ std::vector<uint8_t> v_TU = {'[', '#', 'U', 2, 'T', 'T'};
std::vector<uint8_t> v_T = {'[', '#', 'i', 2, 'T', 'T'};
std::vector<uint8_t> v_F = {'[', '#', 'i', 2, 'F', 'F'};
std::vector<uint8_t> v_Z = {'[', '#', 'i', 2, 'Z', 'Z'};
@@ -1252,6 +1448,7 @@
std::vector<uint8_t> v_C = {'[', '#', 'i', 2, 'C', 'a', 'C', 'a'};
// check if vector is parsed correctly
+ CHECK(json::from_ubjson(v_TU) == json({true, true}));
CHECK(json::from_ubjson(v_T) == json({true, true}));
CHECK(json::from_ubjson(v_F) == json({false, false}));
CHECK(json::from_ubjson(v_Z) == json({nullptr, nullptr}));
@@ -1378,6 +1575,136 @@
CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.112] parse error at 4: expected '#' after UBJSON type information; last byte: 0x02");
}
}
+
+ SECTION("strings")
+ {
+ std::vector<uint8_t> vS = {'S'};
+ CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 2: unexpected end of input");
+ CHECK(json::from_ubjson(vS, true, false).is_discarded());
+
+ std::vector<uint8_t> v = {'S', 'i', '2', 'a'};
+ CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 5: unexpected end of input");
+ CHECK(json::from_ubjson(v, true, false).is_discarded());
+
+ std::vector<uint8_t> vC = {'C'};
+ CHECK_THROWS_AS(json::from_ubjson(vC), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at 2: unexpected end of input");
+ CHECK(json::from_ubjson(vC, true, false).is_discarded());
+ }
+
+ SECTION("sizes")
+ {
+ std::vector<uint8_t> vU = {'[', '#', 'U'};
+ CHECK_THROWS_AS(json::from_ubjson(vU), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vU, true, false).is_discarded());
+
+ std::vector<uint8_t> vi = {'[', '#', 'i'};
+ CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vi, true, false).is_discarded());
+
+ std::vector<uint8_t> vI = {'[', '#', 'I'};
+ CHECK_THROWS_AS(json::from_ubjson(vI), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vI, true, false).is_discarded());
+
+ std::vector<uint8_t> vl = {'[', '#', 'l'};
+ CHECK_THROWS_AS(json::from_ubjson(vl), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vl, true, false).is_discarded());
+
+ std::vector<uint8_t> vL = {'[', '#', 'L'};
+ CHECK_THROWS_AS(json::from_ubjson(vL), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vL, true, false).is_discarded());
+
+ std::vector<uint8_t> v0 = {'[', '#', 'T', ']'};
+ CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at 3: byte after '#' must denote a number type; last byte: 0x54");
+ CHECK(json::from_ubjson(v0, true, false).is_discarded());
+ }
+
+ SECTION("types")
+ {
+ std::vector<uint8_t> v0 = {'[', '$'};
+ CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at 3: unexpected end of input");
+ CHECK(json::from_ubjson(v0, true, false).is_discarded());
+
+ std::vector<uint8_t> vi = {'[', '$', '#'};
+ CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vi, true, false).is_discarded());
+
+ std::vector<uint8_t> vT = {'[', '$', 'T'};
+ CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at 4: unexpected end of input");
+ CHECK(json::from_ubjson(vT, true, false).is_discarded());
+ }
+
+ SECTION("arrays")
+ {
+ std::vector<uint8_t> vST = {'[', '$', 'i', '#', 'i', 2, 1};
+ CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at 8: unexpected end of input");
+ CHECK(json::from_ubjson(vST, true, false).is_discarded());
+
+ std::vector<uint8_t> vS = {'[', '#', 'i', 2, 'i', 1};
+ CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 7: unexpected end of input");
+ CHECK(json::from_ubjson(vS, true, false).is_discarded());
+
+ std::vector<uint8_t> v = {'[', 'i', 2, 'i', 1};
+ CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 6: unexpected end of input");
+ CHECK(json::from_ubjson(v, true, false).is_discarded());
+ }
+
+ SECTION("objects")
+ {
+ std::vector<uint8_t> vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1};
+ CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at 11: unexpected end of input");
+ CHECK(json::from_ubjson(vST, true, false).is_discarded());
+
+ std::vector<uint8_t> vT = {'{', '$', 'i', 'i', 1, 'a', 1};
+ CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at 4: expected '#' after UBJSON type information; last byte: 0x69");
+ CHECK(json::from_ubjson(vT, true, false).is_discarded());
+
+ std::vector<uint8_t> vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1};
+ CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 10: unexpected end of input");
+ CHECK(json::from_ubjson(vS, true, false).is_discarded());
+
+ std::vector<uint8_t> v = {'{', 'i', 1, 'a', 'i', 1};
+ CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 7: unexpected end of input");
+ CHECK(json::from_ubjson(v, true, false).is_discarded());
+
+ std::vector<uint8_t> v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'};
+ CHECK_THROWS_AS(json::from_ubjson(v2), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at 8: unexpected end of input");
+ CHECK(json::from_ubjson(v2, true, false).is_discarded());
+
+ std::vector<uint8_t> v3 = {'{', 'i', 1, 'a'};
+ CHECK_THROWS_AS(json::from_ubjson(v3), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at 5: unexpected end of input");
+ CHECK(json::from_ubjson(v3, true, false).is_discarded());
+
+ std::vector<uint8_t> vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'};
+ CHECK_THROWS_AS(json::from_ubjson(vST1), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at 10: unexpected end of input");
+ CHECK(json::from_ubjson(vST1, true, false).is_discarded());
+
+ std::vector<uint8_t> vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'};
+ CHECK_THROWS_AS(json::from_ubjson(vST2), json::parse_error&);
+ CHECK_THROWS_WITH(json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at 8: unexpected end of input");
+ CHECK(json::from_ubjson(vST2, true, false).is_discarded());
+ }
}
SECTION("writing optimized values")
@@ -1477,257 +1804,6 @@
}
}
-/*
-// use this testcase outside [hide] to run it with Valgrind
-TEST_CASE("single UBJSON 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_ubjson(filename + ".ubj", std::ios::binary);
- std::vector<uint8_t> packed((std::istreambuf_iterator<char>(f_ubjson)),
- std::istreambuf_iterator<char>());
- json j2;
- CHECK_NOTHROW(j2 = json::from_ubjson(packed));
-
- // compare parsed JSON values
- CHECK(j1 == j2);
-
- SECTION("roundtrips")
- {
- SECTION("std::ostringstream")
- {
- std::ostringstream ss;
- json::to_ubjson(j1, ss);
- json j3 = json::from_ubjson(ss.str());
- CHECK(j1 == j3);
- }
-
- SECTION("std::string")
- {
- std::string s;
- json::to_ubjson(j1, s);
- json j3 = json::from_ubjson(s);
- CHECK(j1 == j3);
- }
- }
-
- // check with different start index
- // packed.insert(packed.begin(), 5, 0xff);
- // CHECK(j1 == json::from_ubjson(packed.begin() + 5, packed.end()));
- }
-}
-*/
-
-/*
-TEST_CASE("UBJSON roundtrips", "[hide]")
-{
- SECTION("input from py-ubjson")
- {
- 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);
-
- SECTION("std::vector<uint8_t>")
- {
- // parse UBJSON file
- std::ifstream f_ubjson(filename + ".ubj", std::ios::binary);
- std::vector<uint8_t> packed(
- (std::istreambuf_iterator<char>(f_ubjson)),
- std::istreambuf_iterator<char>());
- json j2;
- CHECK_NOTHROW(j2 = json::from_ubjson(packed));
-
- // compare parsed JSON values
- CHECK(j1 == j2);
- }
-
- SECTION("std::ifstream")
- {
- // parse UBJSON file
- std::ifstream f_ubjson(filename + ".ubj", std::ios::binary);
- json j2;
- CHECK_NOTHROW(j2 = json::from_ubjson(f_ubjson));
-
- // compare parsed JSON values
- CHECK(j1 == j2);
- }
-
- SECTION("uint8_t* and size")
- {
- // parse UBJSON file
- std::ifstream f_ubjson(filename + ".ubj", std::ios::binary);
- std::vector<uint8_t> packed(
- (std::istreambuf_iterator<char>(f_ubjson)),
- std::istreambuf_iterator<char>());
- json j2;
- CHECK_NOTHROW(j2 = json::from_ubjson({packed.data(), packed.size()}));
-
- // compare parsed JSON values
- CHECK(j1 == j2);
- }
- }
- }
-}
-*/
-
TEST_CASE("Universal Binary JSON Specification Examples 1")
{
SECTION("Null Value")
@@ -2037,40 +2113,6 @@
}
}
-/*
-TEST_CASE("Universal Binary JSON Specification Examples 2")
-{
- for (std::string prefix :
- {
- "test/data/universal-binary-json-java/CouchDB4k",
- "test/data/universal-binary-json-java/MediaContent",
- "test/data/universal-binary-json-java/TwitterTimeline"
- })
- {
- CAPTURE(prefix);
-
- // parse JSON file
- std::ifstream f_json(prefix + ".formatted.json");
- json j1 = json::parse(f_json);
-
- SECTION("std::vector<uint8_t>")
- {
- // parse UBJSON file
- std::ifstream f_ubjson(prefix + ".ubj", std::ios::binary);
- std::vector<uint8_t> packed(
- (std::istreambuf_iterator<char>(f_ubjson)),
- std::istreambuf_iterator<char>());
- json j2;
- CHECK_NOTHROW(j2 = json::from_ubjson(packed));
-
- // compare parsed JSON values
- CHECK(j1 == j2);
- }
- }
-}
-*/
-
-
TEST_CASE("all UBJSON first bytes", "[!throws]")
{
// these bytes will fail immediately with exception parse_error.112
@@ -2157,12 +2199,12 @@
{
CAPTURE(filename);
- // parse JSON file
- std::ifstream f_json(filename);
- json j1 = json::parse(f_json);
-
- SECTION("std::vector<uint8_t>")
+ SECTION(filename + ": std::vector<uint8_t>")
{
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
@@ -2175,8 +2217,12 @@
CHECK(j1 == j2);
}
- SECTION("std::ifstream")
+ SECTION(filename + ": std::ifstream")
{
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
json j2;
@@ -2186,8 +2232,12 @@
CHECK(j1 == j2);
}
- SECTION("uint8_t* and size")
+ SECTION(filename + ": uint8_t* and size")
{
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
@@ -2200,15 +2250,19 @@
CHECK(j1 == j2);
}
- SECTION("output to output adapters")
+ SECTION(filename + ": output to output adapters")
{
+ // parse JSON file
+ std::ifstream f_json(filename);
+ json j1 = json::parse(f_json);
+
// parse MessagePack file
std::ifstream f_ubjson(filename + ".ubjson", std::ios::binary);
std::vector<uint8_t> packed(
(std::istreambuf_iterator<char>(f_ubjson)),
std::istreambuf_iterator<char>());
- SECTION("std::vector<uint8_t>")
+ SECTION(filename + ": output adapters: std::vector<uint8_t>")
{
std::vector<uint8_t> vec;
json::to_ubjson(j1, vec);
diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp
index 9cfc6e9..f59999e 100644
--- a/test/src/unit-udt.cpp
+++ b/test/src/unit-udt.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp
index 95925de..083dec1 100644
--- a/test/src/unit-unicode.cpp
+++ b/test/src/unit-unicode.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/src/unit-wstring.cpp b/test/src/unit-wstring.cpp
new file mode 100644
index 0000000..3e83c93
--- /dev/null
+++ b/test/src/unit-wstring.cpp
@@ -0,0 +1,112 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++ (test suite)
+| | |__ | | | | | | version 3.2.0
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2018 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 <nlohmann/json.hpp>
+
+using nlohmann::json;
+
+bool wstring_is_utf16();
+bool wstring_is_utf16()
+{
+ return (std::wstring(L"๐ฉ") == std::wstring(L"\U0001F4A9"));
+}
+
+bool u16string_is_utf16();
+bool u16string_is_utf16()
+{
+ return (std::u16string(u"๐ฉ") == std::u16string(u"\U0001F4A9"));
+}
+
+bool u32string_is_utf32();
+bool u32string_is_utf32()
+{
+ return (std::u32string(U"๐ฉ") == std::u32string(U"\U0001F4A9"));
+}
+
+TEST_CASE("wide strings")
+{
+ SECTION("std::wstring")
+ {
+ if (wstring_is_utf16())
+ {
+ std::wstring w = L"[12.2,\"แ
aäö๐ค๐งข\"]";
+ json j = json::parse(w);
+ CHECK(j.dump() == "[12.2,\"แ
aäö๐ค๐งข\"]");
+ }
+ }
+
+ SECTION("invalid std::wstring")
+ {
+ if (wstring_is_utf16())
+ {
+ std::wstring w = L"\"\xDBFF";
+ CHECK_THROWS_AS(json::parse(w), json::parse_error&);
+ }
+ }
+
+ SECTION("std::u16string")
+ {
+ if (u16string_is_utf16())
+ {
+ std::u16string w = u"[12.2,\"แ
aäö๐ค๐งข\"]";
+ json j = json::parse(w);
+ CHECK(j.dump() == "[12.2,\"แ
aäö๐ค๐งข\"]");
+ }
+ }
+
+ SECTION("invalid std::u16string")
+ {
+ if (wstring_is_utf16())
+ {
+ std::u16string w = u"\"\xDBFF";
+ CHECK_THROWS_AS(json::parse(w), json::parse_error&);
+ }
+ }
+
+ SECTION("std::u32string")
+ {
+ if (u32string_is_utf32())
+ {
+ std::u32string w = U"[12.2,\"แ
aäö๐ค๐งข\"]";
+ json j = json::parse(w);
+ CHECK(j.dump() == "[12.2,\"แ
aäö๐ค๐งข\"]");
+ }
+ }
+
+ SECTION("invalid std::u32string")
+ {
+ if (u32string_is_utf32())
+ {
+ std::u32string w = U"\"\x110000";
+ CHECK_THROWS_AS(json::parse(w), json::parse_error&);
+ }
+ }
+}
diff --git a/test/src/unit.cpp b/test/src/unit.cpp
index 9565995..4f26dbd 100644
--- a/test/src/unit.cpp
+++ b/test/src/unit.cpp
@@ -1,10 +1,11 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
-| | |__ | | | | | | version 3.1.2
+| | |__ | | | | | | version 3.2.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
Copyright (c) 2013-2018 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/test/thirdparty/catch/catch.hpp b/test/thirdparty/catch/catch.hpp
index 7c351e9..6b5129d 100644
--- a/test/thirdparty/catch/catch.hpp
+++ b/test/thirdparty/catch/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v1.9.7
- * Generated: 2017-08-10 23:49:15.233907
+ * Catch v1.12.0
+ * Generated: 2018-01-11 21:56:34.893972
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -228,7 +228,12 @@
( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \
( defined __clang__ && __clang_major__ >= 3 )
-#define CATCH_INTERNAL_CONFIG_COUNTER
+// Use of __COUNTER__ is suppressed during code analysis in CLion/AppCode 2017.2.x and former,
+// because __COUNTER__ is not properly handled by it.
+// This does not affect compilation
+#if ( !defined __JETBRAINS_IDE__ || __JETBRAINS_IDE__ >= 20170300L )
+ #define CATCH_INTERNAL_CONFIG_COUNTER
+#endif
#endif
@@ -309,10 +314,7 @@
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_UNIQUE_PTR
#endif
-// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
-// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
-// This does not affect compilation
-#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
+#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
@@ -1291,6 +1293,7 @@
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#pragma warning(disable:4018) // more "signed/unsigned mismatch"
#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#endif
@@ -2166,6 +2169,12 @@
};
}
+#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
+# define CATCH_INTERNAL_STRINGIFY(expr) #expr
+#else
+# define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
+#endif
+
#if defined(CATCH_CONFIG_FAST_COMPILE)
///////////////////////////////////////////////////////////////////////////////
// We can speedup compilation significantly by breaking into debugger lower in
@@ -2181,7 +2190,7 @@
// the exception before it propagates back up to the runner.
#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
__catchResult.setExceptionGuard(); \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
@@ -2193,9 +2202,9 @@
#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
__catchResult.setExceptionGuard(); \
- __catchResult.captureMatch( arg, matcher, #matcher ); \
+ __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
__catchResult.unsetExceptionGuard(); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
@@ -2214,7 +2223,7 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
try { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
@@ -2240,7 +2249,7 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
try { \
static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
@@ -2254,7 +2263,7 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \
if( __catchResult.allowThrows() ) \
try { \
static_cast<void>(expr); \
@@ -2271,7 +2280,7 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
if( __catchResult.allowThrows() ) \
try { \
static_cast<void>(expr); \
@@ -2314,9 +2323,9 @@
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
try { \
- __catchResult.captureMatch( arg, matcher, #matcher ); \
+ __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
} catch( ... ) { \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
} \
@@ -2822,7 +2831,8 @@
if (relativeOK) {
return true;
}
- return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
+
+ return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin;
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
@@ -2894,7 +2904,7 @@
if (relativeOK) {
return true;
}
- return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
+ return std::fabs(lhs - rhs.m_value) <= rhs.m_margin;
}
friend bool operator == ( Approx const& lhs, double rhs ) {
@@ -3852,6 +3862,12 @@
Yes,
No
}; };
+ struct WaitForKeypress { enum When {
+ Never,
+ BeforeStart = 1,
+ BeforeExit = 2,
+ BeforeStartAndExit = BeforeStart | BeforeExit
+ }; };
class TestSpec;
@@ -3965,13 +3981,15 @@
showHelp( false ),
showInvisibles( false ),
filenamesAsTags( false ),
+ libIdentify( false ),
abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder ),
- useColour( UseColour::Auto )
+ useColour( UseColour::Auto ),
+ waitForKeypress( WaitForKeypress::Never )
{}
bool listTests;
@@ -3986,6 +4004,7 @@
bool showHelp;
bool showInvisibles;
bool filenamesAsTags;
+ bool libIdentify;
int abortAfter;
unsigned int rngSeed;
@@ -3995,6 +4014,7 @@
ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
UseColour::YesOrNo useColour;
+ WaitForKeypress::When waitForKeypress;
std::string outputFilename;
std::string name;
@@ -5188,6 +5208,18 @@
else
throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
}
+ inline void setWaitForKeypress( ConfigData& config, std::string const& keypress ) {
+ std::string keypressLc = toLower( keypress );
+ if( keypressLc == "start" )
+ config.waitForKeypress = WaitForKeypress::BeforeStart;
+ else if( keypressLc == "exit" )
+ config.waitForKeypress = WaitForKeypress::BeforeExit;
+ else if( keypressLc == "both" )
+ config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
+ else
+ throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
+ };
+
inline void forceColour( ConfigData& config ) {
config.useColour = UseColour::Yes;
}
@@ -5323,6 +5355,14 @@
.describe( "should output be colourised" )
.bind( &setUseColour, "yes|no" );
+ cli["--libidentify"]
+ .describe( "report name and version according to libidentify standard" )
+ .bind( &ConfigData::libIdentify );
+
+ cli["--wait-for-keypress"]
+ .describe( "waits for a keypress before exiting" )
+ .bind( &setWaitForKeypress, "start|exit|both" );
+
return cli;
}
@@ -6700,7 +6740,10 @@
m_totals.assertions.passed++;
}
else if( !result.isOk() ) {
- m_totals.assertions.failed++;
+ if( m_activeTestCase->getTestCaseInfo().okToFail() )
+ m_totals.assertions.failedButOk++;
+ else
+ m_totals.assertions.failed++;
}
// We have no use for the return value (whether messages should be cleared), because messages were made scoped
@@ -6889,12 +6932,6 @@
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
- if( testCaseInfo.okToFail() ) {
- std::swap( assertions.failedButOk, assertions.failed );
- m_totals.assertions.failed -= assertions.failedButOk;
- m_totals.assertions.failedButOk += assertions.failedButOk;
- }
-
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
@@ -7101,6 +7138,13 @@
m_cli.usage( Catch::cout(), processName );
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
}
+ void libIdentify() {
+ Catch::cout()
+ << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
+ << std::left << std::setw(16) << "category: " << "testframework\n"
+ << std::left << std::setw(16) << "framework: " << "Catch Test\n"
+ << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
+ }
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
@@ -7108,6 +7152,8 @@
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
if( m_configData.showHelp )
showHelp( m_configData.processName );
+ if( m_configData.libIdentify )
+ libIdentify();
m_config.reset();
}
catch( std::exception& ex ) {
@@ -7164,7 +7210,36 @@
#endif
int run() {
- if( m_configData.showHelp )
+ if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
+ Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
+ static_cast<void>(std::getchar());
+ }
+ int exitCode = runInternal();
+ if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
+ Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
+ static_cast<void>(std::getchar());
+ }
+ return exitCode;
+ }
+
+ Clara::CommandLine<ConfigData> const& cli() const {
+ return m_cli;
+ }
+ std::vector<Clara::Parser::Token> const& unusedTokens() const {
+ return m_unusedTokens;
+ }
+ ConfigData& configData() {
+ return m_configData;
+ }
+ Config& config() {
+ if( !m_config )
+ m_config = new Config( m_configData );
+ return *m_config;
+ }
+ private:
+
+ int runInternal() {
+ if( m_configData.showHelp || m_configData.libIdentify )
return 0;
try
@@ -7188,21 +7263,6 @@
}
}
- Clara::CommandLine<ConfigData> const& cli() const {
- return m_cli;
- }
- std::vector<Clara::Parser::Token> const& unusedTokens() const {
- return m_unusedTokens;
- }
- ConfigData& configData() {
- return m_configData;
- }
- Config& config() {
- if( !m_config )
- m_config = new Config( m_configData );
- return *m_config;
- }
- private:
Clara::CommandLine<ConfigData> m_cli;
std::vector<Clara::Parser::Token> m_unusedTokens;
ConfigData m_configData;
@@ -7227,7 +7287,7 @@
namespace Catch {
struct RandomNumberGenerator {
- typedef std::ptrdiff_t result_type;
+ typedef unsigned int result_type;
result_type operator()( result_type n ) const { return std::rand() % n; }
@@ -8148,7 +8208,7 @@
std::string AssertionResult::getExpression() const {
if( isFalseTest( m_info.resultDisposition ) )
- return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
+ return "!(" + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + ")";
else
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
}
@@ -8406,7 +8466,7 @@
}
inline Version libraryVersion() {
- static Version version( 1, 9, 7, "", 0 );
+ static Version version( 1, 12, 0, "", 0 );
return version;
}
@@ -10220,12 +10280,12 @@
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
- if( includeResults ) {
+ if( includeResults || result.getResultType() == ResultWas::Warning ) {
// Print any info messages in <Info> tags.
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd;
++it ) {
- if( it->type == ResultWas::Info ) {
+ if( it->type == ResultWas::Info && includeResults ) {
m_xml.scopedElement( "Info" )
.writeText( it->message );
} else if ( it->type == ResultWas::Warning ) {