mirror of
https://github.com/nlohmann/json.git
synced 2026-04-18 05:58:53 +00:00
Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional
This commit is contained in:
@@ -37,7 +37,7 @@ struct adl_serializer
|
||||
@param[in,out] j JSON value to write to
|
||||
@param[in] val value to read from
|
||||
*/
|
||||
template <typename BasicJsonType, typename ValueType>
|
||||
template<typename BasicJsonType, typename ValueType>
|
||||
static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
|
||||
noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
|
||||
-> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)), void())
|
||||
|
||||
@@ -39,8 +39,7 @@ class byte_container_with_subtype : public BinaryType
|
||||
: container_type(std::move(b))
|
||||
{}
|
||||
|
||||
byte_container_with_subtype(const container_type& b,
|
||||
std::uint8_t subtype) noexcept(noexcept(container_type(b)))
|
||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b)))
|
||||
: container_type(b)
|
||||
, m_subtype(subtype)
|
||||
, m_has_subtype(true)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// Header <ciso646> is removed in C++20.
|
||||
// See <https://github.com/nlohmann/json/issues/2089> for more information.
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
#include <ciso646> // and, not, or
|
||||
#endif
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <utility> // pair, declval
|
||||
#include <valarray> // valarray
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
@@ -26,7 +25,7 @@ namespace detail
|
||||
template<typename BasicJsonType>
|
||||
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_null()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -49,10 +48,10 @@ void from_json(const BasicJsonType& j, std::optional<T>& opt)
|
||||
#endif
|
||||
|
||||
// overloads for basic_json template parameters
|
||||
template<typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t<std::is_arithmetic<ArithmeticType>::value and
|
||||
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int> = 0>
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
{
|
||||
switch (static_cast<value_t>(j))
|
||||
@@ -81,7 +80,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
template<typename BasicJsonType>
|
||||
void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_boolean()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -91,7 +90,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
|
||||
template<typename BasicJsonType>
|
||||
void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -101,13 +100,13 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
|
||||
template <
|
||||
typename BasicJsonType, typename ConstructibleStringType,
|
||||
enable_if_t <
|
||||
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value and
|
||||
not std::is_same<typename BasicJsonType::string_t,
|
||||
ConstructibleStringType>::value,
|
||||
is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
|
||||
!std::is_same<typename BasicJsonType::string_t,
|
||||
ConstructibleStringType>::value,
|
||||
int > = 0 >
|
||||
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -144,10 +143,10 @@ void from_json(const BasicJsonType& j, EnumType& e)
|
||||
|
||||
// forward_list doesn't have an insert method
|
||||
template<typename BasicJsonType, typename T, typename Allocator,
|
||||
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
|
||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -161,18 +160,22 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||
|
||||
// valarray doesn't have an insert method
|
||||
template<typename BasicJsonType, typename T,
|
||||
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
|
||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||
void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||
}
|
||||
l.resize(j.size());
|
||||
std::copy(j.begin(), j.end(), std::begin(l));
|
||||
std::transform(j.begin(), j.end(), std::begin(l),
|
||||
[](const BasicJsonType & elem)
|
||||
{
|
||||
return elem.template get<T>();
|
||||
});
|
||||
}
|
||||
|
||||
template <typename BasicJsonType, typename T, std::size_t N>
|
||||
template<typename BasicJsonType, typename T, std::size_t N>
|
||||
auto from_json(const BasicJsonType& j, T (&arr)[N])
|
||||
-> decltype(j.template get<T>(), void())
|
||||
{
|
||||
@@ -188,7 +191,7 @@ void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_
|
||||
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
|
||||
}
|
||||
|
||||
template <typename BasicJsonType, typename T, std::size_t N>
|
||||
template<typename BasicJsonType, typename T, std::size_t N>
|
||||
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
||||
priority_tag<2> /*unused*/)
|
||||
-> decltype(j.template get<T>(), void())
|
||||
@@ -220,7 +223,7 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
||||
arr = std::move(ret);
|
||||
}
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType>
|
||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
|
||||
priority_tag<0> /*unused*/)
|
||||
{
|
||||
@@ -238,20 +241,20 @@ void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
|
||||
arr = std::move(ret);
|
||||
}
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType,
|
||||
enable_if_t <
|
||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value and
|
||||
not is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value and
|
||||
not is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value and
|
||||
not std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value and
|
||||
not is_basic_json<ConstructibleArrayType>::value,
|
||||
int > = 0 >
|
||||
template < typename BasicJsonType, typename ConstructibleArrayType,
|
||||
enable_if_t <
|
||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
||||
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
|
||||
!is_basic_json<ConstructibleArrayType>::value,
|
||||
int > = 0 >
|
||||
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
||||
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
|
||||
j.template get<typename ConstructibleArrayType::value_type>(),
|
||||
void())
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " +
|
||||
std::string(j.type_name())));
|
||||
@@ -260,10 +263,10 @@ void())
|
||||
from_json_array_impl(j, arr, priority_tag<3> {});
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_binary()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -275,7 +278,7 @@ template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
||||
void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
|
||||
}
|
||||
@@ -297,14 +300,14 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||
// (BooleanType, etc..); note: Is it really necessary to provide explicit
|
||||
// overloads for boolean_t etc. in case of a custom BooleanType which is not
|
||||
// an arithmetic type?
|
||||
template<typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t <
|
||||
std::is_arithmetic<ArithmeticType>::value and
|
||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value and
|
||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value and
|
||||
not std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value and
|
||||
not std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int> = 0>
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t <
|
||||
std::is_arithmetic<ArithmeticType>::value&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||
{
|
||||
switch (static_cast<value_t>(j))
|
||||
@@ -353,19 +356,19 @@ void from_json(const BasicJsonType& j, std::tuple<Args...>& t)
|
||||
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>>
|
||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
||||
typename = enable_if_t < !std::is_constructible <
|
||||
typename BasicJsonType::string_t, Key >::value >>
|
||||
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||
}
|
||||
m.clear();
|
||||
for (const auto& p : j)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
||||
}
|
||||
@@ -373,19 +376,19 @@ void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>&
|
||||
}
|
||||
}
|
||||
|
||||
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>>
|
||||
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
||||
typename = enable_if_t < !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_HEDLEY_UNLIKELY(not j.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
|
||||
}
|
||||
m.clear();
|
||||
for (const auto& p : j)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
|
||||
{
|
||||
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <cmath> // signbit, isfinite
|
||||
#include <cstdint> // intN_t, uintN_t
|
||||
#include <cstring> // memcpy, memmove
|
||||
#include <limits> // numeric_limits
|
||||
#include <type_traits> // conditional
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
@@ -38,7 +36,7 @@ For a detailed description of the algorithm see:
|
||||
namespace dtoa_impl
|
||||
{
|
||||
|
||||
template <typename Target, typename Source>
|
||||
template<typename Target, typename Source>
|
||||
Target reinterpret_bits(const Source source)
|
||||
{
|
||||
static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
|
||||
@@ -63,8 +61,8 @@ struct diyfp // f * 2^e
|
||||
*/
|
||||
static diyfp sub(const diyfp& x, const diyfp& y) noexcept
|
||||
{
|
||||
assert(x.e == y.e);
|
||||
assert(x.f >= y.f);
|
||||
JSON_ASSERT(x.e == y.e);
|
||||
JSON_ASSERT(x.f >= y.f);
|
||||
|
||||
return {x.f - y.f, x.e};
|
||||
}
|
||||
@@ -140,7 +138,7 @@ struct diyfp // f * 2^e
|
||||
*/
|
||||
static diyfp normalize(diyfp x) noexcept
|
||||
{
|
||||
assert(x.f != 0);
|
||||
JSON_ASSERT(x.f != 0);
|
||||
|
||||
while ((x.f >> 63u) == 0)
|
||||
{
|
||||
@@ -159,8 +157,8 @@ struct diyfp // f * 2^e
|
||||
{
|
||||
const int delta = x.e - target_exponent;
|
||||
|
||||
assert(delta >= 0);
|
||||
assert(((x.f << delta) >> delta) == x.f);
|
||||
JSON_ASSERT(delta >= 0);
|
||||
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
|
||||
|
||||
return {x.f << delta, target_exponent};
|
||||
}
|
||||
@@ -179,11 +177,11 @@ boundaries.
|
||||
|
||||
@pre value must be finite and positive
|
||||
*/
|
||||
template <typename FloatType>
|
||||
template<typename FloatType>
|
||||
boundaries compute_boundaries(FloatType value)
|
||||
{
|
||||
assert(std::isfinite(value));
|
||||
assert(value > 0);
|
||||
JSON_ASSERT(std::isfinite(value));
|
||||
JSON_ASSERT(value > 0);
|
||||
|
||||
// Convert the IEEE representation into a diyfp.
|
||||
//
|
||||
@@ -232,7 +230,7 @@ boundaries compute_boundaries(FloatType value)
|
||||
// -----------------+------+------+-------------+-------------+--- (B)
|
||||
// v- m- v m+ v+
|
||||
|
||||
const bool lower_boundary_is_closer = F == 0 and E > 1;
|
||||
const bool lower_boundary_is_closer = F == 0 && E > 1;
|
||||
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
||||
const diyfp m_minus = lower_boundary_is_closer
|
||||
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
||||
@@ -463,18 +461,18 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
||||
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
|
||||
// for |e| <= 1500, but doesn't require floating-point operations.
|
||||
// NB: log_10(2) ~= 78913 / 2^18
|
||||
assert(e >= -1500);
|
||||
assert(e <= 1500);
|
||||
JSON_ASSERT(e >= -1500);
|
||||
JSON_ASSERT(e <= 1500);
|
||||
const int f = kAlpha - e - 1;
|
||||
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
|
||||
|
||||
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
|
||||
assert(index >= 0);
|
||||
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
|
||||
JSON_ASSERT(index >= 0);
|
||||
JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
|
||||
|
||||
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
|
||||
assert(kAlpha <= cached.e + e + 64);
|
||||
assert(kGamma >= cached.e + e + 64);
|
||||
JSON_ASSERT(kAlpha <= cached.e + e + 64);
|
||||
JSON_ASSERT(kGamma >= cached.e + e + 64);
|
||||
|
||||
return cached;
|
||||
}
|
||||
@@ -542,10 +540,10 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
|
||||
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
||||
std::uint64_t rest, std::uint64_t ten_k)
|
||||
{
|
||||
assert(len >= 1);
|
||||
assert(dist <= delta);
|
||||
assert(rest <= delta);
|
||||
assert(ten_k > 0);
|
||||
JSON_ASSERT(len >= 1);
|
||||
JSON_ASSERT(dist <= delta);
|
||||
JSON_ASSERT(rest <= delta);
|
||||
JSON_ASSERT(ten_k > 0);
|
||||
|
||||
// <--------------------------- delta ---->
|
||||
// <---- dist --------->
|
||||
@@ -567,10 +565,10 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
|
||||
// integer arithmetic.
|
||||
|
||||
while (rest < dist
|
||||
and delta - rest >= ten_k
|
||||
and (rest + ten_k < dist or dist - rest > rest + ten_k - dist))
|
||||
&& delta - rest >= ten_k
|
||||
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
|
||||
{
|
||||
assert(buf[len - 1] != '0');
|
||||
JSON_ASSERT(buf[len - 1] != '0');
|
||||
buf[len - 1]--;
|
||||
rest += ten_k;
|
||||
}
|
||||
@@ -598,8 +596,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
// Grisu2 generates the digits of M+ from left to right and stops as soon as
|
||||
// V is in [M-,M+].
|
||||
|
||||
assert(M_plus.e >= kAlpha);
|
||||
assert(M_plus.e <= kGamma);
|
||||
JSON_ASSERT(M_plus.e >= kAlpha);
|
||||
JSON_ASSERT(M_plus.e <= kGamma);
|
||||
|
||||
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
||||
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
||||
@@ -620,7 +618,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
//
|
||||
// Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
|
||||
|
||||
assert(p1 > 0);
|
||||
JSON_ASSERT(p1 > 0);
|
||||
|
||||
std::uint32_t pow10;
|
||||
const int k = find_largest_pow10(p1, pow10);
|
||||
@@ -656,7 +654,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
||||
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
||||
//
|
||||
assert(d <= 9);
|
||||
JSON_ASSERT(d <= 9);
|
||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||
//
|
||||
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
|
||||
@@ -743,7 +741,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
//
|
||||
// and stop as soon as 10^-m * r * 2^e <= delta * 2^e
|
||||
|
||||
assert(p2 > delta);
|
||||
JSON_ASSERT(p2 > delta);
|
||||
|
||||
int m = 0;
|
||||
for (;;)
|
||||
@@ -754,7 +752,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
|
||||
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
|
||||
//
|
||||
assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
||||
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
||||
p2 *= 10;
|
||||
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
||||
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
||||
@@ -763,7 +761,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
||||
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||
//
|
||||
assert(d <= 9);
|
||||
JSON_ASSERT(d <= 9);
|
||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||
//
|
||||
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||
@@ -824,8 +822,8 @@ JSON_HEDLEY_NON_NULL(1)
|
||||
inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
||||
diyfp m_minus, diyfp v, diyfp m_plus)
|
||||
{
|
||||
assert(m_plus.e == m_minus.e);
|
||||
assert(m_plus.e == v.e);
|
||||
JSON_ASSERT(m_plus.e == m_minus.e);
|
||||
JSON_ASSERT(m_plus.e == v.e);
|
||||
|
||||
// --------(-----------------------+-----------------------)-------- (A)
|
||||
// m- v m+
|
||||
@@ -879,15 +877,15 @@ v = buf * 10^decimal_exponent
|
||||
len is the length of the buffer (number of decimal digits)
|
||||
The buffer must be large enough, i.e. >= max_digits10.
|
||||
*/
|
||||
template <typename FloatType>
|
||||
template<typename FloatType>
|
||||
JSON_HEDLEY_NON_NULL(1)
|
||||
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
|
||||
{
|
||||
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
|
||||
"internal error: not enough precision");
|
||||
|
||||
assert(std::isfinite(value));
|
||||
assert(value > 0);
|
||||
JSON_ASSERT(std::isfinite(value));
|
||||
JSON_ASSERT(value > 0);
|
||||
|
||||
// If the neighbors (and boundaries) of 'value' are always computed for double-precision
|
||||
// numbers, all float's can be recovered using strtod (and strtof). However, the resulting
|
||||
@@ -923,8 +921,8 @@ JSON_HEDLEY_NON_NULL(1)
|
||||
JSON_HEDLEY_RETURNS_NON_NULL
|
||||
inline char* append_exponent(char* buf, int e)
|
||||
{
|
||||
assert(e > -1000);
|
||||
assert(e < 1000);
|
||||
JSON_ASSERT(e > -1000);
|
||||
JSON_ASSERT(e < 1000);
|
||||
|
||||
if (e < 0)
|
||||
{
|
||||
@@ -976,8 +974,8 @@ JSON_HEDLEY_RETURNS_NON_NULL
|
||||
inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||
int min_exp, int max_exp)
|
||||
{
|
||||
assert(min_exp < 0);
|
||||
assert(max_exp > 0);
|
||||
JSON_ASSERT(min_exp < 0);
|
||||
JSON_ASSERT(max_exp > 0);
|
||||
|
||||
const int k = len;
|
||||
const int n = len + decimal_exponent;
|
||||
@@ -986,7 +984,7 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||
// k is the length of the buffer (number of decimal digits)
|
||||
// n is the position of the decimal point relative to the start of the buffer.
|
||||
|
||||
if (k <= n and n <= max_exp)
|
||||
if (k <= n && n <= max_exp)
|
||||
{
|
||||
// digits[000]
|
||||
// len <= max_exp + 2
|
||||
@@ -998,19 +996,19 @@ inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
||||
return buf + (static_cast<size_t>(n) + 2);
|
||||
}
|
||||
|
||||
if (0 < n and n <= max_exp)
|
||||
if (0 < n && n <= max_exp)
|
||||
{
|
||||
// dig.its
|
||||
// len <= max_digits10 + 1
|
||||
|
||||
assert(k > n);
|
||||
JSON_ASSERT(k > n);
|
||||
|
||||
std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
|
||||
buf[n] = '.';
|
||||
return buf + (static_cast<size_t>(k) + 1U);
|
||||
}
|
||||
|
||||
if (min_exp < n and n <= 0)
|
||||
if (min_exp < n && n <= 0)
|
||||
{
|
||||
// 0.[000]digits
|
||||
// len <= 2 + (-min_exp - 1) + max_digits10
|
||||
@@ -1055,13 +1053,13 @@ format. Returns an iterator pointing past-the-end of the decimal representation.
|
||||
@note The buffer must be large enough.
|
||||
@note The result is NOT null-terminated.
|
||||
*/
|
||||
template <typename FloatType>
|
||||
template<typename FloatType>
|
||||
JSON_HEDLEY_NON_NULL(1, 2)
|
||||
JSON_HEDLEY_RETURNS_NON_NULL
|
||||
char* to_chars(char* first, const char* last, FloatType value)
|
||||
{
|
||||
static_cast<void>(last); // maybe unused - fix warning
|
||||
assert(std::isfinite(value));
|
||||
JSON_ASSERT(std::isfinite(value));
|
||||
|
||||
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
||||
if (std::signbit(value))
|
||||
@@ -1079,7 +1077,7 @@ char* to_chars(char* first, const char* last, FloatType value)
|
||||
return first;
|
||||
}
|
||||
|
||||
assert(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
||||
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
||||
|
||||
// Compute v = buffer * 10^decimal_exponent.
|
||||
// The decimal digits are stored in the buffer, which needs to be interpreted
|
||||
@@ -1089,16 +1087,16 @@ char* to_chars(char* first, const char* last, FloatType value)
|
||||
int decimal_exponent = 0;
|
||||
dtoa_impl::grisu2(first, len, decimal_exponent, value);
|
||||
|
||||
assert(len <= std::numeric_limits<FloatType>::max_digits10);
|
||||
JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
|
||||
|
||||
// Format the buffer like printf("%.*g", prec, value)
|
||||
constexpr int kMinExp = -4;
|
||||
// Use digits10 here to increase compatibility with version 2.
|
||||
constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
|
||||
|
||||
assert(last - first >= kMaxExp + 2);
|
||||
assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
||||
assert(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
||||
JSON_ASSERT(last - first >= kMaxExp + 2);
|
||||
JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
|
||||
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
|
||||
|
||||
return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <valarray> // valarray
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
@@ -56,9 +55,9 @@ struct external_constructor<value_t::string>
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename CompatibleStringType,
|
||||
enable_if_t<not std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
|
||||
int> = 0>
|
||||
template < typename BasicJsonType, typename CompatibleStringType,
|
||||
enable_if_t < !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;
|
||||
@@ -144,9 +143,9 @@ struct external_constructor<value_t::array>
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename CompatibleArrayType,
|
||||
enable_if_t<not std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
|
||||
int> = 0>
|
||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
|
||||
int > = 0 >
|
||||
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||
{
|
||||
using std::begin;
|
||||
@@ -203,8 +202,8 @@ struct external_constructor<value_t::object>
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename CompatibleObjectType,
|
||||
enable_if_t<not std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
|
||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
||||
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
|
||||
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||
{
|
||||
using std::begin;
|
||||
@@ -291,20 +290,20 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e)
|
||||
external_constructor<value_t::array>::construct(j, e);
|
||||
}
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleArrayType,
|
||||
enable_if_t<is_compatible_array_type<BasicJsonType,
|
||||
CompatibleArrayType>::value and
|
||||
not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
|
||||
not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
|
||||
not std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value and
|
||||
not is_basic_json<CompatibleArrayType>::value,
|
||||
int> = 0>
|
||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
||||
enable_if_t < is_compatible_array_type<BasicJsonType,
|
||||
CompatibleArrayType>::value&&
|
||||
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
|
||||
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
|
||||
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
|
||||
!is_basic_json<CompatibleArrayType>::value,
|
||||
int > = 0 >
|
||||
void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||
{
|
||||
external_constructor<value_t::array>::construct(j, arr);
|
||||
}
|
||||
|
||||
template <typename BasicJsonType>
|
||||
template<typename BasicJsonType>
|
||||
void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
|
||||
{
|
||||
external_constructor<value_t::binary>::construct(j, bin);
|
||||
@@ -323,8 +322,8 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||
external_constructor<value_t::array>::construct(j, std::move(arr));
|
||||
}
|
||||
|
||||
template<typename BasicJsonType, typename CompatibleObjectType,
|
||||
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
|
||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
||||
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
|
||||
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||
{
|
||||
external_constructor<value_t::object>::construct(j, obj);
|
||||
@@ -338,9 +337,9 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||
|
||||
template <
|
||||
typename BasicJsonType, typename T, std::size_t N,
|
||||
enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
|
||||
const T(&)[N]>::value,
|
||||
int> = 0 >
|
||||
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
|
||||
const T(&)[N]>::value,
|
||||
int > = 0 >
|
||||
void to_json(BasicJsonType& j, const T(&arr)[N])
|
||||
{
|
||||
external_constructor<value_t::array>::construct(j, arr);
|
||||
@@ -353,8 +352,8 @@ void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
|
||||
}
|
||||
|
||||
// for https://github.com/nlohmann/json/pull/1134
|
||||
template < typename BasicJsonType, typename T,
|
||||
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
|
||||
template<typename BasicJsonType, typename T,
|
||||
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
|
||||
void to_json(BasicJsonType& j, const T& b)
|
||||
{
|
||||
j = { {b.key(), b.value()} };
|
||||
|
||||
@@ -97,6 +97,7 @@ json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vect
|
||||
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
|
||||
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
|
||||
json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
|
||||
json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
|
||||
|
||||
@note For an input with n bytes, 1 is the index of the first character and n+1
|
||||
is the index of the terminating null byte or the end of file. This also
|
||||
@@ -285,7 +286,7 @@ json.exception.out_of_range.403 | key 'foo' not found | The provided key was not
|
||||
json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
|
||||
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
|
||||
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
|
||||
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. |
|
||||
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
|
||||
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
|
||||
json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
|
||||
|
||||
|
||||
117
include/nlohmann/detail/hash.hpp
Normal file
117
include/nlohmann/detail/hash.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> // size_t, uint8_t
|
||||
#include <functional> // hash
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// boost::hash_combine
|
||||
inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
|
||||
{
|
||||
seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
|
||||
return seed;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief hash a JSON value
|
||||
|
||||
The hash function tries to rely on std::hash where possible. Furthermore, the
|
||||
type of the JSON value is taken into account to have different hash values for
|
||||
null, 0, 0U, and false, etc.
|
||||
|
||||
@tparam BasicJsonType basic_json specialization
|
||||
@param j JSON value to hash
|
||||
@return hash value of j
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
std::size_t hash(const BasicJsonType& j)
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
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;
|
||||
|
||||
const auto type = static_cast<std::size_t>(j.type());
|
||||
switch (j.type())
|
||||
{
|
||||
case BasicJsonType::value_t::null:
|
||||
case BasicJsonType::value_t::discarded:
|
||||
{
|
||||
return combine(type, 0);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::object:
|
||||
{
|
||||
auto seed = combine(type, j.size());
|
||||
for (const auto& element : j.items())
|
||||
{
|
||||
const auto h = std::hash<string_t> {}(element.key());
|
||||
seed = combine(seed, h);
|
||||
seed = combine(seed, hash(element.value()));
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::array:
|
||||
{
|
||||
auto seed = combine(type, j.size());
|
||||
for (const auto& element : j)
|
||||
{
|
||||
seed = combine(seed, hash(element));
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::string:
|
||||
{
|
||||
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::boolean:
|
||||
{
|
||||
const auto h = std::hash<bool> {}(j.template get<bool>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case BasicJsonType::value_t::number_integer:
|
||||
{
|
||||
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case nlohmann::detail::value_t::number_unsigned:
|
||||
{
|
||||
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case nlohmann::detail::value_t::number_float:
|
||||
{
|
||||
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
||||
return combine(type, h);
|
||||
}
|
||||
|
||||
case nlohmann::detail::value_t::binary:
|
||||
{
|
||||
auto seed = combine(type, j.get_binary().size());
|
||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||
seed = combine(seed, h);
|
||||
seed = combine(seed, j.get_binary().subtype());
|
||||
for (const auto byte : j.get_binary())
|
||||
{
|
||||
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdio> //FILE *
|
||||
#include <cstring> // strlen
|
||||
@@ -34,8 +33,10 @@ Input adapter for stdio file access. This adapter read only 1 byte and do not us
|
||||
class file_input_adapter
|
||||
{
|
||||
public:
|
||||
using char_type = char;
|
||||
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
explicit file_input_adapter(std::FILE* f) noexcept
|
||||
explicit file_input_adapter(std::FILE* f) noexcept
|
||||
: m_file(f)
|
||||
{}
|
||||
|
||||
@@ -68,11 +69,13 @@ subsequent call for input from the std::istream.
|
||||
class input_stream_adapter
|
||||
{
|
||||
public:
|
||||
using char_type = char;
|
||||
|
||||
~input_stream_adapter()
|
||||
{
|
||||
// clear stream flags; we use underlying streambuf I/O, do not
|
||||
// maintain ifstream flags, except eof
|
||||
if (is)
|
||||
if (is != nullptr)
|
||||
{
|
||||
is->clear(is->rdstate() & std::ios::eofbit);
|
||||
}
|
||||
@@ -87,7 +90,7 @@ class input_stream_adapter
|
||||
input_stream_adapter& operator=(input_stream_adapter&) = delete;
|
||||
input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete;
|
||||
|
||||
input_stream_adapter(input_stream_adapter&& rhs) : is(rhs.is), sb(rhs.sb)
|
||||
input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb)
|
||||
{
|
||||
rhs.is = nullptr;
|
||||
rhs.sb = nullptr;
|
||||
@@ -100,7 +103,7 @@ class input_stream_adapter
|
||||
{
|
||||
auto res = sb->sbumpc();
|
||||
// set eof manually, as we don't use the istream interface.
|
||||
if (res == EOF)
|
||||
if (JSON_HEDLEY_UNLIKELY(res == EOF))
|
||||
{
|
||||
is->clear(is->rdstate() | std::ios::eofbit);
|
||||
}
|
||||
@@ -113,51 +116,61 @@ class input_stream_adapter
|
||||
std::streambuf* sb = nullptr;
|
||||
};
|
||||
|
||||
/// input adapter for buffer input
|
||||
class input_buffer_adapter
|
||||
// General-purpose iterator-based adapter. It might not be as fast as
|
||||
// theoretically possible for some containers, but it is extremely versatile.
|
||||
template<typename IteratorType>
|
||||
class iterator_input_adapter
|
||||
{
|
||||
public:
|
||||
input_buffer_adapter(const char* b, const std::size_t l) noexcept
|
||||
: cursor(b), limit(b == nullptr ? nullptr : (b + l))
|
||||
{}
|
||||
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
||||
|
||||
// delete because of pointer members
|
||||
input_buffer_adapter(const input_buffer_adapter&) = delete;
|
||||
input_buffer_adapter& operator=(input_buffer_adapter&) = delete;
|
||||
input_buffer_adapter(input_buffer_adapter&&) = default;
|
||||
input_buffer_adapter& operator=(input_buffer_adapter&&) = delete;
|
||||
iterator_input_adapter(IteratorType first, IteratorType last)
|
||||
: current(std::move(first)), end(std::move(last)) {}
|
||||
|
||||
std::char_traits<char>::int_type get_character() noexcept
|
||||
typename std::char_traits<char_type>::int_type get_character()
|
||||
{
|
||||
if (JSON_HEDLEY_LIKELY(cursor < limit))
|
||||
if (JSON_HEDLEY_LIKELY(current != end))
|
||||
{
|
||||
assert(cursor != nullptr and limit != nullptr);
|
||||
return std::char_traits<char>::to_int_type(*(cursor++));
|
||||
auto result = std::char_traits<char_type>::to_int_type(*current);
|
||||
std::advance(current, 1);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::char_traits<char_type>::eof();
|
||||
}
|
||||
|
||||
return std::char_traits<char>::eof();
|
||||
}
|
||||
|
||||
private:
|
||||
/// pointer to the current character
|
||||
const char* cursor;
|
||||
/// pointer past the last character
|
||||
const char* const limit;
|
||||
IteratorType current;
|
||||
IteratorType end;
|
||||
|
||||
template<typename BaseInputAdapter, size_t T>
|
||||
friend struct wide_string_input_helper;
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return current == end;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename WideStringType, size_t T>
|
||||
struct wide_string_input_helper
|
||||
|
||||
template<typename BaseInputAdapter, size_t T>
|
||||
struct wide_string_input_helper;
|
||||
|
||||
template<typename BaseInputAdapter>
|
||||
struct wide_string_input_helper<BaseInputAdapter, 4>
|
||||
{
|
||||
// UTF-32
|
||||
static void fill_buffer(const WideStringType& str,
|
||||
size_t& current_wchar,
|
||||
static void fill_buffer(BaseInputAdapter& input,
|
||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
||||
size_t& utf8_bytes_index,
|
||||
size_t& utf8_bytes_filled)
|
||||
{
|
||||
utf8_bytes_index = 0;
|
||||
|
||||
if (current_wchar == str.size())
|
||||
if (JSON_HEDLEY_UNLIKELY(input.empty()))
|
||||
{
|
||||
utf8_bytes[0] = std::char_traits<char>::eof();
|
||||
utf8_bytes_filled = 1;
|
||||
@@ -165,7 +178,7 @@ struct wide_string_input_helper
|
||||
else
|
||||
{
|
||||
// get the current character
|
||||
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
|
||||
const auto wc = input.get_character();
|
||||
|
||||
// UTF-32 to UTF-8 encoding
|
||||
if (wc < 0x80)
|
||||
@@ -175,23 +188,23 @@ struct wide_string_input_helper
|
||||
}
|
||||
else if (wc <= 0x7FF)
|
||||
{
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||
utf8_bytes_filled = 2;
|
||||
}
|
||||
else if (wc <= 0xFFFF)
|
||||
{
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||
utf8_bytes_filled = 3;
|
||||
}
|
||||
else if (wc <= 0x10FFFF)
|
||||
{
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||
utf8_bytes_filled = 4;
|
||||
}
|
||||
else
|
||||
@@ -204,19 +217,18 @@ struct wide_string_input_helper
|
||||
}
|
||||
};
|
||||
|
||||
template<typename WideStringType>
|
||||
struct wide_string_input_helper<WideStringType, 2>
|
||||
template<typename BaseInputAdapter>
|
||||
struct wide_string_input_helper<BaseInputAdapter, 2>
|
||||
{
|
||||
// UTF-16
|
||||
static void fill_buffer(const WideStringType& str,
|
||||
size_t& current_wchar,
|
||||
static void fill_buffer(BaseInputAdapter& input,
|
||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
||||
size_t& utf8_bytes_index,
|
||||
size_t& utf8_bytes_filled)
|
||||
{
|
||||
utf8_bytes_index = 0;
|
||||
|
||||
if (current_wchar == str.size())
|
||||
if (JSON_HEDLEY_UNLIKELY(input.empty()))
|
||||
{
|
||||
utf8_bytes[0] = std::char_traits<char>::eof();
|
||||
utf8_bytes_filled = 1;
|
||||
@@ -224,7 +236,7 @@ struct wide_string_input_helper<WideStringType, 2>
|
||||
else
|
||||
{
|
||||
// get the current character
|
||||
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
|
||||
const auto wc = input.get_character();
|
||||
|
||||
// UTF-16 to UTF-8 encoding
|
||||
if (wc < 0x80)
|
||||
@@ -234,23 +246,23 @@ struct wide_string_input_helper<WideStringType, 2>
|
||||
}
|
||||
else if (wc <= 0x7FF)
|
||||
{
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||
utf8_bytes_filled = 2;
|
||||
}
|
||||
else if (0xD800 > wc or wc >= 0xE000)
|
||||
else if (0xD800 > wc || wc >= 0xE000)
|
||||
{
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
|
||||
utf8_bytes_filled = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_wchar < str.size())
|
||||
if (JSON_HEDLEY_UNLIKELY(!input.empty()))
|
||||
{
|
||||
const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
|
||||
const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||
const auto wc2 = static_cast<unsigned int>(input.get_character());
|
||||
const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
|
||||
@@ -259,8 +271,6 @@ struct wide_string_input_helper<WideStringType, 2>
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown character
|
||||
++current_wchar;
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||
utf8_bytes_filled = 1;
|
||||
}
|
||||
@@ -269,44 +279,42 @@ struct wide_string_input_helper<WideStringType, 2>
|
||||
}
|
||||
};
|
||||
|
||||
template<typename WideStringType>
|
||||
// Wraps another input apdater to convert wide character types into individual bytes.
|
||||
template<typename BaseInputAdapter, typename WideCharType>
|
||||
class wide_string_input_adapter
|
||||
{
|
||||
public:
|
||||
explicit wide_string_input_adapter(const WideStringType& w) noexcept
|
||||
: str(w)
|
||||
{}
|
||||
using char_type = char;
|
||||
|
||||
std::char_traits<char>::int_type get_character() noexcept
|
||||
wide_string_input_adapter(BaseInputAdapter base)
|
||||
: base_adapter(base) {}
|
||||
|
||||
typename std::char_traits<char>::int_type get_character() noexcept
|
||||
{
|
||||
// check if buffer needs to be filled
|
||||
if (utf8_bytes_index == utf8_bytes_filled)
|
||||
{
|
||||
fill_buffer<sizeof(typename WideStringType::value_type)>();
|
||||
fill_buffer<sizeof(WideCharType)>();
|
||||
|
||||
assert(utf8_bytes_filled > 0);
|
||||
assert(utf8_bytes_index == 0);
|
||||
JSON_ASSERT(utf8_bytes_filled > 0);
|
||||
JSON_ASSERT(utf8_bytes_index == 0);
|
||||
}
|
||||
|
||||
// use buffer
|
||||
assert(utf8_bytes_filled > 0);
|
||||
assert(utf8_bytes_index < utf8_bytes_filled);
|
||||
JSON_ASSERT(utf8_bytes_filled > 0);
|
||||
JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
|
||||
return utf8_bytes[utf8_bytes_index++];
|
||||
}
|
||||
|
||||
private:
|
||||
BaseInputAdapter base_adapter;
|
||||
|
||||
template<size_t T>
|
||||
void fill_buffer()
|
||||
{
|
||||
wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
|
||||
wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
|
||||
}
|
||||
|
||||
/// 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}};
|
||||
|
||||
@@ -316,6 +324,64 @@ class wide_string_input_adapter
|
||||
std::size_t utf8_bytes_filled = 0;
|
||||
};
|
||||
|
||||
|
||||
template<typename IteratorType, typename Enable = void>
|
||||
struct iterator_input_adapter_factory
|
||||
{
|
||||
using iterator_type = IteratorType;
|
||||
using char_type = typename std::iterator_traits<iterator_type>::value_type;
|
||||
using adapter_type = iterator_input_adapter<iterator_type>;
|
||||
|
||||
static adapter_type create(IteratorType first, IteratorType last)
|
||||
{
|
||||
return adapter_type(std::move(first), std::move(last));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_iterator_of_multibyte
|
||||
{
|
||||
using value_type = typename std::iterator_traits<T>::value_type;
|
||||
enum
|
||||
{
|
||||
value = sizeof(value_type) > 1
|
||||
};
|
||||
};
|
||||
|
||||
template<typename IteratorType>
|
||||
struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
|
||||
{
|
||||
using iterator_type = IteratorType;
|
||||
using char_type = typename std::iterator_traits<iterator_type>::value_type;
|
||||
using base_adapter_type = iterator_input_adapter<iterator_type>;
|
||||
using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
|
||||
|
||||
static adapter_type create(IteratorType first, IteratorType last)
|
||||
{
|
||||
return adapter_type(base_adapter_type(std::move(first), std::move(last)));
|
||||
}
|
||||
};
|
||||
|
||||
// General purpose iterator-based input
|
||||
template<typename IteratorType>
|
||||
typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
|
||||
{
|
||||
using factory_type = iterator_input_adapter_factory<IteratorType>;
|
||||
return factory_type::create(first, last);
|
||||
}
|
||||
|
||||
// Convenience shorthand from container to iterator
|
||||
template<typename ContainerType>
|
||||
auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container)))
|
||||
{
|
||||
// Enable ADL
|
||||
using std::begin;
|
||||
using std::end;
|
||||
|
||||
return input_adapter(begin(container), end(container));
|
||||
}
|
||||
|
||||
// Special cases with fast paths
|
||||
inline file_input_adapter input_adapter(std::FILE* file)
|
||||
{
|
||||
return file_input_adapter(file);
|
||||
@@ -331,96 +397,27 @@ inline input_stream_adapter input_adapter(std::istream&& stream)
|
||||
return input_stream_adapter(stream);
|
||||
}
|
||||
|
||||
template<typename CharT,
|
||||
typename std::enable_if<
|
||||
std::is_pointer<CharT>::value and
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int>::type = 0>
|
||||
input_buffer_adapter input_adapter(CharT b, std::size_t l)
|
||||
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
|
||||
|
||||
// Null-delimited strings, and the like.
|
||||
template < typename CharT,
|
||||
typename std::enable_if <
|
||||
std::is_pointer<CharT>::value&&
|
||||
!std::is_array<CharT>::value&&
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int >::type = 0 >
|
||||
contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||
{
|
||||
return input_buffer_adapter(reinterpret_cast<const char*>(b), l);
|
||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||
const auto* ptr = reinterpret_cast<const char*>(b);
|
||||
return input_adapter(ptr, ptr + length);
|
||||
}
|
||||
|
||||
template<typename CharT,
|
||||
typename std::enable_if<
|
||||
std::is_pointer<CharT>::value and
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int>::type = 0>
|
||||
input_buffer_adapter input_adapter(CharT b)
|
||||
template<typename T, std::size_t N>
|
||||
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N))
|
||||
{
|
||||
return input_adapter(reinterpret_cast<const char*>(b),
|
||||
std::strlen(reinterpret_cast<const char*>(b)));
|
||||
}
|
||||
|
||||
template<class IteratorType,
|
||||
typename std::enable_if<
|
||||
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
||||
int>::type = 0>
|
||||
input_buffer_adapter input_adapter(IteratorType first, IteratorType last)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
// assertion to check that the iterator range is indeed contiguous,
|
||||
// see https://stackoverflow.com/a/35008842/266378 for more discussion
|
||||
const auto is_contiguous = std::accumulate(
|
||||
first, last, std::pair<bool, int>(true, 0),
|
||||
[&first](std::pair<bool, int> res, decltype(*first) val)
|
||||
{
|
||||
res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
|
||||
return res;
|
||||
}).first;
|
||||
assert(is_contiguous);
|
||||
#endif
|
||||
|
||||
// assertion to check that each element is 1 byte long
|
||||
static_assert(
|
||||
sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
|
||||
"each element in the iterator range must have the size of 1 byte");
|
||||
|
||||
const auto len = static_cast<size_t>(std::distance(first, last));
|
||||
if (JSON_HEDLEY_LIKELY(len > 0))
|
||||
{
|
||||
// there is at least one element: use the address of first
|
||||
return input_buffer_adapter(reinterpret_cast<const char*>(&(*first)), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the address of first cannot be used: use nullptr
|
||||
return input_buffer_adapter(nullptr, len);
|
||||
}
|
||||
}
|
||||
|
||||
inline wide_string_input_adapter<std::wstring> input_adapter(const std::wstring& ws)
|
||||
{
|
||||
return wide_string_input_adapter<std::wstring>(ws);
|
||||
}
|
||||
|
||||
|
||||
inline wide_string_input_adapter<std::u16string> input_adapter(const std::u16string& ws)
|
||||
{
|
||||
return wide_string_input_adapter<std::u16string>(ws);
|
||||
}
|
||||
|
||||
inline wide_string_input_adapter<std::u32string> input_adapter(const std::u32string& ws)
|
||||
{
|
||||
return wide_string_input_adapter<std::u32string>(ws);
|
||||
}
|
||||
|
||||
template<class ContiguousContainer, typename
|
||||
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
||||
std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
||||
int>::type = 0>
|
||||
input_buffer_adapter input_adapter(const ContiguousContainer& c)
|
||||
{
|
||||
return input_adapter(std::begin(c), std::end(c));
|
||||
}
|
||||
|
||||
|
||||
template<class T, std::size_t N>
|
||||
input_buffer_adapter input_adapter(T (&array)[N])
|
||||
{
|
||||
return input_adapter(std::begin(array), std::end(array));
|
||||
return input_adapter(array, array + N);
|
||||
}
|
||||
|
||||
// This class only handles inputs of input_buffer_adapter type.
|
||||
@@ -429,24 +426,14 @@ input_buffer_adapter input_adapter(T (&array)[N])
|
||||
class span_input_adapter
|
||||
{
|
||||
public:
|
||||
template<typename CharT,
|
||||
typename std::enable_if<
|
||||
std::is_pointer<CharT>::value and
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int>::type = 0>
|
||||
template < typename CharT,
|
||||
typename std::enable_if <
|
||||
std::is_pointer<CharT>::value&&
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int >::type = 0 >
|
||||
span_input_adapter(CharT b, std::size_t l)
|
||||
: ia(reinterpret_cast<const char*>(b), l) {}
|
||||
|
||||
template<typename CharT,
|
||||
typename std::enable_if<
|
||||
std::is_pointer<CharT>::value and
|
||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value and
|
||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||
int>::type = 0>
|
||||
span_input_adapter(CharT b)
|
||||
: span_input_adapter(reinterpret_cast<const char*>(b),
|
||||
std::strlen(reinterpret_cast<const char*>(b))) {}
|
||||
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
|
||||
|
||||
template<class IteratorType,
|
||||
typename std::enable_if<
|
||||
@@ -455,25 +442,13 @@ class span_input_adapter
|
||||
span_input_adapter(IteratorType first, IteratorType last)
|
||||
: ia(input_adapter(first, last)) {}
|
||||
|
||||
template<class T, std::size_t N>
|
||||
span_input_adapter(T (&array)[N])
|
||||
: span_input_adapter(std::begin(array), std::end(array)) {}
|
||||
|
||||
/// input adapter for contiguous container
|
||||
template<class ContiguousContainer, typename
|
||||
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
||||
std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
||||
int>::type = 0>
|
||||
span_input_adapter(const ContiguousContainer& c)
|
||||
: span_input_adapter(std::begin(c), std::end(c)) {}
|
||||
|
||||
input_buffer_adapter&& get()
|
||||
contiguous_bytes_input_adapter&& get()
|
||||
{
|
||||
return std::move(ia);
|
||||
}
|
||||
|
||||
private:
|
||||
input_buffer_adapter ia;
|
||||
contiguous_bytes_input_adapter ia;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert> // assert
|
||||
#include <cstddef>
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
@@ -218,7 +217,7 @@ class json_sax_dom_parser
|
||||
{
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408,
|
||||
"excessive object size: " + std::to_string(len)));
|
||||
@@ -244,7 +243,7 @@ class json_sax_dom_parser
|
||||
{
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408,
|
||||
"excessive array size: " + std::to_string(len)));
|
||||
@@ -259,30 +258,15 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Exception>
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||
const detail::exception& ex)
|
||||
const Exception& ex)
|
||||
{
|
||||
errored = true;
|
||||
static_cast<void>(ex);
|
||||
if (allow_exceptions)
|
||||
{
|
||||
// determine the proper exception type from the id
|
||||
switch ((ex.id / 100) % 100)
|
||||
{
|
||||
case 1:
|
||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||
case 4:
|
||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
||||
// LCOV_EXCL_START
|
||||
case 2:
|
||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||
case 3:
|
||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
JSON_THROW(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -309,7 +293,7 @@ class json_sax_dom_parser
|
||||
return &root;
|
||||
}
|
||||
|
||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
||||
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
|
||||
|
||||
if (ref_stack.back()->is_array())
|
||||
{
|
||||
@@ -317,8 +301,8 @@ class json_sax_dom_parser
|
||||
return &(ref_stack.back()->m_value.array->back());
|
||||
}
|
||||
|
||||
assert(ref_stack.back()->is_object());
|
||||
assert(object_element);
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
JSON_ASSERT(object_element);
|
||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||
return object_element;
|
||||
}
|
||||
@@ -414,7 +398,7 @@ class json_sax_dom_callback_parser
|
||||
ref_stack.push_back(val.second);
|
||||
|
||||
// check object limit
|
||||
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
|
||||
}
|
||||
@@ -431,7 +415,7 @@ class json_sax_dom_callback_parser
|
||||
key_keep_stack.push_back(keep);
|
||||
|
||||
// add discarded value at given key and store the reference for later
|
||||
if (keep and ref_stack.back())
|
||||
if (keep && ref_stack.back())
|
||||
{
|
||||
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
|
||||
}
|
||||
@@ -441,18 +425,18 @@ class json_sax_dom_callback_parser
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
||||
if (ref_stack.back() && !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());
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
|
||||
if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
|
||||
if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
|
||||
{
|
||||
// remove discarded value
|
||||
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
|
||||
@@ -477,7 +461,7 @@ class json_sax_dom_callback_parser
|
||||
ref_stack.push_back(val.second);
|
||||
|
||||
// check array limit
|
||||
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
|
||||
}
|
||||
@@ -492,20 +476,20 @@ class json_sax_dom_callback_parser
|
||||
if (ref_stack.back())
|
||||
{
|
||||
keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
|
||||
if (not keep)
|
||||
if (!keep)
|
||||
{
|
||||
// discard array
|
||||
*ref_stack.back() = discarded;
|
||||
}
|
||||
}
|
||||
|
||||
assert(not ref_stack.empty());
|
||||
assert(not keep_stack.empty());
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
|
||||
// remove discarded value
|
||||
if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
|
||||
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
|
||||
{
|
||||
ref_stack.back()->m_value.array->pop_back();
|
||||
}
|
||||
@@ -513,30 +497,15 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Exception>
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||
const detail::exception& ex)
|
||||
const Exception& ex)
|
||||
{
|
||||
errored = true;
|
||||
static_cast<void>(ex);
|
||||
if (allow_exceptions)
|
||||
{
|
||||
// determine the proper exception type from the id
|
||||
switch ((ex.id / 100) % 100)
|
||||
{
|
||||
case 1:
|
||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||
case 4:
|
||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
||||
// LCOV_EXCL_START
|
||||
case 2:
|
||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||
case 3:
|
||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
JSON_THROW(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -565,11 +534,11 @@ class json_sax_dom_callback_parser
|
||||
template<typename Value>
|
||||
std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
|
||||
{
|
||||
assert(not keep_stack.empty());
|
||||
JSON_ASSERT(!keep_stack.empty());
|
||||
|
||||
// do not handle this value if we know it would be added to a discarded
|
||||
// container
|
||||
if (not keep_stack.back())
|
||||
if (!keep_stack.back())
|
||||
{
|
||||
return {false, nullptr};
|
||||
}
|
||||
@@ -578,10 +547,10 @@ class json_sax_dom_callback_parser
|
||||
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);
|
||||
const bool keep = skip_callback || 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)
|
||||
if (!keep)
|
||||
{
|
||||
return {false, nullptr};
|
||||
}
|
||||
@@ -594,13 +563,13 @@ class json_sax_dom_callback_parser
|
||||
|
||||
// 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())
|
||||
if (!ref_stack.back())
|
||||
{
|
||||
return {false, nullptr};
|
||||
}
|
||||
|
||||
// we now only expect arrays and objects
|
||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
||||
JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
|
||||
|
||||
// array
|
||||
if (ref_stack.back()->is_array())
|
||||
@@ -610,18 +579,18 @@ class json_sax_dom_callback_parser
|
||||
}
|
||||
|
||||
// object
|
||||
assert(ref_stack.back()->is_object());
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
// check if we should store an element for the current key
|
||||
assert(not key_keep_stack.empty());
|
||||
JSON_ASSERT(!key_keep_stack.empty());
|
||||
const bool store_element = key_keep_stack.back();
|
||||
key_keep_stack.pop_back();
|
||||
|
||||
if (not store_element)
|
||||
if (!store_element)
|
||||
{
|
||||
return {false, nullptr};
|
||||
}
|
||||
|
||||
assert(object_element);
|
||||
JSON_ASSERT(object_element);
|
||||
*object_element = std::move(value);
|
||||
return {true, object_element};
|
||||
}
|
||||
|
||||
@@ -106,12 +106,17 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
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 char_type = typename InputAdapterType::char_type;
|
||||
using char_int_type = typename std::char_traits<char_type>::int_type;
|
||||
|
||||
public:
|
||||
using token_type = typename lexer_base<BasicJsonType>::token_type;
|
||||
|
||||
explicit lexer(InputAdapterType&& adapter)
|
||||
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
|
||||
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false)
|
||||
: ia(std::move(adapter))
|
||||
, ignore_comments(ignore_comments_)
|
||||
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
|
||||
{}
|
||||
|
||||
// delete because of pointer members
|
||||
lexer(const lexer&) = delete;
|
||||
@@ -129,8 +134,8 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
JSON_HEDLEY_PURE
|
||||
static char get_decimal_point() noexcept
|
||||
{
|
||||
const auto loc = localeconv();
|
||||
assert(loc != nullptr);
|
||||
const auto* loc = localeconv();
|
||||
JSON_ASSERT(loc != nullptr);
|
||||
return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
|
||||
}
|
||||
|
||||
@@ -156,7 +161,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
int get_codepoint()
|
||||
{
|
||||
// this function only makes sense after reading `\u`
|
||||
assert(current == 'u');
|
||||
JSON_ASSERT(current == 'u');
|
||||
int codepoint = 0;
|
||||
|
||||
const auto factors = { 12u, 8u, 4u, 0u };
|
||||
@@ -164,15 +169,15 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
{
|
||||
get();
|
||||
|
||||
if (current >= '0' and current <= '9')
|
||||
if (current >= '0' && current <= '9')
|
||||
{
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
|
||||
}
|
||||
else if (current >= 'A' and current <= 'F')
|
||||
else if (current >= 'A' && current <= 'F')
|
||||
{
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
|
||||
}
|
||||
else if (current >= 'a' and current <= 'f')
|
||||
else if (current >= 'a' && current <= 'f')
|
||||
{
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
|
||||
}
|
||||
@@ -182,7 +187,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
}
|
||||
|
||||
assert(0x0000 <= codepoint and codepoint <= 0xFFFF);
|
||||
JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
@@ -201,15 +206,15 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
|
||||
@return true if and only if no range violation was detected
|
||||
*/
|
||||
bool next_byte_in_range(std::initializer_list<int> ranges)
|
||||
bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
|
||||
{
|
||||
assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6);
|
||||
JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
|
||||
add(current);
|
||||
|
||||
for (auto range = ranges.begin(); range != ranges.end(); ++range)
|
||||
{
|
||||
get();
|
||||
if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
|
||||
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
|
||||
{
|
||||
add(current);
|
||||
}
|
||||
@@ -244,7 +249,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
reset();
|
||||
|
||||
// we entered the function by reading an open quote
|
||||
assert(current == '\"');
|
||||
JSON_ASSERT(current == '\"');
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -252,7 +257,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
switch (get())
|
||||
{
|
||||
// end of file while parsing string
|
||||
case std::char_traits<char>::eof():
|
||||
case std::char_traits<char_type>::eof():
|
||||
{
|
||||
error_message = "invalid string: missing closing quote";
|
||||
return token_type::parse_error;
|
||||
@@ -315,10 +320,10 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
|
||||
// check if code point is a high surrogate
|
||||
if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
|
||||
if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
|
||||
{
|
||||
// expect next \uxxxx entry
|
||||
if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
|
||||
if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
|
||||
{
|
||||
const int codepoint2 = get_codepoint();
|
||||
|
||||
@@ -329,7 +334,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
|
||||
// check if codepoint2 is a low surrogate
|
||||
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
|
||||
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
|
||||
{
|
||||
// overwrite codepoint
|
||||
codepoint = static_cast<int>(
|
||||
@@ -356,7 +361,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
|
||||
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
|
||||
{
|
||||
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
|
||||
return token_type::parse_error;
|
||||
@@ -364,34 +369,34 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
|
||||
// result of the above calculation yields a proper codepoint
|
||||
assert(0x00 <= codepoint and codepoint <= 0x10FFFF);
|
||||
JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
|
||||
|
||||
// translate codepoint into bytes
|
||||
if (codepoint < 0x80)
|
||||
{
|
||||
// 1-byte characters: 0xxxxxxx (ASCII)
|
||||
add(codepoint);
|
||||
add(static_cast<char_int_type>(codepoint));
|
||||
}
|
||||
else if (codepoint <= 0x7FF)
|
||||
{
|
||||
// 2-byte characters: 110xxxxx 10xxxxxx
|
||||
add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
|
||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
else if (codepoint <= 0xFFFF)
|
||||
{
|
||||
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
||||
add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
|
||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
|
||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -731,7 +736,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
|
||||
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -741,7 +746,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
|
||||
case 0xE0:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -765,7 +770,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -775,7 +780,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
|
||||
case 0xED:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -785,7 +790,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
||||
case 0xF0:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -797,7 +802,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -807,7 +812,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
|
||||
case 0xF4:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
@@ -824,6 +829,77 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief scan a comment
|
||||
* @return whether comment could be scanned successfully
|
||||
*/
|
||||
bool scan_comment()
|
||||
{
|
||||
switch (get())
|
||||
{
|
||||
// single-line comments skip input until a newline or EOF is read
|
||||
case '/':
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
switch (get())
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
case std::char_traits<char_type>::eof():
|
||||
case '\0':
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// multi-line comments skip input until */ is read
|
||||
case '*':
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
switch (get())
|
||||
{
|
||||
case std::char_traits<char_type>::eof():
|
||||
case '\0':
|
||||
{
|
||||
error_message = "invalid comment; missing closing '*/'";
|
||||
return false;
|
||||
}
|
||||
|
||||
case '*':
|
||||
{
|
||||
switch (get())
|
||||
{
|
||||
case '/':
|
||||
return true;
|
||||
|
||||
default:
|
||||
{
|
||||
unget();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unexpected character after reading '/'
|
||||
default:
|
||||
{
|
||||
error_message = "invalid comment; expecting '/' or '*' after '/'";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
static void strtof(float& f, const char* str, char** endptr) noexcept
|
||||
{
|
||||
@@ -922,7 +998,7 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
|
||||
// all other characters are rejected outside scan_number()
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
scan_number_minus:
|
||||
@@ -1169,7 +1245,7 @@ scan_number_done:
|
||||
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
|
||||
|
||||
// we checked the number format before
|
||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
|
||||
if (errno == 0)
|
||||
{
|
||||
@@ -1185,7 +1261,7 @@ scan_number_done:
|
||||
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
|
||||
|
||||
// we checked the number format before
|
||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
|
||||
if (errno == 0)
|
||||
{
|
||||
@@ -1202,7 +1278,7 @@ scan_number_done:
|
||||
strtof(value_float, token_buffer.data(), &endptr);
|
||||
|
||||
// we checked the number format before
|
||||
assert(endptr == token_buffer.data() + token_buffer.size());
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
|
||||
return token_type::value_float;
|
||||
}
|
||||
@@ -1213,13 +1289,13 @@ scan_number_done:
|
||||
@param[in] return_type the token type to return on success
|
||||
*/
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
token_type scan_literal(const char* literal_text, const std::size_t length,
|
||||
token_type scan_literal(const char_type* literal_text, const std::size_t length,
|
||||
token_type return_type)
|
||||
{
|
||||
assert(current == literal_text[0]);
|
||||
JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
|
||||
for (std::size_t i = 1; i < length; ++i)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
|
||||
if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
|
||||
{
|
||||
error_message = "invalid literal";
|
||||
return token_type::parse_error;
|
||||
@@ -1237,7 +1313,7 @@ scan_number_done:
|
||||
{
|
||||
token_buffer.clear();
|
||||
token_string.clear();
|
||||
token_string.push_back(std::char_traits<char>::to_char_type(current));
|
||||
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1250,7 +1326,7 @@ scan_number_done:
|
||||
|
||||
@return character read from the input
|
||||
*/
|
||||
std::char_traits<char>::int_type get()
|
||||
char_int_type get()
|
||||
{
|
||||
++position.chars_read_total;
|
||||
++position.chars_read_current_line;
|
||||
@@ -1265,9 +1341,9 @@ scan_number_done:
|
||||
current = ia.get_character();
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
|
||||
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
|
||||
{
|
||||
token_string.push_back(std::char_traits<char>::to_char_type(current));
|
||||
token_string.push_back(std::char_traits<char_type>::to_char_type(current));
|
||||
}
|
||||
|
||||
if (current == '\n')
|
||||
@@ -1306,17 +1382,17 @@ scan_number_done:
|
||||
--position.chars_read_current_line;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
|
||||
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
|
||||
{
|
||||
assert(not token_string.empty());
|
||||
JSON_ASSERT(!token_string.empty());
|
||||
token_string.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// add a character to token_buffer
|
||||
void add(int c)
|
||||
void add(char_int_type c)
|
||||
{
|
||||
token_buffer.push_back(std::char_traits<char>::to_char_type(c));
|
||||
token_buffer.push_back(static_cast<typename string_t::value_type>(c));
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1367,7 +1443,7 @@ scan_number_done:
|
||||
std::string result;
|
||||
for (const auto c : token_string)
|
||||
{
|
||||
if ('\x00' <= c and c <= '\x1F')
|
||||
if (static_cast<unsigned char>(c) <= '\x1F')
|
||||
{
|
||||
// escape control characters
|
||||
std::array<char, 9> cs{{}};
|
||||
@@ -1377,7 +1453,7 @@ scan_number_done:
|
||||
else
|
||||
{
|
||||
// add character as is
|
||||
result.push_back(c);
|
||||
result.push_back(static_cast<std::string::value_type>(c));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1404,7 +1480,7 @@ scan_number_done:
|
||||
if (get() == 0xEF)
|
||||
{
|
||||
// check if we completely parse the BOM
|
||||
return get() == 0xBB and get() == 0xBF;
|
||||
return get() == 0xBB && get() == 0xBF;
|
||||
}
|
||||
|
||||
// the first character is not the beginning of the BOM; unget it to
|
||||
@@ -1413,21 +1489,38 @@ scan_number_done:
|
||||
return true;
|
||||
}
|
||||
|
||||
void skip_whitespace()
|
||||
{
|
||||
do
|
||||
{
|
||||
get();
|
||||
}
|
||||
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
|
||||
}
|
||||
|
||||
token_type scan()
|
||||
{
|
||||
// initially, skip the BOM
|
||||
if (position.chars_read_total == 0 and not skip_bom())
|
||||
if (position.chars_read_total == 0 && !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
|
||||
skip_whitespace();
|
||||
|
||||
// ignore comments
|
||||
while (ignore_comments && current == '/')
|
||||
{
|
||||
get();
|
||||
if (!scan_comment())
|
||||
{
|
||||
return token_type::parse_error;
|
||||
}
|
||||
|
||||
// skip following whitespace
|
||||
skip_whitespace();
|
||||
}
|
||||
while (current == ' ' or current == '\t' or current == '\n' or current == '\r');
|
||||
|
||||
switch (current)
|
||||
{
|
||||
@@ -1447,11 +1540,20 @@ scan_number_done:
|
||||
|
||||
// literals
|
||||
case 't':
|
||||
return scan_literal("true", 4, token_type::literal_true);
|
||||
{
|
||||
std::array<char_type, 4> true_literal = {{'t', 'r', 'u', 'e'}};
|
||||
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
|
||||
}
|
||||
case 'f':
|
||||
return scan_literal("false", 5, token_type::literal_false);
|
||||
{
|
||||
std::array<char_type, 5> false_literal = {{'f', 'a', 'l', 's', 'e'}};
|
||||
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
|
||||
}
|
||||
case 'n':
|
||||
return scan_literal("null", 4, token_type::literal_null);
|
||||
{
|
||||
std::array<char_type, 4> null_literal = {{'n', 'u', 'l', 'l'}};
|
||||
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
|
||||
}
|
||||
|
||||
// string
|
||||
case '\"':
|
||||
@@ -1474,7 +1576,7 @@ scan_number_done:
|
||||
// end of input (the null byte is needed when parsing from
|
||||
// string literals)
|
||||
case '\0':
|
||||
case std::char_traits<char>::eof():
|
||||
case std::char_traits<char_type>::eof():
|
||||
return token_type::end_of_input;
|
||||
|
||||
// error
|
||||
@@ -1488,8 +1590,11 @@ scan_number_done:
|
||||
/// input adapter
|
||||
InputAdapterType ia;
|
||||
|
||||
/// whether comments should be ignored (true) or signaled as errors (false)
|
||||
const bool ignore_comments = false;
|
||||
|
||||
/// the current character
|
||||
std::char_traits<char>::int_type current = std::char_traits<char>::eof();
|
||||
char_int_type current = std::char_traits<char_type>::eof();
|
||||
|
||||
/// whether the next get() call should just return current
|
||||
bool next_unget = false;
|
||||
@@ -1498,7 +1603,7 @@ scan_number_done:
|
||||
position_t position {};
|
||||
|
||||
/// raw input token string (for error messages)
|
||||
std::vector<char> token_string {};
|
||||
std::vector<char_type> token_string {};
|
||||
|
||||
/// buffer for variable-length tokens (numbers, strings)
|
||||
string_t token_buffer {};
|
||||
@@ -1512,7 +1617,7 @@ scan_number_done:
|
||||
number_float_t value_float = 0;
|
||||
|
||||
/// the decimal point
|
||||
const char decimal_point_char = '.';
|
||||
const char_int_type decimal_point_char = '.';
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert> // assert
|
||||
#include <cmath> // isfinite
|
||||
#include <cstdint> // uint8_t
|
||||
#include <functional> // function
|
||||
@@ -63,8 +62,11 @@ class parser
|
||||
/// a parser reading from an input adapter
|
||||
explicit parser(InputAdapterType&& adapter,
|
||||
const parser_callback_t<BasicJsonType> cb = nullptr,
|
||||
const bool allow_exceptions_ = true)
|
||||
: callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
|
||||
const bool allow_exceptions_ = true,
|
||||
const bool skip_comments = false)
|
||||
: callback(cb)
|
||||
, m_lexer(std::move(adapter), skip_comments)
|
||||
, allow_exceptions(allow_exceptions_)
|
||||
{
|
||||
// read first token
|
||||
get_token();
|
||||
@@ -89,7 +91,7 @@ class parser
|
||||
result.assert_invariant();
|
||||
|
||||
// in strict mode, input must be completely read
|
||||
if (strict and (get_token() != token_type::end_of_input))
|
||||
if (strict && (get_token() != token_type::end_of_input))
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
@@ -118,7 +120,7 @@ class parser
|
||||
result.assert_invariant();
|
||||
|
||||
// in strict mode, input must be completely read
|
||||
if (strict and (get_token() != token_type::end_of_input))
|
||||
if (strict && (get_token() != token_type::end_of_input))
|
||||
{
|
||||
sdp.parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
@@ -147,7 +149,7 @@ class parser
|
||||
return sax_parse(&sax_acceptor, strict);
|
||||
}
|
||||
|
||||
template <typename SAX>
|
||||
template<typename SAX>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
bool sax_parse(SAX* sax, const bool strict = true)
|
||||
{
|
||||
@@ -155,7 +157,7 @@ class parser
|
||||
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))
|
||||
if (result && strict && (get_token() != token_type::end_of_input))
|
||||
{
|
||||
return sax->parse_error(m_lexer.get_position(),
|
||||
m_lexer.get_token_string(),
|
||||
@@ -167,7 +169,7 @@ class parser
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename SAX>
|
||||
template<typename SAX>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
bool sax_parse_internal(SAX* sax)
|
||||
{
|
||||
@@ -179,14 +181,14 @@ class parser
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (not skip_to_state_evaluation)
|
||||
if (!skip_to_state_evaluation)
|
||||
{
|
||||
// invariant: get_token() was called before each iteration
|
||||
switch (last_token)
|
||||
{
|
||||
case token_type::begin_object:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -194,7 +196,7 @@ class parser
|
||||
// closing } -> we are done
|
||||
if (get_token() == token_type::end_object)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -209,7 +211,7 @@ class parser
|
||||
parse_error::create(101, m_lexer.get_position(),
|
||||
exception_message(token_type::value_string, "object key")));
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -233,7 +235,7 @@ class parser
|
||||
|
||||
case token_type::begin_array:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -241,7 +243,7 @@ class parser
|
||||
// closing ] -> we are done
|
||||
if (get_token() == token_type::end_array)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -259,14 +261,14 @@ class parser
|
||||
{
|
||||
const auto res = m_lexer.get_number_float();
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!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() + "'"));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -276,7 +278,7 @@ class parser
|
||||
|
||||
case token_type::literal_false:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -285,7 +287,7 @@ class parser
|
||||
|
||||
case token_type::literal_null:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->null()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->null()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -294,7 +296,7 @@ class parser
|
||||
|
||||
case token_type::literal_true:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -303,7 +305,7 @@ class parser
|
||||
|
||||
case token_type::value_integer:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -312,7 +314,7 @@ class parser
|
||||
|
||||
case token_type::value_string:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -321,7 +323,7 @@ class parser
|
||||
|
||||
case token_type::value_unsigned:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -371,7 +373,7 @@ class parser
|
||||
// closing ]
|
||||
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -380,7 +382,7 @@ class parser
|
||||
// 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());
|
||||
JSON_ASSERT(!states.empty());
|
||||
states.pop_back();
|
||||
skip_to_state_evaluation = true;
|
||||
continue;
|
||||
@@ -405,7 +407,7 @@ class parser
|
||||
exception_message(token_type::value_string, "object key")));
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -427,7 +429,7 @@ class parser
|
||||
// closing }
|
||||
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -436,7 +438,7 @@ class parser
|
||||
// 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());
|
||||
JSON_ASSERT(!states.empty());
|
||||
states.pop_back();
|
||||
skip_to_state_evaluation = true;
|
||||
continue;
|
||||
@@ -460,7 +462,7 @@ class parser
|
||||
{
|
||||
std::string error_msg = "syntax error ";
|
||||
|
||||
if (not context.empty())
|
||||
if (!context.empty())
|
||||
{
|
||||
error_msg += "while parsing " + context + " ";
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ template<typename BasicJsonType> struct internal_iterator
|
||||
typename BasicJsonType::object_t::iterator object_iterator {};
|
||||
/// iterator for JSON arrays
|
||||
typename BasicJsonType::array_t::iterator array_iterator {};
|
||||
/// iterator for JSON binary arrays
|
||||
typename BasicJsonType::binary_t::container_type::iterator binary_iterator {};
|
||||
/// generic iterator for all other types
|
||||
primitive_iterator_t primitive_iterator {};
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
|
||||
#include <type_traits> // conditional, is_const, remove_const
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
||||
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
|
||||
@@ -85,7 +84,7 @@ class iter_impl
|
||||
*/
|
||||
explicit iter_impl(pointer object) noexcept : m_object(object)
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -171,7 +170,7 @@ class iter_impl
|
||||
*/
|
||||
void set_begin() noexcept
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -208,7 +207,7 @@ class iter_impl
|
||||
*/
|
||||
void set_end() noexcept
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -239,19 +238,19 @@ class iter_impl
|
||||
*/
|
||||
reference operator*() const
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
assert(m_it.object_iterator != m_object->m_value.object->end());
|
||||
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
|
||||
return m_it.object_iterator->second;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
assert(m_it.array_iterator != m_object->m_value.array->end());
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
|
||||
return *m_it.array_iterator;
|
||||
}
|
||||
|
||||
@@ -276,19 +275,19 @@ class iter_impl
|
||||
*/
|
||||
pointer operator->() const
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
assert(m_it.object_iterator != m_object->m_value.object->end());
|
||||
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
|
||||
return &(m_it.object_iterator->second);
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
assert(m_it.array_iterator != m_object->m_value.array->end());
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
|
||||
return &*m_it.array_iterator;
|
||||
}
|
||||
|
||||
@@ -321,7 +320,7 @@ class iter_impl
|
||||
*/
|
||||
iter_impl& operator++()
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -364,7 +363,7 @@ class iter_impl
|
||||
*/
|
||||
iter_impl& operator--()
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -402,7 +401,7 @@ class iter_impl
|
||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
||||
}
|
||||
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -423,7 +422,7 @@ class iter_impl
|
||||
*/
|
||||
bool operator!=(const iter_impl& other) const
|
||||
{
|
||||
return not operator==(other);
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -438,7 +437,7 @@ class iter_impl
|
||||
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
|
||||
}
|
||||
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -459,7 +458,7 @@ class iter_impl
|
||||
*/
|
||||
bool operator<=(const iter_impl& other) const
|
||||
{
|
||||
return not other.operator < (*this);
|
||||
return !other.operator < (*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -468,7 +467,7 @@ class iter_impl
|
||||
*/
|
||||
bool operator>(const iter_impl& other) const
|
||||
{
|
||||
return not operator<=(other);
|
||||
return !operator<=(other);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -477,7 +476,7 @@ class iter_impl
|
||||
*/
|
||||
bool operator>=(const iter_impl& other) const
|
||||
{
|
||||
return not operator<(other);
|
||||
return !operator<(other);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -486,7 +485,7 @@ class iter_impl
|
||||
*/
|
||||
iter_impl& operator+=(difference_type i)
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -557,7 +556,7 @@ class iter_impl
|
||||
*/
|
||||
difference_type operator-(const iter_impl& other) const
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -578,7 +577,7 @@ class iter_impl
|
||||
*/
|
||||
reference operator[](difference_type n) const
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
switch (m_object->m_type)
|
||||
{
|
||||
@@ -609,7 +608,7 @@ class iter_impl
|
||||
*/
|
||||
const typename object_t::key_type& key() const
|
||||
{
|
||||
assert(m_object != nullptr);
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
|
||||
{
|
||||
|
||||
@@ -15,9 +15,11 @@ namespace detail
|
||||
template<typename string_type>
|
||||
void int_to_string( string_type& target, std::size_t value )
|
||||
{
|
||||
target = std::to_string(value);
|
||||
// For ADL
|
||||
using std::to_string;
|
||||
target = to_string(value);
|
||||
}
|
||||
template <typename IteratorType> class iteration_proxy_value
|
||||
template<typename IteratorType> class iteration_proxy_value
|
||||
{
|
||||
public:
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@@ -72,7 +74,7 @@ template <typename IteratorType> class iteration_proxy_value
|
||||
/// return key of the iterator
|
||||
const string_type& key() const
|
||||
{
|
||||
assert(anchor.m_object != nullptr);
|
||||
JSON_ASSERT(anchor.m_object != nullptr);
|
||||
|
||||
switch (anchor.m_object->type())
|
||||
{
|
||||
@@ -131,7 +133,7 @@ template<typename IteratorType> class iteration_proxy
|
||||
// Structured Bindings Support
|
||||
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
|
||||
// And see https://github.com/nlohmann/json/pull/1391
|
||||
template <std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
|
||||
template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
|
||||
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
|
||||
{
|
||||
return i.key();
|
||||
@@ -139,7 +141,7 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
|
||||
// Structured Bindings Support
|
||||
// For further reference see https://blog.tartanllama.xyz/structured-bindings/
|
||||
// And see https://github.com/nlohmann/json/pull/1391
|
||||
template <std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
|
||||
template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
|
||||
auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
|
||||
{
|
||||
return i.value();
|
||||
@@ -158,11 +160,11 @@ namespace std
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
template <typename IteratorType>
|
||||
template<typename IteratorType>
|
||||
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
|
||||
: public std::integral_constant<std::size_t, 2> {};
|
||||
|
||||
template <std::size_t N, typename IteratorType>
|
||||
template<std::size_t N, typename IteratorType>
|
||||
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename It, typename = void>
|
||||
template<typename It, typename = void>
|
||||
struct iterator_types {};
|
||||
|
||||
template <typename It>
|
||||
template<typename It>
|
||||
struct iterator_types <
|
||||
It,
|
||||
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
|
||||
@@ -27,18 +27,18 @@ struct iterator_types <
|
||||
|
||||
// This is required as some compilers implement std::iterator_traits in a way that
|
||||
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
|
||||
template <typename T, typename = void>
|
||||
template<typename T, typename = void>
|
||||
struct iterator_traits
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
|
||||
: iterator_types<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
|
||||
{
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm> // all_of
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <limits> // max
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
@@ -325,12 +325,17 @@ class json_pointer
|
||||
|
||||
@return integer representation of @a s
|
||||
|
||||
@throw parse_error.106 if an array index begins with '0'
|
||||
@throw parse_error.109 if an array index begins not with a digit
|
||||
@throw out_of_range.404 if string @a s could not be converted to an integer
|
||||
@throw out_of_range.410 if an array index exceeds size_type
|
||||
*/
|
||||
static int array_index(const std::string& s)
|
||||
static typename BasicJsonType::size_type array_index(const std::string& s)
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and s[0] == '0'))
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(106, 0,
|
||||
"array index '" + s +
|
||||
@@ -338,16 +343,16 @@ class json_pointer
|
||||
}
|
||||
|
||||
// error condition (cf. RFC 6901, Sect. 4)
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 and not (s[0] >= '1' and s[0] <= '9')))
|
||||
if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number"));
|
||||
}
|
||||
|
||||
std::size_t processed_chars = 0;
|
||||
int res = 0;
|
||||
unsigned long long res = 0;
|
||||
JSON_TRY
|
||||
{
|
||||
res = std::stoi(s, &processed_chars);
|
||||
res = std::stoull(s, &processed_chars);
|
||||
}
|
||||
JSON_CATCH(std::out_of_range&)
|
||||
{
|
||||
@@ -360,7 +365,14 @@ class json_pointer
|
||||
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
|
||||
}
|
||||
|
||||
return res;
|
||||
// only triggered on special platforms (like 32bit), see also
|
||||
// https://github.com/nlohmann/json/pull/2203
|
||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return static_cast<size_type>(res);
|
||||
}
|
||||
|
||||
json_pointer top() const
|
||||
@@ -385,7 +397,6 @@ class json_pointer
|
||||
*/
|
||||
BasicJsonType& get_and_create(BasicJsonType& j) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
auto result = &j;
|
||||
|
||||
// in case no reference tokens exist, return a reference to the JSON value
|
||||
@@ -419,7 +430,7 @@ class json_pointer
|
||||
case detail::value_t::array:
|
||||
{
|
||||
// create an entry in the array
|
||||
result = &result->operator[](static_cast<size_type>(array_index(reference_token)));
|
||||
result = &result->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -458,7 +469,6 @@ class json_pointer
|
||||
*/
|
||||
BasicJsonType& get_unchecked(BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
// convert null values to arrays or objects before continuing
|
||||
@@ -473,7 +483,7 @@ class json_pointer
|
||||
});
|
||||
|
||||
// change value to array for numbers or "-" or to object otherwise
|
||||
*ptr = (nums or reference_token == "-")
|
||||
*ptr = (nums || reference_token == "-")
|
||||
? detail::value_t::array
|
||||
: detail::value_t::object;
|
||||
}
|
||||
@@ -497,8 +507,7 @@ class json_pointer
|
||||
else
|
||||
{
|
||||
// convert array index to number; unchecked access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -519,7 +528,6 @@ class json_pointer
|
||||
*/
|
||||
BasicJsonType& get_checked(BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->type())
|
||||
@@ -542,7 +550,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -569,7 +577,6 @@ class json_pointer
|
||||
*/
|
||||
const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->type())
|
||||
@@ -592,8 +599,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
// use unchecked array access
|
||||
ptr = &ptr->operator[](
|
||||
static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->operator[](array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -613,7 +619,6 @@ class json_pointer
|
||||
*/
|
||||
const BasicJsonType& get_checked(const BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->type())
|
||||
@@ -636,7 +641,7 @@ class json_pointer
|
||||
}
|
||||
|
||||
// note: at performs range check
|
||||
ptr = &ptr->at(static_cast<size_type>(array_index(reference_token)));
|
||||
ptr = &ptr->at(array_index(reference_token));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -654,14 +659,13 @@ class json_pointer
|
||||
*/
|
||||
bool contains(const BasicJsonType* ptr) const
|
||||
{
|
||||
using size_type = typename BasicJsonType::size_type;
|
||||
for (const auto& reference_token : reference_tokens)
|
||||
{
|
||||
switch (ptr->type())
|
||||
{
|
||||
case detail::value_t::object:
|
||||
{
|
||||
if (not ptr->contains(reference_token))
|
||||
if (!ptr->contains(reference_token))
|
||||
{
|
||||
// we did not find the key in the object
|
||||
return false;
|
||||
@@ -678,21 +682,21 @@ class json_pointer
|
||||
// "-" always fails the range check
|
||||
return false;
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 and not ("0" <= reference_token and reference_token <= "9")))
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
||||
{
|
||||
// invalid char
|
||||
return false;
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not ('1' <= reference_token[0] and reference_token[0] <= '9')))
|
||||
if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
|
||||
{
|
||||
// first char should be between '1' and '9'
|
||||
return false;
|
||||
}
|
||||
for (std::size_t i = 1; i < reference_token.size(); i++)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not ('0' <= reference_token[i] and reference_token[i] <= '9')))
|
||||
if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
|
||||
{
|
||||
// other char should be between '0' and '9'
|
||||
return false;
|
||||
@@ -700,7 +704,7 @@ class json_pointer
|
||||
}
|
||||
}
|
||||
|
||||
const auto idx = static_cast<size_type>(array_index(reference_token));
|
||||
const auto idx = array_index(reference_token);
|
||||
if (idx >= ptr->size())
|
||||
{
|
||||
// index out of range
|
||||
@@ -776,11 +780,11 @@ class json_pointer
|
||||
pos != std::string::npos;
|
||||
pos = reference_token.find_first_of('~', pos + 1))
|
||||
{
|
||||
assert(reference_token[pos] == '~');
|
||||
JSON_ASSERT(reference_token[pos] == '~');
|
||||
|
||||
// ~ must be followed by 0 or 1
|
||||
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or
|
||||
(reference_token[pos + 1] != '0' and
|
||||
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
|
||||
(reference_token[pos + 1] != '0' &&
|
||||
reference_token[pos + 1] != '1')))
|
||||
{
|
||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
|
||||
@@ -811,7 +815,7 @@ class json_pointer
|
||||
static void replace_substring(std::string& s, const std::string& f,
|
||||
const std::string& t)
|
||||
{
|
||||
assert(not f.empty());
|
||||
JSON_ASSERT(!f.empty());
|
||||
for (auto pos = s.find(f); // find first occurrence of f
|
||||
pos != std::string::npos; // make sure f was found
|
||||
s.replace(pos, f.size(), t), // replace with t, and
|
||||
@@ -906,7 +910,7 @@ class json_pointer
|
||||
static BasicJsonType
|
||||
unflatten(const BasicJsonType& value)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not value.is_object()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
|
||||
}
|
||||
@@ -916,7 +920,7 @@ class json_pointer
|
||||
// iterate the JSON object values
|
||||
for (const auto& element : *value.m_value.object)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive()))
|
||||
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
|
||||
{
|
||||
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
|
||||
}
|
||||
@@ -962,7 +966,7 @@ class json_pointer
|
||||
friend bool operator!=(json_pointer const& lhs,
|
||||
json_pointer const& rhs) noexcept
|
||||
{
|
||||
return not (lhs == rhs);
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// the reference tokens
|
||||
|
||||
@@ -16,23 +16,30 @@ class json_ref
|
||||
using value_type = BasicJsonType;
|
||||
|
||||
json_ref(value_type&& value)
|
||||
: owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true)
|
||||
: owned_value(std::move(value))
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
json_ref(const value_type& value)
|
||||
: value_ref(const_cast<value_type*>(&value)), is_rvalue(false)
|
||||
: value_ref(const_cast<value_type*>(&value))
|
||||
, is_rvalue(false)
|
||||
{}
|
||||
|
||||
json_ref(std::initializer_list<json_ref> init)
|
||||
: owned_value(init), value_ref(&owned_value), is_rvalue(true)
|
||||
: owned_value(init)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
template <
|
||||
class... Args,
|
||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
||||
json_ref(Args && ... args)
|
||||
: owned_value(std::forward<Args>(args)...), value_ref(&owned_value),
|
||||
is_rvalue(true) {}
|
||||
: owned_value(std::forward<Args>(args)...)
|
||||
, value_ref(&owned_value)
|
||||
, is_rvalue(true)
|
||||
{}
|
||||
|
||||
// class should be movable only
|
||||
json_ref(json_ref&&) = default;
|
||||
@@ -63,7 +70,7 @@ class json_ref
|
||||
private:
|
||||
mutable value_type owned_value = nullptr;
|
||||
value_type* value_ref = nullptr;
|
||||
const bool is_rvalue;
|
||||
const bool is_rvalue = true;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
#endif
|
||||
|
||||
// C++ language standard detection
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
|
||||
#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#define JSON_HAS_CPP_20
|
||||
#define JSON_HAS_CPP_17
|
||||
#define JSON_HAS_CPP_14
|
||||
#elif (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)
|
||||
@@ -81,6 +85,12 @@
|
||||
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
|
||||
#endif
|
||||
|
||||
// allow to override assert
|
||||
#if !defined(JSON_ASSERT)
|
||||
#include <cassert> // assert
|
||||
#define JSON_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief macro to briefly define a mapping between an enum and JSON
|
||||
@def NLOHMANN_JSON_SERIALIZE_ENUM
|
||||
@@ -128,3 +138,167 @@
|
||||
basic_json<ObjectType, ArrayType, StringType, BooleanType, \
|
||||
NumberIntegerType, NumberUnsignedType, NumberFloatType, \
|
||||
AllocatorType, JSONSerializer, BinaryType>
|
||||
|
||||
// Macros to simplify conversion from/to types
|
||||
|
||||
#define NLOHMANN_JSON_EXPAND( x ) x
|
||||
#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
|
||||
#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
|
||||
NLOHMANN_JSON_PASTE64, \
|
||||
NLOHMANN_JSON_PASTE63, \
|
||||
NLOHMANN_JSON_PASTE62, \
|
||||
NLOHMANN_JSON_PASTE61, \
|
||||
NLOHMANN_JSON_PASTE60, \
|
||||
NLOHMANN_JSON_PASTE59, \
|
||||
NLOHMANN_JSON_PASTE58, \
|
||||
NLOHMANN_JSON_PASTE57, \
|
||||
NLOHMANN_JSON_PASTE56, \
|
||||
NLOHMANN_JSON_PASTE55, \
|
||||
NLOHMANN_JSON_PASTE54, \
|
||||
NLOHMANN_JSON_PASTE53, \
|
||||
NLOHMANN_JSON_PASTE52, \
|
||||
NLOHMANN_JSON_PASTE51, \
|
||||
NLOHMANN_JSON_PASTE50, \
|
||||
NLOHMANN_JSON_PASTE49, \
|
||||
NLOHMANN_JSON_PASTE48, \
|
||||
NLOHMANN_JSON_PASTE47, \
|
||||
NLOHMANN_JSON_PASTE46, \
|
||||
NLOHMANN_JSON_PASTE45, \
|
||||
NLOHMANN_JSON_PASTE44, \
|
||||
NLOHMANN_JSON_PASTE43, \
|
||||
NLOHMANN_JSON_PASTE42, \
|
||||
NLOHMANN_JSON_PASTE41, \
|
||||
NLOHMANN_JSON_PASTE40, \
|
||||
NLOHMANN_JSON_PASTE39, \
|
||||
NLOHMANN_JSON_PASTE38, \
|
||||
NLOHMANN_JSON_PASTE37, \
|
||||
NLOHMANN_JSON_PASTE36, \
|
||||
NLOHMANN_JSON_PASTE35, \
|
||||
NLOHMANN_JSON_PASTE34, \
|
||||
NLOHMANN_JSON_PASTE33, \
|
||||
NLOHMANN_JSON_PASTE32, \
|
||||
NLOHMANN_JSON_PASTE31, \
|
||||
NLOHMANN_JSON_PASTE30, \
|
||||
NLOHMANN_JSON_PASTE29, \
|
||||
NLOHMANN_JSON_PASTE28, \
|
||||
NLOHMANN_JSON_PASTE27, \
|
||||
NLOHMANN_JSON_PASTE26, \
|
||||
NLOHMANN_JSON_PASTE25, \
|
||||
NLOHMANN_JSON_PASTE24, \
|
||||
NLOHMANN_JSON_PASTE23, \
|
||||
NLOHMANN_JSON_PASTE22, \
|
||||
NLOHMANN_JSON_PASTE21, \
|
||||
NLOHMANN_JSON_PASTE20, \
|
||||
NLOHMANN_JSON_PASTE19, \
|
||||
NLOHMANN_JSON_PASTE18, \
|
||||
NLOHMANN_JSON_PASTE17, \
|
||||
NLOHMANN_JSON_PASTE16, \
|
||||
NLOHMANN_JSON_PASTE15, \
|
||||
NLOHMANN_JSON_PASTE14, \
|
||||
NLOHMANN_JSON_PASTE13, \
|
||||
NLOHMANN_JSON_PASTE12, \
|
||||
NLOHMANN_JSON_PASTE11, \
|
||||
NLOHMANN_JSON_PASTE10, \
|
||||
NLOHMANN_JSON_PASTE9, \
|
||||
NLOHMANN_JSON_PASTE8, \
|
||||
NLOHMANN_JSON_PASTE7, \
|
||||
NLOHMANN_JSON_PASTE6, \
|
||||
NLOHMANN_JSON_PASTE5, \
|
||||
NLOHMANN_JSON_PASTE4, \
|
||||
NLOHMANN_JSON_PASTE3, \
|
||||
NLOHMANN_JSON_PASTE2, \
|
||||
NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
|
||||
#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
|
||||
#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
|
||||
#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
|
||||
#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
|
||||
#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
|
||||
#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
|
||||
#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
|
||||
#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
|
||||
#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
|
||||
#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
|
||||
#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
|
||||
#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
|
||||
#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
|
||||
#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
|
||||
#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
|
||||
#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
|
||||
#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
|
||||
#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
|
||||
#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
|
||||
#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
|
||||
#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
|
||||
#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
|
||||
#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
|
||||
#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
|
||||
#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
|
||||
#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
|
||||
#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
|
||||
#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
|
||||
#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
|
||||
#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
|
||||
#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
|
||||
#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
|
||||
#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
|
||||
#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
|
||||
#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
|
||||
#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
|
||||
#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
|
||||
#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
|
||||
#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
|
||||
#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
|
||||
#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
|
||||
#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
|
||||
#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
|
||||
#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
|
||||
#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
|
||||
#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
|
||||
#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
|
||||
#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
|
||||
#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
|
||||
#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
|
||||
#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
|
||||
#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
|
||||
#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
|
||||
#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
|
||||
#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
|
||||
#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
|
||||
#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
|
||||
#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
|
||||
#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
|
||||
#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
|
||||
#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
|
||||
#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
|
||||
#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
|
||||
|
||||
#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
|
||||
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
|
||||
|
||||
/*!
|
||||
@brief macro
|
||||
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
|
||||
@since version 3.9.0
|
||||
*/
|
||||
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
|
||||
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
|
||||
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
|
||||
|
||||
/*!
|
||||
@brief macro
|
||||
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
|
||||
@since version 3.9.0
|
||||
*/
|
||||
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
|
||||
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
|
||||
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
|
||||
|
||||
#ifndef JSON_USE_IMPLICIT_CONVERSIONS
|
||||
#define JSON_USE_IMPLICIT_CONVERSIONS 1
|
||||
#endif
|
||||
|
||||
#if JSON_USE_IMPLICIT_CONVERSIONS
|
||||
#define JSON_EXPLICIT
|
||||
#else
|
||||
#define JSON_EXPLICIT explicit
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#endif
|
||||
|
||||
// clean up
|
||||
#undef JSON_ASSERT
|
||||
#undef JSON_INTERNAL_CATCH
|
||||
#undef JSON_CATCH
|
||||
#undef JSON_THROW
|
||||
@@ -17,5 +18,6 @@
|
||||
#undef JSON_HAS_CPP_17
|
||||
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||
#undef NLOHMANN_BASIC_JSON_TPL
|
||||
#undef JSON_EXPLICIT
|
||||
|
||||
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#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
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
|
||||
@@ -19,39 +19,39 @@ struct nonesuch
|
||||
void operator=(nonesuch&&) = delete;
|
||||
};
|
||||
|
||||
template <class Default,
|
||||
class AlwaysVoid,
|
||||
template <class...> class Op,
|
||||
class... Args>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
template<class To, template<class...> class Op, class... Args>
|
||||
using is_detected_convertible =
|
||||
std::is_convertible<detected_t<Op, Args...>, To>;
|
||||
} // namespace detail
|
||||
|
||||
@@ -11,53 +11,57 @@ namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using null_function_t = decltype(std::declval<T&>().null());
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using boolean_function_t =
|
||||
decltype(std::declval<T&>().boolean(std::declval<bool>()));
|
||||
|
||||
template <typename T, typename Integer>
|
||||
template<typename T, typename Integer>
|
||||
using number_integer_function_t =
|
||||
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
|
||||
|
||||
template <typename T, typename Unsigned>
|
||||
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>
|
||||
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>
|
||||
template<typename T, typename String>
|
||||
using string_function_t =
|
||||
decltype(std::declval<T&>().string(std::declval<String&>()));
|
||||
|
||||
template <typename T>
|
||||
template<typename T, typename Binary>
|
||||
using binary_function_t =
|
||||
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
||||
|
||||
template<typename T>
|
||||
using start_object_function_t =
|
||||
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
||||
|
||||
template <typename T, typename String>
|
||||
template<typename T, typename String>
|
||||
using key_function_t =
|
||||
decltype(std::declval<T&>().key(std::declval<String&>()));
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using end_object_function_t = decltype(std::declval<T&>().end_object());
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using start_array_function_t =
|
||||
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using end_array_function_t = decltype(std::declval<T&>().end_array());
|
||||
|
||||
template <typename T, typename Exception>
|
||||
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>
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
struct is_sax
|
||||
{
|
||||
private:
|
||||
@@ -68,19 +72,18 @@ struct is_sax
|
||||
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 binary_t = typename BasicJsonType::binary_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, 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, binary_function_t, SAX, binary_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 &&
|
||||
@@ -89,7 +92,7 @@ struct is_sax
|
||||
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
|
||||
};
|
||||
|
||||
template <typename SAX, typename BasicJsonType>
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
struct is_sax_static_asserts
|
||||
{
|
||||
private:
|
||||
@@ -100,6 +103,7 @@ struct is_sax_static_asserts
|
||||
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 binary_t = typename BasicJsonType::binary_t;
|
||||
using exception_t = typename BasicJsonType::exception;
|
||||
|
||||
public:
|
||||
@@ -123,6 +127,9 @@ struct is_sax_static_asserts
|
||||
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, binary_function_t, SAX, binary_t>::value,
|
||||
"Missing/invalid function: bool binary(binary_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,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
@@ -45,59 +44,69 @@ struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
|
||||
// json_ref helpers //
|
||||
//////////////////////
|
||||
|
||||
template <typename>
|
||||
template<typename>
|
||||
class json_ref;
|
||||
|
||||
template<typename>
|
||||
struct is_json_ref : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct is_json_ref<json_ref<T>> : std::true_type {};
|
||||
|
||||
//////////////////////////
|
||||
// aliases for detected //
|
||||
//////////////////////////
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using mapped_type_t = typename T::mapped_type;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using key_type_t = typename T::key_type;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using value_type_t = typename T::value_type;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using difference_type_t = typename T::difference_type;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using pointer_t = typename T::pointer;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using reference_t = typename T::reference;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using iterator_category_t = typename T::iterator_category;
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
using iterator_t = typename T::iterator;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
template<typename T, typename... Args>
|
||||
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
|
||||
|
||||
template <typename T, typename... Args>
|
||||
template<typename T, typename... Args>
|
||||
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
|
||||
|
||||
template <typename T, typename U>
|
||||
template<typename T, typename U>
|
||||
using get_template_function = decltype(std::declval<T>().template get<U>());
|
||||
|
||||
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
||||
template <typename BasicJsonType, typename T, typename = void>
|
||||
template<typename BasicJsonType, typename T, typename = void>
|
||||
struct has_from_json : std::false_type {};
|
||||
|
||||
// trait checking if j.get<T> is valid
|
||||
// use this trait instead of std::is_constructible or std::is_convertible,
|
||||
// both rely on, or make use of implicit conversions, and thus fail when T
|
||||
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
|
||||
template <typename BasicJsonType, typename T>
|
||||
struct has_from_json<BasicJsonType, T,
|
||||
enable_if_t<not is_basic_json<T>::value>>
|
||||
struct is_getable
|
||||
{
|
||||
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
|
||||
};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct has_from_json < BasicJsonType, T,
|
||||
enable_if_t < !is_basic_json<T>::value >>
|
||||
{
|
||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||
|
||||
@@ -108,11 +117,11 @@ struct has_from_json<BasicJsonType, T,
|
||||
|
||||
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
||||
// this overload is used for non-default-constructible user-defined-types
|
||||
template <typename BasicJsonType, typename T, typename = void>
|
||||
template<typename BasicJsonType, typename T, typename = void>
|
||||
struct has_non_default_from_json : std::false_type {};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
|
||||
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||
{
|
||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||
|
||||
@@ -123,11 +132,11 @@ struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json
|
||||
|
||||
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
||||
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
|
||||
template <typename BasicJsonType, typename T, typename = void>
|
||||
template<typename BasicJsonType, typename T, typename = void>
|
||||
struct has_to_json : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename T>
|
||||
struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
||||
{
|
||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||
|
||||
@@ -141,10 +150,10 @@ struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
|
||||
// is_ functions //
|
||||
///////////////////
|
||||
|
||||
template <typename T, typename = void>
|
||||
template<typename T, typename = void>
|
||||
struct is_iterator_traits : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct is_iterator_traits<iterator_traits<T>>
|
||||
{
|
||||
private:
|
||||
@@ -161,20 +170,20 @@ struct is_iterator_traits<iterator_traits<T>>
|
||||
|
||||
// source: https://stackoverflow.com/a/37193089/4116453
|
||||
|
||||
template <typename T, typename = void>
|
||||
template<typename T, typename = void>
|
||||
struct is_complete_type : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleObjectType,
|
||||
typename = void>
|
||||
template<typename BasicJsonType, typename CompatibleObjectType,
|
||||
typename = void>
|
||||
struct is_compatible_object_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleObjectType>
|
||||
template<typename BasicJsonType, typename CompatibleObjectType>
|
||||
struct is_compatible_object_type_impl <
|
||||
BasicJsonType, CompatibleObjectType,
|
||||
enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
|
||||
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
|
||||
is_detected<key_type_t, CompatibleObjectType>::value >>
|
||||
{
|
||||
|
||||
@@ -183,53 +192,53 @@ struct is_compatible_object_type_impl <
|
||||
// macOS's is_constructible does not play well with nonesuch...
|
||||
static constexpr bool value =
|
||||
std::is_constructible<typename object_t::key_type,
|
||||
typename CompatibleObjectType::key_type>::value and
|
||||
typename CompatibleObjectType::key_type>::value &&
|
||||
std::is_constructible<typename object_t::mapped_type,
|
||||
typename CompatibleObjectType::mapped_type>::value;
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleObjectType>
|
||||
template<typename BasicJsonType, typename CompatibleObjectType>
|
||||
struct is_compatible_object_type
|
||||
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleObjectType,
|
||||
typename = void>
|
||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
||||
typename = void>
|
||||
struct is_constructible_object_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleObjectType>
|
||||
template<typename BasicJsonType, typename ConstructibleObjectType>
|
||||
struct is_constructible_object_type_impl <
|
||||
BasicJsonType, ConstructibleObjectType,
|
||||
enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value and
|
||||
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
|
||||
is_detected<key_type_t, ConstructibleObjectType>::value >>
|
||||
{
|
||||
using object_t = typename BasicJsonType::object_t;
|
||||
|
||||
static constexpr bool value =
|
||||
(std::is_default_constructible<ConstructibleObjectType>::value and
|
||||
(std::is_move_assignable<ConstructibleObjectType>::value or
|
||||
std::is_copy_assignable<ConstructibleObjectType>::value) and
|
||||
(std::is_default_constructible<ConstructibleObjectType>::value &&
|
||||
(std::is_move_assignable<ConstructibleObjectType>::value ||
|
||||
std::is_copy_assignable<ConstructibleObjectType>::value) &&
|
||||
(std::is_constructible<typename ConstructibleObjectType::key_type,
|
||||
typename object_t::key_type>::value and
|
||||
typename object_t::key_type>::value &&
|
||||
std::is_same <
|
||||
typename object_t::mapped_type,
|
||||
typename ConstructibleObjectType::mapped_type >::value)) or
|
||||
typename ConstructibleObjectType::mapped_type >::value)) ||
|
||||
(has_from_json<BasicJsonType,
|
||||
typename ConstructibleObjectType::mapped_type>::value or
|
||||
typename ConstructibleObjectType::mapped_type>::value ||
|
||||
has_non_default_from_json <
|
||||
BasicJsonType,
|
||||
typename ConstructibleObjectType::mapped_type >::value);
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleObjectType>
|
||||
template<typename BasicJsonType, typename ConstructibleObjectType>
|
||||
struct is_constructible_object_type
|
||||
: is_constructible_object_type_impl<BasicJsonType,
|
||||
ConstructibleObjectType> {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleStringType,
|
||||
typename = void>
|
||||
template<typename BasicJsonType, typename CompatibleStringType,
|
||||
typename = void>
|
||||
struct is_compatible_string_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleStringType>
|
||||
template<typename BasicJsonType, typename CompatibleStringType>
|
||||
struct is_compatible_string_type_impl <
|
||||
BasicJsonType, CompatibleStringType,
|
||||
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
|
||||
@@ -239,15 +248,15 @@ struct is_compatible_string_type_impl <
|
||||
std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleStringType>
|
||||
template<typename BasicJsonType, typename ConstructibleStringType>
|
||||
struct is_compatible_string_type
|
||||
: is_compatible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleStringType,
|
||||
typename = void>
|
||||
template<typename BasicJsonType, typename ConstructibleStringType,
|
||||
typename = void>
|
||||
struct is_constructible_string_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleStringType>
|
||||
template<typename BasicJsonType, typename ConstructibleStringType>
|
||||
struct is_constructible_string_type_impl <
|
||||
BasicJsonType, ConstructibleStringType,
|
||||
enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
|
||||
@@ -258,55 +267,55 @@ struct is_constructible_string_type_impl <
|
||||
typename BasicJsonType::string_t>::value;
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleStringType>
|
||||
template<typename BasicJsonType, typename ConstructibleStringType>
|
||||
struct is_constructible_string_type
|
||||
: is_constructible_string_type_impl<BasicJsonType, ConstructibleStringType> {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
|
||||
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
|
||||
struct is_compatible_array_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleArrayType>
|
||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||
struct is_compatible_array_type_impl <
|
||||
BasicJsonType, CompatibleArrayType,
|
||||
enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
|
||||
is_detected<iterator_t, CompatibleArrayType>::value and
|
||||
enable_if_t < is_detected<value_type_t, CompatibleArrayType>::value&&
|
||||
is_detected<iterator_t, CompatibleArrayType>::value&&
|
||||
// This is needed because json_reverse_iterator has a ::iterator type...
|
||||
// Therefore it is detected as a CompatibleArrayType.
|
||||
// The real fix would be to have an Iterable concept.
|
||||
not is_iterator_traits<
|
||||
iterator_traits<CompatibleArrayType>>::value >>
|
||||
!is_iterator_traits <
|
||||
iterator_traits<CompatibleArrayType >>::value >>
|
||||
{
|
||||
static constexpr bool value =
|
||||
std::is_constructible<BasicJsonType,
|
||||
typename CompatibleArrayType::value_type>::value;
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleArrayType>
|
||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||
struct is_compatible_array_type
|
||||
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType, typename = void>
|
||||
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
|
||||
struct is_constructible_array_type_impl : std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType>
|
||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
struct is_constructible_array_type_impl <
|
||||
BasicJsonType, ConstructibleArrayType,
|
||||
enable_if_t<std::is_same<ConstructibleArrayType,
|
||||
typename BasicJsonType::value_type>::value >>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType>
|
||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
struct is_constructible_array_type_impl <
|
||||
BasicJsonType, ConstructibleArrayType,
|
||||
enable_if_t<not std::is_same<ConstructibleArrayType,
|
||||
typename BasicJsonType::value_type>::value and
|
||||
std::is_default_constructible<ConstructibleArrayType>::value and
|
||||
(std::is_move_assignable<ConstructibleArrayType>::value or
|
||||
std::is_copy_assignable<ConstructibleArrayType>::value) and
|
||||
is_detected<value_type_t, ConstructibleArrayType>::value and
|
||||
is_detected<iterator_t, ConstructibleArrayType>::value and
|
||||
is_complete_type<
|
||||
detected_t<value_type_t, ConstructibleArrayType>>::value >>
|
||||
enable_if_t < !std::is_same<ConstructibleArrayType,
|
||||
typename BasicJsonType::value_type>::value&&
|
||||
std::is_default_constructible<ConstructibleArrayType>::value&&
|
||||
(std::is_move_assignable<ConstructibleArrayType>::value ||
|
||||
std::is_copy_assignable<ConstructibleArrayType>::value)&&
|
||||
is_detected<value_type_t, ConstructibleArrayType>::value&&
|
||||
is_detected<iterator_t, ConstructibleArrayType>::value&&
|
||||
is_complete_type <
|
||||
detected_t<value_type_t, ConstructibleArrayType >>::value >>
|
||||
{
|
||||
static constexpr bool value =
|
||||
// This is needed because json_reverse_iterator has a ::iterator type,
|
||||
@@ -314,30 +323,30 @@ detected_t<value_type_t, ConstructibleArrayType>>::value >>
|
||||
// base class `iterator`... Therefore it is detected as a
|
||||
// ConstructibleArrayType. The real fix would be to have an Iterable
|
||||
// concept.
|
||||
not is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value and
|
||||
!is_iterator_traits<iterator_traits<ConstructibleArrayType>>::value &&
|
||||
|
||||
(std::is_same<typename ConstructibleArrayType::value_type,
|
||||
typename BasicJsonType::array_t::value_type>::value or
|
||||
typename BasicJsonType::array_t::value_type>::value ||
|
||||
has_from_json<BasicJsonType,
|
||||
typename ConstructibleArrayType::value_type>::value or
|
||||
typename ConstructibleArrayType::value_type>::value ||
|
||||
has_non_default_from_json <
|
||||
BasicJsonType, typename ConstructibleArrayType::value_type >::value);
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename ConstructibleArrayType>
|
||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
struct is_constructible_array_type
|
||||
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
|
||||
|
||||
template <typename RealIntegerType, typename CompatibleNumberIntegerType,
|
||||
typename = void>
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
|
||||
typename = void>
|
||||
struct is_compatible_integer_type_impl : std::false_type {};
|
||||
|
||||
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type_impl <
|
||||
RealIntegerType, CompatibleNumberIntegerType,
|
||||
enable_if_t<std::is_integral<RealIntegerType>::value and
|
||||
std::is_integral<CompatibleNumberIntegerType>::value and
|
||||
not std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
||||
enable_if_t < std::is_integral<RealIntegerType>::value&&
|
||||
std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
||||
{
|
||||
// is there an assert somewhere on overflows?
|
||||
using RealLimits = std::numeric_limits<RealIntegerType>;
|
||||
@@ -345,20 +354,20 @@ struct is_compatible_integer_type_impl <
|
||||
|
||||
static constexpr auto value =
|
||||
std::is_constructible<RealIntegerType,
|
||||
CompatibleNumberIntegerType>::value and
|
||||
CompatibleLimits::is_integer and
|
||||
CompatibleNumberIntegerType>::value &&
|
||||
CompatibleLimits::is_integer &&
|
||||
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||
};
|
||||
|
||||
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type
|
||||
: is_compatible_integer_type_impl<RealIntegerType,
|
||||
CompatibleNumberIntegerType> {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleType, typename = void>
|
||||
template<typename BasicJsonType, typename CompatibleType, typename = void>
|
||||
struct is_compatible_type_impl: std::false_type {};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleType>
|
||||
template<typename BasicJsonType, typename CompatibleType>
|
||||
struct is_compatible_type_impl <
|
||||
BasicJsonType, CompatibleType,
|
||||
enable_if_t<is_complete_type<CompatibleType>::value >>
|
||||
@@ -367,7 +376,7 @@ struct is_compatible_type_impl <
|
||||
has_to_json<BasicJsonType, CompatibleType>::value;
|
||||
};
|
||||
|
||||
template <typename BasicJsonType, typename CompatibleType>
|
||||
template<typename BasicJsonType, typename CompatibleType>
|
||||
struct is_compatible_type
|
||||
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
|
||||
|
||||
@@ -378,10 +387,10 @@ template<class B1, class... Bn>
|
||||
struct conjunction<B1, Bn...>
|
||||
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
template<typename T1, typename T2>
|
||||
struct is_constructible_tuple : std::false_type {};
|
||||
|
||||
template <typename T1, typename... Args>
|
||||
template<typename T1, typename... Args>
|
||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@@ -4,10 +4,10 @@ namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename ...Ts> struct make_void
|
||||
template<typename ...Ts> struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
|
||||
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@@ -28,6 +28,7 @@ class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
|
||||
public:
|
||||
/*!
|
||||
@@ -37,7 +38,7 @@ class binary_writer
|
||||
*/
|
||||
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
|
||||
{
|
||||
assert(oa);
|
||||
JSON_ASSERT(oa);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -194,18 +195,7 @@ class binary_writer
|
||||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<double>(j.m_value.number_float) >= static_cast<double>(std::numeric_limits<float>::lowest()) and
|
||||
static_cast<double>(j.m_value.number_float) <= static_cast<double>((std::numeric_limits<float>::max)()) and
|
||||
static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
|
||||
write_number(static_cast<float>(j.m_value.number_float));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
}
|
||||
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -289,6 +279,12 @@ class binary_writer
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
if (j.m_value.binary->has_subtype())
|
||||
{
|
||||
write_number(static_cast<std::uint8_t>(0xd8));
|
||||
write_number(j.m_value.binary->subtype());
|
||||
}
|
||||
|
||||
// step 1: write control byte and the binary array size
|
||||
const auto N = j.m_value.binary->size();
|
||||
if (N <= 0x17)
|
||||
@@ -436,28 +432,28 @@ class binary_writer
|
||||
// negative fixnum
|
||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
// int 8
|
||||
oa->write_character(to_char_type(0xD0));
|
||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
// int 16
|
||||
oa->write_character(to_char_type(0xD1));
|
||||
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
// int 32
|
||||
oa->write_character(to_char_type(0xD2));
|
||||
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
// int 64
|
||||
@@ -504,8 +500,7 @@ class binary_writer
|
||||
|
||||
case value_t::number_float:
|
||||
{
|
||||
oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -584,7 +579,7 @@ class binary_writer
|
||||
const auto N = j.m_value.binary->size();
|
||||
if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
std::uint8_t output_type{};
|
||||
bool fixed = true;
|
||||
if (use_ext)
|
||||
{
|
||||
@@ -619,37 +614,25 @@ class binary_writer
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
if (not fixed)
|
||||
if (!fixed)
|
||||
{
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
if (use_ext)
|
||||
{
|
||||
output_type = 0xC8; // ext 16
|
||||
}
|
||||
else
|
||||
{
|
||||
output_type = 0xC5; // bin 16
|
||||
}
|
||||
std::uint8_t output_type = use_ext
|
||||
? 0xC8 // ext 16
|
||||
: 0xC5; // bin 16
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
std::uint8_t output_type;
|
||||
if (use_ext)
|
||||
{
|
||||
output_type = 0xC9; // ext 32
|
||||
}
|
||||
else
|
||||
{
|
||||
output_type = 0xC6; // bin 32
|
||||
}
|
||||
std::uint8_t output_type = use_ext
|
||||
? 0xC9 // ext 32
|
||||
: 0xC6; // bin 32
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
@@ -775,9 +758,9 @@ class binary_writer
|
||||
}
|
||||
|
||||
bool prefix_required = true;
|
||||
if (use_type and not j.m_value.array->empty())
|
||||
if (use_type && !j.m_value.array->empty())
|
||||
{
|
||||
assert(use_count);
|
||||
JSON_ASSERT(use_count);
|
||||
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)
|
||||
@@ -804,7 +787,7 @@ class binary_writer
|
||||
write_ubjson(el, use_count, use_type, prefix_required);
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
if (!use_count)
|
||||
{
|
||||
oa->write_character(to_char_type(']'));
|
||||
}
|
||||
@@ -819,9 +802,9 @@ class binary_writer
|
||||
oa->write_character(to_char_type('['));
|
||||
}
|
||||
|
||||
if (use_type and not j.m_value.binary->empty())
|
||||
if (use_type && !j.m_value.binary->empty())
|
||||
{
|
||||
assert(use_count);
|
||||
JSON_ASSERT(use_count);
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character('U');
|
||||
}
|
||||
@@ -847,7 +830,7 @@ class binary_writer
|
||||
}
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
if (!use_count)
|
||||
{
|
||||
oa->write_character(to_char_type(']'));
|
||||
}
|
||||
@@ -863,9 +846,9 @@ class binary_writer
|
||||
}
|
||||
|
||||
bool prefix_required = true;
|
||||
if (use_type and not j.m_value.object->empty())
|
||||
if (use_type && !j.m_value.object->empty())
|
||||
{
|
||||
assert(use_count);
|
||||
JSON_ASSERT(use_count);
|
||||
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)
|
||||
@@ -896,7 +879,7 @@ class binary_writer
|
||||
write_ubjson(el.second, use_count, use_type, prefix_required);
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
if (!use_count)
|
||||
{
|
||||
oa->write_character(to_char_type('}'));
|
||||
}
|
||||
@@ -997,7 +980,7 @@ class binary_writer
|
||||
*/
|
||||
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
||||
{
|
||||
return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
|
||||
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
|
||||
? sizeof(std::int32_t)
|
||||
: sizeof(std::int64_t);
|
||||
}
|
||||
@@ -1008,7 +991,7 @@ class binary_writer
|
||||
void write_bson_integer(const string_t& name,
|
||||
const std::int64_t value)
|
||||
{
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
write_bson_entry_header(name, 0x10); // int32
|
||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
|
||||
@@ -1157,7 +1140,7 @@ class binary_writer
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
assert(false);
|
||||
JSON_ASSERT(false);
|
||||
return 0ul;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
@@ -1204,7 +1187,7 @@ class binary_writer
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
assert(false);
|
||||
JSON_ASSERT(false);
|
||||
return;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
@@ -1336,18 +1319,28 @@ class binary_writer
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('H')); // high-precision number
|
||||
}
|
||||
|
||||
const auto number = BasicJsonType(n).dump();
|
||||
write_number_with_ubjson_prefix(number.size(), true);
|
||||
for (std::size_t i = 0; i < number.size(); ++i)
|
||||
{
|
||||
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UBJSON: write number (signed integer)
|
||||
template<typename NumberType, typename std::enable_if<
|
||||
std::is_signed<NumberType>::value and
|
||||
not std::is_floating_point<NumberType>::value, int>::type = 0>
|
||||
template < typename NumberType, typename std::enable_if <
|
||||
std::is_signed<NumberType>::value&&
|
||||
!std::is_floating_point<NumberType>::value, int >::type = 0 >
|
||||
void write_number_with_ubjson_prefix(const NumberType n,
|
||||
const bool add_prefix)
|
||||
{
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
@@ -1355,7 +1348,7 @@ class binary_writer
|
||||
}
|
||||
write_number(static_cast<std::int8_t>(n));
|
||||
}
|
||||
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
||||
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
@@ -1363,7 +1356,7 @@ class binary_writer
|
||||
}
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
|
||||
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
@@ -1371,7 +1364,7 @@ class binary_writer
|
||||
}
|
||||
write_number(static_cast<std::int16_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
|
||||
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
@@ -1379,7 +1372,7 @@ class binary_writer
|
||||
}
|
||||
write_number(static_cast<std::int32_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
|
||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
@@ -1390,19 +1383,23 @@ class binary_writer
|
||||
// LCOV_EXCL_START
|
||||
else
|
||||
{
|
||||
JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(n) + " cannot be represented by UBJSON as it does not fit int64"));
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('H')); // high-precision number
|
||||
}
|
||||
|
||||
const auto number = BasicJsonType(n).dump();
|
||||
write_number_with_ubjson_prefix(number.size(), true);
|
||||
for (std::size_t i = 0; i < number.size(); ++i)
|
||||
{
|
||||
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief determine the type prefix of container values
|
||||
|
||||
@note This function does not need to be 100% accurate when it comes to
|
||||
integer limits. In case a number exceeds the limits of int64_t,
|
||||
this will be detected by a later call to function
|
||||
write_number_with_ubjson_prefix. Therefore, we return 'L' for any
|
||||
value that does not fit the previous limits.
|
||||
*/
|
||||
CharType ubjson_prefix(const BasicJsonType& j) const noexcept
|
||||
{
|
||||
@@ -1416,24 +1413,28 @@ class binary_writer
|
||||
|
||||
case value_t::number_integer:
|
||||
{
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
return 'i';
|
||||
}
|
||||
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
return 'U';
|
||||
}
|
||||
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
return 'I';
|
||||
}
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
return 'l';
|
||||
}
|
||||
// no check and assume int64_t (see note above)
|
||||
return 'L';
|
||||
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
return 'L';
|
||||
}
|
||||
// anything else is treated as high-precision number
|
||||
return 'H'; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
case value_t::number_unsigned:
|
||||
@@ -1454,8 +1455,12 @@ class binary_writer
|
||||
{
|
||||
return 'l';
|
||||
}
|
||||
// no check and assume int64_t (see note above)
|
||||
return 'L';
|
||||
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
|
||||
{
|
||||
return 'L';
|
||||
}
|
||||
// anything else is treated as high-precision number
|
||||
return 'H'; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
case value_t::number_float:
|
||||
@@ -1518,20 +1523,40 @@ class binary_writer
|
||||
oa->write_characters(vec.data(), sizeof(NumberType));
|
||||
}
|
||||
|
||||
void write_compact_float(const number_float_t n, detail::input_format_t format)
|
||||
{
|
||||
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
||||
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
||||
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
|
||||
{
|
||||
oa->write_character(format == detail::input_format_t::cbor
|
||||
? get_cbor_float_prefix(static_cast<float>(n))
|
||||
: get_msgpack_float_prefix(static_cast<float>(n)));
|
||||
write_number(static_cast<float>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(format == detail::input_format_t::cbor
|
||||
? get_cbor_float_prefix(n)
|
||||
: get_msgpack_float_prefix(n));
|
||||
write_number(n);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// The following to_char_type functions are implement the conversion
|
||||
// between uint8_t and CharType. In case CharType is not unsigned,
|
||||
// such a conversion is required to allow values greater than 128.
|
||||
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
|
||||
template < typename C = CharType,
|
||||
enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
|
||||
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
|
||||
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
||||
{
|
||||
return *reinterpret_cast<char*>(&x);
|
||||
}
|
||||
|
||||
template < typename C = CharType,
|
||||
enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
|
||||
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
|
||||
static CharType to_char_type(std::uint8_t x) noexcept
|
||||
{
|
||||
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
|
||||
@@ -1550,8 +1575,8 @@ class binary_writer
|
||||
|
||||
template < typename InputCharType, typename C = CharType,
|
||||
enable_if_t <
|
||||
std::is_signed<C>::value and
|
||||
std::is_signed<char>::value and
|
||||
std::is_signed<C>::value &&
|
||||
std::is_signed<char>::value &&
|
||||
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
|
||||
> * = nullptr >
|
||||
static constexpr CharType to_char_type(InputCharType x) noexcept
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
|
||||
#include <algorithm> // reverse, remove, fill, find, none_of
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <clocale> // localeconv, lconv
|
||||
#include <cmath> // labs, isfinite, isnan, signbit
|
||||
#include <cstddef> // size_t, ptrdiff_t
|
||||
#include <cstdint> // uint8_t
|
||||
#include <cstdio> // snprintf
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // string
|
||||
#include <string> // string, char_traits
|
||||
#include <type_traits> // is_same
|
||||
#include <utility> // move
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
@@ -59,8 +57,8 @@ class serializer
|
||||
error_handler_t error_handler_ = error_handler_t::strict)
|
||||
: o(std::move(s))
|
||||
, loc(std::localeconv())
|
||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : * (loc->thousands_sep))
|
||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : * (loc->decimal_point))
|
||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
|
||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
|
||||
, indent_char(ichar)
|
||||
, indent_string(512, indent_char)
|
||||
, error_handler(error_handler_)
|
||||
@@ -135,8 +133,8 @@ class serializer
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
assert(std::next(i) == val.m_value.object->cend());
|
||||
JSON_ASSERT(i != val.m_value.object->cend());
|
||||
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o->write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
@@ -163,8 +161,8 @@ class serializer
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
assert(std::next(i) == val.m_value.object->cend());
|
||||
JSON_ASSERT(i != val.m_value.object->cend());
|
||||
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
|
||||
o->write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
o->write_characters("\":", 2);
|
||||
@@ -205,7 +203,7 @@ class serializer
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
JSON_ASSERT(!val.m_value.array->empty());
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
|
||||
|
||||
@@ -226,7 +224,7 @@ class serializer
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
JSON_ASSERT(!val.m_value.array->empty());
|
||||
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
|
||||
|
||||
o->write_character(']');
|
||||
@@ -260,7 +258,7 @@ class serializer
|
||||
|
||||
o->write_characters("\"bytes\": [", 10);
|
||||
|
||||
if (not val.m_value.binary->empty())
|
||||
if (!val.m_value.binary->empty())
|
||||
{
|
||||
for (auto i = val.m_value.binary->cbegin();
|
||||
i != val.m_value.binary->cend() - 1; ++i)
|
||||
@@ -291,7 +289,7 @@ class serializer
|
||||
{
|
||||
o->write_characters("{\"bytes\":[", 10);
|
||||
|
||||
if (not val.m_value.binary->empty())
|
||||
if (!val.m_value.binary->empty())
|
||||
{
|
||||
for (auto i = val.m_value.binary->cbegin();
|
||||
i != val.m_value.binary->cend() - 1; ++i)
|
||||
@@ -360,7 +358,7 @@ class serializer
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +450,7 @@ class serializer
|
||||
{
|
||||
// escape control characters (0x00..0x1F) or, if
|
||||
// ensure_ascii parameter is used, non-ASCII characters
|
||||
if ((codepoint <= 0x1F) or (ensure_ascii and (codepoint >= 0x7F)))
|
||||
if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
|
||||
{
|
||||
if (codepoint <= 0xFFFF)
|
||||
{
|
||||
@@ -559,14 +557,14 @@ class serializer
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: // decode found yet incomplete multi-byte code point
|
||||
{
|
||||
if (not ensure_ascii)
|
||||
if (!ensure_ascii)
|
||||
{
|
||||
// code point will not be escaped - copy byte to buffer
|
||||
string_buffer[bytes++] = s[i];
|
||||
@@ -622,7 +620,7 @@ class serializer
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,11 +668,11 @@ class serializer
|
||||
@param[in] x integer number (signed or unsigned) to dump
|
||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||
*/
|
||||
template<typename NumberType, detail::enable_if_t<
|
||||
std::is_same<NumberType, number_unsigned_t>::value or
|
||||
std::is_same<NumberType, number_integer_t>::value or
|
||||
std::is_same<NumberType, binary_char_t>::value,
|
||||
int> = 0>
|
||||
template < typename NumberType, detail::enable_if_t <
|
||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||
std::is_same<NumberType, number_integer_t>::value ||
|
||||
std::is_same<NumberType, binary_char_t>::value,
|
||||
int > = 0 >
|
||||
void dump_integer(NumberType x)
|
||||
{
|
||||
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
|
||||
@@ -703,7 +701,7 @@ class serializer
|
||||
// use a pointer to fill the buffer
|
||||
auto buffer_ptr = number_buffer.begin();
|
||||
|
||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
|
||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
|
||||
number_unsigned_t abs_value;
|
||||
|
||||
unsigned int n_chars;
|
||||
@@ -723,7 +721,7 @@ class serializer
|
||||
}
|
||||
|
||||
// spare 1 byte for '\0'
|
||||
assert(n_chars < number_buffer.size() - 1);
|
||||
JSON_ASSERT(n_chars < number_buffer.size() - 1);
|
||||
|
||||
// jump to the end to generate the string from backward
|
||||
// so we later avoid reversing the result
|
||||
@@ -764,7 +762,7 @@ class serializer
|
||||
void dump_float(number_float_t x)
|
||||
{
|
||||
// NaN / inf
|
||||
if (not std::isfinite(x))
|
||||
if (!std::isfinite(x))
|
||||
{
|
||||
o->write_characters("null", 4);
|
||||
return;
|
||||
@@ -776,8 +774,8 @@ class serializer
|
||||
//
|
||||
// NB: The test below works if <long double> == <double>.
|
||||
static constexpr bool is_ieee_single_or_double
|
||||
= (std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 24 and std::numeric_limits<number_float_t>::max_exponent == 128) or
|
||||
(std::numeric_limits<number_float_t>::is_iec559 and std::numeric_limits<number_float_t>::digits == 53 and std::numeric_limits<number_float_t>::max_exponent == 1024);
|
||||
= (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
|
||||
(std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
|
||||
|
||||
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
||||
}
|
||||
@@ -799,9 +797,9 @@ class serializer
|
||||
std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
|
||||
|
||||
// negative value indicates an error
|
||||
assert(len > 0);
|
||||
JSON_ASSERT(len > 0);
|
||||
// check if buffer was large enough
|
||||
assert(static_cast<std::size_t>(len) < number_buffer.size());
|
||||
JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
|
||||
|
||||
// erase thousands separator
|
||||
if (thousands_sep != '\0')
|
||||
@@ -809,12 +807,12 @@ class serializer
|
||||
const auto end = std::remove(number_buffer.begin(),
|
||||
number_buffer.begin() + len, thousands_sep);
|
||||
std::fill(end, number_buffer.end(), '\0');
|
||||
assert((end - number_buffer.begin()) <= len);
|
||||
JSON_ASSERT((end - number_buffer.begin()) <= len);
|
||||
len = (end - number_buffer.begin());
|
||||
}
|
||||
|
||||
// convert decimal point to '.'
|
||||
if (decimal_point != '\0' and decimal_point != '.')
|
||||
if (decimal_point != '\0' && decimal_point != '.')
|
||||
{
|
||||
const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
|
||||
if (dec_pos != number_buffer.end())
|
||||
@@ -830,7 +828,7 @@ class serializer
|
||||
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
||||
[](char c)
|
||||
{
|
||||
return c == '.' or c == 'e';
|
||||
return c == '.' || c == 'e';
|
||||
});
|
||||
|
||||
if (value_is_int_like)
|
||||
@@ -889,7 +887,7 @@ class serializer
|
||||
: (0xFFu >> type) & (byte);
|
||||
|
||||
std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
|
||||
assert(index < 400);
|
||||
JSON_ASSERT(index < 400);
|
||||
state = utf8d[index];
|
||||
return state;
|
||||
}
|
||||
@@ -901,7 +899,7 @@ class serializer
|
||||
*/
|
||||
number_unsigned_t remove_sign(number_unsigned_t x)
|
||||
{
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
JSON_ASSERT(false); // LCOV_EXCL_LINE
|
||||
return x; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
@@ -916,7 +914,7 @@ class serializer
|
||||
*/
|
||||
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||
{
|
||||
assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
|
||||
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
|
||||
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <cstdint> // uint8_t
|
||||
#include <string> // string
|
||||
|
||||
#include <nlohmann/detail/boolean_operators.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
@@ -77,7 +75,7 @@ inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
||||
|
||||
const auto l_index = static_cast<std::size_t>(lhs);
|
||||
const auto r_index = static_cast<std::size_t>(rhs);
|
||||
return l_index < order.size() and r_index < order.size() and order[l_index] < order[r_index];
|
||||
return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,19 @@ uses the standard template types.
|
||||
@since version 1.0.0
|
||||
*/
|
||||
using json = basic_json<>;
|
||||
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct ordered_map;
|
||||
|
||||
/*!
|
||||
@brief ordered JSON class
|
||||
|
||||
This type preserves the insertion order of object keys.
|
||||
|
||||
@since version 3.9.0
|
||||
*/
|
||||
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||
|
||||
} // namespace nlohmann
|
||||
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
171
include/nlohmann/ordered_map.hpp
Normal file
171
include/nlohmann/ordered_map.hpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional> // less
|
||||
#include <memory> // allocator
|
||||
#include <utility> // pair
|
||||
#include <vector> // vector
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
||||
/// ordered_map: a minimal map-like container that preserves insertion order
|
||||
/// for use within nlohmann::basic_json<ordered_map>
|
||||
template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
|
||||
{
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using Container = std::vector<std::pair<const Key, T>, Allocator>;
|
||||
using typename Container::iterator;
|
||||
using typename Container::const_iterator;
|
||||
using typename Container::size_type;
|
||||
using typename Container::value_type;
|
||||
|
||||
// Explicit constructors instead of `using Container::Container`
|
||||
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
||||
ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
|
||||
template <class It>
|
||||
ordered_map(It first, It last, const Allocator& alloc = Allocator())
|
||||
: Container{first, last, alloc} {}
|
||||
ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
|
||||
: Container{init, alloc} {}
|
||||
|
||||
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::emplace_back(key, t);
|
||||
return {--this->end(), true};
|
||||
}
|
||||
|
||||
T& operator[](const Key& key)
|
||||
{
|
||||
return emplace(key, T{}).first->second;
|
||||
}
|
||||
|
||||
const T& operator[](const Key& key) const
|
||||
{
|
||||
return at(key);
|
||||
}
|
||||
|
||||
T& at(const Key& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
|
||||
const T& at(const Key& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::out_of_range("key not found");
|
||||
}
|
||||
|
||||
size_type erase(const Key& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
{
|
||||
it->~value_type(); // Destroy but keep allocation
|
||||
new (&*it) value_type{std::move(*next)};
|
||||
}
|
||||
Container::pop_back();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator erase(iterator pos)
|
||||
{
|
||||
auto it = pos;
|
||||
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
{
|
||||
it->~value_type(); // Destroy but keep allocation
|
||||
new (&*it) value_type{std::move(*next)};
|
||||
}
|
||||
Container::pop_back();
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_type count(const Key& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert( value_type&& value )
|
||||
{
|
||||
return emplace(value.first, std::move(value.second));
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert( const value_type& value )
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (it->first == value.first)
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::push_back(value);
|
||||
return {--this->end(), true};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nlohmann
|
||||
Reference in New Issue
Block a user