Merge branch 'develop' of https://github.com/nlohmann/json into feature/optional
This commit is contained in:
333 files changed
+16557
-6954
No files matched your search
@@ -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()} };
|
||||
|
||||
Reference in new issue
Block a user