Merge remote-tracking branch 'nlohmann/develop' into iterate-on-destruction

This commit is contained in:
Isaac Nickaein 2019-11-09 14:50:48 +03:30
commit eec1974218
148 changed files with 27046 additions and 18980 deletions

View file

@ -26,7 +26,7 @@ namespace detail
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
{
if (JSON_UNLIKELY(not j.is_null()))
if (JSON_HEDLEY_UNLIKELY(not j.is_null()))
{
JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name())));
}
@ -66,7 +66,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_UNLIKELY(not j.is_boolean()))
if (JSON_HEDLEY_UNLIKELY(not j.is_boolean()))
{
JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name())));
}
@ -76,7 +76,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_UNLIKELY(not j.is_string()))
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
}
@ -92,7 +92,7 @@ template <
int > = 0 >
void from_json(const BasicJsonType& j, ConstructibleStringType& s)
{
if (JSON_UNLIKELY(not j.is_string()))
if (JSON_HEDLEY_UNLIKELY(not j.is_string()))
{
JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name())));
}
@ -132,10 +132,11 @@ template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
{
if (JSON_UNLIKELY(not j.is_array()))
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
l.clear();
std::transform(j.rbegin(), j.rend(),
std::front_inserter(l), [](const BasicJsonType & i)
{
@ -148,12 +149,22 @@ template<typename BasicJsonType, typename T,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
void from_json(const BasicJsonType& j, std::valarray<T>& l)
{
if (JSON_UNLIKELY(not j.is_array()))
if (JSON_HEDLEY_UNLIKELY(not 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.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
std::copy(j.begin(), j.end(), std::begin(l));
}
template <typename BasicJsonType, typename T, std::size_t N>
auto from_json(const BasicJsonType& j, T (&arr)[N])
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{
arr[i] = j.at(i).template get<T>();
}
}
template<typename BasicJsonType>
@ -182,14 +193,16 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
{
using std::end;
arr.reserve(j.size());
ConstructibleArrayType ret;
ret.reserve(j.size());
std::transform(j.begin(), j.end(),
std::inserter(arr, end(arr)), [](const BasicJsonType & i)
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
});
arr = std::move(ret);
}
template <typename BasicJsonType, typename ConstructibleArrayType>
@ -198,14 +211,16 @@ void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
{
using std::end;
ConstructibleArrayType ret;
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)),
j.begin(), j.end(), std::inserter(ret, end(ret)),
[](const BasicJsonType & i)
{
// get<BasicJsonType>() returns *this, this won't call a from_json
// method when value_type is BasicJsonType
return i.template get<typename ConstructibleArrayType::value_type>();
});
arr = std::move(ret);
}
template <typename BasicJsonType, typename ConstructibleArrayType,
@ -221,7 +236,7 @@ auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
j.template get<typename ConstructibleArrayType::value_type>(),
void())
{
if (JSON_UNLIKELY(not j.is_array()))
if (JSON_HEDLEY_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " +
std::string(j.type_name())));
@ -234,20 +249,22 @@ 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_UNLIKELY(not j.is_object()))
if (JSON_HEDLEY_UNLIKELY(not j.is_object()))
{
JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name())));
}
ConstructibleObjectType ret;
auto inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type;
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(obj, obj.begin()),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
{
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
});
obj = std::move(ret);
}
// overload for arithmetic types, not chosen for basic_json template arguments
@ -315,13 +332,14 @@ template <typename BasicJsonType, typename Key, typename Value, typename Compare
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
if (JSON_HEDLEY_UNLIKELY(not 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_UNLIKELY(not p.is_array()))
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
@ -334,13 +352,14 @@ template <typename BasicJsonType, typename Key, typename Value, typename Hash, t
typename BasicJsonType::string_t, Key>::value>>
void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
{
if (JSON_UNLIKELY(not j.is_array()))
if (JSON_HEDLEY_UNLIKELY(not 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_UNLIKELY(not p.is_array()))
if (JSON_HEDLEY_UNLIKELY(not p.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name())));
}
@ -367,4 +386,4 @@ namespace
{
constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value;
} // namespace
} // namespace nlohmann
} // namespace nlohmann

View file

@ -1,5 +1,6 @@
#pragma once
#include <array> // array
#include <cassert> // assert
#include <ciso646> // or, and, not
#include <cmath> // signbit, isfinite
@ -7,6 +8,7 @@
#include <cstring> // memcpy, memmove
#include <limits> // numeric_limits
#include <type_traits> // conditional
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
@ -49,10 +51,10 @@ struct diyfp // f * 2^e
{
static constexpr int kPrecision = 64; // = q
uint64_t f = 0;
std::uint64_t f = 0;
int e = 0;
constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
/*!
@brief returns x - y
@ -97,23 +99,23 @@ struct diyfp // f * 2^e
//
// = p_lo + 2^64 p_hi
const uint64_t u_lo = x.f & 0xFFFFFFFF;
const uint64_t u_hi = x.f >> 32;
const uint64_t v_lo = y.f & 0xFFFFFFFF;
const uint64_t v_hi = y.f >> 32;
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
const std::uint64_t u_hi = x.f >> 32u;
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
const std::uint64_t v_hi = y.f >> 32u;
const uint64_t p0 = u_lo * v_lo;
const uint64_t p1 = u_lo * v_hi;
const uint64_t p2 = u_hi * v_lo;
const uint64_t p3 = u_hi * v_hi;
const std::uint64_t p0 = u_lo * v_lo;
const std::uint64_t p1 = u_lo * v_hi;
const std::uint64_t p2 = u_hi * v_lo;
const std::uint64_t p3 = u_hi * v_hi;
const uint64_t p0_hi = p0 >> 32;
const uint64_t p1_lo = p1 & 0xFFFFFFFF;
const uint64_t p1_hi = p1 >> 32;
const uint64_t p2_lo = p2 & 0xFFFFFFFF;
const uint64_t p2_hi = p2 >> 32;
const std::uint64_t p0_hi = p0 >> 32u;
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
const std::uint64_t p1_hi = p1 >> 32u;
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
const std::uint64_t p2_hi = p2 >> 32u;
uint64_t Q = p0_hi + p1_lo + p2_lo;
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
// The full product might now be computed as
//
@ -124,9 +126,9 @@ struct diyfp // f * 2^e
// Effectively we only need to add the highest bit in p_lo to p_hi (and
// Q_hi + 1 does not overflow).
Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
return {h, x.e + y.e + 64};
}
@ -139,9 +141,9 @@ struct diyfp // f * 2^e
{
assert(x.f != 0);
while ((x.f >> 63) == 0)
while ((x.f >> 63u) == 0)
{
x.f <<= 1;
x.f <<= 1u;
x.e--;
}
@ -195,15 +197,15 @@ boundaries compute_boundaries(FloatType value)
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
constexpr int kMinExp = 1 - kBias;
constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
const uint64_t bits = reinterpret_bits<bits_type>(value);
const uint64_t E = bits >> (kPrecision - 1);
const uint64_t F = bits & (kHiddenBit - 1);
const std::uint64_t bits = reinterpret_bits<bits_type>(value);
const std::uint64_t E = bits >> (kPrecision - 1);
const std::uint64_t F = bits & (kHiddenBit - 1);
const bool is_denormal = (E == 0);
const bool is_denormal = E == 0;
const diyfp v = is_denormal
? diyfp(F, kMinExp)
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
@ -229,7 +231,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 and 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)
@ -304,7 +306,7 @@ constexpr int kGamma = -32;
struct cached_power // c = f * 2^e ~= 10^k
{
uint64_t f;
std::uint64_t f;
int e;
int k;
};
@ -328,7 +330,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
// ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
// ==> 2^(alpha - e - 1) <= c
//
// If c were an exakt power of ten, i.e. c = 10^k, one may determine k as
// If c were an exact power of ten, i.e. c = 10^k, one may determine k as
//
// k = ceil( log_10( 2^(alpha - e - 1) ) )
// = ceil( (alpha - e - 1) * log_10(2) )
@ -368,91 +370,92 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
// NB:
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
constexpr int kCachedPowersSize = 79;
constexpr int kCachedPowersMinDecExp = -300;
constexpr int kCachedPowersDecStep = 8;
static constexpr cached_power kCachedPowers[] =
static constexpr std::array<cached_power, 79> kCachedPowers =
{
{ 0xAB70FE17C79AC6CA, -1060, -300 },
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
{ 0xBE5691EF416BD60C, -1007, -284 },
{ 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 },
{ 0x9D71AC8FADA6C9B5, -927, -260 },
{ 0xEA9C227723EE8BCB, -901, -252 },
{ 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 },
{ 0xC21094364DFB5637, -821, -228 },
{ 0x9096EA6F3848984F, -794, -220 },
{ 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 },
{ 0xEF340A98172AACE5, -715, -196 },
{ 0xB23867FB2A35B28E, -688, -188 },
{ 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 },
{ 0x936B9FCEBB25C996, -608, -164 },
{ 0xDBAC6C247D62A584, -582, -156 },
{ 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 },
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
{ 0x87625F056C7C4A8B, -475, -124 },
{ 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 },
{ 0xDFF9772470297EBD, -396, -100 },
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
{ 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 },
{ 0x8A08F0F8BF0F156B, -289, -68 },
{ 0xCDB02555653131B6, -263, -60 },
{ 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 },
{ 0xAA242499697392D3, -183, -36 },
{ 0xFD87B5F28300CA0E, -157, -28 },
{ 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 },
{ 0xD1B71758E219652C, -77, -4 },
{ 0x9C40000000000000, -50, 4 },
{ 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 },
{ 0x813F3978F8940984, 30, 28 },
{ 0xC097CE7BC90715B3, 56, 36 },
{ 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 },
{ 0x9F4F2726179A2245, 136, 60 },
{ 0xED63A231D4C4FB27, 162, 68 },
{ 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 },
{ 0xC45D1DF942711D9A, 242, 92 },
{ 0x924D692CA61BE758, 269, 100 },
{ 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 },
{ 0xF209787BB47D6B85, 348, 124 },
{ 0xB454E4A179DD1877, 375, 132 },
{ 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 },
{ 0x952AB45CFA97A0B3, 455, 156 },
{ 0xDE469FBD99A05FE3, 481, 164 },
{ 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 },
{ 0xB7DCBF5354E9BECE, 561, 188 },
{ 0x88FCF317F22241E2, 588, 196 },
{ 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 },
{ 0xE2A0B5DC971F303A, 667, 220 },
{ 0xA8D9D1535CE3B396, 694, 228 },
{ 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 },
{ 0x8BAB8EEFB6409C1A, 774, 252 },
{ 0xD01FEF10A657842C, 800, 260 },
{ 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 },
{ 0xAC2820D9623BF429, 880, 284 },
{ 0x80444B5E7AA7CF85, 907, 292 },
{ 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 },
{ 0xD433179D9C8CB841, 986, 316 },
{ 0x9E19DB92B4E31BA9, 1013, 324 },
{
{ 0xAB70FE17C79AC6CA, -1060, -300 },
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
{ 0xBE5691EF416BD60C, -1007, -284 },
{ 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 },
{ 0x9D71AC8FADA6C9B5, -927, -260 },
{ 0xEA9C227723EE8BCB, -901, -252 },
{ 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 },
{ 0xC21094364DFB5637, -821, -228 },
{ 0x9096EA6F3848984F, -794, -220 },
{ 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 },
{ 0xEF340A98172AACE5, -715, -196 },
{ 0xB23867FB2A35B28E, -688, -188 },
{ 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 },
{ 0x936B9FCEBB25C996, -608, -164 },
{ 0xDBAC6C247D62A584, -582, -156 },
{ 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 },
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
{ 0x87625F056C7C4A8B, -475, -124 },
{ 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 },
{ 0xDFF9772470297EBD, -396, -100 },
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
{ 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 },
{ 0x8A08F0F8BF0F156B, -289, -68 },
{ 0xCDB02555653131B6, -263, -60 },
{ 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 },
{ 0xAA242499697392D3, -183, -36 },
{ 0xFD87B5F28300CA0E, -157, -28 },
{ 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 },
{ 0xD1B71758E219652C, -77, -4 },
{ 0x9C40000000000000, -50, 4 },
{ 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 },
{ 0x813F3978F8940984, 30, 28 },
{ 0xC097CE7BC90715B3, 56, 36 },
{ 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 },
{ 0x9F4F2726179A2245, 136, 60 },
{ 0xED63A231D4C4FB27, 162, 68 },
{ 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 },
{ 0xC45D1DF942711D9A, 242, 92 },
{ 0x924D692CA61BE758, 269, 100 },
{ 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 },
{ 0xF209787BB47D6B85, 348, 124 },
{ 0xB454E4A179DD1877, 375, 132 },
{ 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 },
{ 0x952AB45CFA97A0B3, 455, 156 },
{ 0xDE469FBD99A05FE3, 481, 164 },
{ 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 },
{ 0xB7DCBF5354E9BECE, 561, 188 },
{ 0x88FCF317F22241E2, 588, 196 },
{ 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 },
{ 0xE2A0B5DC971F303A, 667, 220 },
{ 0xA8D9D1535CE3B396, 694, 228 },
{ 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 },
{ 0x8BAB8EEFB6409C1A, 774, 252 },
{ 0xD01FEF10A657842C, 800, 260 },
{ 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 },
{ 0xAC2820D9623BF429, 880, 284 },
{ 0x80444B5E7AA7CF85, 907, 292 },
{ 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 },
{ 0xD433179D9C8CB841, 986, 316 },
{ 0x9E19DB92B4E31BA9, 1013, 324 },
}
};
// This computation gives exactly the same results for k as
@ -466,10 +469,9 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
assert(index >= 0);
assert(index < kCachedPowersSize);
static_cast<void>(kCachedPowersSize); // Fix warning.
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
const cached_power cached = kCachedPowers[index];
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
assert(kAlpha <= cached.e + e + 64);
assert(kGamma >= cached.e + e + 64);
@ -480,7 +482,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
For n == 0, returns 1 and sets pow10 := 1.
*/
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
{
// LCOV_EXCL_START
if (n >= 1000000000)
@ -536,8 +538,8 @@ inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
}
}
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
uint64_t rest, uint64_t ten_k)
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);
@ -598,8 +600,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
assert(M_plus.e >= kAlpha);
assert(M_plus.e <= kGamma);
uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
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)
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
//
@ -608,10 +610,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// = ((p1 ) * 2^-e + (p2 )) * 2^e
// = p1 + p2 * 2^e
const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
// 1)
//
@ -619,7 +621,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
assert(p1 > 0);
uint32_t pow10;
std::uint32_t pow10;
const int k = find_largest_pow10(p1, pow10);
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
@ -647,8 +649,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
// pow10 = 10^(n-1) <= p1 < 10^n
//
const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
//
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
@ -673,7 +675,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// Note:
// Since rest and delta share the same exponent e, it suffices to
// compare the significands.
const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
if (rest <= delta)
{
// V = buffer * 10^n, with M- <= V <= M+.
@ -689,7 +691,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
//
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
//
const uint64_t ten_n = uint64_t{pow10} << -one.e;
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
grisu2_round(buffer, length, dist, delta, rest, ten_n);
return;
@ -751,10 +753,10 @@ 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 <= UINT64_MAX / 10);
assert(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
p2 *= 10;
const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
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
//
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
@ -794,7 +796,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
//
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
//
const uint64_t ten_m = one.f;
const std::uint64_t ten_m = one.f;
grisu2_round(buffer, length, dist, delta, p2, ten_m);
// By construction this algorithm generates the shortest possible decimal
@ -817,6 +819,7 @@ 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.
*/
JSON_HEDLEY_NON_NULL(1)
inline void grisu2(char* buf, int& len, int& decimal_exponent,
diyfp m_minus, diyfp v, diyfp m_plus)
{
@ -876,6 +879,7 @@ len is the length of the buffer (number of decimal digits)
The buffer must be large enough, i.e. >= max_digits10.
*/
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,
@ -914,6 +918,8 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
@return a pointer to the element following the exponent.
@pre -1000 < e < 1000
*/
JSON_HEDLEY_NON_NULL(1)
JSON_HEDLEY_RETURNS_NON_NULL
inline char* append_exponent(char* buf, int e)
{
assert(e > -1000);
@ -929,7 +935,7 @@ inline char* append_exponent(char* buf, int e)
*buf++ = '+';
}
auto k = static_cast<uint32_t>(e);
auto k = static_cast<std::uint32_t>(e);
if (k < 10)
{
// Always print at least two digits in the exponent.
@ -964,6 +970,8 @@ notation. Otherwise it will be printed in exponential notation.
@pre min_exp < 0
@pre max_exp > 0
*/
JSON_HEDLEY_NON_NULL(1)
JSON_HEDLEY_RETURNS_NON_NULL
inline char* format_buffer(char* buf, int len, int decimal_exponent,
int min_exp, int max_exp)
{
@ -1047,6 +1055,8 @@ format. Returns an iterator pointing past-the-end of the decimal representation.
@note The result is NOT null-terminated.
*/
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

View file

@ -1,17 +1,19 @@
#pragma once
#include <algorithm> // copy
#include <ciso646> // or, and, not
#include <iterator> // begin, end
#include <string> // string
#include <tuple> // tuple, get
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
namespace nlohmann
{
@ -152,7 +154,10 @@ struct external_constructor<value_t::array>
j.m_type = value_t::array;
j.m_value = value_t::array;
j.m_value.array->resize(arr.size());
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
if (arr.size() > 0)
{
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
}
j.assert_invariant();
}
};
@ -297,8 +302,8 @@ void to_json(BasicJsonType& j, const T(&arr)[N])
external_constructor<value_t::array>::construct(j, arr);
}
template<typename BasicJsonType, typename... Args>
void to_json(BasicJsonType& j, const std::pair<Args...>& p)
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
{
j = { p.first, p.second };
}
@ -317,10 +322,10 @@ void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...>
j = { std::get<Idx>(t)... };
}
template<typename BasicJsonType, typename... Args>
void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
void to_json(BasicJsonType& j, const T& t)
{
to_json_tuple_impl(j, t, index_sequence_for<Args...> {});
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
}
struct to_json_fn
@ -339,4 +344,4 @@ namespace
{
constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value;
} // namespace
} // namespace nlohmann
} // namespace nlohmann

View file

@ -5,6 +5,7 @@
#include <string> // to_string
#include <nlohmann/detail/input/position_t.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
@ -46,6 +47,7 @@ class exception : public std::exception
{
public:
/// returns the explanatory string
JSON_HEDLEY_RETURNS_NON_NULL
const char* what() const noexcept override
{
return m.what();
@ -55,6 +57,7 @@ class exception : public std::exception
const int id;
protected:
JSON_HEDLEY_NON_NULL(3)
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {}
static std::string name(const std::string& ename, int id_)
@ -102,12 +105,12 @@ json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F
@liveexample{The following code shows how a `parse_error` exception can be
caught.,parse_error}
@sa @ref exception for the base class of the library exceptions
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -117,7 +120,7 @@ class parse_error : public exception
/*!
@brief create a parse error exception
@param[in] id_ the id of the exception
@param[in] position the position where the error occurred (or with
@param[in] pos the position where the error occurred (or with
chars_read_total=0 if the position cannot be
determined)
@param[in] what_arg the explanatory string
@ -188,12 +191,12 @@ json.exception.invalid_iterator.214 | cannot get value | Cannot get value for it
@liveexample{The following code shows how an `invalid_iterator` exception can be
caught.,invalid_iterator}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -207,6 +210,7 @@ class invalid_iterator : public exception
}
private:
JSON_HEDLEY_NON_NULL(3)
invalid_iterator(int id_, const char* what_arg)
: exception(id_, what_arg) {}
};
@ -223,7 +227,7 @@ name / id | example message | description
----------------------------- | --------------- | -------------------------
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
@ -242,11 +246,11 @@ json.exception.type_error.317 | JSON value cannot be serialized to requested for
@liveexample{The following code shows how a `type_error` exception can be
caught.,type_error}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -260,6 +264,7 @@ class type_error : public exception
}
private:
JSON_HEDLEY_NON_NULL(3)
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
@ -287,12 +292,12 @@ json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at
@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -306,6 +311,7 @@ class out_of_range : public exception
}
private:
JSON_HEDLEY_NON_NULL(3)
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
@ -321,12 +327,12 @@ name / id | example message | description
------------------------------ | --------------- | -------------------------
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@liveexample{The following code shows how an `other_error` exception can be
caught.,other_error}
@ -343,6 +349,7 @@ class other_error : public exception
}
private:
JSON_HEDLEY_NON_NULL(3)
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
};
} // namespace detail

View file

@ -13,9 +13,9 @@
#include <string> // char_traits, string
#include <utility> // make_pair, move
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
@ -52,6 +52,13 @@ class binary_reader
assert(ia);
}
// make class move-only
binary_reader(const binary_reader&) = delete;
binary_reader(binary_reader&&) = default;
binary_reader& operator=(const binary_reader&) = delete;
binary_reader& operator=(binary_reader&&) = default;
~binary_reader() = default;
/*!
@param[in] format the binary format to parse
@param[in] sax_ a SAX event processor
@ -59,6 +66,7 @@ class binary_reader
@return
*/
JSON_HEDLEY_NON_NULL(3)
bool sax_parse(const input_format_t format,
json_sax_t* sax_,
const bool strict = true)
@ -84,10 +92,8 @@ class binary_reader
result = parse_ubjson_internal();
break;
// LCOV_EXCL_START
default:
assert(false);
// LCOV_EXCL_STOP
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
// strict mode: next byte must be EOF
@ -102,7 +108,7 @@ class binary_reader
get();
}
if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char>::eof()))
{
return sax->parse_error(chars_read, get_token_string(),
parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value")));
@ -121,7 +127,7 @@ class binary_reader
*/
static constexpr bool little_endianess(int num = 1) noexcept
{
return (*reinterpret_cast<char*>(&num) == 1);
return *reinterpret_cast<char*>(&num) == 1;
}
private:
@ -138,12 +144,12 @@ class binary_reader
std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
return false;
}
if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/false)))
{
return false;
}
@ -164,7 +170,7 @@ class binary_reader
while (true)
{
get();
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring")))
{
return false;
}
@ -192,7 +198,7 @@ class binary_reader
template<typename NumberType>
bool get_bson_string(const NumberType len, string_t& result)
{
if (JSON_UNLIKELY(len < 1))
if (JSON_HEDLEY_UNLIKELY(len < 1))
{
auto last_token = get_token_string();
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string")));
@ -263,9 +269,9 @@ class binary_reader
default: // anything else not supported (yet)
{
char cr[3];
(std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr)));
std::array<char, 3> cr{{}};
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
}
}
}
@ -287,26 +293,23 @@ class binary_reader
string_t key;
while (int element_type = get())
{
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list")))
{
return false;
}
const std::size_t element_type_parse_position = chars_read;
if (JSON_UNLIKELY(not get_bson_cstr(key)))
if (JSON_HEDLEY_UNLIKELY(not get_bson_cstr(key)))
{
return false;
}
if (not is_array)
if (not is_array and not sax->key(key))
{
if (not sax->key(key))
{
return false;
}
return false;
}
if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
{
return false;
}
@ -327,12 +330,12 @@ class binary_reader
std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
{
return false;
}
if (JSON_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/true)))
{
return false;
}
@ -388,25 +391,25 @@ class binary_reader
case 0x18: // Unsigned integer (one-byte uint8_t follows)
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x19: // Unsigned integer (two-byte uint16_t follows)
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
@ -435,29 +438,29 @@ class binary_reader
case 0x35:
case 0x36:
case 0x37:
return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
case 0x38: // Negative integer (one-byte uint8_t follows)
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
- static_cast<number_integer_t>(number));
}
@ -522,29 +525,29 @@ class binary_reader
case 0x95:
case 0x96:
case 0x97:
return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
case 0x98: // array (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x99: // array (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9A: // array (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
@ -576,29 +579,29 @@ class binary_reader
case 0xB5:
case 0xB6:
case 0xB7:
return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
case 0xB8: // map (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xB9: // map (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBA: // map (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
@ -617,12 +620,12 @@ class binary_reader
case 0xF9: // Half-Precision Float (two-byte IEEE 754)
{
const int byte1_raw = get();
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
{
return false;
}
const int byte2_raw = get();
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number")))
{
return false;
}
@ -638,13 +641,13 @@ class binary_reader
// without such support. An example of a small decoder for
// half-precision floating-point numbers in the C language
// is shown in Fig. 3.
const int half = (byte1 << 8) + byte2;
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
const double val = [&half]
{
const int exp = (half >> 10) & 0x1F;
const int mant = half & 0x3FF;
const int exp = (half >> 10u) & 0x1Fu;
const unsigned int mant = half & 0x3FFu;
assert(0 <= exp and exp <= 32);
assert(0 <= mant and mant <= 1024);
assert(mant <= 1024);
switch (exp)
{
case 0:
@ -657,7 +660,7 @@ class binary_reader
return std::ldexp(mant + 1024, exp - 25);
}
}();
return sax->number_float((half & 0x8000) != 0
return sax->number_float((half & 0x8000u) != 0
? static_cast<number_float_t>(-val)
: static_cast<number_float_t>(val), "");
}
@ -695,7 +698,7 @@ class binary_reader
*/
bool get_cbor_string(string_t& result)
{
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string")))
{
return false;
}
@ -728,30 +731,30 @@ class binary_reader
case 0x76:
case 0x77:
{
return get_string(input_format_t::cbor, current & 0x1F, result);
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
}
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
@ -784,7 +787,7 @@ class binary_reader
*/
bool get_cbor_array(const std::size_t len)
{
if (JSON_UNLIKELY(not sax->start_array(len)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
{
return false;
}
@ -793,7 +796,7 @@ class binary_reader
{
for (std::size_t i = 0; i < len; ++i)
{
if (JSON_UNLIKELY(not parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
{
return false;
}
@ -803,7 +806,7 @@ class binary_reader
{
while (get() != 0xFF)
{
if (JSON_UNLIKELY(not parse_cbor_internal(false)))
if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal(false)))
{
return false;
}
@ -820,7 +823,7 @@ class binary_reader
*/
bool get_cbor_object(const std::size_t len)
{
if (JSON_UNLIKELY(not sax->start_object(len)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
{
return false;
}
@ -831,12 +834,12 @@ class binary_reader
for (std::size_t i = 0; i < len; ++i)
{
get();
if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
{
return false;
}
@ -847,12 +850,12 @@ class binary_reader
{
while (get() != 0xFF)
{
if (JSON_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal()))
{
return false;
}
@ -1026,7 +1029,7 @@ class binary_reader
case 0x8D:
case 0x8E:
case 0x8F:
return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixarray
case 0x90:
@ -1045,7 +1048,7 @@ class binary_reader
case 0x9D:
case 0x9E:
case 0x9F:
return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixstr
case 0xA0:
@ -1080,6 +1083,9 @@ class binary_reader
case 0xBD:
case 0xBE:
case 0xBF:
case 0xD9: // str 8
case 0xDA: // str 16
case 0xDB: // str 32
{
string_t s;
return get_msgpack_string(s) and sax->string(s);
@ -1108,81 +1114,73 @@ class binary_reader
case 0xCC: // uint 8
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCD: // uint 16
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCE: // uint 32
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCF: // uint 64
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xD0: // int 8
{
int8_t number;
std::int8_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD1: // int 16
{
int16_t number;
std::int16_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD2: // int 32
{
int32_t number;
std::int32_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD3: // int 64
{
int64_t number;
std::int64_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD9: // str 8
case 0xDA: // str 16
case 0xDB: // str 32
{
string_t s;
return get_msgpack_string(s) and sax->string(s);
}
case 0xDC: // array 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDD: // array 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDE: // map 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
}
case 0xDF: // map 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
}
@ -1219,7 +1217,7 @@ class binary_reader
case 0xFD:
case 0xFE:
case 0xFF:
return sax->number_integer(static_cast<int8_t>(current));
return sax->number_integer(static_cast<std::int8_t>(current));
default: // anything else
{
@ -1241,7 +1239,7 @@ class binary_reader
*/
bool get_msgpack_string(string_t& result)
{
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string")))
{
return false;
}
@ -1282,24 +1280,24 @@ class binary_reader
case 0xBE:
case 0xBF:
{
return get_string(input_format_t::msgpack, current & 0x1F, result);
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
}
case 0xD9: // str 8
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
case 0xDA: // str 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
case 0xDB: // str 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
@ -1317,14 +1315,14 @@ class binary_reader
*/
bool get_msgpack_array(const std::size_t len)
{
if (JSON_UNLIKELY(not sax->start_array(len)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len)))
{
return false;
}
for (std::size_t i = 0; i < len; ++i)
{
if (JSON_UNLIKELY(not parse_msgpack_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
{
return false;
}
@ -1339,7 +1337,7 @@ class binary_reader
*/
bool get_msgpack_object(const std::size_t len)
{
if (JSON_UNLIKELY(not sax->start_object(len)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len)))
{
return false;
}
@ -1348,12 +1346,12 @@ class binary_reader
for (std::size_t i = 0; i < len; ++i)
{
get();
if (JSON_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_msgpack_string(key) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not parse_msgpack_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal()))
{
return false;
}
@ -1397,10 +1395,10 @@ class binary_reader
{
if (get_char)
{
get(); // TODO: may we ignore N here?
get(); // TODO(niels): may we ignore N here?
}
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
{
return false;
}
@ -1409,31 +1407,31 @@ class binary_reader
{
case 'U':
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'i':
{
int8_t len;
std::int8_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'I':
{
int16_t len;
std::int16_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'l':
{
int32_t len;
std::int32_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'L':
{
int64_t len;
std::int64_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
@ -1453,8 +1451,8 @@ class binary_reader
{
case 'U':
{
uint8_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
std::uint8_t number;
if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
}
@ -1464,8 +1462,8 @@ class binary_reader
case 'i':
{
int8_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
std::int8_t number;
if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
}
@ -1475,8 +1473,8 @@ class binary_reader
case 'I':
{
int16_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
std::int16_t number;
if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
}
@ -1486,8 +1484,8 @@ class binary_reader
case 'l':
{
int32_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
std::int32_t number;
if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
}
@ -1497,8 +1495,8 @@ class binary_reader
case 'L':
{
int64_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
std::int64_t number;
if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
}
@ -1534,15 +1532,15 @@ class binary_reader
if (current == '$')
{
result.second = get(); // must not ignore 'N', because 'N' maybe the type
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type")))
{
return false;
}
get_ignore_noop();
if (JSON_UNLIKELY(current != '#'))
if (JSON_HEDLEY_UNLIKELY(current != '#'))
{
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
{
return false;
}
@ -1552,10 +1550,12 @@ class binary_reader
return get_ubjson_size_value(result.first);
}
else if (current == '#')
if (current == '#')
{
return get_ubjson_size_value(result.first);
}
return true;
}
@ -1580,31 +1580,31 @@ class binary_reader
case 'U':
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
}
case 'i':
{
int8_t number;
std::int8_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'I':
{
int16_t number;
std::int16_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'l':
{
int32_t number;
std::int32_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'L':
{
int64_t number;
std::int64_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
@ -1623,11 +1623,11 @@ class binary_reader
case 'C': // char
{
get();
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char")))
{
return false;
}
if (JSON_UNLIKELY(current > 127))
if (JSON_HEDLEY_UNLIKELY(current > 127))
{
auto last_token = get_token_string();
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char")));
@ -1662,14 +1662,14 @@ class binary_reader
bool get_ubjson_array()
{
std::pair<std::size_t, int> size_and_type;
if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
{
return false;
}
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(not sax->start_array(size_and_type.first)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(size_and_type.first)))
{
return false;
}
@ -1680,7 +1680,7 @@ class binary_reader
{
for (std::size_t i = 0; i < size_and_type.first; ++i)
{
if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
{
return false;
}
@ -1691,7 +1691,7 @@ class binary_reader
{
for (std::size_t i = 0; i < size_and_type.first; ++i)
{
if (JSON_UNLIKELY(not parse_ubjson_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
{
return false;
}
@ -1700,14 +1700,14 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
{
return false;
}
while (current != ']')
{
if (JSON_UNLIKELY(not parse_ubjson_internal(false)))
if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal(false)))
{
return false;
}
@ -1724,7 +1724,7 @@ class binary_reader
bool get_ubjson_object()
{
std::pair<std::size_t, int> size_and_type;
if (JSON_UNLIKELY(not get_ubjson_size_type(size_and_type)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type)))
{
return false;
}
@ -1732,7 +1732,7 @@ class binary_reader
string_t key;
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(not sax->start_object(size_and_type.first)))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(size_and_type.first)))
{
return false;
}
@ -1741,11 +1741,11 @@ class binary_reader
{
for (std::size_t i = 0; i < size_and_type.first; ++i)
{
if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not get_ubjson_value(size_and_type.second)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second)))
{
return false;
}
@ -1756,11 +1756,11 @@ class binary_reader
{
for (std::size_t i = 0; i < size_and_type.first; ++i)
{
if (JSON_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not parse_ubjson_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
{
return false;
}
@ -1770,18 +1770,18 @@ class binary_reader
}
else
{
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
return false;
}
while (current != '}')
{
if (JSON_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key)))
{
return false;
}
if (JSON_UNLIKELY(not parse_ubjson_internal()))
if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal()))
{
return false;
}
@ -1809,7 +1809,7 @@ class binary_reader
int get()
{
++chars_read;
return (current = ia->get_character());
return current = ia->get_character();
}
/*!
@ -1843,23 +1843,23 @@ class binary_reader
bool get_number(const input_format_t format, NumberType& result)
{
// step 1: read input into array with system's byte order
std::array<uint8_t, sizeof(NumberType)> vec;
std::array<std::uint8_t, sizeof(NumberType)> vec;
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
{
get();
if (JSON_UNLIKELY(not unexpect_eof(format, "number")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "number")))
{
return false;
}
// reverse byte order prior to conversion if necessary
if (is_little_endian && !InputIsLittleEndian)
if (is_little_endian != InputIsLittleEndian)
{
vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
}
else
{
vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
}
}
@ -1891,7 +1891,7 @@ class binary_reader
std::generate_n(std::back_inserter(result), len, [this, &success, &format]()
{
get();
if (JSON_UNLIKELY(not unexpect_eof(format, "string")))
if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "string")))
{
success = false;
}
@ -1905,9 +1905,10 @@ class binary_reader
@param[in] context further context information (for diagnostics)
@return whether the last read character is not EOF
*/
JSON_HEDLEY_NON_NULL(3)
bool unexpect_eof(const input_format_t format, const char* context) const
{
if (JSON_UNLIKELY(current == std::char_traits<char>::eof()))
if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char>::eof()))
{
return sax->parse_error(chars_read, "<end of file>",
parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context)));
@ -1920,15 +1921,15 @@ class binary_reader
*/
std::string get_token_string() const
{
char cr[3];
(std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
return std::string{cr};
std::array<char, 3> cr{{}};
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
return std::string{cr.data()};
}
/*!
@param[in] format the current format
@param[in] detail a detailed error message
@param[in] context further contect information
@param[in] context further context information
@return a message string to use in the parse_error exceptions
*/
std::string exception_message(const input_format_t format,
@ -1955,10 +1956,8 @@ class binary_reader
error_msg += "BSON";
break;
// LCOV_EXCL_START
default:
assert(false);
// LCOV_EXCL_STOP
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
return error_msg + " " + context + ": " + detail;

View file

@ -1,7 +1,9 @@
#pragma once
#include <array> // array
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstdio> //FILE *
#include <cstring> // strlen
#include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
@ -10,7 +12,6 @@
#include <string> // string, char_traits
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
#include <utility> // pair, declval
#include <cstdio> //FILE *
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@ -54,14 +55,23 @@ Input adapter for stdio file access. This adapter read only 1 byte and do not us
class file_input_adapter : public input_adapter_protocol
{
public:
JSON_HEDLEY_NON_NULL(2)
explicit file_input_adapter(std::FILE* f) noexcept
: m_file(f)
{}
// make class move-only
file_input_adapter(const file_input_adapter&) = delete;
file_input_adapter(file_input_adapter&&) = default;
file_input_adapter& operator=(const file_input_adapter&) = delete;
file_input_adapter& operator=(file_input_adapter&&) = default;
~file_input_adapter() override = default;
std::char_traits<char>::int_type get_character() noexcept override
{
return std::fgetc(m_file);
}
private:
/// the file pointer to read from
std::FILE* m_file;
@ -122,7 +132,7 @@ class input_buffer_adapter : public input_adapter_protocol
{
public:
input_buffer_adapter(const char* b, const std::size_t l) noexcept
: cursor(b), limit(b + l)
: cursor(b), limit(b == nullptr ? nullptr : (b + l))
{}
// delete because of pointer members
@ -134,8 +144,9 @@ class input_buffer_adapter : public input_adapter_protocol
std::char_traits<char>::int_type get_character() noexcept override
{
if (JSON_LIKELY(cursor < limit))
if (JSON_HEDLEY_LIKELY(cursor < limit))
{
assert(cursor != nullptr and limit != nullptr);
return std::char_traits<char>::to_int_type(*(cursor++));
}
@ -153,7 +164,11 @@ template<typename WideStringType, size_t T>
struct wide_string_input_helper
{
// UTF-32
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(const WideStringType& str,
size_t& current_wchar,
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;
@ -165,39 +180,39 @@ struct wide_string_input_helper
else
{
// get the current character
const auto wc = static_cast<int>(str[current_wchar++]);
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
// UTF-32 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
utf8_bytes[1] = 0x80 | (wc & 0x3F);
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_filled = 2;
}
else if (wc <= 0xFFFF)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes[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_filled = 3;
}
else if (wc <= 0x10FFFF)
{
utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (wc & 0x3F);
utf8_bytes[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_filled = 4;
}
else
{
// unknown character
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
@ -208,7 +223,11 @@ template<typename WideStringType>
struct wide_string_input_helper<WideStringType, 2>
{
// UTF-16
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(const WideStringType& str,
size_t& current_wchar,
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;
@ -220,44 +239,44 @@ struct wide_string_input_helper<WideStringType, 2>
else
{
// get the current character
const auto wc = static_cast<int>(str[current_wchar++]);
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
// UTF-16 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6));
utf8_bytes[1] = 0x80 | (wc & 0x3F);
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_filled = 2;
}
else if (0xD800 > wc or wc >= 0xE000)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12));
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes[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_filled = 3;
}
else
{
if (current_wchar < str.size())
{
const auto wc2 = static_cast<int>(str[current_wchar++]);
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
utf8_bytes[0] = 0xf0 | (charcode >> 18);
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
const auto charcode = 0x10000u + (((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));
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
utf8_bytes_filled = 4;
}
else
{
// unknown character
++current_wchar;
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
@ -269,7 +288,7 @@ template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol
{
public:
explicit wide_string_input_adapter(const WideStringType& w) noexcept
explicit wide_string_input_adapter(const WideStringType& w) noexcept
: str(w)
{}
@ -316,6 +335,7 @@ class input_adapter
{
public:
// native support
JSON_HEDLEY_NON_NULL(2)
input_adapter(std::FILE* file)
: ia(std::make_shared<file_input_adapter>(file)) {}
/// input adapter for input stream
@ -384,7 +404,7 @@ class input_adapter
"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_LIKELY(len > 0))
if (JSON_HEDLEY_LIKELY(len > 0))
{
// there is at least one element: use the address of first
ia = std::make_shared<input_buffer_adapter>(reinterpret_cast<const char*>(&(*first)), len);

View file

@ -1,9 +1,10 @@
#pragma once
#include <cassert>
#include <cassert> // assert
#include <cstddef>
#include <string>
#include <vector>
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@ -158,6 +159,13 @@ class json_sax_dom_parser
: root(r), allow_exceptions(allow_exceptions_)
{}
// make class move-only
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
json_sax_dom_parser(json_sax_dom_parser&&) = default;
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
~json_sax_dom_parser() = default;
bool null()
{
handle_value(nullptr);
@ -198,7 +206,7 @@ class json_sax_dom_parser
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
@ -224,7 +232,7 @@ class json_sax_dom_parser
{
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
@ -249,16 +257,16 @@ class json_sax_dom_parser
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
@ -280,6 +288,7 @@ class json_sax_dom_parser
object to which we can add elements
*/
template<typename Value>
JSON_HEDLEY_RETURNS_NON_NULL
BasicJsonType* handle_value(Value&& v)
{
if (ref_stack.empty())
@ -295,18 +304,17 @@ class json_sax_dom_parser
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_value.array->back());
}
else
{
assert(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
assert(ref_stack.back()->is_object());
assert(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
std::vector<BasicJsonType*> ref_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
@ -334,6 +342,13 @@ class json_sax_dom_callback_parser
keep_stack.push_back(true);
}
// make class move-only
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
~json_sax_dom_callback_parser() = default;
bool null()
{
handle_value(nullptr);
@ -380,13 +395,9 @@ class json_sax_dom_callback_parser
ref_stack.push_back(val.second);
// check object limit
if (ref_stack.back())
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
}
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
}
return true;
@ -411,13 +422,10 @@ class json_sax_dom_callback_parser
bool end_object()
{
if (ref_stack.back())
if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
// discard object
*ref_stack.back() = discarded;
}
// discard object
*ref_stack.back() = discarded;
}
assert(not ref_stack.empty());
@ -425,18 +433,15 @@ class json_sax_dom_callback_parser
ref_stack.pop_back();
keep_stack.pop_back();
if (not ref_stack.empty() and ref_stack.back())
if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
{
// remove discarded value
if (ref_stack.back()->is_object())
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
{
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
if (it->is_discarded())
{
if (it->is_discarded())
{
ref_stack.back()->erase(it);
break;
}
ref_stack.back()->erase(it);
break;
}
}
}
@ -453,13 +458,9 @@ class json_sax_dom_callback_parser
ref_stack.push_back(val.second);
// check array limit
if (ref_stack.back())
if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
}
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
}
return true;
@ -485,12 +486,9 @@ class json_sax_dom_callback_parser
keep_stack.pop_back();
// remove discarded value
if (not keep and not ref_stack.empty())
if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
{
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->pop_back();
}
ref_stack.back()->m_value.array->pop_back();
}
return true;
@ -506,16 +504,16 @@ class json_sax_dom_callback_parser
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
@ -585,37 +583,38 @@ class json_sax_dom_callback_parser
// we now only expect arrays and objects
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
// array
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->push_back(std::move(value));
return {true, &(ref_stack.back()->m_value.array->back())};
}
else
// object
assert(ref_stack.back()->is_object());
// check if we should store an element for the current key
assert(not key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (not store_element)
{
// check if we should store an element for the current key
assert(not key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (not store_element)
{
return {false, nullptr};
}
assert(object_element);
*object_element = std::move(value);
return {true, object_element};
return {false, nullptr};
}
assert(object_element);
*object_element = std::move(value);
return {true, object_element};
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
std::vector<BasicJsonType*> ref_stack {};
/// stack to manage which values to keep
std::vector<bool> keep_stack;
std::vector<bool> keep_stack {};
/// stack to manage which object keys to keep
std::vector<bool> key_keep_stack;
std::vector<bool> key_keep_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred

View file

@ -1,16 +1,18 @@
#pragma once
#include <array> // array
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <cstdio> // snprintf
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <initializer_list> // initializer_list
#include <string> // char_traits, string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/position_t.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
@ -57,6 +59,8 @@ class lexer
};
/// return name of values of type token_type (only used for errors)
JSON_HEDLEY_RETURNS_NON_NULL
JSON_HEDLEY_CONST
static const char* token_type_name(const token_type t) noexcept
{
switch (t)
@ -116,6 +120,7 @@ class lexer
/////////////////////
/// return the locale-dependent decimal point
JSON_HEDLEY_PURE
static char get_decimal_point() noexcept
{
const auto loc = localeconv();
@ -148,22 +153,22 @@ class lexer
assert(current == 'u');
int codepoint = 0;
const auto factors = { 12, 8, 4, 0 };
const auto factors = { 12u, 8u, 4u, 0u };
for (const auto factor : factors)
{
get();
if (current >= '0' and current <= '9')
{
codepoint += ((current - 0x30) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
}
else if (current >= 'A' and current <= 'F')
{
codepoint += ((current - 0x37) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
}
else if (current >= 'a' and current <= 'f')
{
codepoint += ((current - 0x57) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
}
else
{
@ -198,7 +203,7 @@ class lexer
for (auto range = ranges.begin(); range != ranges.end(); ++range)
{
get();
if (JSON_LIKELY(*range <= current and current <= *(++range)))
if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range)))
{
add(current);
}
@ -297,7 +302,7 @@ class lexer
const int codepoint1 = get_codepoint();
int codepoint = codepoint1; // start with codepoint1
if (JSON_UNLIKELY(codepoint1 == -1))
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
{
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
return token_type::parse_error;
@ -307,29 +312,29 @@ class lexer
if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF)
{
// expect next \uxxxx entry
if (JSON_LIKELY(get() == '\\' and get() == 'u'))
if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u'))
{
const int codepoint2 = get_codepoint();
if (JSON_UNLIKELY(codepoint2 == -1))
if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
{
error_message = "invalid string: '\\u' must be followed by 4 hex digits";
return token_type::parse_error;
}
// check if codepoint2 is a low surrogate
if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
{
// overwrite codepoint
codepoint =
// high surrogate occupies the most significant 22 bits
(codepoint1 << 10)
// low surrogate occupies the least significant 15 bits
+ codepoint2
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00;
codepoint = static_cast<int>(
// high surrogate occupies the most significant 22 bits
(static_cast<unsigned int>(codepoint1) << 10u)
// low surrogate occupies the least significant 15 bits
+ static_cast<unsigned int>(codepoint2)
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00u);
}
else
{
@ -345,7 +350,7 @@ class lexer
}
else
{
if (JSON_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF))
{
error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
return token_type::parse_error;
@ -364,23 +369,23 @@ class lexer
else if (codepoint <= 0x7FF)
{
// 2-byte characters: 110xxxxx 10xxxxxx
add(0xC0 | (codepoint >> 6));
add(0x80 | (codepoint & 0x3F));
add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
}
else if (codepoint <= 0xFFFF)
{
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
add(0xE0 | (codepoint >> 12));
add(0x80 | ((codepoint >> 6) & 0x3F));
add(0x80 | (codepoint & 0x3F));
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)));
}
else
{
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
add(0xF0 | (codepoint >> 18));
add(0x80 | ((codepoint >> 12) & 0x3F));
add(0x80 | ((codepoint >> 6) & 0x3F));
add(0x80 | (codepoint & 0x3F));
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)));
}
break;
@ -720,7 +725,7 @@ class lexer
case 0xDE:
case 0xDF:
{
if (JSON_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF})))
{
return token_type::parse_error;
}
@ -730,7 +735,7 @@ class lexer
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
case 0xE0:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -754,7 +759,7 @@ class lexer
case 0xEE:
case 0xEF:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -764,7 +769,7 @@ class lexer
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
case 0xED:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -774,7 +779,7 @@ class lexer
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
case 0xF0:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -786,7 +791,7 @@ class lexer
case 0xF2:
case 0xF3:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -796,7 +801,7 @@ class lexer
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
case 0xF4:
{
if (JSON_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
{
return token_type::parse_error;
}
@ -813,16 +818,19 @@ class lexer
}
}
JSON_HEDLEY_NON_NULL(2)
static void strtof(float& f, const char* str, char** endptr) noexcept
{
f = std::strtof(str, endptr);
}
JSON_HEDLEY_NON_NULL(2)
static void strtof(double& f, const char* str, char** endptr) noexcept
{
f = std::strtod(str, endptr);
}
JSON_HEDLEY_NON_NULL(2)
static void strtof(long double& f, const char* str, char** endptr) noexcept
{
f = std::strtold(str, endptr);
@ -906,13 +914,9 @@ class lexer
goto scan_number_any1;
}
// LCOV_EXCL_START
default:
{
// all other characters are rejected outside scan_number()
assert(false);
}
// LCOV_EXCL_STOP
// all other characters are rejected outside scan_number()
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
scan_number_minus:
@ -1202,13 +1206,14 @@ scan_number_done:
@param[in] length the length of the passed literal text
@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 return_type)
{
assert(current == literal_text[0]);
for (std::size_t i = 1; i < length; ++i)
{
if (JSON_UNLIKELY(get() != literal_text[i]))
if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i]))
{
error_message = "invalid literal";
return token_type::parse_error;
@ -1254,7 +1259,7 @@ scan_number_done:
current = ia->get_character();
}
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
{
token_string.push_back(std::char_traits<char>::to_char_type(current));
}
@ -1295,9 +1300,9 @@ scan_number_done:
--position.chars_read_current_line;
}
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
if (JSON_HEDLEY_LIKELY(current != std::char_traits<char>::eof()))
{
assert(token_string.size() != 0);
assert(not token_string.empty());
token_string.pop_back();
}
}
@ -1359,9 +1364,9 @@ scan_number_done:
if ('\x00' <= c and c <= '\x1F')
{
// escape control characters
char cs[9];
(std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
result += cs;
std::array<char, 9> cs{{}};
(std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
result += cs.data();
}
else
{
@ -1374,6 +1379,7 @@ scan_number_done:
}
/// return syntax error message
JSON_HEDLEY_RETURNS_NON_NULL
constexpr const char* get_error_message() const noexcept
{
return error_message;
@ -1483,7 +1489,7 @@ scan_number_done:
bool next_unget = false;
/// the start position of the current token
position_t position;
position_t position {};
/// raw input token string (for error messages)
std::vector<char> token_string {};

View file

@ -6,13 +6,14 @@
#include <functional> // function
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@ -146,6 +147,7 @@ class parser
}
template <typename SAX>
JSON_HEDLEY_NON_NULL(2)
bool sax_parse(SAX* sax, const bool strict = true)
{
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
@ -165,6 +167,7 @@ class parser
private:
template <typename SAX>
JSON_HEDLEY_NON_NULL(2)
bool sax_parse_internal(SAX* sax)
{
// stack to remember the hierarchy of structured values we are parsing
@ -182,7 +185,7 @@ class parser
{
case token_type::begin_object:
{
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1))))
{
return false;
}
@ -190,7 +193,7 @@ class parser
// closing } -> we are done
if (get_token() == token_type::end_object)
{
if (JSON_UNLIKELY(not sax->end_object()))
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
{
return false;
}
@ -198,20 +201,20 @@ class parser
}
// parse key
if (JSON_UNLIKELY(last_token != token_type::value_string))
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
}
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
// parse separator (:)
if (JSON_UNLIKELY(get_token() != token_type::name_separator))
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
@ -229,7 +232,7 @@ class parser
case token_type::begin_array:
{
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1))))
{
return false;
}
@ -237,7 +240,7 @@ class parser
// closing ] -> we are done
if (get_token() == token_type::end_array)
{
if (JSON_UNLIKELY(not sax->end_array()))
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
{
return false;
}
@ -255,25 +258,24 @@ class parser
{
const auto res = m_lexer.get_number_float();
if (JSON_UNLIKELY(not std::isfinite(res)))
if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res)))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'"));
}
else
if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
{
if (JSON_UNLIKELY(not sax->number_float(res, m_lexer.get_string())))
{
return false;
}
break;
return false;
}
break;
}
case token_type::literal_false:
{
if (JSON_UNLIKELY(not sax->boolean(false)))
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false)))
{
return false;
}
@ -282,7 +284,7 @@ class parser
case token_type::literal_null:
{
if (JSON_UNLIKELY(not sax->null()))
if (JSON_HEDLEY_UNLIKELY(not sax->null()))
{
return false;
}
@ -291,7 +293,7 @@ class parser
case token_type::literal_true:
{
if (JSON_UNLIKELY(not sax->boolean(true)))
if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true)))
{
return false;
}
@ -300,7 +302,7 @@ class parser
case token_type::value_integer:
{
if (JSON_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer())))
{
return false;
}
@ -309,7 +311,7 @@ class parser
case token_type::value_string:
{
if (JSON_UNLIKELY(not sax->string(m_lexer.get_string())))
if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string())))
{
return false;
}
@ -318,7 +320,7 @@ class parser
case token_type::value_unsigned:
{
if (JSON_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned())))
{
return false;
}
@ -354,103 +356,95 @@ class parser
// empty stack: we reached the end of the hierarchy: done
return true;
}
else
if (states.back()) // array
{
if (states.back()) // array
// comma -> next value
if (get_token() == token_type::value_separator)
{
// comma -> next value
if (get_token() == token_type::value_separator)
// parse a new value
get_token();
continue;
}
// closing ]
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
{
if (JSON_HEDLEY_UNLIKELY(not sax->end_array()))
{
// parse a new value
get_token();
continue;
return false;
}
// closing ]
if (JSON_LIKELY(last_token == token_type::end_array))
{
if (JSON_UNLIKELY(not sax->end_array()))
{
return false;
}
// We are done with this array. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
// We are done with this array. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_array, "array")));
}
else // object
{
// comma -> next value
if (get_token() == token_type::value_separator)
{
// parse key
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_array, "array")));
exception_message(token_type::value_string, "object key")));
}
}
else // object
{
// comma -> next value
if (get_token() == token_type::value_separator)
if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string())))
{
// parse key
if (JSON_UNLIKELY(get_token() != token_type::value_string))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::value_string, "object key")));
}
else
{
if (JSON_UNLIKELY(not sax->key(m_lexer.get_string())))
{
return false;
}
}
// parse separator (:)
if (JSON_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
return false;
}
// closing }
if (JSON_LIKELY(last_token == token_type::end_object))
{
if (JSON_UNLIKELY(not sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
else
// parse separator (:)
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
{
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
exception_message(token_type::name_separator, "object separator")));
}
// parse values
get_token();
continue;
}
// closing }
if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
{
if (JSON_HEDLEY_UNLIKELY(not sax->end_object()))
{
return false;
}
// We are done with this object. Before we can parse a
// new value, we need to evaluate the new state first.
// By setting skip_to_state_evaluation to false, we
// are effectively jumping to the beginning of this if.
assert(not states.empty());
states.pop_back();
skip_to_state_evaluation = true;
continue;
}
return sax->parse_error(m_lexer.get_position(),
m_lexer.get_token_string(),
parse_error::create(101, m_lexer.get_position(),
exception_message(token_type::end_object, "object")));
}
}
}
@ -458,7 +452,7 @@ class parser
/// get next token from lexer
token_type get_token()
{
return (last_token = m_lexer.scan());
return last_token = m_lexer.scan();
}
std::string exception_message(const token_type expected, const std::string& context)

View file

@ -23,5 +23,5 @@ struct position_t
}
};
}
}
} // namespace detail
} // namespace nlohmann

View file

@ -118,17 +118,42 @@ class iter_impl
to iterator is not defined.
*/
/*!
@brief const copy constructor
@param[in] other const iterator to copy from
@note This copy constructor had to be defined explicitly to circumvent a bug
occurring on msvc v19.0 compiler (VS 2015) debug build. For more
information refer to: https://github.com/nlohmann/json/issues/1608
*/
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
: m_object(other.m_object), m_it(other.m_it)
{}
/*!
@brief converting assignment
@param[in] other const iterator to copy from
@return const/non-const iterator
@note It is not checked whether @a other is initialized.
*/
iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
{
m_object = other.m_object;
m_it = other.m_it;
return *this;
}
/*!
@brief converting constructor
@param[in] other non-const iterator to copy from
@note It is not checked whether @a other is initialized.
*/
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
: m_object(other.m_object), m_it(other.m_it) {}
: m_object(other.m_object), m_it(other.m_it)
{}
/*!
@brief converting assignment
@param[in,out] other non-const iterator to copy from
@param[in] other non-const iterator to copy from
@return const/non-const iterator
@note It is not checked whether @a other is initialized.
*/
@ -235,7 +260,7 @@ class iter_impl
default:
{
if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
{
return *m_object;
}
@ -269,7 +294,7 @@ class iter_impl
default:
{
if (JSON_LIKELY(m_it.primitive_iterator.is_begin()))
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
{
return m_object;
}
@ -372,7 +397,7 @@ class iter_impl
bool operator==(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (JSON_UNLIKELY(m_object != other.m_object))
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
}
@ -408,7 +433,7 @@ class iter_impl
bool operator<(const iter_impl& other) const
{
// if objects are not the same, the comparison is undefined
if (JSON_UNLIKELY(m_object != other.m_object))
if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
{
JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers"));
}
@ -568,7 +593,7 @@ class iter_impl
default:
{
if (JSON_LIKELY(m_it.primitive_iterator.get_value() == -n))
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
{
return *m_object;
}
@ -586,7 +611,7 @@ class iter_impl
{
assert(m_object != nullptr);
if (JSON_LIKELY(m_object->is_object()))
if (JSON_HEDLEY_LIKELY(m_object->is_object()))
{
return m_it.object_iterator->first;
}
@ -607,7 +632,7 @@ class iter_impl
/// associated JSON instance
pointer m_object = nullptr;
/// the actual iterator of the associated instance
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
};
} // namespace detail
} // namespace nlohmann
} // namespace detail
} // namespace nlohmann

View file

@ -1,17 +1,22 @@
#pragma once
#include <cstddef> // size_t
#include <string> // string, to_string
#include <iterator> // input_iterator_tag
#include <string> // string, to_string
#include <tuple> // tuple_size, get, tuple_element
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
{
namespace detail
{
template<typename string_type>
void int_to_string( string_type& target, std::size_t value )
{
target = std::to_string(value);
}
template <typename IteratorType> class iteration_proxy_value
{
public:
@ -20,6 +25,7 @@ template <typename IteratorType> class iteration_proxy_value
using pointer = value_type * ;
using reference = value_type & ;
using iterator_category = std::input_iterator_tag;
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
private:
/// the iterator
@ -29,9 +35,9 @@ template <typename IteratorType> class iteration_proxy_value
/// last stringified array index
mutable std::size_t array_index_last = 0;
/// a string representation of the array index
mutable std::string array_index_str = "0";
mutable string_type array_index_str = "0";
/// an empty string (to return a reference for primitive values)
const std::string empty_str = "";
const string_type empty_str = "";
public:
explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {}
@ -64,7 +70,7 @@ template <typename IteratorType> class iteration_proxy_value
}
/// return key of the iterator
const std::string& key() const
const string_type& key() const
{
assert(anchor.m_object != nullptr);
@ -75,7 +81,7 @@ template <typename IteratorType> class iteration_proxy_value
{
if (array_index != array_index_last)
{
array_index_str = std::to_string(array_index);
int_to_string( array_index_str, array_index );
array_index_last = array_index;
}
return array_index_str;
@ -147,6 +153,11 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
// And see https://github.com/nlohmann/json/pull/1391
namespace std
{
#if defined(__clang__)
// Fix: https://github.com/nlohmann/json/issues/1401
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template <typename IteratorType>
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
: public std::integral_constant<std::size_t, 2> {};
@ -159,4 +170,7 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
get<N>(std::declval <
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
};
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace std

View file

@ -13,15 +13,16 @@ template <typename It, typename = void>
struct iterator_types {};
template <typename It>
struct iterator_types<
struct iterator_types <
It,
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
typename It::reference, typename It::iterator_category>> {
using difference_type = typename It::difference_type;
using value_type = typename It::value_type;
using pointer = typename It::pointer;
using reference = typename It::reference;
using iterator_category = typename It::iterator_category;
typename It::reference, typename It::iterator_category >>
{
using difference_type = typename It::difference_type;
using value_type = typename It::value_type;
using pointer = typename It::pointer;
using reference = typename It::reference;
using iterator_category = typename It::iterator_category;
};
// This is required as some compilers implement std::iterator_traits in a way that
@ -32,18 +33,19 @@ struct iterator_traits
};
template <typename T>
struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>>
: iterator_types<T>
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
: iterator_types<T>
{
};
template <typename T>
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
{
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
};
}
}
} // namespace detail
} // namespace nlohmann

View file

@ -2,12 +2,14 @@
#include <algorithm> // all_of
#include <cassert> // assert
#include <cctype> // isdigit
#include <numeric> // accumulate
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@ -55,8 +57,7 @@ class json_pointer
@return a string representation of the JSON pointer
@liveexample{The example shows the result of `to_string`.,
json_pointer__to_string}
@liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
@since version 2.0.0
*/
@ -76,6 +77,249 @@ class json_pointer
return to_string();
}
/*!
@brief append another JSON pointer at the end of this JSON pointer
@param[in] ptr JSON pointer to append
@return JSON pointer with @a ptr appended
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
@complexity Linear in the length of @a ptr.
@sa @ref operator/=(std::string) to append a reference token
@sa @ref operator/=(std::size_t) to append an array index
@sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
@since version 3.6.0
*/
json_pointer& operator/=(const json_pointer& ptr)
{
reference_tokens.insert(reference_tokens.end(),
ptr.reference_tokens.begin(),
ptr.reference_tokens.end());
return *this;
}
/*!
@brief append an unescaped reference token at the end of this JSON pointer
@param[in] token reference token to append
@return JSON pointer with @a token appended without escaping @a token
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
@complexity Amortized constant.
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
@sa @ref operator/=(std::size_t) to append an array index
@sa @ref operator/(const json_pointer&, std::size_t) for a binary operator
@since version 3.6.0
*/
json_pointer& operator/=(std::string token)
{
push_back(std::move(token));
return *this;
}
/*!
@brief append an array index at the end of this JSON pointer
@param[in] array_index array index to append
@return JSON pointer with @a array_index appended
@liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
@complexity Amortized constant.
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
@sa @ref operator/=(std::string) to append a reference token
@sa @ref operator/(const json_pointer&, std::string) for a binary operator
@since version 3.6.0
*/
json_pointer& operator/=(std::size_t array_index)
{
return *this /= std::to_string(array_index);
}
/*!
@brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
@param[in] lhs JSON pointer
@param[in] rhs JSON pointer
@return a new JSON pointer with @a rhs appended to @a lhs
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
@complexity Linear in the length of @a lhs and @a rhs.
@sa @ref operator/=(const json_pointer&) to append a JSON pointer
@since version 3.6.0
*/
friend json_pointer operator/(const json_pointer& lhs,
const json_pointer& rhs)
{
return json_pointer(lhs) /= rhs;
}
/*!
@brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
@param[in] ptr JSON pointer
@param[in] token reference token
@return a new JSON pointer with unescaped @a token appended to @a ptr
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
@complexity Linear in the length of @a ptr.
@sa @ref operator/=(std::string) to append a reference token
@since version 3.6.0
*/
friend json_pointer operator/(const json_pointer& ptr, std::string token)
{
return json_pointer(ptr) /= std::move(token);
}
/*!
@brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
@param[in] ptr JSON pointer
@param[in] array_index array index
@return a new JSON pointer with @a array_index appended to @a ptr
@liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
@complexity Linear in the length of @a ptr.
@sa @ref operator/=(std::size_t) to append an array index
@since version 3.6.0
*/
friend json_pointer operator/(const json_pointer& ptr, std::size_t array_index)
{
return json_pointer(ptr) /= array_index;
}
/*!
@brief returns the parent of this JSON pointer
@return parent of this JSON pointer; in case this JSON pointer is the root,
the root itself is returned
@complexity Linear in the length of the JSON pointer.
@liveexample{The example shows the result of `parent_pointer` for different
JSON Pointers.,json_pointer__parent_pointer}
@since version 3.6.0
*/
json_pointer parent_pointer() const
{
if (empty())
{
return *this;
}
json_pointer res = *this;
res.pop_back();
return res;
}
/*!
@brief remove last reference token
@pre not `empty()`
@liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
@complexity Constant.
@throw out_of_range.405 if JSON pointer has no parent
@since version 3.6.0
*/
void pop_back()
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
reference_tokens.pop_back();
}
/*!
@brief return last reference token
@pre not `empty()`
@return last reference token
@liveexample{The example shows the usage of `back`.,json_pointer__back}
@complexity Constant.
@throw out_of_range.405 if JSON pointer has no parent
@since version 3.6.0
*/
const std::string& back() const
{
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
return reference_tokens.back();
}
/*!
@brief append an unescaped token at the end of the reference pointer
@param[in] token token to add
@complexity Amortized constant.
@liveexample{The example shows the result of `push_back` for different
JSON Pointers.,json_pointer__push_back}
@since version 3.6.0
*/
void push_back(const std::string& token)
{
reference_tokens.push_back(token);
}
/// @copydoc push_back(const std::string&)
void push_back(std::string&& token)
{
reference_tokens.push_back(std::move(token));
}
/*!
@brief return whether pointer points to the root document
@return true iff the JSON pointer points to the root document
@complexity Constant.
@exceptionsafety No-throw guarantee: this function never throws exceptions.
@liveexample{The example shows the result of `empty` for different JSON
Pointers.,json_pointer__empty}
@since version 3.6.0
*/
bool empty() const noexcept
{
return reference_tokens.empty();
}
private:
/*!
@param[in] s reference token to be converted into an array index
@ -89,7 +333,7 @@ class json_pointer
const int res = std::stoi(s, &processed_chars);
// check if the string was completely read
if (JSON_UNLIKELY(processed_chars != s.size()))
if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
{
JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'"));
}
@ -97,41 +341,9 @@ class json_pointer
return res;
}
/*!
@brief remove and return last reference pointer
@throw out_of_range.405 if JSON pointer has no parent
*/
std::string pop_back()
{
if (JSON_UNLIKELY(is_root()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
auto last = reference_tokens.back();
reference_tokens.pop_back();
return last;
}
/*!
@brief remove and return last reference pointer
@throw out_of_range.405 if JSON pointer has no parent
*/
void push_back(const std::string& tok)
{
reference_tokens.push_back(tok);
}
private:
/// return whether pointer points to the root document
bool is_root() const noexcept
{
return reference_tokens.empty();
}
json_pointer top() const
{
if (JSON_UNLIKELY(is_root()))
if (JSON_HEDLEY_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
@ -158,7 +370,7 @@ class json_pointer
// j which will be overwritten by a primitive value
for (const auto& reference_token : reference_tokens)
{
switch (result->m_type)
switch (result->type())
{
case detail::value_t::null:
{
@ -235,14 +447,14 @@ class json_pointer
for (const auto& reference_token : reference_tokens)
{
// convert null values to arrays or objects before continuing
if (ptr->m_type == detail::value_t::null)
if (ptr->is_null())
{
// check if reference token is a number
const bool nums =
std::all_of(reference_token.begin(), reference_token.end(),
[](const char x)
[](const unsigned char x)
{
return (x >= '0' and x <= '9');
return std::isdigit(x);
});
// change value to array for numbers or "-" or to object otherwise
@ -251,7 +463,7 @@ class json_pointer
: detail::value_t::object;
}
switch (ptr->m_type)
switch (ptr->type())
{
case detail::value_t::object:
{
@ -263,7 +475,7 @@ class json_pointer
case detail::value_t::array:
{
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
@ -310,7 +522,7 @@ class json_pointer
using size_type = typename BasicJsonType::size_type;
for (const auto& reference_token : reference_tokens)
{
switch (ptr->m_type)
switch (ptr->type())
{
case detail::value_t::object:
{
@ -321,7 +533,7 @@ class json_pointer
case detail::value_t::array:
{
if (JSON_UNLIKELY(reference_token == "-"))
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402,
@ -330,7 +542,7 @@ class json_pointer
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
@ -375,7 +587,7 @@ class json_pointer
using size_type = typename BasicJsonType::size_type;
for (const auto& reference_token : reference_tokens)
{
switch (ptr->m_type)
switch (ptr->type())
{
case detail::value_t::object:
{
@ -386,7 +598,7 @@ class json_pointer
case detail::value_t::array:
{
if (JSON_UNLIKELY(reference_token == "-"))
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" cannot be used for const access
JSON_THROW(detail::out_of_range::create(402,
@ -395,7 +607,7 @@ class json_pointer
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
@ -434,7 +646,7 @@ class json_pointer
using size_type = typename BasicJsonType::size_type;
for (const auto& reference_token : reference_tokens)
{
switch (ptr->m_type)
switch (ptr->type())
{
case detail::value_t::object:
{
@ -445,7 +657,7 @@ class json_pointer
case detail::value_t::array:
{
if (JSON_UNLIKELY(reference_token == "-"))
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402,
@ -454,7 +666,7 @@ class json_pointer
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
@ -481,6 +693,77 @@ class json_pointer
return *ptr;
}
/*!
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index was not a number
*/
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))
{
// we did not find the key in the object
return false;
}
ptr = &ptr->operator[](reference_token);
break;
}
case detail::value_t::array:
{
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" always fails the range check
return false;
}
// error condition (cf. RFC 6901, Sect. 4)
if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0'))
{
JSON_THROW(detail::parse_error::create(106, 0,
"array index '" + reference_token +
"' must not begin with '0'"));
}
JSON_TRY
{
const auto idx = static_cast<size_type>(array_index(reference_token));
if (idx >= ptr->size())
{
// index out of range
return false;
}
ptr = &ptr->operator[](idx);
break;
}
JSON_CATCH(std::invalid_argument&)
{
JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number"));
}
break;
}
default:
{
// we do not expect primitive values if there is still a
// reference token to process
return false;
}
}
}
// no reference token left means we found a primitive value
return true;
}
/*!
@brief split the string input to reference tokens
@ -501,7 +784,7 @@ class json_pointer
}
// check if nonempty reference string begins with slash
if (JSON_UNLIKELY(reference_string[0] != '/'))
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
{
JSON_THROW(detail::parse_error::create(107, 1,
"JSON pointer must be empty or begin with '/' - was: '" +
@ -536,9 +819,9 @@ class json_pointer
assert(reference_token[pos] == '~');
// ~ must be followed by 0 or 1
if (JSON_UNLIKELY(pos == reference_token.size() - 1 or
(reference_token[pos + 1] != '0' and
reference_token[pos + 1] != '1')))
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or
(reference_token[pos + 1] != '0' and
reference_token[pos + 1] != '1')))
{
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'"));
}
@ -602,7 +885,7 @@ class json_pointer
const BasicJsonType& value,
BasicJsonType& result)
{
switch (value.m_type)
switch (value.type())
{
case detail::value_t::array:
{
@ -663,7 +946,7 @@ class json_pointer
static BasicJsonType
unflatten(const BasicJsonType& value)
{
if (JSON_UNLIKELY(not value.is_object()))
if (JSON_HEDLEY_UNLIKELY(not value.is_object()))
{
JSON_THROW(detail::type_error::create(314, "only objects can be unflattened"));
}
@ -673,7 +956,7 @@ class json_pointer
// iterate the JSON object values
for (const auto& element : *value.m_value.object)
{
if (JSON_UNLIKELY(not element.second.is_primitive()))
if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive()))
{
JSON_THROW(detail::type_error::create(315, "values in object must be primitive"));
}
@ -688,12 +971,34 @@ class json_pointer
return result;
}
/*!
@brief compares two JSON pointers for equality
@param[in] lhs JSON pointer to compare
@param[in] rhs JSON pointer to compare
@return whether @a lhs is equal to @a rhs
@complexity Linear in the length of the JSON pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
friend bool operator==(json_pointer const& lhs,
json_pointer const& rhs) noexcept
{
return (lhs.reference_tokens == rhs.reference_tokens);
return lhs.reference_tokens == rhs.reference_tokens;
}
/*!
@brief compares two JSON pointers for inequality
@param[in] lhs JSON pointer to compare
@param[in] rhs JSON pointer to compare
@return whether @a lhs is not equal @a rhs
@complexity Linear in the length of the JSON pointer
@exceptionsafety No-throw guarantee: this function never throws exceptions.
*/
friend bool operator!=(json_pointer const& lhs,
json_pointer const& rhs) noexcept
{

View file

@ -1,5 +1,8 @@
#pragma once
#include <utility> // pair
#include <nlohmann/thirdparty/hedley/hedley.hpp>
// This file contains all internal macro definitions
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
@ -16,6 +19,14 @@
#endif
#endif
// C++ language standard detection
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
#define JSON_HAS_CPP_14
#endif
// disable float-equal warnings on GCC/clang
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic push
@ -28,28 +39,6 @@
#pragma GCC diagnostic ignored "-Wdocumentation"
#endif
// allow for portable deprecation warnings
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define JSON_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define JSON_DEPRECATED __declspec(deprecated)
#else
#define JSON_DEPRECATED
#endif
// allow for portable nodiscard warnings
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(nodiscard)
#define JSON_NODISCARD [[nodiscard]]
#elif __has_cpp_attribute(gnu::warn_unused_result)
#define JSON_NODISCARD [[gnu::warn_unused_result]]
#else
#define JSON_NODISCARD
#endif
#else
#define JSON_NODISCARD
#endif
// allow to disable exceptions
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
#define JSON_THROW(exception) throw exception
@ -57,6 +46,7 @@
#define JSON_CATCH(exception) catch(exception)
#define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#include <cstdlib>
#define JSON_THROW(exception) std::abort()
#define JSON_TRY if(true)
#define JSON_CATCH(exception) if(false)
@ -83,52 +73,35 @@
#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
#endif
// manual branch prediction
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
#define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define JSON_LIKELY(x) x
#define JSON_UNLIKELY(x) x
#endif
// C++ language standard detection
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
#define JSON_HAS_CPP_17
#define JSON_HAS_CPP_14
#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
#define JSON_HAS_CPP_14
#endif
/*!
@brief macro to briefly define a mapping between an enum and JSON
@def NLOHMANN_JSON_SERIALIZE_ENUM
@since version 3.4.0
*/
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
template<typename BasicJsonType> \
inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.first == e; \
}); \
j = ((it != std::end(m)) ? it : std::begin(m))->second; \
} \
template<typename BasicJsonType> \
inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
{ \
static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
auto it = std::find_if(std::begin(m), std::end(m), \
[&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
{ \
return ej_pair.second == j; \
}); \
e = ((it != std::end(m)) ? it : std::begin(m))->first; \
}
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They

View file

@ -13,11 +13,9 @@
#undef JSON_CATCH
#undef JSON_THROW
#undef JSON_TRY
#undef JSON_LIKELY
#undef JSON_UNLIKELY
#undef JSON_DEPRECATED
#undef JSON_NODISCARD
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL
#include <nlohmann/thirdparty/hedley/hedley_undef.hpp>

View file

@ -14,7 +14,9 @@ struct nonesuch
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
nonesuch(nonesuch const&&) = delete;
void operator=(nonesuch const&) = delete;
void operator=(nonesuch&&) = delete;
};
template <class Default,

View file

@ -2,6 +2,7 @@
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
@ -23,119 +24,119 @@ using number_integer_function_t =
template <typename T, typename Unsigned>
using number_unsigned_function_t =
decltype(std::declval<T &>().number_unsigned(std::declval<Unsigned>()));
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
template <typename T, typename Float, typename String>
using number_float_function_t = decltype(std::declval<T &>().number_float(
std::declval<Float>(), std::declval<const String &>()));
using number_float_function_t = decltype(std::declval<T&>().number_float(
std::declval<Float>(), std::declval<const String&>()));
template <typename T, typename String>
using string_function_t =
decltype(std::declval<T &>().string(std::declval<String &>()));
decltype(std::declval<T&>().string(std::declval<String&>()));
template <typename T>
using start_object_function_t =
decltype(std::declval<T &>().start_object(std::declval<std::size_t>()));
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
template <typename T, typename String>
using key_function_t =
decltype(std::declval<T &>().key(std::declval<String &>()));
decltype(std::declval<T&>().key(std::declval<String&>()));
template <typename T>
using end_object_function_t = decltype(std::declval<T &>().end_object());
using end_object_function_t = decltype(std::declval<T&>().end_object());
template <typename T>
using start_array_function_t =
decltype(std::declval<T &>().start_array(std::declval<std::size_t>()));
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
template <typename T>
using end_array_function_t = decltype(std::declval<T &>().end_array());
using end_array_function_t = decltype(std::declval<T&>().end_array());
template <typename T, typename Exception>
using parse_error_function_t = decltype(std::declval<T &>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string &>(),
std::declval<const Exception &>()));
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
std::declval<std::size_t>(), std::declval<const std::string&>(),
std::declval<const Exception&>()));
template <typename SAX, typename BasicJsonType>
struct is_sax
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
public:
static constexpr bool value =
is_detected_exact<bool, null_function_t, SAX>::value &&
is_detected_exact<bool, boolean_function_t, SAX>::value &&
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value &&
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value &&
is_detected_exact<bool, number_float_function_t, SAX, number_float_t,
string_t>::value &&
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
is_detected_exact<bool, start_object_function_t, SAX>::value &&
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
is_detected_exact<bool, end_object_function_t, SAX>::value &&
is_detected_exact<bool, start_array_function_t, SAX>::value &&
is_detected_exact<bool, end_array_function_t, SAX>::value &&
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
};
template <typename SAX, typename BasicJsonType>
struct is_sax_static_asserts
{
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
private:
static_assert(is_basic_json<BasicJsonType>::value,
"BasicJsonType must be of type basic_json<...>");
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
using string_t = typename BasicJsonType::string_t;
using exception_t = typename BasicJsonType::exception;
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"Missing/invalid function: bool string(string_t&)");
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
public:
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
"Missing/invalid function: bool null()");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
"Missing/invalid function: bool boolean(bool)");
static_assert(
is_detected_exact<bool, number_integer_function_t, SAX,
number_integer_t>::value,
"Missing/invalid function: bool number_integer(number_integer_t)");
static_assert(
is_detected_exact<bool, number_unsigned_function_t, SAX,
number_unsigned_t>::value,
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
number_float_t, string_t>::value,
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
static_assert(
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
"Missing/invalid function: bool string(string_t&)");
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
"Missing/invalid function: bool start_object(std::size_t)");
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
"Missing/invalid function: bool key(string_t&)");
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
"Missing/invalid function: bool end_object()");
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
"Missing/invalid function: bool start_array(std::size_t)");
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
"Missing/invalid function: bool end_array()");
static_assert(
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
"Missing/invalid function: bool parse_error(std::size_t, const "
"std::string&, const exception&)");
};
} // namespace detail
} // namespace nlohmann

View file

@ -5,11 +5,11 @@
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/json_fwd.hpp>
namespace nlohmann
{
@ -192,10 +192,19 @@ struct is_constructible_object_type_impl <
using object_t = typename BasicJsonType::object_t;
static constexpr bool value =
(std::is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value and
std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value) or
(has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value or
has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type >::value);
(std::is_default_constructible<ConstructibleObjectType>::value and
(std::is_move_assignable<ConstructibleObjectType>::value or
std::is_copy_assignable<ConstructibleObjectType>::value) and
(std::is_constructible<typename ConstructibleObjectType::key_type,
typename object_t::key_type>::value and
std::is_same <
typename object_t::mapped_type,
typename ConstructibleObjectType::mapped_type >::value)) or
(has_from_json<BasicJsonType,
typename ConstructibleObjectType::mapped_type>::value or
has_non_default_from_json <
BasicJsonType,
typename ConstructibleObjectType::mapped_type >::value);
};
template <typename BasicJsonType, typename ConstructibleObjectType>
@ -278,20 +287,24 @@ struct is_constructible_array_type_impl <
BasicJsonType, ConstructibleArrayType,
enable_if_t<not std::is_same<ConstructibleArrayType,
typename BasicJsonType::value_type>::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 >>
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 >>
{
static constexpr bool value =
// This is needed because json_reverse_iterator has a ::iterator type,
// furthermore, std::back_insert_iterator (and other iterators) have a 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
// furthermore, std::back_insert_iterator (and other iterators) have a
// 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
(std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
(std::is_same<typename ConstructibleArrayType::value_type,
typename BasicJsonType::array_t::value_type>::value or
has_from_json<BasicJsonType,
typename ConstructibleArrayType::value_type>::value or
has_non_default_from_json <
@ -344,5 +357,18 @@ struct is_compatible_type_impl <
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
// https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template <typename T1, typename T2>
struct is_constructible_tuple : std::false_type {};
template <typename T1, typename... Args>
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<std::is_constructible<T1, Args>...> {};
} // namespace detail
} // namespace nlohmann

View file

@ -5,8 +5,10 @@
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <cstring> // memcpy
#include <limits> // numeric_limits
#include <string> // string
#include <nlohmann/detail/input/binary_reader.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
namespace nlohmann
@ -87,27 +89,27 @@ class binary_writer
// code from the value_t::number_unsigned case here.
if (j.m_value.number_integer <= 0x17)
{
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else
{
oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
}
else
@ -117,27 +119,27 @@ class binary_writer
const auto positive_number = -1 - j.m_value.number_integer;
if (j.m_value.number_integer >= -24)
{
write_number(static_cast<uint8_t>(0x20 + positive_number));
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
}
else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x38));
write_number(static_cast<uint8_t>(positive_number));
write_number(static_cast<std::uint8_t>(positive_number));
}
else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x39));
write_number(static_cast<uint16_t>(positive_number));
write_number(static_cast<std::uint16_t>(positive_number));
}
else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x3A));
write_number(static_cast<uint32_t>(positive_number));
write_number(static_cast<std::uint32_t>(positive_number));
}
else
{
oa->write_character(to_char_type(0x3B));
write_number(static_cast<uint64_t>(positive_number));
write_number(static_cast<std::uint64_t>(positive_number));
}
}
break;
@ -147,27 +149,27 @@ class binary_writer
{
if (j.m_value.number_unsigned <= 0x17)
{
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
}
else
{
oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
}
break;
}
@ -185,28 +187,28 @@ class binary_writer
const auto N = j.m_value.string->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0x60 + N));
write_number(static_cast<std::uint8_t>(0x60 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x78));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x79));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x7A));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0x7B));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -223,28 +225,28 @@ class binary_writer
const auto N = j.m_value.array->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0x80 + N));
write_number(static_cast<std::uint8_t>(0x80 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x98));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x99));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x9A));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0x9B));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -262,28 +264,28 @@ class binary_writer
const auto N = j.m_value.object->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0xA0 + N));
write_number(static_cast<std::uint8_t>(0xA0 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0xB8));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0xB9));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0xBA));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0xBB));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -332,31 +334,31 @@ class binary_writer
if (j.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
}
else
@ -364,35 +366,35 @@ class binary_writer
if (j.m_value.number_integer >= -32)
{
// negative fixnum
write_number(static_cast<int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
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<int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
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<int16_t>(j.m_value.number_integer));
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
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<int32_t>(j.m_value.number_integer));
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
{
// int 64
oa->write_character(to_char_type(0xD3));
write_number(static_cast<int64_t>(j.m_value.number_integer));
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
}
}
break;
@ -403,31 +405,31 @@ class binary_writer
if (j.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
break;
}
@ -446,25 +448,25 @@ class binary_writer
if (N <= 31)
{
// fixstr
write_number(static_cast<uint8_t>(0xA0 | N));
write_number(static_cast<std::uint8_t>(0xA0 | N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
// str 8
oa->write_character(to_char_type(0xD9));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// str 16
oa->write_character(to_char_type(0xDA));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// str 32
oa->write_character(to_char_type(0xDB));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write the string
@ -481,19 +483,19 @@ class binary_writer
if (N <= 15)
{
// fixarray
write_number(static_cast<uint8_t>(0x90 | N));
write_number(static_cast<std::uint8_t>(0x90 | N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// array 16
oa->write_character(to_char_type(0xDC));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// array 32
oa->write_character(to_char_type(0xDD));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write each element
@ -511,19 +513,19 @@ class binary_writer
if (N <= 15)
{
// fixmap
write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// map 16
oa->write_character(to_char_type(0xDE));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// map 32
oa->write_character(to_char_type(0xDF));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write each element
@ -713,7 +715,7 @@ class binary_writer
static std::size_t calc_bson_entry_header_size(const string_t& name)
{
const auto it = name.find(static_cast<typename string_t::value_type>(0));
if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
{
JSON_THROW(out_of_range::create(409,
"BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")"));
@ -789,14 +791,9 @@ class binary_writer
*/
static std::size_t calc_bson_integer_size(const std::int64_t value)
{
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
{
return sizeof(std::int32_t);
}
else
{
return sizeof(std::int64_t);
}
return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
? sizeof(std::int32_t)
: sizeof(std::int64_t);
}
/*!
@ -864,13 +861,12 @@ class binary_writer
*/
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
{
std::size_t embedded_document_size = 0ul;
std::size_t array_index = 0ul;
for (const auto& el : value)
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), 0ul, [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
{
embedded_document_size += calc_bson_element_size(std::to_string(array_index++), el);
}
return result + calc_bson_element_size(std::to_string(array_index++), el);
});
return sizeof(std::int32_t) + embedded_document_size + 1ul;
}
@ -1064,45 +1060,45 @@ class binary_writer
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix)
{
if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('i')); // int8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if (n <= (std::numeric_limits<uint8_t>::max)())
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('U')); // uint8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('I')); // int16
}
write_number(static_cast<int16_t>(n));
write_number(static_cast<std::int16_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('l')); // int32
}
write_number(static_cast<int32_t>(n));
write_number(static_cast<std::int32_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('L')); // int64
}
write_number(static_cast<int64_t>(n));
write_number(static_cast<std::int64_t>(n));
}
else
{
@ -1117,45 +1113,45 @@ class binary_writer
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix)
{
if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('i')); // int8
}
write_number(static_cast<int8_t>(n));
write_number(static_cast<std::int8_t>(n));
}
else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
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)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('U')); // uint8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('I')); // int16
}
write_number(static_cast<int16_t>(n));
write_number(static_cast<std::int16_t>(n));
}
else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('l')); // int32
}
write_number(static_cast<int32_t>(n));
write_number(static_cast<std::int32_t>(n));
}
else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('L')); // int64
}
write_number(static_cast<int64_t>(n));
write_number(static_cast<std::int64_t>(n));
}
// LCOV_EXCL_START
else
@ -1186,19 +1182,19 @@ class binary_writer
case value_t::number_integer:
{
if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
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)())
{
return 'i';
}
if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
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)())
{
return 'U';
}
if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
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)())
{
return 'I';
}
if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
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)())
{
return 'l';
}
@ -1208,19 +1204,19 @@ class binary_writer
case value_t::number_unsigned:
{
if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
return 'i';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
{
return 'U';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{
return 'I';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
return 'l';
}
@ -1278,7 +1274,7 @@ class binary_writer
std::memcpy(vec.data(), &n, sizeof(NumberType));
// step 2: write array to output (with possible reordering)
if (is_little_endian and not OutputIsLittleEndian)
if (is_little_endian != OutputIsLittleEndian)
{
// reverse byte order prior to conversion if necessary
std::reverse(vec.begin(), vec.end());

View file

@ -8,6 +8,7 @@
#include <ostream> // basic_ostream
#include <string> // basic_string
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
@ -39,6 +40,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
v.push_back(c);
}
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
std::copy(s, s + length, std::back_inserter(v));
@ -62,6 +64,7 @@ class output_stream_adapter : public output_adapter_protocol<CharType>
stream.put(c);
}
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
stream.write(s, static_cast<std::streamsize>(length));
@ -85,6 +88,7 @@ class output_string_adapter : public output_adapter_protocol<CharType>
str.push_back(c);
}
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
str.append(s, length);

View file

@ -12,9 +12,10 @@
#include <limits> // numeric_limits
#include <string> // string
#include <type_traits> // is_same
#include <utility> // move
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/output/binary_writer.hpp>
@ -44,8 +45,8 @@ class serializer
using number_float_t = typename BasicJsonType::number_float_t;
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
static constexpr uint8_t UTF8_ACCEPT = 0;
static constexpr uint8_t UTF8_REJECT = 1;
static constexpr std::uint8_t UTF8_ACCEPT = 0;
static constexpr std::uint8_t UTF8_REJECT = 1;
public:
/*!
@ -109,7 +110,7 @@ class serializer
// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_UNLIKELY(indent_string.size() < new_indent))
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
@ -182,7 +183,7 @@ class serializer
// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_UNLIKELY(indent_string.size() < new_indent))
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
@ -277,6 +278,9 @@ class serializer
o->write_characters("null", 4);
return;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
}
@ -297,8 +301,8 @@ class serializer
*/
void dump_escaped(const string_t& s, const bool ensure_ascii)
{
uint32_t codepoint;
uint8_t state = UTF8_ACCEPT;
std::uint32_t codepoint;
std::uint8_t state = UTF8_ACCEPT;
std::size_t bytes = 0; // number of bytes written to string_buffer
// number of bytes written at the point of the last valid byte
@ -373,14 +377,14 @@ class serializer
if (codepoint <= 0xFFFF)
{
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
static_cast<uint16_t>(codepoint));
static_cast<std::uint16_t>(codepoint));
bytes += 6;
}
else
{
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
bytes += 12;
}
}
@ -473,6 +477,9 @@ class serializer
state = UTF8_ACCEPT;
break;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
break;
}
@ -491,7 +498,7 @@ class serializer
}
// we finished processing the string
if (JSON_LIKELY(state == UTF8_ACCEPT))
if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
{
// write buffer
if (bytes > 0)
@ -507,7 +514,7 @@ class serializer
case error_handler_t::strict:
{
std::string sn(3, '\0');
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
}
@ -533,6 +540,9 @@ class serializer
}
break;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
}
}
@ -589,16 +599,16 @@ class serializer
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
{
{
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
{'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
{'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
{'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
{'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
{'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
{'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'},
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
}
};
@ -610,7 +620,7 @@ class serializer
}
// use a pointer to fill the buffer
auto buffer_ptr = begin(number_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
number_unsigned_t abs_value;
@ -620,7 +630,7 @@ class serializer
if (is_negative)
{
*buffer_ptr = '-';
abs_value = static_cast<number_unsigned_t>(-1 - x) + 1;
abs_value = remove_sign(x);
// account one more byte for the minus sign
n_chars = 1 + count_digits(abs_value);
@ -739,7 +749,7 @@ class serializer
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
[](char c)
{
return (c == '.' or c == 'e');
return c == '.' or c == 'e';
});
if (value_is_int_like)
@ -769,9 +779,9 @@ class serializer
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
*/
static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
{
static const std::array<uint8_t, 400> utf8d =
static const std::array<std::uint8_t, 400> utf8d =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
@ -791,16 +801,42 @@ class serializer
}
};
const uint8_t type = utf8d[byte];
const std::uint8_t type = utf8d[byte];
codep = (state != UTF8_ACCEPT)
? (byte & 0x3fu) | (codep << 6)
: static_cast<uint32_t>(0xff >> type) & (byte);
? (byte & 0x3fu) | (codep << 6u)
: (0xFFu >> type) & (byte);
state = utf8d[256u + state * 16u + type];
return state;
}
/*
* Overload to make the compiler happy while it is instantiating
* dump_integer for number_unsigned_t.
* Must never be called.
*/
number_unsigned_t remove_sign(number_unsigned_t x)
{
assert(false); // LCOV_EXCL_LINE
return x; // LCOV_EXCL_LINE
}
/*
* Helper function for dump_integer
*
* This function takes a negative signed integer and returns its absolute
* value as unsigned integer. The plus/minus shuffling is necessary as we can
* not directly remove the sign of an arbitrary signed integer as the
* absolute values of INT_MIN and INT_MAX are usually not the same. See
* #1708 for details.
*/
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
{
assert(x < 0 and x < (std::numeric_limits<number_integer_t>::max)());
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
}
private:
/// the output of the serializer
output_adapter_t<char> o = nullptr;

View file

@ -4,6 +4,7 @@
#include <ciso646> // and
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <string> // string
namespace nlohmann
{

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#ifndef NLOHMANN_JSON_FWD_HPP
#define NLOHMANN_JSON_FWD_HPP
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
@ -61,4 +61,4 @@ uses the standard template types.
using json = basic_json<>;
} // namespace nlohmann
#endif
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
#undef JSON_HEDLEY_ALWAYS_INLINE
#undef JSON_HEDLEY_ARM_VERSION
#undef JSON_HEDLEY_ARM_VERSION_CHECK
#undef JSON_HEDLEY_ARRAY_PARAM
#undef JSON_HEDLEY_ASSUME
#undef JSON_HEDLEY_BEGIN_C_DECLS
#undef JSON_HEDLEY_C_DECL
#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
#undef JSON_HEDLEY_CLANG_HAS_FEATURE
#undef JSON_HEDLEY_CLANG_HAS_WARNING
#undef JSON_HEDLEY_COMPCERT_VERSION
#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
#undef JSON_HEDLEY_CONCAT
#undef JSON_HEDLEY_CONCAT_EX
#undef JSON_HEDLEY_CONST
#undef JSON_HEDLEY_CONST_CAST
#undef JSON_HEDLEY_CONSTEXPR
#undef JSON_HEDLEY_CPP_CAST
#undef JSON_HEDLEY_CRAY_VERSION
#undef JSON_HEDLEY_CRAY_VERSION_CHECK
#undef JSON_HEDLEY_DEPRECATED
#undef JSON_HEDLEY_DEPRECATED_FOR
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
#undef JSON_HEDLEY_DIAGNOSTIC_POP
#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
#undef JSON_HEDLEY_DMC_VERSION
#undef JSON_HEDLEY_DMC_VERSION_CHECK
#undef JSON_HEDLEY_EMPTY_BASES
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
#undef JSON_HEDLEY_END_C_DECLS
#undef JSON_HEDLEY_FALL_THROUGH
#undef JSON_HEDLEY_FLAGS
#undef JSON_HEDLEY_FLAGS_CAST
#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
#undef JSON_HEDLEY_GCC_HAS_BUILTIN
#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_GCC_HAS_EXTENSION
#undef JSON_HEDLEY_GCC_HAS_FEATURE
#undef JSON_HEDLEY_GCC_HAS_WARNING
#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
#undef JSON_HEDLEY_GCC_VERSION
#undef JSON_HEDLEY_GCC_VERSION_CHECK
#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
#undef JSON_HEDLEY_GNUC_HAS_FEATURE
#undef JSON_HEDLEY_GNUC_HAS_WARNING
#undef JSON_HEDLEY_GNUC_VERSION
#undef JSON_HEDLEY_GNUC_VERSION_CHECK
#undef JSON_HEDLEY_HAS_ATTRIBUTE
#undef JSON_HEDLEY_HAS_BUILTIN
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
#undef JSON_HEDLEY_HAS_EXTENSION
#undef JSON_HEDLEY_HAS_FEATURE
#undef JSON_HEDLEY_HAS_WARNING
#undef JSON_HEDLEY_IAR_VERSION
#undef JSON_HEDLEY_IAR_VERSION_CHECK
#undef JSON_HEDLEY_IBM_VERSION
#undef JSON_HEDLEY_IBM_VERSION_CHECK
#undef JSON_HEDLEY_IMPORT
#undef JSON_HEDLEY_INLINE
#undef JSON_HEDLEY_INTEL_VERSION
#undef JSON_HEDLEY_INTEL_VERSION_CHECK
#undef JSON_HEDLEY_IS_CONSTANT
#undef JSON_HEDLEY_IS_CONSTEXPR_
#undef JSON_HEDLEY_LIKELY
#undef JSON_HEDLEY_MALLOC
#undef JSON_HEDLEY_MESSAGE
#undef JSON_HEDLEY_MSVC_VERSION
#undef JSON_HEDLEY_MSVC_VERSION_CHECK
#undef JSON_HEDLEY_NEVER_INLINE
#undef JSON_HEDLEY_NO_ESCAPE
#undef JSON_HEDLEY_NON_NULL
#undef JSON_HEDLEY_NO_RETURN
#undef JSON_HEDLEY_NO_THROW
#undef JSON_HEDLEY_NULL
#undef JSON_HEDLEY_PELLES_VERSION
#undef JSON_HEDLEY_PELLES_VERSION_CHECK
#undef JSON_HEDLEY_PGI_VERSION
#undef JSON_HEDLEY_PGI_VERSION_CHECK
#undef JSON_HEDLEY_PREDICT
#undef JSON_HEDLEY_PRINTF_FORMAT
#undef JSON_HEDLEY_PRIVATE
#undef JSON_HEDLEY_PUBLIC
#undef JSON_HEDLEY_PURE
#undef JSON_HEDLEY_REINTERPRET_CAST
#undef JSON_HEDLEY_REQUIRE
#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
#undef JSON_HEDLEY_REQUIRE_MSG
#undef JSON_HEDLEY_RESTRICT
#undef JSON_HEDLEY_RETURNS_NON_NULL
#undef JSON_HEDLEY_SENTINEL
#undef JSON_HEDLEY_STATIC_ASSERT
#undef JSON_HEDLEY_STATIC_CAST
#undef JSON_HEDLEY_STRINGIFY
#undef JSON_HEDLEY_STRINGIFY_EX
#undef JSON_HEDLEY_SUNPRO_VERSION
#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
#undef JSON_HEDLEY_TINYC_VERSION
#undef JSON_HEDLEY_TINYC_VERSION_CHECK
#undef JSON_HEDLEY_TI_VERSION
#undef JSON_HEDLEY_TI_VERSION_CHECK
#undef JSON_HEDLEY_UNAVAILABLE
#undef JSON_HEDLEY_UNLIKELY
#undef JSON_HEDLEY_UNPREDICTABLE
#undef JSON_HEDLEY_UNREACHABLE
#undef JSON_HEDLEY_UNREACHABLE_RETURN
#undef JSON_HEDLEY_VERSION
#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
#undef JSON_HEDLEY_VERSION_DECODE_MINOR
#undef JSON_HEDLEY_VERSION_DECODE_REVISION
#undef JSON_HEDLEY_VERSION_ENCODE
#undef JSON_HEDLEY_WARNING
#undef JSON_HEDLEY_WARN_UNUSED_RESULT