Unverified Commit 039e2f03 by Niels Lohmann

Merge branch 'develop' into feature/update

parents e523312f 7f4722a7
...@@ -120,6 +120,9 @@ matrix: ...@@ -120,6 +120,9 @@ matrix:
compiler: clang compiler: clang
before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt before_install: echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
addons: addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['g++-6', 'clang-3.6']
coverity_scan: coverity_scan:
project: project:
name: "nlohmann/json" name: "nlohmann/json"
...@@ -129,8 +132,8 @@ matrix: ...@@ -129,8 +132,8 @@ matrix:
build_command: "make" build_command: "make"
branch_pattern: coverity_scan branch_pattern: coverity_scan
env: env:
- LLVM_VERSION=3.6.0
- SPECIAL=coverity - SPECIAL=coverity
- COMPILER=clang++-3.6
# OSX / Clang # OSX / Clang
...@@ -202,119 +205,71 @@ matrix: ...@@ -202,119 +205,71 @@ matrix:
# Linux / Clang # Linux / Clang
- os: linux - os: linux
env: LLVM_VERSION=3.6.0
compiler: clang compiler: clang
env: COMPILER=clang++-3.5
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.5']
packages: ['g++-6', 'clang-3.5']
- os: linux - os: linux
env: LLVM_VERSION=3.6.1
compiler: clang compiler: clang
env: COMPILER=clang++-3.6
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
packages: ['g++-6', 'clang-3.6']
- os: linux - os: linux
env: LLVM_VERSION=3.6.2
compiler: clang compiler: clang
env: COMPILER=clang++-3.7
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7']
packages: ['g++-6', 'clang-3.7']
- os: linux - os: linux
env: LLVM_VERSION=3.7.0
compiler: clang compiler: clang
env: COMPILER=clang++-3.8
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.8']
- os: linux - os: linux
env: LLVM_VERSION=3.7.1
compiler: clang compiler: clang
env: COMPILER=clang++-3.9
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'clang-3.9']
- os: linux - os: linux
env: LLVM_VERSION=3.8.0
compiler: clang compiler: clang
env: COMPILER=clang++-4.0
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
packages: ['g++-6', 'clang-4.0']
- os: linux - os: linux
env: LLVM_VERSION=3.8.1
compiler: clang compiler: clang
env:
# - os: linux - COMPILER=clang++-4.0
# addons: - CXXFLAGS=-std=c++1z
# apt: addons:
# sources: llvm-toolchain-trusty-3.9 apt:
# packages: clang-3.9 sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0']
# env: COMPILER=clang++-3.9 packages: ['g++-6', 'clang-4.0']
#
# - os: linux
# addons:
# apt:
# sources: llvm-toolchain-trusty-4.0
# packages: clang-4.0
# env: COMPILER=clang++-4.0
#
# - os: linux
# addons:
# apt:
# sources: llvm-toolchain-trusty
# packages: clang-5.0
# env: COMPILER=clang++-5.0
#####################
# installation step #
#####################
# set directories to cache
cache:
directories:
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.2
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.1
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.6.0
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.0
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.7.1
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.0
- ${TRAVIS_BUILD_DIR}/deps/llvm-3.8.1
install:
# create deps dir if not existing
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- mkdir -p ${DEPS_DIR}
# make sure CXX is correctly set
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
# get CMake (only for systems with brew - macOS)
- |
if [[ !(-x $(which cmake)) && (-x $(which brew)) ]]; then
brew update
brew install cmake
cmake --version
fi
# install LLVM/clang when LLVM_VERSION is set
- |
if [[ "${LLVM_VERSION}" != "" ]]; then
LLVM_DIR=${DEPS_DIR}/llvm-${LLVM_VERSION}
if [[ -z "$(ls -A ${LLVM_DIR})" ]]; then
travis_retry wget --quiet https://cmake.org/files/v3.6/cmake-3.6.1.tar.gz
tar xfz cmake-3.6.1.tar.gz
(cd cmake-3.6.1 && ./configure --prefix=${LLVM_DIR}/cmake && make install)
export PATH="${LLVM_DIR}/cmake/bin:${PATH}"
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
CLANG_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz"
mkdir -p ${LLVM_DIR} ${LLVM_DIR}/build ${LLVM_DIR}/projects/libcxx ${LLVM_DIR}/projects/libcxxabi ${LLVM_DIR}/clang
travis_retry wget --quiet -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}
travis_retry wget --quiet -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/projects/libcxx
travis_retry wget --quiet -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/projects/libcxxabi
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xJ -C ${LLVM_DIR}/clang
(cd ${LLVM_DIR}/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_DIR}/install -DCMAKE_CXX_COMPILER=clang++)
(cd ${LLVM_DIR}/build/projects/libcxx && make install -j2)
(cd ${LLVM_DIR}/build/projects/libcxxabi && make install -j2)
fi
export CXXFLAGS="-nostdinc++ -isystem ${LLVM_DIR}/install/include/c++/v1"
export LDFLAGS="-L ${LLVM_DIR}/install/lib -l c++ -l c++abi"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_DIR}/install/lib"
export PATH="${LLVM_DIR}/clang/bin:${PATH}"
fi
################ ################
# build script # # build script #
################ ################
script: script:
# make sure CXX is correctly set
- if [[ "${COMPILER}" != "" ]]; then export CXX=${COMPILER}; fi
# show OS/compiler version # show OS/compiler version
- uname -a - uname -a
- $CXX --version - $CXX --version
......
...@@ -368,7 +368,7 @@ json j_umset(c_umset); // both entries for "one" are used ...@@ -368,7 +368,7 @@ json j_umset(c_umset); // both entries for "one" are used
// maybe ["one", "two", "one", "four"] // maybe ["one", "two", "one", "four"]
``` ```
Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON types (see examples above) can be used to to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container. Likewise, any associative key-value containers (`std::map`, `std::multimap`, `std::unordered_map`, `std::unordered_multimap`) whose keys can construct an `std::string` and whose values can be used to construct JSON types (see examples above) can be used to create a JSON object. Note that in case of multimaps only one key is used in the JSON object and the value depends on the internal order of the STL container.
```cpp ```cpp
std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} }; std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
...@@ -712,7 +712,7 @@ json j_from_msgpack = json::from_msgpack(v_msgpack); ...@@ -712,7 +712,7 @@ json j_from_msgpack = json::from_msgpack(v_msgpack);
Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work: Though it's 2016 already, the support for C++11 is still a bit sparse. Currently, the following compilers are known to work:
- GCC 4.9 - 7.1 (and possibly later) - GCC 4.9 - 7.1 (and possibly later)
- Clang 3.4 - 3.9 (and possibly later) - Clang 3.4 - 4.0 (and possibly later)
- Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later) - Microsoft Visual C++ 2015 / Build Tools 14.0.25123.0 (and possibly later)
- Microsoft Visual C++ 2017 / Build Tools 15.1.548.43366 (and possibly later) - Microsoft Visual C++ 2017 / Build Tools 15.1.548.43366 (and possibly later)
...@@ -741,13 +741,12 @@ The following compilers are currently used in continuous integration at [Travis] ...@@ -741,13 +741,12 @@ The following compilers are currently used in continuous integration at [Travis]
| GCC 5.4.1 | Ubuntu 14.04.5 LTS | g++-5 (Ubuntu 5.4.1-2ubuntu1~14.04) 5.4.1 20160904 | | 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 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 | GCC 7.1.0 | Ubuntu 14.04.5 LTS | g++-7 (Ubuntu 7.1.0-5ubuntu2~14.04) 7.1.0
| Clang 3.6.0 | Ubuntu 14.04.5 LTS | clang version 3.6.0 (tags/RELEASE_360/final) | | Clang 3.5.0 | Ubuntu 14.04.5 LTS | clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) |
| Clang 3.6.1 | Ubuntu 14.04.5 LTS | clang version 3.6.1 (tags/RELEASE_361/final) | | Clang 3.6.2 | Ubuntu 14.04.5 LTS | clang version 3.6.2-svn240577-1~exp1 (branches/release_36) |
| Clang 3.6.2 | Ubuntu 14.04.5 LTS | clang version 3.6.2 (tags/RELEASE_362/final) | | Clang 3.7.1 | Ubuntu 14.04.5 LTS | clang version 3.7.1-svn253571-1~exp1 (branches/release_37) |
| Clang 3.7.0 | Ubuntu 14.04.5 LTS | clang version 3.7.0 (tags/RELEASE_370/final) | | Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0-2ubuntu3~trusty5 (tags/RELEASE_380/final) |
| Clang 3.7.1 | Ubuntu 14.04.5 LTS | clang version 3.7.1 (tags/RELEASE_371/final) | | Clang 3.9.1 | Ubuntu 14.04.5 LTS | clang version 3.9.1-4ubuntu3~14.04.2 (tags/RELEASE_391/rc2) |
| Clang 3.8.0 | Ubuntu 14.04.5 LTS | clang version 3.8.0 (tags/RELEASE_380/final) | | Clang 4.0.1 | Ubuntu 14.04.5 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
| Clang 3.8.1 | Ubuntu 14.04.5 LTS | clang version 3.8.1 (tags/RELEASE_381/final) |
| 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 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 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.0 | Darwin Kernel Version 15.6.0 | Apple LLVM version 8.0.0 (clang-800.0.38) |
...@@ -854,6 +853,11 @@ I deeply appreciate the help of the following people. ...@@ -854,6 +853,11 @@ I deeply appreciate the help of the following people.
- [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`. - [Oleg Endo](https://github.com/olegendo) reduced the memory consumption by replacing `<iostream>` with `<iosfwd>`.
- [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library. - [dan-42](https://github.com/dan-42) cleaned up the CMake files to simplify including/reusing of the library.
- [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists. - [Nikita Ofitserov](https://github.com/himikof) allowed for moving values from initializer lists.
- [Greg Hurrell](https://github.com/wincent) fixed a typo.
- [Dmitry Kukovinets](https://github.com/DmitryKuk) fixed a typo.
- [kbthomp1](https://github.com/kbthomp1) fixed an issue related to the Intel OSX compiler.
- [Markus Werle](https://github.com/daixtrose) fixed a typo.
- [WebProdPP](https://github.com/WebProdPP) fixed a subtle error in a precondition check.
Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone. Thanks a lot for helping out! Please [let me know](mailto:mail@nlohmann.me) if I forgot someone.
......
...@@ -29,7 +29,7 @@ SOFTWARE. ...@@ -29,7 +29,7 @@ SOFTWARE.
#ifndef NLOHMANN_JSON_HPP #ifndef NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP #define NLOHMANN_JSON_HPP
#include <algorithm> // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform #include <algorithm> // all_of, copy, fill, find, for_each, generate_n, none_of, remove, reverse, transform
#include <array> // array #include <array> // array
#include <cassert> // assert #include <cassert> // assert
#include <ciso646> // and, not, or #include <ciso646> // and, not, or
...@@ -215,7 +215,7 @@ file. ...@@ -215,7 +215,7 @@ file.
Exceptions have ids 1xx. Exceptions have ids 1xx.
name / id | example massage | description name / id | example message | description
------------------------------ | --------------- | ------------------------- ------------------------------ | --------------- | -------------------------
json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
...@@ -272,7 +272,7 @@ class parse_error : public exception ...@@ -272,7 +272,7 @@ class parse_error : public exception
Exceptions have ids 2xx. Exceptions have ids 2xx.
name / id | example massage | description name / id | example message | description
----------------------------------- | --------------- | ------------------------- ----------------------------------- | --------------- | -------------------------
json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
...@@ -463,13 +463,8 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept ...@@ -463,13 +463,8 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
}; };
// discarded values are not comparable // discarded values are not comparable
if (lhs == value_t::discarded or rhs == value_t::discarded) return lhs != value_t::discarded and rhs != value_t::discarded and
{ order[static_cast<std::size_t>(lhs)] < order[static_cast<std::size_t>(rhs)];
return false;
}
return order[static_cast<std::size_t>(lhs)] <
order[static_cast<std::size_t>(rhs)];
} }
...@@ -1007,10 +1002,9 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) ...@@ -1007,10 +1002,9 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>()); val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
break; break;
} }
default: default:
{
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
}
} }
} }
...@@ -1080,11 +1074,11 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l) ...@@ -1080,11 +1074,11 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{ {
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
} }
std::transform(j.rbegin(), j.rend(),
for (auto it = j.rbegin(), end = j.rend(); it != end; ++it) std::front_inserter(l), [](const BasicJsonType & i)
{ {
l.push_front(it->template get<T>()); return i.template get<T>();
} });
} }
template<typename BasicJsonType, typename CompatibleArrayType> template<typename BasicJsonType, typename CompatibleArrayType>
...@@ -1198,10 +1192,9 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) ...@@ -1198,10 +1192,9 @@ void from_json(const BasicJsonType& j, ArithmeticType& val)
val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>()); val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
break; break;
} }
default: default:
{
JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name())));
}
} }
} }
...@@ -1629,11 +1622,8 @@ class lexer ...@@ -1629,11 +1622,8 @@ class lexer
return "end of input"; return "end of input";
case token_type::literal_or_value: case token_type::literal_or_value:
return "'[', '{', or a literal"; return "'[', '{', or a literal";
default: default: // catch non-enum values
{
// catch non-enum values
return "unknown token"; // LCOV_EXCL_LINE return "unknown token"; // LCOV_EXCL_LINE
}
} }
} }
...@@ -1682,7 +1672,8 @@ class lexer ...@@ -1682,7 +1672,8 @@ class lexer
assert(current == 'u'); assert(current == 'u');
int codepoint = 0; int codepoint = 0;
for (int factor = 12; factor >= 0; factor -= 4) const auto factors = { 12, 8, 4, 0 };
for (const auto factor : factors)
{ {
get(); get();
...@@ -2339,9 +2330,7 @@ scan_number_zero: ...@@ -2339,9 +2330,7 @@ scan_number_zero:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
}
} }
scan_number_any1: scan_number_any1:
...@@ -2377,9 +2366,7 @@ scan_number_any1: ...@@ -2377,9 +2366,7 @@ scan_number_any1:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
}
} }
scan_number_decimal1: scan_number_decimal1:
...@@ -2436,9 +2423,7 @@ scan_number_decimal2: ...@@ -2436,9 +2423,7 @@ scan_number_decimal2:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
}
} }
scan_number_exponent: scan_number_exponent:
...@@ -2522,9 +2507,7 @@ scan_number_any2: ...@@ -2522,9 +2507,7 @@ scan_number_any2:
} }
default: default:
{
goto scan_number_done; goto scan_number_done;
}
} }
scan_number_done: scan_number_done:
...@@ -2537,11 +2520,12 @@ scan_number_done: ...@@ -2537,11 +2520,12 @@ scan_number_done:
add('\0'); add('\0');
--yylen; --yylen;
char* endptr = nullptr;
errno = 0;
// try to parse integers first and fall back to floats // try to parse integers first and fall back to floats
if (number_type == token_type::value_unsigned) if (number_type == token_type::value_unsigned)
{ {
char* endptr = nullptr;
errno = 0;
const auto x = std::strtoull(yytext.data(), &endptr, 10); const auto x = std::strtoull(yytext.data(), &endptr, 10);
// we checked the number format before // we checked the number format before
...@@ -2558,8 +2542,6 @@ scan_number_done: ...@@ -2558,8 +2542,6 @@ scan_number_done:
} }
else if (number_type == token_type::value_integer) else if (number_type == token_type::value_integer)
{ {
char* endptr = nullptr;
errno = 0;
const auto x = std::strtoll(yytext.data(), &endptr, 10); const auto x = std::strtoll(yytext.data(), &endptr, 10);
// we checked the number format before // we checked the number format before
...@@ -2577,7 +2559,11 @@ scan_number_done: ...@@ -2577,7 +2559,11 @@ scan_number_done:
// this code is reached if we parse a floating-point number or if an // this code is reached if we parse a floating-point number or if an
// integer conversion above failed // integer conversion above failed
strtof(value_float, yytext.data(), nullptr); strtof(value_float, yytext.data(), &endptr);
// we checked the number format before
assert(endptr == yytext.data() + yylen);
return token_type::value_float; return token_type::value_float;
} }
...@@ -2700,7 +2686,7 @@ scan_number_done: ...@@ -2700,7 +2686,7 @@ scan_number_done:
else else
{ {
// add character as is // add character as is
result.append(1, c); result.push_back(c);
} }
} }
...@@ -2851,8 +2837,7 @@ class parser ...@@ -2851,8 +2837,7 @@ class parser
explicit parser(detail::input_adapter_t adapter, explicit parser(detail::input_adapter_t adapter,
const parser_callback_t cb = nullptr, const parser_callback_t cb = nullptr,
const bool allow_exceptions_ = true) const bool allow_exceptions_ = true)
: callback(cb), m_lexer(adapter), : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
allow_exceptions(allow_exceptions_)
{} {}
/*! /*!
...@@ -2911,12 +2896,8 @@ class parser ...@@ -2911,12 +2896,8 @@ class parser
return false; return false;
} }
if (strict and get_token() != token_type::end_of_input) // strict => last token must be EOF
{ return not strict or (get_token() == token_type::end_of_input);
return false;
}
return true;
} }
private: private:
...@@ -3156,10 +3137,7 @@ class parser ...@@ -3156,10 +3137,7 @@ class parser
JSON_THROW(out_of_range::create(406, "number overflow parsing '" + JSON_THROW(out_of_range::create(406, "number overflow parsing '" +
m_lexer.get_token_string() + "'")); m_lexer.get_token_string() + "'"));
} }
else expect(token_type::uninitialized);
{
expect(token_type::uninitialized);
}
} }
break; break;
} }
...@@ -3297,15 +3275,10 @@ class parser ...@@ -3297,15 +3275,10 @@ class parser
case token_type::value_integer: case token_type::value_integer:
case token_type::value_string: case token_type::value_string:
case token_type::value_unsigned: case token_type::value_unsigned:
{
return true; return true;
}
default: default: // the last token was unexpected
{
// the last token was unexpected
return false; return false;
}
} }
} }
...@@ -3740,9 +3713,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3740,9 +3713,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
} }
case value_t::null: case value_t::null:
{
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, "cannot get value"));
}
default: default:
{ {
...@@ -3893,19 +3864,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3893,19 +3864,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
return (m_it.object_iterator == other.m_it.object_iterator); return (m_it.object_iterator == other.m_it.object_iterator);
}
case value_t::array: case value_t::array:
{
return (m_it.array_iterator == other.m_it.array_iterator); return (m_it.array_iterator == other.m_it.array_iterator);
}
default: default:
{
return (m_it.primitive_iterator == other.m_it.primitive_iterator); return (m_it.primitive_iterator == other.m_it.primitive_iterator);
}
} }
} }
...@@ -3935,19 +3900,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3935,19 +3900,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators"));
}
case value_t::array: case value_t::array:
{
return (m_it.array_iterator < other.m_it.array_iterator); return (m_it.array_iterator < other.m_it.array_iterator);
}
default: default:
{
return (m_it.primitive_iterator < other.m_it.primitive_iterator); return (m_it.primitive_iterator < other.m_it.primitive_iterator);
}
} }
} }
...@@ -3989,9 +3948,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -3989,9 +3948,7 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
}
case value_t::array: case value_t::array:
{ {
...@@ -4062,19 +4019,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4062,19 +4019,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators"));
}
case value_t::array: case value_t::array:
{
return m_it.array_iterator - other.m_it.array_iterator; return m_it.array_iterator - other.m_it.array_iterator;
}
default: default:
{
return m_it.primitive_iterator - other.m_it.primitive_iterator; return m_it.primitive_iterator - other.m_it.primitive_iterator;
}
} }
} }
...@@ -4089,19 +4040,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso ...@@ -4089,19 +4040,13 @@ class iter_impl : public std::iterator<std::random_access_iterator_tag, BasicJso
switch (m_object->m_type) switch (m_object->m_type)
{ {
case value_t::object: case value_t::object:
{
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators"));
}
case value_t::array: case value_t::array:
{
return *std::next(m_it.array_iterator, n); return *std::next(m_it.array_iterator, n);
}
case value_t::null: case value_t::null:
{
JSON_THROW(invalid_iterator::create(214, "cannot get value")); JSON_THROW(invalid_iterator::create(214, "cannot get value"));
}
default: default:
{ {
...@@ -4193,21 +4138,15 @@ template<typename IteratorType> class iteration_proxy ...@@ -4193,21 +4138,15 @@ template<typename IteratorType> class iteration_proxy
{ {
// use integer array index as key // use integer array index as key
case value_t::array: case value_t::array:
{
return std::to_string(array_index); return std::to_string(array_index);
}
// use key from the object // use key from the object
case value_t::object: case value_t::object:
{
return anchor.key(); return anchor.key();
}
// use an empty key for all primitive types // use an empty key for all primitive types
default: default:
{
return ""; return "";
}
} }
} }
...@@ -4486,9 +4425,7 @@ class binary_reader ...@@ -4486,9 +4425,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
{
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
}
// Integer 0x00..0x17 (0..23) // Integer 0x00..0x17 (0..23)
case 0x00: case 0x00:
...@@ -4515,29 +4452,19 @@ class binary_reader ...@@ -4515,29 +4452,19 @@ class binary_reader
case 0x15: case 0x15:
case 0x16: case 0x16:
case 0x17: case 0x17:
{
return static_cast<number_unsigned_t>(current); return static_cast<number_unsigned_t>(current);
}
case 0x18: // Unsigned integer (one-byte uint8_t follows) case 0x18: // Unsigned integer (one-byte uint8_t follows)
{
return get_number<uint8_t>(); return get_number<uint8_t>();
}
case 0x19: // Unsigned integer (two-byte uint16_t follows) case 0x19: // Unsigned integer (two-byte uint16_t follows)
{
return get_number<uint16_t>(); return get_number<uint16_t>();
}
case 0x1a: // Unsigned integer (four-byte uint32_t follows) case 0x1a: // Unsigned integer (four-byte uint32_t follows)
{
return get_number<uint32_t>(); return get_number<uint32_t>();
}
case 0x1b: // Unsigned integer (eight-byte uint64_t follows) case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
{
return get_number<uint64_t>(); return get_number<uint64_t>();
}
// Negative integer -1-0x00..-1-0x17 (-1..-24) // Negative integer -1-0x00..-1-0x17 (-1..-24)
case 0x20: case 0x20:
...@@ -4564,9 +4491,7 @@ class binary_reader ...@@ -4564,9 +4491,7 @@ class binary_reader
case 0x35: case 0x35:
case 0x36: case 0x36:
case 0x37: case 0x37:
{
return static_cast<int8_t>(0x20 - 1 - current); return static_cast<int8_t>(0x20 - 1 - current);
}
case 0x38: // Negative integer (one-byte uint8_t follows) case 0x38: // Negative integer (one-byte uint8_t follows)
{ {
...@@ -4650,57 +4575,27 @@ class binary_reader ...@@ -4650,57 +4575,27 @@ class binary_reader
case 0x96: case 0x96:
case 0x97: case 0x97:
{ {
BasicJsonType result = value_t::array; return get_cbor_array(current & 0x1f);
const auto len = static_cast<size_t>(current & 0x1f);
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x98: // array (one-byte uint8_t for n follows) case 0x98: // array (one-byte uint8_t for n follows)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint8_t>());
const auto len = static_cast<size_t>(get_number<uint8_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x99: // array (two-byte uint16_t for n follow) case 0x99: // array (two-byte uint16_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9a: // array (four-byte uint32_t for n follow) case 0x9a: // array (four-byte uint32_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9b: // array (eight-byte uint64_t for n follow) case 0x9b: // array (eight-byte uint64_t for n follow)
{ {
BasicJsonType result = value_t::array; return get_cbor_array(get_number<uint64_t>());
const auto len = static_cast<size_t>(get_number<uint64_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_cbor());
}
return result;
} }
case 0x9f: // array (indefinite length) case 0x9f: // array (indefinite length)
...@@ -4739,67 +4634,27 @@ class binary_reader ...@@ -4739,67 +4634,27 @@ class binary_reader
case 0xb6: case 0xb6:
case 0xb7: case 0xb7:
{ {
BasicJsonType result = value_t::object; return get_cbor_object(current & 0x1f);
const auto len = static_cast<size_t>(current & 0x1f);
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xb8: // map (one-byte uint8_t for n follows) case 0xb8: // map (one-byte uint8_t for n follows)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint8_t>());
const auto len = static_cast<size_t>(get_number<uint8_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xb9: // map (two-byte uint16_t for n follow) case 0xb9: // map (two-byte uint16_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xba: // map (four-byte uint32_t for n follow) case 0xba: // map (four-byte uint32_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xbb: // map (eight-byte uint64_t for n follow) case 0xbb: // map (eight-byte uint64_t for n follow)
{ {
BasicJsonType result = value_t::object; return get_cbor_object(get_number<uint64_t>());
const auto len = static_cast<size_t>(get_number<uint64_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_cbor_string();
result[key] = parse_cbor();
}
return result;
} }
case 0xbf: // map (indefinite length) case 0xbf: // map (indefinite length)
...@@ -4896,9 +4751,7 @@ class binary_reader ...@@ -4896,9 +4751,7 @@ class binary_reader
{ {
// EOF // EOF
case std::char_traits<char>::eof(): case std::char_traits<char>::eof():
{
JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input"));
}
// positive fixint // positive fixint
case 0x00: case 0x00:
...@@ -5029,9 +4882,7 @@ class binary_reader ...@@ -5029,9 +4882,7 @@ class binary_reader
case 0x7d: case 0x7d:
case 0x7e: case 0x7e:
case 0x7f: case 0x7f:
{
return static_cast<number_unsigned_t>(current); return static_cast<number_unsigned_t>(current);
}
// fixmap // fixmap
case 0x80: case 0x80:
...@@ -5051,15 +4902,7 @@ class binary_reader ...@@ -5051,15 +4902,7 @@ class binary_reader
case 0x8e: case 0x8e:
case 0x8f: case 0x8f:
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(current & 0x0f);
const auto len = static_cast<size_t>(current & 0x0f);
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
// fixarray // fixarray
...@@ -5080,13 +4923,7 @@ class binary_reader ...@@ -5080,13 +4923,7 @@ class binary_reader
case 0x9e: case 0x9e:
case 0x9f: case 0x9f:
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(current & 0x0f);
const auto len = static_cast<size_t>(current & 0x0f);
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
// fixstr // fixstr
...@@ -5122,128 +4959,70 @@ class binary_reader ...@@ -5122,128 +4959,70 @@ class binary_reader
case 0xbd: case 0xbd:
case 0xbe: case 0xbe:
case 0xbf: case 0xbf:
{
return get_msgpack_string(); return get_msgpack_string();
}
case 0xc0: // nil case 0xc0: // nil
{
return value_t::null; return value_t::null;
}
case 0xc2: // false case 0xc2: // false
{
return false; return false;
}
case 0xc3: // true case 0xc3: // true
{
return true; return true;
}
case 0xca: // float 32 case 0xca: // float 32
{
return get_number<float>(); return get_number<float>();
}
case 0xcb: // float 64 case 0xcb: // float 64
{
return get_number<double>(); return get_number<double>();
}
case 0xcc: // uint 8 case 0xcc: // uint 8
{
return get_number<uint8_t>(); return get_number<uint8_t>();
}
case 0xcd: // uint 16 case 0xcd: // uint 16
{
return get_number<uint16_t>(); return get_number<uint16_t>();
}
case 0xce: // uint 32 case 0xce: // uint 32
{
return get_number<uint32_t>(); return get_number<uint32_t>();
}
case 0xcf: // uint 64 case 0xcf: // uint 64
{
return get_number<uint64_t>(); return get_number<uint64_t>();
}
case 0xd0: // int 8 case 0xd0: // int 8
{
return get_number<int8_t>(); return get_number<int8_t>();
}
case 0xd1: // int 16 case 0xd1: // int 16
{
return get_number<int16_t>(); return get_number<int16_t>();
}
case 0xd2: // int 32 case 0xd2: // int 32
{
return get_number<int32_t>(); return get_number<int32_t>();
}
case 0xd3: // int 64 case 0xd3: // int 64
{
return get_number<int64_t>(); return get_number<int64_t>();
}
case 0xd9: // str 8 case 0xd9: // str 8
case 0xda: // str 16 case 0xda: // str 16
case 0xdb: // str 32 case 0xdb: // str 32
{
return get_msgpack_string(); return get_msgpack_string();
}
case 0xdc: // array 16 case 0xdc: // array 16
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
case 0xdd: // array 32 case 0xdd: // array 32
{ {
BasicJsonType result = value_t::array; return get_msgpack_array(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
result.push_back(parse_msgpack());
}
return result;
} }
case 0xde: // map 16 case 0xde: // map 16
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(get_number<uint16_t>());
const auto len = static_cast<size_t>(get_number<uint16_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
case 0xdf: // map 32 case 0xdf: // map 32
{ {
BasicJsonType result = value_t::object; return get_msgpack_object(get_number<uint32_t>());
const auto len = static_cast<size_t>(get_number<uint32_t>());
for (std::size_t i = 0; i < len; ++i)
{
get();
auto key = get_msgpack_string();
result[key] = parse_msgpack();
}
return result;
} }
// positive fixint // positive fixint
...@@ -5279,9 +5058,7 @@ class binary_reader ...@@ -5279,9 +5058,7 @@ class binary_reader
case 0xfd: case 0xfd:
case 0xfe: case 0xfe:
case 0xff: case 0xff:
{
return static_cast<int8_t>(current); return static_cast<int8_t>(current);
}
default: // anything else default: // anything else
{ {
...@@ -5373,15 +5150,16 @@ class binary_reader ...@@ -5373,15 +5150,16 @@ class binary_reader
@throw parse_error.110 if input has less than @a len bytes @throw parse_error.110 if input has less than @a len bytes
*/ */
std::string get_string(const std::size_t len) template<typename NumberType>
std::string get_string(const NumberType len)
{ {
std::string result; std::string result;
for (std::size_t i = 0; i < len; ++i) std::generate_n(std::back_inserter(result), len, [this]()
{ {
get(); get();
check_eof(); check_eof();
result.append(1, static_cast<char>(current)); return current;
} });
return result; return result;
} }
...@@ -5429,32 +5207,27 @@ class binary_reader ...@@ -5429,32 +5207,27 @@ class binary_reader
case 0x76: case 0x76:
case 0x77: case 0x77:
{ {
const auto len = static_cast<size_t>(current & 0x1f); return get_string(current & 0x1f);
return get_string(len);
} }
case 0x78: // UTF-8 string (one-byte uint8_t for n follows) case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{ {
const auto len = static_cast<size_t>(get_number<uint8_t>()); return get_string(get_number<uint8_t>());
return get_string(len);
} }
case 0x79: // UTF-8 string (two-byte uint16_t for n follow) case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint16_t>()); return get_string(get_number<uint16_t>());
return get_string(len);
} }
case 0x7a: // UTF-8 string (four-byte uint32_t for n follow) case 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint32_t>()); return get_string(get_number<uint32_t>());
return get_string(len);
} }
case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow) case 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
{ {
const auto len = static_cast<size_t>(get_number<uint64_t>()); return get_string(get_number<uint64_t>());
return get_string(len);
} }
case 0x7f: // UTF-8 string (indefinite length) case 0x7f: // UTF-8 string (indefinite length)
...@@ -5463,7 +5236,7 @@ class binary_reader ...@@ -5463,7 +5236,7 @@ class binary_reader
while (get() != 0xff) while (get() != 0xff)
{ {
check_eof(); check_eof();
result.append(1, static_cast<char>(current)); result.push_back(static_cast<char>(current));
} }
return result; return result;
} }
...@@ -5477,6 +5250,33 @@ class binary_reader ...@@ -5477,6 +5250,33 @@ class binary_reader
} }
} }
template<typename NumberType>
BasicJsonType get_cbor_array(const NumberType len)
{
BasicJsonType result = value_t::array;
std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
{
return parse_cbor();
});
return result;
}
template<typename NumberType>
BasicJsonType get_cbor_object(const NumberType len)
{
BasicJsonType result = value_t::object;
std::generate_n(std::inserter(*result.m_value.object,
result.m_value.object->end()),
len, [this]()
{
get();
auto key = get_cbor_string();
auto val = parse_cbor();
return std::make_pair(std::move(key), std::move(val));
});
return result;
}
/*! /*!
@brief reads a MessagePack string @brief reads a MessagePack string
...@@ -5528,26 +5328,22 @@ class binary_reader ...@@ -5528,26 +5328,22 @@ class binary_reader
case 0xbe: case 0xbe:
case 0xbf: case 0xbf:
{ {
const auto len = static_cast<size_t>(current & 0x1f); return get_string(current & 0x1f);
return get_string(len);
} }
case 0xd9: // str 8 case 0xd9: // str 8
{ {
const auto len = static_cast<size_t>(get_number<uint8_t>()); return get_string(get_number<uint8_t>());
return get_string(len);
} }
case 0xda: // str 16 case 0xda: // str 16
{ {
const auto len = static_cast<size_t>(get_number<uint16_t>()); return get_string(get_number<uint16_t>());
return get_string(len);
} }
case 0xdb: // str 32 case 0xdb: // str 32
{ {
const auto len = static_cast<size_t>(get_number<uint32_t>()); return get_string(get_number<uint32_t>());
return get_string(len);
} }
default: default:
...@@ -5560,6 +5356,33 @@ class binary_reader ...@@ -5560,6 +5356,33 @@ class binary_reader
} }
} }
template<typename NumberType>
BasicJsonType get_msgpack_array(const NumberType len)
{
BasicJsonType result = value_t::array;
std::generate_n(std::back_inserter(*result.m_value.array), len, [this]()
{
return parse_msgpack();
});
return result;
}
template<typename NumberType>
BasicJsonType get_msgpack_object(const NumberType len)
{
BasicJsonType result = value_t::object;
std::generate_n(std::inserter(*result.m_value.object,
result.m_value.object->end()),
len, [this]()
{
get();
auto key = get_msgpack_string();
auto val = parse_msgpack();
return std::make_pair(std::move(key), std::move(val));
});
return result;
}
/*! /*!
@brief check if input ended @brief check if input ended
@throw parse_error.110 if input ended @throw parse_error.110 if input ended
...@@ -5718,9 +5541,8 @@ class binary_writer ...@@ -5718,9 +5541,8 @@ class binary_writer
break; break;
} }
case value_t::number_float: case value_t::number_float: // Double-Precision Float
{ {
// Double-Precision Float
oa->write_character(static_cast<CharType>(0xfb)); oa->write_character(static_cast<CharType>(0xfb));
write_number(j.m_value.number_float); write_number(j.m_value.number_float);
break; break;
...@@ -5844,9 +5666,7 @@ class binary_writer ...@@ -5844,9 +5666,7 @@ class binary_writer
} }
default: default:
{
break; break;
}
} }
} }
...@@ -5857,16 +5677,14 @@ class binary_writer ...@@ -5857,16 +5677,14 @@ class binary_writer
{ {
switch (j.type()) switch (j.type())
{ {
case value_t::null: case value_t::null: // nil
{ {
// nil
oa->write_character(static_cast<CharType>(0xc0)); oa->write_character(static_cast<CharType>(0xc0));
break; break;
} }
case value_t::boolean: case value_t::boolean: // true and false
{ {
// true and false
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xc3) ? static_cast<CharType>(0xc3)
: static_cast<CharType>(0xc2)); : static_cast<CharType>(0xc2));
...@@ -5983,9 +5801,8 @@ class binary_writer ...@@ -5983,9 +5801,8 @@ class binary_writer
break; break;
} }
case value_t::number_float: case value_t::number_float: // float 64
{ {
// float 64
oa->write_character(static_cast<CharType>(0xcb)); oa->write_character(static_cast<CharType>(0xcb));
write_number(j.m_value.number_float); write_number(j.m_value.number_float);
break; break;
...@@ -6088,9 +5905,7 @@ class binary_writer ...@@ -6088,9 +5905,7 @@ class binary_writer
} }
default: default:
{
break; break;
}
} }
} }
...@@ -6212,6 +6027,7 @@ class serializer ...@@ -6212,6 +6027,7 @@ class serializer
// last element // last element
assert(i != val.m_value.object->cend()); assert(i != val.m_value.object->cend());
assert(std::next(i) == val.m_value.object->cend());
o->write_characters(indent_string.c_str(), new_indent); o->write_characters(indent_string.c_str(), new_indent);
o->write_character('\"'); o->write_character('\"');
dump_escaped(i->first, ensure_ascii); dump_escaped(i->first, ensure_ascii);
...@@ -6239,6 +6055,7 @@ class serializer ...@@ -6239,6 +6055,7 @@ class serializer
// last element // last element
assert(i != val.m_value.object->cend()); assert(i != val.m_value.object->cend());
assert(std::next(i) == val.m_value.object->cend());
o->write_character('\"'); o->write_character('\"');
dump_escaped(i->first, ensure_ascii); dump_escaped(i->first, ensure_ascii);
o->write_characters("\":", 2); o->write_characters("\":", 2);
...@@ -6459,7 +6276,7 @@ class serializer ...@@ -6459,7 +6276,7 @@ class serializer
if (bytes == 3) if (bytes == 3)
{ {
// codepoints that need 4 bytes (i.e., 3 additional // codepoints that need 4 bytes (i.e., 3 additional
// bytes) in UTF-8 needs a surrogate pair when \u // bytes) in UTF-8 need a surrogate pair when \u
// escaping is used: from 4 bytes to \uxxxx\uxxxx // escaping is used: from 4 bytes to \uxxxx\uxxxx
// (12 bytes) // (12 bytes)
res += (12 - bytes - 1); res += (12 - bytes - 1);
...@@ -6481,7 +6298,7 @@ class serializer ...@@ -6481,7 +6298,7 @@ class serializer
return res; return res;
} }
static void escape_codepoint(int codepoint, string_t& result, size_t& pos) static void escape_codepoint(int codepoint, string_t& result, std::size_t& pos)
{ {
// expecting a proper codepoint // expecting a proper codepoint
assert(0x00 <= codepoint and codepoint <= 0x10FFFF); assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
...@@ -6563,56 +6380,49 @@ class serializer ...@@ -6563,56 +6380,49 @@ class serializer
{ {
switch (s[i]) switch (s[i])
{ {
// quotation mark (0x22) case '"': // quotation mark (0x22)
case '"':
{ {
result[pos + 1] = '"'; result[pos + 1] = '"';
pos += 2; pos += 2;
break; break;
} }
// reverse solidus (0x5c) case '\\': // reverse solidus (0x5c)
case '\\':
{ {
// nothing to change // nothing to change
pos += 2; pos += 2;
break; break;
} }
// backspace (0x08) case '\b': // backspace (0x08)
case '\b':
{ {
result[pos + 1] = 'b'; result[pos + 1] = 'b';
pos += 2; pos += 2;
break; break;
} }
// formfeed (0x0c) case '\f': // formfeed (0x0c)
case '\f':
{ {
result[pos + 1] = 'f'; result[pos + 1] = 'f';
pos += 2; pos += 2;
break; break;
} }
// newline (0x0a) case '\n': // newline (0x0a)
case '\n':
{ {
result[pos + 1] = 'n'; result[pos + 1] = 'n';
pos += 2; pos += 2;
break; break;
} }
// carriage return (0x0d) case '\r': // carriage return (0x0d)
case '\r':
{ {
result[pos + 1] = 'r'; result[pos + 1] = 'r';
pos += 2; pos += 2;
break; break;
} }
// horizontal tab (0x09) case '\t': // horizontal tab (0x09)
case '\t':
{ {
result[pos + 1] = 't'; result[pos + 1] = 't';
pos += 2; pos += 2;
...@@ -6780,7 +6590,7 @@ class serializer ...@@ -6780,7 +6590,7 @@ class serializer
// negative value indicates an error // negative value indicates an error
assert(len > 0); assert(len > 0);
// check if buffer was large enough // check if buffer was large enough
assert(static_cast<size_t>(len) < number_buffer.size()); assert(static_cast<std::size_t>(len) < number_buffer.size());
// erase thousands separator // erase thousands separator
if (thousands_sep != '\0') if (thousands_sep != '\0')
...@@ -6795,17 +6605,14 @@ class serializer ...@@ -6795,17 +6605,14 @@ class serializer
// convert decimal point to '.' // convert decimal point to '.'
if (decimal_point != '\0' and decimal_point != '.') if (decimal_point != '\0' and decimal_point != '.')
{ {
for (auto& c : number_buffer) const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
if (dec_pos != number_buffer.end())
{ {
if (c == decimal_point) *dec_pos = '.';
{
c = '.';
break;
}
} }
} }
o->write_characters(number_buffer.data(), static_cast<size_t>(len)); o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
// determine if need to append ".0" // determine if need to append ".0"
const bool value_is_int_like = const bool value_is_int_like =
...@@ -7372,6 +7179,9 @@ class basic_json ...@@ -7372,6 +7179,9 @@ class basic_json
friend class ::nlohmann::detail::iter_impl; friend class ::nlohmann::detail::iter_impl;
template<typename BasicJsonType, typename CharType> template<typename BasicJsonType, typename CharType>
friend class ::nlohmann::detail::binary_writer; friend class ::nlohmann::detail::binary_writer;
template<typename BasicJsonType>
friend class ::nlohmann::detail::binary_reader;
/// workaround type for MSVC /// workaround type for MSVC
using basic_json_t = NLOHMANN_BASIC_JSON_TPL; using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
...@@ -7526,10 +7336,10 @@ class basic_json ...@@ -7526,10 +7336,10 @@ class basic_json
result["platform"] = "unknown"; result["platform"] = "unknown";
#endif #endif
#if defined(__clang__) #if defined(__ICC) || defined(__INTEL_COMPILER)
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
#elif defined(__ICC) || defined(__INTEL_COMPILER)
result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
#elif defined(__clang__)
result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
#elif defined(__GNUC__) || defined(__GNUG__) #elif defined(__GNUC__) || defined(__GNUG__)
result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
#elif defined(__HP_cc) || defined(__HP_aCC) #elif defined(__HP_cc) || defined(__HP_aCC)
...@@ -8710,9 +8520,7 @@ class basic_json ...@@ -8710,9 +8520,7 @@ class basic_json
} }
default: default:
{
break; break;
}
} }
switch (m_type) switch (m_type)
...@@ -8762,10 +8570,8 @@ class basic_json ...@@ -8762,10 +8570,8 @@ class basic_json
} }
default: default:
{
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
std::string(first.m_object->type_name()))); std::string(first.m_object->type_name())));
}
} }
assert_invariant(); assert_invariant();
...@@ -8851,9 +8657,7 @@ class basic_json ...@@ -8851,9 +8657,7 @@ class basic_json
} }
default: default:
{
break; break;
}
} }
assert_invariant(); assert_invariant();
...@@ -10648,9 +10452,7 @@ class basic_json ...@@ -10648,9 +10452,7 @@ class basic_json
} }
default: default:
{
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
} }
return result; return result;
...@@ -10758,9 +10560,7 @@ class basic_json ...@@ -10758,9 +10560,7 @@ class basic_json
} }
default: default:
{
JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name())));
}
} }
return result; return result;
...@@ -11529,9 +11329,7 @@ class basic_json ...@@ -11529,9 +11329,7 @@ class basic_json
} }
default: default:
{
break; break;
}
} }
} }
...@@ -12058,7 +11856,7 @@ class basic_json ...@@ -12058,7 +11856,7 @@ class basic_json
// passed iterators must belong to objects // passed iterators must belong to objects
if (JSON_UNLIKELY(not first.m_object->is_object() if (JSON_UNLIKELY(not first.m_object->is_object()
or not first.m_object->is_object())) or not last.m_object->is_object()))
{ {
JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects"));
} }
...@@ -12309,41 +12107,31 @@ class basic_json ...@@ -12309,41 +12107,31 @@ class basic_json
switch (lhs_type) switch (lhs_type)
{ {
case value_t::array: case value_t::array:
{
return (*lhs.m_value.array == *rhs.m_value.array); return (*lhs.m_value.array == *rhs.m_value.array);
}
case value_t::object: case value_t::object:
{
return (*lhs.m_value.object == *rhs.m_value.object); return (*lhs.m_value.object == *rhs.m_value.object);
}
case value_t::null: case value_t::null:
{
return true; return true;
}
case value_t::string: case value_t::string:
{
return (*lhs.m_value.string == *rhs.m_value.string); return (*lhs.m_value.string == *rhs.m_value.string);
}
case value_t::boolean: case value_t::boolean:
{
return (lhs.m_value.boolean == rhs.m_value.boolean); return (lhs.m_value.boolean == rhs.m_value.boolean);
}
case value_t::number_integer: case value_t::number_integer:
{
return (lhs.m_value.number_integer == rhs.m_value.number_integer); return (lhs.m_value.number_integer == rhs.m_value.number_integer);
}
case value_t::number_unsigned: case value_t::number_unsigned:
{
return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned); return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
}
case value_t::number_float: case value_t::number_float:
{
return (lhs.m_value.number_float == rhs.m_value.number_float); return (lhs.m_value.number_float == rhs.m_value.number_float);
}
default: default:
{
return false; return false;
}
} }
} }
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
...@@ -12473,41 +12261,31 @@ class basic_json ...@@ -12473,41 +12261,31 @@ class basic_json
switch (lhs_type) switch (lhs_type)
{ {
case value_t::array: case value_t::array:
{
return (*lhs.m_value.array) < (*rhs.m_value.array); return (*lhs.m_value.array) < (*rhs.m_value.array);
}
case value_t::object: case value_t::object:
{
return *lhs.m_value.object < *rhs.m_value.object; return *lhs.m_value.object < *rhs.m_value.object;
}
case value_t::null: case value_t::null:
{
return false; return false;
}
case value_t::string: case value_t::string:
{
return *lhs.m_value.string < *rhs.m_value.string; return *lhs.m_value.string < *rhs.m_value.string;
}
case value_t::boolean: case value_t::boolean:
{
return lhs.m_value.boolean < rhs.m_value.boolean; return lhs.m_value.boolean < rhs.m_value.boolean;
}
case value_t::number_integer: case value_t::number_integer:
{
return lhs.m_value.number_integer < rhs.m_value.number_integer; return lhs.m_value.number_integer < rhs.m_value.number_integer;
}
case value_t::number_unsigned: case value_t::number_unsigned:
{
return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned; return lhs.m_value.number_unsigned < rhs.m_value.number_unsigned;
}
case value_t::number_float: case value_t::number_float:
{
return lhs.m_value.number_float < rhs.m_value.number_float; return lhs.m_value.number_float < rhs.m_value.number_float;
}
default: default:
{
return false; return false;
}
} }
} }
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float) else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
...@@ -13089,6 +12867,10 @@ class basic_json ...@@ -13089,6 +12867,10 @@ class basic_json
@note The mapping is **complete** in the sense that any JSON value type @note The mapping is **complete** in the sense that any JSON value type
can be converted to a CBOR value. can be converted to a CBOR value.
@note If NaN or Infinity are stored inside a JSON number, they are
serialized properly. This behavior differs from the @ref dump()
function which serializes NaN or Infinity to `null`.
@note The following CBOR types are not used in the conversion: @note The following CBOR types are not used in the conversion:
- byte strings (0x40..0x5f) - byte strings (0x40..0x5f)
- UTF-8 strings terminated by "break" (0x7f) - UTF-8 strings terminated by "break" (0x7f)
...@@ -13116,7 +12898,7 @@ class basic_json ...@@ -13116,7 +12898,7 @@ class basic_json
@sa http://cbor.io @sa http://cbor.io
@sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the @sa @ref from_cbor(const std::vector<uint8_t>&, const size_t) for the
analogous deserialization analogous deserialization
@sa @ref to_msgpack(const basic_json& for the related MessagePack format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
@since version 2.0.9 @since version 2.0.9
*/ */
...@@ -13196,6 +12978,10 @@ class basic_json ...@@ -13196,6 +12978,10 @@ class basic_json
@note Any MessagePack output created @ref to_msgpack can be successfully @note Any MessagePack output created @ref to_msgpack can be successfully
parsed by @ref from_msgpack. parsed by @ref from_msgpack.
@note If NaN or Infinity are stored inside a JSON number, they are
serialized properly. This behavior differs from the @ref dump()
function which serializes NaN or Infinity to `null`.
@param[in] j JSON value to serialize @param[in] j JSON value to serialize
@return MessagePack serialization as byte vector @return MessagePack serialization as byte vector
...@@ -14176,9 +13962,7 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const ...@@ -14176,9 +13962,7 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const
single value; that is, with an empty list of reference tokens. single value; that is, with an empty list of reference tokens.
*/ */
default: default:
{
JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); JSON_THROW(detail::type_error::create(313, "invalid value to unflatten"));
}
} }
} }
...@@ -14250,9 +14034,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14250,9 +14034,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
}
} }
} }
...@@ -14306,9 +14088,7 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14306,9 +14088,7 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
}
} }
} }
...@@ -14363,9 +14143,7 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14363,9 +14143,7 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
}
} }
} }
...@@ -14419,9 +14197,7 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const ...@@ -14419,9 +14197,7 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const
} }
default: default:
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'"));
}
} }
} }
...@@ -14562,8 +14338,10 @@ struct hash<nlohmann::json> ...@@ -14562,8 +14338,10 @@ struct hash<nlohmann::json>
}; };
/// specialization for std::less<value_t> /// specialization for std::less<value_t>
/// @note: do not remove the space after '<',
/// see https://github.com/nlohmann/json/pull/679
template<> template<>
struct less<::nlohmann::detail::value_t> struct less< ::nlohmann::detail::value_t>
{ {
/*! /*!
@brief compare two value_t enum values @brief compare two value_t enum values
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment