mirror of
https://github.com/nlohmann/json.git
synced 2026-09-27 10:10:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c637e73bea |
@@ -42,10 +42,6 @@ namespace detail
|
|||||||
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
|
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
|
||||||
* allocated value (e.g., a string). See bug issue
|
* allocated value (e.g., a string). See bug issue
|
||||||
* https://github.com/nlohmann/json/issues/2865 for more information.
|
* https://github.com/nlohmann/json/issues/2865 for more information.
|
||||||
*
|
|
||||||
* A value that has to be allocated is created before the old one is destroyed:
|
|
||||||
* were it the other way around, an exception while creating the new value would
|
|
||||||
* leave j with the type of the new value, but the pointer to the destroyed old one.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<value_t> struct external_constructor;
|
template<value_t> struct external_constructor;
|
||||||
@@ -69,20 +65,18 @@ struct external_constructor<value_t::string>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(s);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = s;
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(s));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(s);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,10 +85,9 @@ struct external_constructor<value_t::string>
|
|||||||
int > = 0 >
|
int > = 0 >
|
||||||
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
||||||
{
|
{
|
||||||
auto* created = j.template create<typename BasicJsonType::string_t>(str);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value.string = created;
|
j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -105,20 +98,18 @@ struct external_constructor<value_t::binary>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(b);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::binary;
|
j.m_data.m_type = value_t::binary;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = typename BasicJsonType::binary_t(b);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
|
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(b));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::binary;
|
j.m_data.m_type = value_t::binary;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -168,10 +159,9 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(arr);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = arr;
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -179,10 +169,9 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(arr));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(arr);
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -198,10 +187,9 @@ struct external_constructor<value_t::array>
|
|||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
auto* created = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value.array = created;
|
j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -209,17 +197,15 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
|
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements;
|
|
||||||
elements.reserve(arr.size());
|
|
||||||
for (const bool x : arr)
|
|
||||||
{
|
|
||||||
elements.push_back(x);
|
|
||||||
}
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
j.set_parents();
|
j.m_data.m_value.array->reserve(arr.size());
|
||||||
|
for (const bool x : arr)
|
||||||
|
{
|
||||||
|
j.m_data.m_value.array->push_back(x);
|
||||||
|
j.set_parent(j.m_data.m_value.array->back());
|
||||||
|
}
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,12 +213,11 @@ struct external_constructor<value_t::array>
|
|||||||
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements(arr.size());
|
|
||||||
std::copy(std::begin(arr), std::end(arr), elements.begin());
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
|
j.m_data.m_value.array->resize(arr.size());
|
||||||
|
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -244,16 +229,14 @@ struct external_constructor<value_t::array>
|
|||||||
enable_if_t<is_compatible_range_view<std::remove_cvref_t<CompatibleArrayType>>::value, int> = 0>
|
enable_if_t<is_compatible_range_view<std::remove_cvref_t<CompatibleArrayType>>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, CompatibleArrayType && arr)
|
static void construct(BasicJsonType& j, CompatibleArrayType && arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements;
|
|
||||||
for (auto&& x : std::forward<CompatibleArrayType>(arr))
|
|
||||||
{
|
|
||||||
elements.push_back(x);
|
|
||||||
}
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
j.set_parents();
|
for (auto&& x : std::forward<CompatibleArrayType>(arr))
|
||||||
|
{
|
||||||
|
j.m_data.m_value.array->push_back(x);
|
||||||
|
j.set_parent(j.m_data.m_value.array->back());
|
||||||
|
}
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -265,10 +248,9 @@ struct external_constructor<value_t::object>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(obj);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = obj;
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -276,10 +258,9 @@ struct external_constructor<value_t::object>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(obj));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(obj);
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -291,10 +272,9 @@ struct external_constructor<value_t::object>
|
|||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
auto* created = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value.object = created;
|
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,92 +168,20 @@ class binary_writer
|
|||||||
if (j.m_data.m_value.number_integer >= 0)
|
if (j.m_data.m_value.number_integer >= 0)
|
||||||
{
|
{
|
||||||
// CBOR does not differentiate between positive signed
|
// CBOR does not differentiate between positive signed
|
||||||
// integers and unsigned integers. Therefore, we used the
|
// integers and unsigned integers
|
||||||
// code from the value_t::number_unsigned case here.
|
write_cbor_head(0x00, static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
|
||||||
if (j.m_data.m_value.number_integer <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x18));
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x19));
|
|
||||||
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1A));
|
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1B));
|
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The conversions below encode the sign in the first
|
// a negative integer n is encoded as -1 - n
|
||||||
// byte, and the value is converted to a positive number.
|
write_cbor_head(0x20, static_cast<std::uint64_t>(-1 - j.m_data.m_value.number_integer));
|
||||||
const auto positive_number = -1 - j.m_data.m_value.number_integer;
|
|
||||||
if (j.m_data.m_value.number_integer >= -24)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x38));
|
|
||||||
write_number(static_cast<std::uint8_t>(positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x39));
|
|
||||||
write_number(static_cast<std::uint16_t>(positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x3A));
|
|
||||||
write_number(static_cast<std::uint32_t>(positive_number));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x3B));
|
|
||||||
write_number(static_cast<std::uint64_t>(positive_number));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
if (j.m_data.m_value.number_unsigned <= 0x17)
|
write_cbor_head(0x00, j.m_data.m_value.number_unsigned);
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x18));
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x19));
|
|
||||||
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1A));
|
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1B));
|
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,33 +211,7 @@ class binary_writer
|
|||||||
case value_t::string:
|
case value_t::string:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the string length
|
// step 1: write control byte and the string length
|
||||||
const auto N = j.m_data.m_value.string->size();
|
write_cbor_head(0x60, j.m_data.m_value.string->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x60 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x78));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x79));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x7A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x7B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write the string
|
// step 2: write the string
|
||||||
oa.write_characters(
|
oa.write_characters(
|
||||||
@@ -321,33 +223,7 @@ class binary_writer
|
|||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the array size
|
// step 1: write control byte and the array size
|
||||||
const auto N = j.m_data.m_value.array->size();
|
write_cbor_head(0x80, j.m_data.m_value.array->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x80 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x98));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x99));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x9A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x9B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
for (const auto& el : *j.m_data.m_value.array)
|
for (const auto& el : *j.m_data.m_value.array)
|
||||||
@@ -376,7 +252,7 @@ class binary_writer
|
|||||||
write_number(static_cast<std::uint8_t>(0xda));
|
write_number(static_cast<std::uint8_t>(0xda));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
write_number(static_cast<std::uint8_t>(0xdb));
|
write_number(static_cast<std::uint8_t>(0xdb));
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
|
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
|
||||||
@@ -385,32 +261,7 @@ class binary_writer
|
|||||||
|
|
||||||
// step 1: write control byte and the binary array size
|
// step 1: write control byte and the binary array size
|
||||||
const auto N = j.m_data.m_value.binary->size();
|
const auto N = j.m_data.m_value.binary->size();
|
||||||
if (N <= 0x17)
|
write_cbor_head(0x40, N);
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x40 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x58));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x59));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x5A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x5B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
oa.write_characters(
|
oa.write_characters(
|
||||||
@@ -423,33 +274,7 @@ class binary_writer
|
|||||||
case value_t::object:
|
case value_t::object:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the object size
|
// step 1: write control byte and the object size
|
||||||
const auto N = j.m_data.m_value.object->size();
|
write_cbor_head(0xA0, j.m_data.m_value.object->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0xA0 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xB8));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xB9));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xBA));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xBB));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
for (const auto& el : *j.m_data.m_value.object)
|
for (const auto& el : *j.m_data.m_value.object)
|
||||||
@@ -517,7 +342,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xCE));
|
oa.write_character(to_char_type(0xCE));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
// uint 64
|
// uint 64
|
||||||
oa.write_character(to_char_type(0xCF));
|
oa.write_character(to_char_type(0xCF));
|
||||||
@@ -552,8 +377,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xD2));
|
oa.write_character(to_char_type(0xD2));
|
||||||
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
|
else
|
||||||
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
|
||||||
{
|
{
|
||||||
// int 64
|
// int 64
|
||||||
oa.write_character(to_char_type(0xD3));
|
oa.write_character(to_char_type(0xD3));
|
||||||
@@ -588,7 +412,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xCE));
|
oa.write_character(to_char_type(0xCE));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
// uint 64
|
// uint 64
|
||||||
oa.write_character(to_char_type(0xCF));
|
oa.write_character(to_char_type(0xCF));
|
||||||
@@ -1526,6 +1350,46 @@ class binary_writer
|
|||||||
// CBOR //
|
// CBOR //
|
||||||
//////////
|
//////////
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief write the head of a CBOR data item
|
||||||
|
|
||||||
|
The head is the major type in the upper three bits of the first byte and
|
||||||
|
an argument - an unsigned integer, the length of a string, the number of
|
||||||
|
elements of a container - in the shortest of its encodings: in the lower
|
||||||
|
five bits of the first byte itself if it is at most 23, otherwise in the
|
||||||
|
1, 2, 4, or 8 bytes that follow (RFC 8949, section 3).
|
||||||
|
|
||||||
|
@param[in] major_type the major type, shifted into the upper three bits
|
||||||
|
@param[in] argument the argument of the data item
|
||||||
|
*/
|
||||||
|
void write_cbor_head(const std::uint8_t major_type, const std::uint64_t argument)
|
||||||
|
{
|
||||||
|
if (argument <= 0x17)
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(major_type + argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x18)));
|
||||||
|
write_number(static_cast<std::uint8_t>(argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x19)));
|
||||||
|
write_number(static_cast<std::uint16_t>(argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x1A)));
|
||||||
|
write_number(static_cast<std::uint32_t>(argument));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x1B)));
|
||||||
|
write_number(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
|
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
|
||||||
{
|
{
|
||||||
return to_char_type(0xFA); // Single-Precision Float
|
return to_char_type(0xFA); // Single-Precision Float
|
||||||
@@ -1631,7 +1495,7 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
|
else if (use_bjdata)
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -1711,30 +1575,59 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<uint32_t>(n), use_bjdata);
|
write_number(static_cast<uint32_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
|
||||||
{
|
|
||||||
if (add_prefix)
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type('L')); // int64
|
|
||||||
}
|
|
||||||
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
// every value of an integer type of at most 64 bits fits into an
|
||||||
{
|
// int64; only a wider type needs a range check
|
||||||
oa.write_character(to_char_type('H')); // high-precision number
|
write_ubjson_int64_or_high_precision(n, add_prefix, use_bjdata,
|
||||||
}
|
std::integral_constant < bool, std::numeric_limits<NumberType>::digits <= std::numeric_limits<std::int64_t>::digits > {});
|
||||||
|
|
||||||
const auto number = BasicJsonType(n).dump();
|
|
||||||
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
|
|
||||||
for (std::size_t i = 0; i < number.size(); ++i)
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
void write_ubjson_int64_or_high_precision(const NumberType n, const bool add_prefix, const bool use_bjdata, std::true_type /*fits_int64*/)
|
||||||
|
{
|
||||||
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type('L')); // int64
|
||||||
|
}
|
||||||
|
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
void write_ubjson_int64_or_high_precision(const NumberType n, const bool add_prefix, const bool use_bjdata, std::false_type /*fits_int64*/)
|
||||||
|
{
|
||||||
|
if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
|
{
|
||||||
|
write_ubjson_int64_or_high_precision(n, add_prefix, use_bjdata, std::true_type {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type('H')); // high-precision number
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto number = BasicJsonType(n).dump();
|
||||||
|
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
|
||||||
|
for (std::size_t i = 0; i < number.size(); ++i)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
static constexpr CharType ubjson_int64_or_high_precision_prefix(const NumberType /*n*/, std::true_type /*fits_int64*/) noexcept
|
||||||
|
{
|
||||||
|
return 'L';
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
static CharType ubjson_int64_or_high_precision_prefix(const NumberType n, std::false_type /*fits_int64*/) noexcept
|
||||||
|
{
|
||||||
|
// anything outside of the range of an int64 is treated as a
|
||||||
|
// high-precision number
|
||||||
|
return ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) ? 'L' : 'H';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1776,12 +1669,10 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
return 'm';
|
return 'm';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
// every value of an integer type of at most 64 bits fits into
|
||||||
{
|
// an int64; only a wider type needs a range check
|
||||||
return 'L';
|
return ubjson_int64_or_high_precision_prefix(j.m_data.m_value.number_integer,
|
||||||
}
|
std::integral_constant < bool, std::numeric_limits<typename BasicJsonType::number_integer_t>::digits <= std::numeric_limits<std::int64_t>::digits > {});
|
||||||
// anything else is treated as a high-precision number
|
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
@@ -1814,12 +1705,12 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
return 'L';
|
return 'L';
|
||||||
}
|
}
|
||||||
if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
if (use_bjdata)
|
||||||
{
|
{
|
||||||
return 'M';
|
return 'M';
|
||||||
}
|
}
|
||||||
// anything else is treated as a high-precision number
|
// anything else is treated as a high-precision number
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
return 'H';
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
|
|||||||
+15
-26
@@ -1687,8 +1687,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
if (is_an_object)
|
if (is_an_object)
|
||||||
{
|
{
|
||||||
// the initializer list is a list of pairs -> create an object
|
// the initializer list is a list of pairs -> create an object
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
|
|
||||||
for (auto& element_ref : init)
|
for (auto& element_ref : init)
|
||||||
{
|
{
|
||||||
@@ -1710,8 +1710,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// the initializer list describes an array -> create an array
|
// the initializer list describes an array -> create an array
|
||||||
m_data.m_value.array = create<array_t>(init.begin(), init.end());
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value.array = create<array_t>(init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
set_parents();
|
set_parents();
|
||||||
@@ -1724,8 +1724,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(const typename binary_t::container_type& init)
|
static basic_json binary(const typename binary_t::container_type& init)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = init;
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = init;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1735,8 +1735,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = binary_t(init, subtype);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = binary_t(init, subtype);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1746,8 +1746,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(typename binary_t::container_type&& init)
|
static basic_json binary(typename binary_t::container_type&& init)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = std::move(init);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = std::move(init);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1757,8 +1757,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = binary_t(std::move(init), subtype);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = binary_t(std::move(init), subtype);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2157,17 +2157,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// value access //
|
// value access //
|
||||||
//////////////////
|
//////////////////
|
||||||
|
|
||||||
/// get a boolean (explicit)
|
|
||||||
boolean_t get_impl(boolean_t* /*unused*/) const
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_LIKELY(is_boolean()))
|
|
||||||
{
|
|
||||||
return m_data.m_value.boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get a pointer to the value (object)
|
/// get a pointer to the value (object)
|
||||||
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
|
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
|
||||||
{
|
{
|
||||||
@@ -2815,8 +2804,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty array
|
// implicitly convert a null value to an empty array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.array = create<array_t>();
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value.array = create<array_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2875,8 +2864,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2928,8 +2917,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3864,8 +3853,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3897,8 +3886,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3929,8 +3918,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an object
|
// transform a null object into an object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3985,8 +3974,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4010,8 +3999,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an object
|
// transform a null object into an object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4192,8 +4181,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+152
-292
@@ -6571,10 +6571,6 @@ namespace detail
|
|||||||
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
|
* j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
|
||||||
* allocated value (e.g., a string). See bug issue
|
* allocated value (e.g., a string). See bug issue
|
||||||
* https://github.com/nlohmann/json/issues/2865 for more information.
|
* https://github.com/nlohmann/json/issues/2865 for more information.
|
||||||
*
|
|
||||||
* A value that has to be allocated is created before the old one is destroyed:
|
|
||||||
* were it the other way around, an exception while creating the new value would
|
|
||||||
* leave j with the type of the new value, but the pointer to the destroyed old one.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<value_t> struct external_constructor;
|
template<value_t> struct external_constructor;
|
||||||
@@ -6598,20 +6594,18 @@ struct external_constructor<value_t::string>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(s);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = s;
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(s));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(s);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6620,10 +6614,9 @@ struct external_constructor<value_t::string>
|
|||||||
int > = 0 >
|
int > = 0 >
|
||||||
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
||||||
{
|
{
|
||||||
auto* created = j.template create<typename BasicJsonType::string_t>(str);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::string;
|
j.m_data.m_type = value_t::string;
|
||||||
j.m_data.m_value.string = created;
|
j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6634,20 +6627,18 @@ struct external_constructor<value_t::binary>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(b);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::binary;
|
j.m_data.m_type = value_t::binary;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = typename BasicJsonType::binary_t(b);
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
|
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(b));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::binary;
|
j.m_data.m_type = value_t::binary;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6697,10 +6688,9 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(arr);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = arr;
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6708,10 +6698,9 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(arr));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(arr);
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6727,10 +6716,9 @@ struct external_constructor<value_t::array>
|
|||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
auto* created = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value.array = created;
|
j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6738,17 +6726,15 @@ struct external_constructor<value_t::array>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
|
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements;
|
|
||||||
elements.reserve(arr.size());
|
|
||||||
for (const bool x : arr)
|
|
||||||
{
|
|
||||||
elements.push_back(x);
|
|
||||||
}
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
j.set_parents();
|
j.m_data.m_value.array->reserve(arr.size());
|
||||||
|
for (const bool x : arr)
|
||||||
|
{
|
||||||
|
j.m_data.m_value.array->push_back(x);
|
||||||
|
j.set_parent(j.m_data.m_value.array->back());
|
||||||
|
}
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6756,12 +6742,11 @@ struct external_constructor<value_t::array>
|
|||||||
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements(arr.size());
|
|
||||||
std::copy(std::begin(arr), std::end(arr), elements.begin());
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
|
j.m_data.m_value.array->resize(arr.size());
|
||||||
|
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6773,16 +6758,14 @@ struct external_constructor<value_t::array>
|
|||||||
enable_if_t<is_compatible_range_view<std::remove_cvref_t<CompatibleArrayType>>::value, int> = 0>
|
enable_if_t<is_compatible_range_view<std::remove_cvref_t<CompatibleArrayType>>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, CompatibleArrayType && arr)
|
static void construct(BasicJsonType& j, CompatibleArrayType && arr)
|
||||||
{
|
{
|
||||||
typename BasicJsonType::array_t elements;
|
|
||||||
for (auto&& x : std::forward<CompatibleArrayType>(arr))
|
|
||||||
{
|
|
||||||
elements.push_back(x);
|
|
||||||
}
|
|
||||||
const typename BasicJsonType::json_value value(std::move(elements));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::array;
|
j.m_data.m_type = value_t::array;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = value_t::array;
|
||||||
j.set_parents();
|
for (auto&& x : std::forward<CompatibleArrayType>(arr))
|
||||||
|
{
|
||||||
|
j.m_data.m_value.array->push_back(x);
|
||||||
|
j.set_parent(j.m_data.m_value.array->back());
|
||||||
|
}
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6794,10 +6777,9 @@ struct external_constructor<value_t::object>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
|
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(obj);
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = obj;
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6805,10 +6787,9 @@ struct external_constructor<value_t::object>
|
|||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||||
{
|
{
|
||||||
const typename BasicJsonType::json_value value(std::move(obj));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value = value;
|
j.m_data.m_value = std::move(obj);
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -6820,10 +6801,9 @@ struct external_constructor<value_t::object>
|
|||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
auto* created = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
|
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
j.m_data.m_type = value_t::object;
|
j.m_data.m_type = value_t::object;
|
||||||
j.m_data.m_value.object = created;
|
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
|
||||||
j.set_parents();
|
j.set_parents();
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
@@ -19653,92 +19633,20 @@ class binary_writer
|
|||||||
if (j.m_data.m_value.number_integer >= 0)
|
if (j.m_data.m_value.number_integer >= 0)
|
||||||
{
|
{
|
||||||
// CBOR does not differentiate between positive signed
|
// CBOR does not differentiate between positive signed
|
||||||
// integers and unsigned integers. Therefore, we used the
|
// integers and unsigned integers
|
||||||
// code from the value_t::number_unsigned case here.
|
write_cbor_head(0x00, static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
|
||||||
if (j.m_data.m_value.number_integer <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x18));
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x19));
|
|
||||||
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1A));
|
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1B));
|
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The conversions below encode the sign in the first
|
// a negative integer n is encoded as -1 - n
|
||||||
// byte, and the value is converted to a positive number.
|
write_cbor_head(0x20, static_cast<std::uint64_t>(-1 - j.m_data.m_value.number_integer));
|
||||||
const auto positive_number = -1 - j.m_data.m_value.number_integer;
|
|
||||||
if (j.m_data.m_value.number_integer >= -24)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x38));
|
|
||||||
write_number(static_cast<std::uint8_t>(positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x39));
|
|
||||||
write_number(static_cast<std::uint16_t>(positive_number));
|
|
||||||
}
|
|
||||||
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x3A));
|
|
||||||
write_number(static_cast<std::uint32_t>(positive_number));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x3B));
|
|
||||||
write_number(static_cast<std::uint64_t>(positive_number));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
if (j.m_data.m_value.number_unsigned <= 0x17)
|
write_cbor_head(0x00, j.m_data.m_value.number_unsigned);
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x18));
|
|
||||||
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x19));
|
|
||||||
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1A));
|
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x1B));
|
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19768,33 +19676,7 @@ class binary_writer
|
|||||||
case value_t::string:
|
case value_t::string:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the string length
|
// step 1: write control byte and the string length
|
||||||
const auto N = j.m_data.m_value.string->size();
|
write_cbor_head(0x60, j.m_data.m_value.string->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x60 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x78));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x79));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x7A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x7B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write the string
|
// step 2: write the string
|
||||||
oa.write_characters(
|
oa.write_characters(
|
||||||
@@ -19806,33 +19688,7 @@ class binary_writer
|
|||||||
case value_t::array:
|
case value_t::array:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the array size
|
// step 1: write control byte and the array size
|
||||||
const auto N = j.m_data.m_value.array->size();
|
write_cbor_head(0x80, j.m_data.m_value.array->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x80 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x98));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x99));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x9A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x9B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
for (const auto& el : *j.m_data.m_value.array)
|
for (const auto& el : *j.m_data.m_value.array)
|
||||||
@@ -19861,7 +19717,7 @@ class binary_writer
|
|||||||
write_number(static_cast<std::uint8_t>(0xda));
|
write_number(static_cast<std::uint8_t>(0xda));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
write_number(static_cast<std::uint8_t>(0xdb));
|
write_number(static_cast<std::uint8_t>(0xdb));
|
||||||
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
|
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
|
||||||
@@ -19870,32 +19726,7 @@ class binary_writer
|
|||||||
|
|
||||||
// step 1: write control byte and the binary array size
|
// step 1: write control byte and the binary array size
|
||||||
const auto N = j.m_data.m_value.binary->size();
|
const auto N = j.m_data.m_value.binary->size();
|
||||||
if (N <= 0x17)
|
write_cbor_head(0x40, N);
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0x40 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x58));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x59));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x5A));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0x5B));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
oa.write_characters(
|
oa.write_characters(
|
||||||
@@ -19908,33 +19739,7 @@ class binary_writer
|
|||||||
case value_t::object:
|
case value_t::object:
|
||||||
{
|
{
|
||||||
// step 1: write control byte and the object size
|
// step 1: write control byte and the object size
|
||||||
const auto N = j.m_data.m_value.object->size();
|
write_cbor_head(0xA0, j.m_data.m_value.object->size());
|
||||||
if (N <= 0x17)
|
|
||||||
{
|
|
||||||
write_number(static_cast<std::uint8_t>(0xA0 + N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xB8));
|
|
||||||
write_number(static_cast<std::uint8_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xB9));
|
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
|
||||||
}
|
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xBA));
|
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(0xBB));
|
|
||||||
write_number(static_cast<std::uint64_t>(N));
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
for (const auto& el : *j.m_data.m_value.object)
|
for (const auto& el : *j.m_data.m_value.object)
|
||||||
@@ -20002,7 +19807,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xCE));
|
oa.write_character(to_char_type(0xCE));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
// uint 64
|
// uint 64
|
||||||
oa.write_character(to_char_type(0xCF));
|
oa.write_character(to_char_type(0xCF));
|
||||||
@@ -20037,8 +19842,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xD2));
|
oa.write_character(to_char_type(0xD2));
|
||||||
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
|
else
|
||||||
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
|
||||||
{
|
{
|
||||||
// int 64
|
// int 64
|
||||||
oa.write_character(to_char_type(0xD3));
|
oa.write_character(to_char_type(0xD3));
|
||||||
@@ -20073,7 +19877,7 @@ class binary_writer
|
|||||||
oa.write_character(to_char_type(0xCE));
|
oa.write_character(to_char_type(0xCE));
|
||||||
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
|
||||||
}
|
}
|
||||||
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
else
|
||||||
{
|
{
|
||||||
// uint 64
|
// uint 64
|
||||||
oa.write_character(to_char_type(0xCF));
|
oa.write_character(to_char_type(0xCF));
|
||||||
@@ -21011,6 +20815,46 @@ class binary_writer
|
|||||||
// CBOR //
|
// CBOR //
|
||||||
//////////
|
//////////
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief write the head of a CBOR data item
|
||||||
|
|
||||||
|
The head is the major type in the upper three bits of the first byte and
|
||||||
|
an argument - an unsigned integer, the length of a string, the number of
|
||||||
|
elements of a container - in the shortest of its encodings: in the lower
|
||||||
|
five bits of the first byte itself if it is at most 23, otherwise in the
|
||||||
|
1, 2, 4, or 8 bytes that follow (RFC 8949, section 3).
|
||||||
|
|
||||||
|
@param[in] major_type the major type, shifted into the upper three bits
|
||||||
|
@param[in] argument the argument of the data item
|
||||||
|
*/
|
||||||
|
void write_cbor_head(const std::uint8_t major_type, const std::uint64_t argument)
|
||||||
|
{
|
||||||
|
if (argument <= 0x17)
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(major_type + argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x18)));
|
||||||
|
write_number(static_cast<std::uint8_t>(argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x19)));
|
||||||
|
write_number(static_cast<std::uint16_t>(argument));
|
||||||
|
}
|
||||||
|
else if (argument <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x1A)));
|
||||||
|
write_number(static_cast<std::uint32_t>(argument));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(major_type + 0x1B)));
|
||||||
|
write_number(argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
|
static constexpr CharType get_cbor_float_prefix(float /*unused*/)
|
||||||
{
|
{
|
||||||
return to_char_type(0xFA); // Single-Precision Float
|
return to_char_type(0xFA); // Single-Precision Float
|
||||||
@@ -21116,7 +20960,7 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
|
else if (use_bjdata)
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -21196,30 +21040,59 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<uint32_t>(n), use_bjdata);
|
write_number(static_cast<uint32_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
|
||||||
{
|
|
||||||
if (add_prefix)
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type('L')); // int64
|
|
||||||
}
|
|
||||||
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
|
||||||
}
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
// every value of an integer type of at most 64 bits fits into an
|
||||||
{
|
// int64; only a wider type needs a range check
|
||||||
oa.write_character(to_char_type('H')); // high-precision number
|
write_ubjson_int64_or_high_precision(n, add_prefix, use_bjdata,
|
||||||
}
|
std::integral_constant < bool, std::numeric_limits<NumberType>::digits <= std::numeric_limits<std::int64_t>::digits > {});
|
||||||
|
|
||||||
const auto number = BasicJsonType(n).dump();
|
|
||||||
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
|
|
||||||
for (std::size_t i = 0; i < number.size(); ++i)
|
|
||||||
{
|
|
||||||
oa.write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// LCOV_EXCL_STOP
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
void write_ubjson_int64_or_high_precision(const NumberType n, const bool add_prefix, const bool use_bjdata, std::true_type /*fits_int64*/)
|
||||||
|
{
|
||||||
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type('L')); // int64
|
||||||
|
}
|
||||||
|
write_number(static_cast<std::int64_t>(n), use_bjdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
void write_ubjson_int64_or_high_precision(const NumberType n, const bool add_prefix, const bool use_bjdata, std::false_type /*fits_int64*/)
|
||||||
|
{
|
||||||
|
if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
|
{
|
||||||
|
write_ubjson_int64_or_high_precision(n, add_prefix, use_bjdata, std::true_type {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_prefix)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type('H')); // high-precision number
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto number = BasicJsonType(n).dump();
|
||||||
|
write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
|
||||||
|
for (std::size_t i = 0; i < number.size(); ++i)
|
||||||
|
{
|
||||||
|
oa.write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
static constexpr CharType ubjson_int64_or_high_precision_prefix(const NumberType /*n*/, std::true_type /*fits_int64*/) noexcept
|
||||||
|
{
|
||||||
|
return 'L';
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename NumberType>
|
||||||
|
static CharType ubjson_int64_or_high_precision_prefix(const NumberType n, std::false_type /*fits_int64*/) noexcept
|
||||||
|
{
|
||||||
|
// anything outside of the range of an int64 is treated as a
|
||||||
|
// high-precision number
|
||||||
|
return ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) ? 'L' : 'H';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -21261,12 +21134,10 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
return 'm';
|
return 'm';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
// every value of an integer type of at most 64 bits fits into
|
||||||
{
|
// an int64; only a wider type needs a range check
|
||||||
return 'L';
|
return ubjson_int64_or_high_precision_prefix(j.m_data.m_value.number_integer,
|
||||||
}
|
std::integral_constant < bool, std::numeric_limits<typename BasicJsonType::number_integer_t>::digits <= std::numeric_limits<std::int64_t>::digits > {});
|
||||||
// anything else is treated as a high-precision number
|
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
@@ -21299,12 +21170,12 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
return 'L';
|
return 'L';
|
||||||
}
|
}
|
||||||
if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
if (use_bjdata)
|
||||||
{
|
{
|
||||||
return 'M';
|
return 'M';
|
||||||
}
|
}
|
||||||
// anything else is treated as a high-precision number
|
// anything else is treated as a high-precision number
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
return 'H';
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
@@ -26665,8 +26536,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
if (is_an_object)
|
if (is_an_object)
|
||||||
{
|
{
|
||||||
// the initializer list is a list of pairs -> create an object
|
// the initializer list is a list of pairs -> create an object
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
|
|
||||||
for (auto& element_ref : init)
|
for (auto& element_ref : init)
|
||||||
{
|
{
|
||||||
@@ -26688,8 +26559,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// the initializer list describes an array -> create an array
|
// the initializer list describes an array -> create an array
|
||||||
m_data.m_value.array = create<array_t>(init.begin(), init.end());
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value.array = create<array_t>(init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
set_parents();
|
set_parents();
|
||||||
@@ -26702,8 +26573,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(const typename binary_t::container_type& init)
|
static basic_json binary(const typename binary_t::container_type& init)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = init;
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = init;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26713,8 +26584,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = binary_t(init, subtype);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = binary_t(init, subtype);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26724,8 +26595,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(typename binary_t::container_type&& init)
|
static basic_json binary(typename binary_t::container_type&& init)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = std::move(init);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = std::move(init);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26735,8 +26606,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_data.m_value = binary_t(std::move(init), subtype);
|
|
||||||
res.m_data.m_type = value_t::binary;
|
res.m_data.m_type = value_t::binary;
|
||||||
|
res.m_data.m_value = binary_t(std::move(init), subtype);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27135,17 +27006,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// value access //
|
// value access //
|
||||||
//////////////////
|
//////////////////
|
||||||
|
|
||||||
/// get a boolean (explicit)
|
|
||||||
boolean_t get_impl(boolean_t* /*unused*/) const
|
|
||||||
{
|
|
||||||
if (JSON_HEDLEY_LIKELY(is_boolean()))
|
|
||||||
{
|
|
||||||
return m_data.m_value.boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get a pointer to the value (object)
|
/// get a pointer to the value (object)
|
||||||
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
|
object_t* get_impl_ptr(object_t* /*unused*/) noexcept
|
||||||
{
|
{
|
||||||
@@ -27793,8 +27653,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty array
|
// implicitly convert a null value to an empty array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.array = create<array_t>();
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value.array = create<array_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27853,8 +27713,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27906,8 +27766,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28842,8 +28702,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28875,8 +28735,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28907,8 +28767,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an object
|
// transform a null object into an object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28963,8 +28823,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an array
|
// transform a null object into an array
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::array;
|
|
||||||
m_data.m_type = value_t::array;
|
m_data.m_type = value_t::array;
|
||||||
|
m_data.m_value = value_t::array;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28988,8 +28848,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// transform a null object into an object
|
// transform a null object into an object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value = value_t::object;
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value = value_t::object;
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29170,8 +29030,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
// implicitly convert a null value to an empty object
|
// implicitly convert a null value to an empty object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
{
|
{
|
||||||
m_data.m_value.object = create<object_t>();
|
|
||||||
m_data.m_type = value_t::object;
|
m_data.m_type = value_t::object;
|
||||||
|
m_data.m_value.object = create<object_t>();
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -388,120 +388,3 @@ TEST_CASE("bad my_allocator::construct")
|
|||||||
j["test"].push_back("should not leak");
|
j["test"].push_back("should not leak");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the no-exceptions CI job skips every CHECK_THROWS_AS, which would leave
|
|
||||||
// next_construct_fails set for the next allocation outside a check
|
|
||||||
#if !defined(JSON_NOEXCEPTION)
|
|
||||||
TEST_CASE("a failed allocation leaves the value unchanged")
|
|
||||||
{
|
|
||||||
// create JSON type using the throwing allocator
|
|
||||||
using my_json = nlohmann::basic_json<std::map,
|
|
||||||
std::vector,
|
|
||||||
std::string,
|
|
||||||
bool,
|
|
||||||
std::int64_t,
|
|
||||||
std::uint64_t,
|
|
||||||
double,
|
|
||||||
my_allocator>;
|
|
||||||
|
|
||||||
// Each of these creates a string, array, object, or binary value. The
|
|
||||||
// value must be created before the type is changed: otherwise, a failed
|
|
||||||
// creation left a value of the new type without anything behind it (an
|
|
||||||
// assertion in its destructor, a null pointer everywhere else) or, when
|
|
||||||
// an old value was destroyed first, with a pointer to that destroyed one.
|
|
||||||
|
|
||||||
SECTION("creating a binary value")
|
|
||||||
{
|
|
||||||
const std::vector<std::uint8_t> bytes = {1, 2, 3};
|
|
||||||
my_json _;
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(_ = my_json::binary(bytes), std::bad_alloc&);
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(_ = my_json::binary(bytes, 42), std::bad_alloc&);
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(_ = my_json::binary(std::vector<std::uint8_t>(bytes)), std::bad_alloc&);
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(_ = my_json::binary(std::vector<std::uint8_t>(bytes), 42), std::bad_alloc&);
|
|
||||||
next_construct_fails = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("turning a null value into an array or object")
|
|
||||||
{
|
|
||||||
my_json j;
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j[0], std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j["key"], std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
#ifdef JSON_HAS_CPP_17
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j[std::string_view("key")], std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.push_back(my_json(1)), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
const my_json one = 1;
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.push_back(one), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.push_back(my_json::object_t::value_type("key", 1)), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.emplace_back(1), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.emplace("key", 1), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
const my_json object = {{"key", 1}};
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(j.update(object), std::bad_alloc&);
|
|
||||||
CHECK(j.is_null());
|
|
||||||
|
|
||||||
next_construct_fails = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("converting into an existing value")
|
|
||||||
{
|
|
||||||
// to_json replaces the value it is given; the old one must survive a
|
|
||||||
// failed creation of the new one
|
|
||||||
my_json j = "old";
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(nlohmann::to_json(j, std::string("new")), std::bad_alloc&);
|
|
||||||
CHECK(j == "old");
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(nlohmann::to_json(j, std::vector<int> {1, 2}), std::bad_alloc&);
|
|
||||||
CHECK(j == "old");
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(nlohmann::to_json(j, std::vector<bool> {true, false}), std::bad_alloc&);
|
|
||||||
CHECK(j == "old");
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(nlohmann::to_json(j, std::map<std::string, int> {{"a", 1}}), std::bad_alloc&);
|
|
||||||
CHECK(j == "old");
|
|
||||||
|
|
||||||
next_construct_fails = true;
|
|
||||||
CHECK_THROWS_AS(nlohmann::to_json(j, my_json::binary_t({1, 2})), std::bad_alloc&);
|
|
||||||
CHECK(j == "old");
|
|
||||||
|
|
||||||
next_construct_fails = false;
|
|
||||||
nlohmann::to_json(j, std::vector<int> {1, 2});
|
|
||||||
CHECK(j == my_json({1, 2}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -2981,3 +2981,18 @@ TEST_CASE("UBJSON roundtrips" * doctest::skip())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("UBJSON optimized array of unsigned integers beyond int64")
|
||||||
|
{
|
||||||
|
// UBJSON has no unsigned 64-bit type, so such values are written as
|
||||||
|
// high-precision numbers - also as the type of an optimized container
|
||||||
|
const json j = {18446744073709551615ULL, 9223372036854775808ULL};
|
||||||
|
const std::vector<std::uint8_t> expected =
|
||||||
|
{
|
||||||
|
'[', '$', 'H', '#', 'i', 2,
|
||||||
|
'i', 20, '1', '8', '4', '4', '6', '7', '4', '4', '0', '7', '3', '7', '0', '9', '5', '5', '1', '6', '1', '5',
|
||||||
|
'i', 19, '9', '2', '2', '3', '3', '7', '2', '0', '3', '6', '8', '5', '4', '7', '7', '5', '8', '0', '8'
|
||||||
|
};
|
||||||
|
CHECK(json::to_ubjson(j, true, true) == expected);
|
||||||
|
CHECK(json::from_ubjson(expected) == j);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user