Prevent memory leak when exception is thrown in adl_serializer::to_json (#3901)

Co-authored-by: barcode <barcode@example.com>
pull/3981/head
Raphael Grimm 2023-03-08 13:43:45 +01:00 committed by GitHub
parent fe4b66355c
commit bbe337c3a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1321 additions and 1167 deletions

View File

@ -7,11 +7,11 @@ check_task:
- tar xfz cmake-3.20.2.tar.gz
- cd cmake-3.20.2
- ./configure
- make cmake ctest -j10
- make cmake ctest -j4
- cd ..
- mkdir build
- cd build
- ../cmake-3.20.2/bin/cmake .. -DJSON_FastTests=ON
- make -j10
- make -j4
- cd tests
- ../../cmake-3.20.2/bin/ctest -j10
- ../../cmake-3.20.2/bin/ctest -j4

View File

@ -34,7 +34,7 @@ namespace detail
/*
* Note all external_constructor<>::construct functions need to call
* j.m_value.destroy(j.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
* https://github.com/nlohmann/json/issues/2865 for more information.
*/
@ -47,9 +47,9 @@ struct external_constructor<value_t::boolean>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::boolean;
j.m_value = b;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::boolean;
j.m_data.m_value = b;
j.assert_invariant();
}
};
@ -60,18 +60,18 @@ struct external_constructor<value_t::string>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value = s;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::string;
j.m_data.m_value = s;
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value = std::move(s);
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::string;
j.m_data.m_value = std::move(s);
j.assert_invariant();
}
@ -80,9 +80,9 @@ struct external_constructor<value_t::string>
int > = 0 >
static void construct(BasicJsonType& j, const CompatibleStringType& str)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::string;
j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::string;
j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
j.assert_invariant();
}
};
@ -93,18 +93,18 @@ struct external_constructor<value_t::binary>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::binary;
j.m_value = typename BasicJsonType::binary_t(b);
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::binary;
j.m_data.m_value = typename BasicJsonType::binary_t(b);
j.assert_invariant();
}
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::binary;
j.m_value = typename BasicJsonType::binary_t(std::move(b));
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::binary;
j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
j.assert_invariant();
}
};
@ -115,9 +115,9 @@ struct external_constructor<value_t::number_float>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_float;
j.m_value = val;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::number_float;
j.m_data.m_value = val;
j.assert_invariant();
}
};
@ -128,9 +128,9 @@ struct external_constructor<value_t::number_unsigned>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_unsigned;
j.m_value = val;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::number_unsigned;
j.m_data.m_value = val;
j.assert_invariant();
}
};
@ -141,9 +141,9 @@ struct external_constructor<value_t::number_integer>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::number_integer;
j.m_value = val;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::number_integer;
j.m_data.m_value = val;
j.assert_invariant();
}
};
@ -154,9 +154,9 @@ struct external_constructor<value_t::array>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = arr;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::array;
j.m_data.m_value = arr;
j.set_parents();
j.assert_invariant();
}
@ -164,9 +164,9 @@ struct external_constructor<value_t::array>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = std::move(arr);
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::array;
j.m_data.m_value = std::move(arr);
j.set_parents();
j.assert_invariant();
}
@ -179,9 +179,9 @@ struct external_constructor<value_t::array>
using std::begin;
using std::end;
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value.array = 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_type = value_t::array;
j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
j.set_parents();
j.assert_invariant();
}
@ -189,14 +189,14 @@ struct external_constructor<value_t::array>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const std::vector<bool>& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = value_t::array;
j.m_value.array->reserve(arr.size());
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::array;
j.m_data.m_value = value_t::array;
j.m_data.m_value.array->reserve(arr.size());
for (const bool x : arr)
{
j.m_value.array->push_back(x);
j.set_parent(j.m_value.array->back());
j.m_data.m_value.array->push_back(x);
j.set_parent(j.m_data.m_value.array->back());
}
j.assert_invariant();
}
@ -205,13 +205,13 @@ struct external_constructor<value_t::array>
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::array;
j.m_value = value_t::array;
j.m_value.array->resize(arr.size());
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::array;
j.m_data.m_value = value_t::array;
j.m_data.m_value.array->resize(arr.size());
if (arr.size() > 0)
{
std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
}
j.set_parents();
j.assert_invariant();
@ -224,9 +224,9 @@ struct external_constructor<value_t::object>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value = obj;
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::object;
j.m_data.m_value = obj;
j.set_parents();
j.assert_invariant();
}
@ -234,9 +234,9 @@ struct external_constructor<value_t::object>
template<typename BasicJsonType>
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
{
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value = std::move(obj);
j.m_data.m_value.destroy(j.m_data.m_type);
j.m_data.m_type = value_t::object;
j.m_data.m_value = std::move(obj);
j.set_parents();
j.assert_invariant();
}
@ -248,9 +248,9 @@ struct external_constructor<value_t::object>
using std::begin;
using std::end;
j.m_value.destroy(j.m_type);
j.m_type = value_t::object;
j.m_value.object = 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_type = value_t::object;
j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
j.set_parents();
j.assert_invariant();
}

View File

@ -73,9 +73,9 @@ class exception : public std::exception
{
case value_t::array:
{
for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
{
if (&current->m_parent->m_value.array->operator[](i) == current)
if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
{
tokens.emplace_back(std::to_string(i));
break;
@ -86,7 +86,7 @@ class exception : public std::exception
case value_t::object:
{
for (const auto& element : *current->m_parent->m_value.object)
for (const auto& element : *current->m_parent->m_data.m_value.object)
{
if (&element.second == current)
{

View File

@ -244,7 +244,7 @@ class json_sax_dom_parser
JSON_ASSERT(ref_stack.back()->is_object());
// add null at given key and store the reference for later
object_element = &(ref_stack.back()->m_value.object->operator[](val));
object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
return true;
}
@ -319,8 +319,8 @@ class json_sax_dom_parser
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_value.array->back());
ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_data.m_value.array->back());
}
JSON_ASSERT(ref_stack.back()->is_object());
@ -439,7 +439,7 @@ class json_sax_dom_callback_parser
// add discarded value at given key and store the reference for later
if (keep && ref_stack.back())
{
object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
}
return true;
@ -524,7 +524,7 @@ class json_sax_dom_callback_parser
// remove discarded value
if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->pop_back();
ref_stack.back()->m_data.m_value.array->pop_back();
}
return true;
@ -607,8 +607,8 @@ class json_sax_dom_callback_parser
// array
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->emplace_back(std::move(value));
return {true, &(ref_stack.back()->m_value.array->back())};
ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
return {true, &(ref_stack.back()->m_data.m_value.array->back())};
}
// object

View File

@ -101,7 +101,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
@ -198,17 +198,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
m_it.object_iterator = m_object->m_value.object->begin();
m_it.object_iterator = m_object->m_data.m_value.object->begin();
break;
}
case value_t::array:
{
m_it.array_iterator = m_object->m_value.array->begin();
m_it.array_iterator = m_object->m_data.m_value.array->begin();
break;
}
@ -242,17 +242,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
m_it.object_iterator = m_object->m_value.object->end();
m_it.object_iterator = m_object->m_data.m_value.object->end();
break;
}
case value_t::array:
{
m_it.array_iterator = m_object->m_value.array->end();
m_it.array_iterator = m_object->m_data.m_value.array->end();
break;
}
@ -281,17 +281,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
return m_it.object_iterator->second;
}
case value_t::array:
{
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
return *m_it.array_iterator;
}
@ -325,17 +325,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
return &(m_it.object_iterator->second);
}
case value_t::array:
{
JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
return &*m_it.array_iterator;
}
@ -378,7 +378,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
@ -429,7 +429,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
{
@ -476,7 +476,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
return (m_it.object_iterator == other.m_it.object_iterator);
@ -521,7 +521,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
@ -577,7 +577,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
@ -656,7 +656,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
@ -685,7 +685,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
{
JSON_ASSERT(m_object != nullptr);
switch (m_object->m_type)
switch (m_object->m_data.m_type)
{
case value_t::object:
JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));

View File

@ -386,7 +386,7 @@ class json_pointer
if (reference_token == "-")
{
// explicitly treat "-" as index beyond the end
ptr = &ptr->operator[](ptr->m_value.array->size());
ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
}
else
{
@ -438,7 +438,7 @@ class json_pointer
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_value.array->size()),
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
@ -495,7 +495,7 @@ class json_pointer
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
{
// "-" cannot be used for const access
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
}
// use unchecked array access
@ -545,7 +545,7 @@ class json_pointer
{
// "-" always fails the range check
JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_value.array->size()),
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
}
@ -740,7 +740,7 @@ class json_pointer
{
case detail::value_t::array:
{
if (value.m_value.array->empty())
if (value.m_data.m_value.array->empty())
{
// flatten empty array as null
result[reference_string] = nullptr;
@ -748,10 +748,10 @@ class json_pointer
else
{
// iterate array and use index as reference string
for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
{
flatten(detail::concat(reference_string, '/', std::to_string(i)),
value.m_value.array->operator[](i), result);
value.m_data.m_value.array->operator[](i), result);
}
}
break;
@ -759,7 +759,7 @@ class json_pointer
case detail::value_t::object:
{
if (value.m_value.object->empty())
if (value.m_data.m_value.object->empty())
{
// flatten empty object as null
result[reference_string] = nullptr;
@ -767,7 +767,7 @@ class json_pointer
else
{
// iterate object and use keys as reference string
for (const auto& element : *value.m_value.object)
for (const auto& element : *value.m_data.m_value.object)
{
flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
}
@ -814,7 +814,7 @@ class json_pointer
BasicJsonType result;
// iterate the JSON object values
for (const auto& element : *value.m_value.object)
for (const auto& element : *value.m_data.m_value.object)
{
if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
{

View File

@ -63,7 +63,7 @@ class binary_writer
{
case value_t::object:
{
write_bson_object(*j.m_value.object);
write_bson_object(*j.m_data.m_value.object);
break;
}
@ -98,7 +98,7 @@ class binary_writer
case value_t::boolean:
{
oa->write_character(j.m_value.boolean
oa->write_character(j.m_data.m_value.boolean
? to_char_type(0xF5)
: to_char_type(0xF4));
break;
@ -106,42 +106,42 @@ class binary_writer
case value_t::number_integer:
{
if (j.m_value.number_integer >= 0)
if (j.m_data.m_value.number_integer >= 0)
{
// CBOR does not differentiate between positive signed
// integers and unsigned integers. Therefore, we used the
// code from the value_t::number_unsigned case here.
if (j.m_value.number_integer <= 0x17)
if (j.m_data.m_value.number_integer <= 0x17)
{
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
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_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
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_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
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_value.number_integer));
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_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
}
}
else
{
// The conversions below encode the sign in the first
// byte, and the value is converted to a positive number.
const auto positive_number = -1 - j.m_value.number_integer;
if (j.m_value.number_integer >= -24)
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));
}
@ -171,52 +171,52 @@ class binary_writer
case value_t::number_unsigned:
{
if (j.m_value.number_unsigned <= 0x17)
if (j.m_data.m_value.number_unsigned <= 0x17)
{
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
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_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
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_value.number_unsigned));
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
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_value.number_unsigned));
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_value.number_unsigned));
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
}
break;
}
case value_t::number_float:
{
if (std::isnan(j.m_value.number_float))
if (std::isnan(j.m_data.m_value.number_float))
{
// NaN is 0xf97e00 in CBOR
oa->write_character(to_char_type(0xF9));
oa->write_character(to_char_type(0x7E));
oa->write_character(to_char_type(0x00));
}
else if (std::isinf(j.m_value.number_float))
else if (std::isinf(j.m_data.m_value.number_float))
{
// Infinity is 0xf97c00, -Infinity is 0xf9fc00
oa->write_character(to_char_type(0xf9));
oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
oa->write_character(to_char_type(0x00));
}
else
{
write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
}
break;
}
@ -224,7 +224,7 @@ class binary_writer
case value_t::string:
{
// step 1: write control byte and the string length
const auto N = j.m_value.string->size();
const auto N = j.m_data.m_value.string->size();
if (N <= 0x17)
{
write_number(static_cast<std::uint8_t>(0x60 + N));
@ -254,15 +254,15 @@ class binary_writer
// step 2: write the string
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size());
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
case value_t::array:
{
// step 1: write control byte and the array size
const auto N = j.m_value.array->size();
const auto N = j.m_data.m_value.array->size();
if (N <= 0x17)
{
write_number(static_cast<std::uint8_t>(0x80 + N));
@ -291,7 +291,7 @@ class binary_writer
// LCOV_EXCL_STOP
// step 2: write each element
for (const auto& el : *j.m_value.array)
for (const auto& el : *j.m_data.m_value.array)
{
write_cbor(el);
}
@ -300,32 +300,32 @@ class binary_writer
case value_t::binary:
{
if (j.m_value.binary->has_subtype())
if (j.m_data.m_value.binary->has_subtype())
{
if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
{
write_number(static_cast<std::uint8_t>(0xd8));
write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
}
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
{
write_number(static_cast<std::uint8_t>(0xd9));
write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
}
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
{
write_number(static_cast<std::uint8_t>(0xda));
write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
}
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
{
write_number(static_cast<std::uint8_t>(0xdb));
write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
}
}
// step 1: write control byte and the binary array size
const auto N = j.m_value.binary->size();
const auto N = j.m_data.m_value.binary->size();
if (N <= 0x17)
{
write_number(static_cast<std::uint8_t>(0x40 + N));
@ -355,7 +355,7 @@ class binary_writer
// step 2: write each element
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
N);
break;
@ -364,7 +364,7 @@ class binary_writer
case value_t::object:
{
// step 1: write control byte and the object size
const auto N = j.m_value.object->size();
const auto N = j.m_data.m_value.object->size();
if (N <= 0x17)
{
write_number(static_cast<std::uint8_t>(0xA0 + N));
@ -393,7 +393,7 @@ class binary_writer
// LCOV_EXCL_STOP
// step 2: write each element
for (const auto& el : *j.m_value.object)
for (const auto& el : *j.m_data.m_value.object)
{
write_cbor(el.first);
write_cbor(el.second);
@ -422,7 +422,7 @@ class binary_writer
case value_t::boolean: // true and false
{
oa->write_character(j.m_value.boolean
oa->write_character(j.m_data.m_value.boolean
? to_char_type(0xC3)
: to_char_type(0xC2));
break;
@ -430,75 +430,75 @@ class binary_writer
case value_t::number_integer:
{
if (j.m_value.number_integer >= 0)
if (j.m_data.m_value.number_integer >= 0)
{
// MessagePack does not differentiate between positive
// signed integers and unsigned integers. Therefore, we used
// the code from the value_t::number_unsigned case here.
if (j.m_value.number_unsigned < 128)
if (j.m_data.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
}
}
else
{
if (j.m_value.number_integer >= -32)
if (j.m_data.m_value.number_integer >= -32)
{
// negative fixnum
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
{
// int 8
oa->write_character(to_char_type(0xD0));
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
{
// int 16
oa->write_character(to_char_type(0xD1));
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
{
// int 32
oa->write_character(to_char_type(0xD2));
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
{
// int 64
oa->write_character(to_char_type(0xD3));
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
}
}
break;
@ -506,48 +506,48 @@ class binary_writer
case value_t::number_unsigned:
{
if (j.m_value.number_unsigned < 128)
if (j.m_data.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
}
break;
}
case value_t::number_float:
{
write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
break;
}
case value_t::string:
{
// step 1: write control byte and the string length
const auto N = j.m_value.string->size();
const auto N = j.m_data.m_value.string->size();
if (N <= 31)
{
// fixstr
@ -574,15 +574,15 @@ class binary_writer
// step 2: write the string
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size());
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
case value_t::array:
{
// step 1: write control byte and the array size
const auto N = j.m_value.array->size();
const auto N = j.m_data.m_value.array->size();
if (N <= 15)
{
// fixarray
@ -602,7 +602,7 @@ class binary_writer
}
// step 2: write each element
for (const auto& el : *j.m_value.array)
for (const auto& el : *j.m_data.m_value.array)
{
write_msgpack(el);
}
@ -613,10 +613,10 @@ class binary_writer
{
// step 0: determine if the binary type has a set subtype to
// determine whether or not to use the ext or fixext types
const bool use_ext = j.m_value.binary->has_subtype();
const bool use_ext = j.m_data.m_value.binary->has_subtype();
// step 1: write control byte and the byte string length
const auto N = j.m_value.binary->size();
const auto N = j.m_data.m_value.binary->size();
if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
std::uint8_t output_type{};
@ -681,12 +681,12 @@ class binary_writer
// step 1.5: if this is an ext type, write the subtype
if (use_ext)
{
write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
}
// step 2: write the byte string
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
N);
break;
@ -695,7 +695,7 @@ class binary_writer
case value_t::object:
{
// step 1: write control byte and the object size
const auto N = j.m_value.object->size();
const auto N = j.m_data.m_value.object->size();
if (N <= 15)
{
// fixmap
@ -715,7 +715,7 @@ class binary_writer
}
// step 2: write each element
for (const auto& el : *j.m_value.object)
for (const auto& el : *j.m_data.m_value.object)
{
write_msgpack(el.first);
write_msgpack(el.second);
@ -755,7 +755,7 @@ class binary_writer
{
if (add_prefix)
{
oa->write_character(j.m_value.boolean
oa->write_character(j.m_data.m_value.boolean
? to_char_type('T')
: to_char_type('F'));
}
@ -764,19 +764,19 @@ class binary_writer
case value_t::number_integer:
{
write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
break;
}
case value_t::number_unsigned:
{
write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
break;
}
case value_t::number_float:
{
write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
break;
}
@ -786,10 +786,10 @@ class binary_writer
{
oa->write_character(to_char_type('S'));
}
write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size());
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
j.m_data.m_value.string->size());
break;
}
@ -801,7 +801,7 @@ class binary_writer
}
bool prefix_required = true;
if (use_type && !j.m_value.array->empty())
if (use_type && !j.m_data.m_value.array->empty())
{
JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
@ -824,10 +824,10 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
}
for (const auto& el : *j.m_value.array)
for (const auto& el : *j.m_data.m_value.array)
{
write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
}
@ -847,7 +847,7 @@ class binary_writer
oa->write_character(to_char_type('['));
}
if (use_type && !j.m_value.binary->empty())
if (use_type && !j.m_data.m_value.binary->empty())
{
JSON_ASSERT(use_count);
oa->write_character(to_char_type('$'));
@ -857,21 +857,21 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
}
if (use_type)
{
oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
j.m_value.binary->size());
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
j.m_data.m_value.binary->size());
}
else
{
for (size_t i = 0; i < j.m_value.binary->size(); ++i)
for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
{
oa->write_character(to_char_type('U'));
oa->write_character(j.m_value.binary->data()[i]);
oa->write_character(j.m_data.m_value.binary->data()[i]);
}
}
@ -885,9 +885,9 @@ class binary_writer
case value_t::object:
{
if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
{
if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
{
break;
}
@ -899,7 +899,7 @@ class binary_writer
}
bool prefix_required = true;
if (use_type && !j.m_value.object->empty())
if (use_type && !j.m_data.m_value.object->empty())
{
JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
@ -922,10 +922,10 @@ class binary_writer
if (use_count)
{
oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
}
for (const auto& el : *j.m_value.object)
for (const auto& el : *j.m_data.m_value.object)
{
write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
oa->write_characters(
@ -1075,19 +1075,19 @@ class binary_writer
void write_bson_unsigned(const string_t& name,
const BasicJsonType& j)
{
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
write_bson_entry_header(name, 0x10 /* int32 */);
write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
}
else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
write_bson_entry_header(name, 0x12 /* int64 */);
write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
}
else
{
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
}
}
@ -1168,13 +1168,13 @@ class binary_writer
switch (j.type())
{
case value_t::object:
return header_size + calc_bson_object_size(*j.m_value.object);
return header_size + calc_bson_object_size(*j.m_data.m_value.object);
case value_t::array:
return header_size + calc_bson_array_size(*j.m_value.array);
return header_size + calc_bson_array_size(*j.m_data.m_value.array);
case value_t::binary:
return header_size + calc_bson_binary_size(*j.m_value.binary);
return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
case value_t::boolean:
return header_size + 1ul;
@ -1183,13 +1183,13 @@ class binary_writer
return header_size + 8ul;
case value_t::number_integer:
return header_size + calc_bson_integer_size(j.m_value.number_integer);
return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
case value_t::number_unsigned:
return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
case value_t::string:
return header_size + calc_bson_string_size(*j.m_value.string);
return header_size + calc_bson_string_size(*j.m_data.m_value.string);
case value_t::null:
return header_size + 0ul;
@ -1215,28 +1215,28 @@ class binary_writer
switch (j.type())
{
case value_t::object:
return write_bson_object_entry(name, *j.m_value.object);
return write_bson_object_entry(name, *j.m_data.m_value.object);
case value_t::array:
return write_bson_array(name, *j.m_value.array);
return write_bson_array(name, *j.m_data.m_value.array);
case value_t::binary:
return write_bson_binary(name, *j.m_value.binary);
return write_bson_binary(name, *j.m_data.m_value.binary);
case value_t::boolean:
return write_bson_boolean(name, j.m_value.boolean);
return write_bson_boolean(name, j.m_data.m_value.boolean);
case value_t::number_float:
return write_bson_double(name, j.m_value.number_float);
return write_bson_double(name, j.m_data.m_value.number_float);
case value_t::number_integer:
return write_bson_integer(name, j.m_value.number_integer);
return write_bson_integer(name, j.m_data.m_value.number_integer);
case value_t::number_unsigned:
return write_bson_unsigned(name, j);
case value_t::string:
return write_bson_string(name, *j.m_value.string);
return write_bson_string(name, *j.m_data.m_value.string);
case value_t::null:
return write_bson_null(name);
@ -1509,35 +1509,35 @@ class binary_writer
return 'Z';
case value_t::boolean:
return j.m_value.boolean ? 'T' : 'F';
return j.m_data.m_value.boolean ? 'T' : 'F';
case value_t::number_integer:
{
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
{
return 'i';
}
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
{
return 'U';
}
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
{
return 'I';
}
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
{
return 'u';
}
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
{
return 'l';
}
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
{
return 'm';
}
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
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)())
{
return 'L';
}
@ -1547,35 +1547,35 @@ class binary_writer
case value_t::number_unsigned:
{
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
return 'i';
}
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
{
return 'U';
}
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{
return 'I';
}
if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
{
return 'u';
}
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
return 'l';
}
if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
{
return 'm';
}
if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
return 'L';
}
if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
return 'M';
}
@ -1584,7 +1584,7 @@ class binary_writer
}
case value_t::number_float:
return get_ubjson_float_prefix(j.m_value.number_float);
return get_ubjson_float_prefix(j.m_data.m_value.number_float);
case value_t::string:
return 'S';
@ -1633,7 +1633,7 @@ class binary_writer
std::size_t len = (value.at(key).empty() ? 0 : 1);
for (const auto& el : value.at(key))
{
len *= static_cast<std::size_t>(el.m_value.number_unsigned);
len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
}
key = "_ArrayData_";
@ -1655,70 +1655,70 @@ class binary_writer
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
}
}
else if (dtype == 'i')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
}
}
else if (dtype == 'u')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
}
}
else if (dtype == 'I')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
}
}
else if (dtype == 'm')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
}
}
else if (dtype == 'l')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
}
}
else if (dtype == 'M')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
}
}
else if (dtype == 'L')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
}
}
else if (dtype == 'd')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<float>(el.m_value.number_float), true);
write_number(static_cast<float>(el.m_data.m_value.number_float), true);
}
}
else if (dtype == 'D')
{
for (const auto& el : value.at(key))
{
write_number(static_cast<double>(el.m_value.number_float), true);
write_number(static_cast<double>(el.m_data.m_value.number_float), true);
}
}
return false;

View File

@ -110,11 +110,11 @@ class serializer
const unsigned int indent_step,
const unsigned int current_indent = 0)
{
switch (val.m_type)
switch (val.m_data.m_type)
{
case value_t::object:
{
if (val.m_value.object->empty())
if (val.m_data.m_value.object->empty())
{
o->write_characters("{}", 2);
return;
@ -132,8 +132,8 @@ class serializer
}
// first n-1 elements
auto i = val.m_value.object->cbegin();
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
auto i = val.m_data.m_value.object->cbegin();
for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
{
o->write_characters(indent_string.c_str(), new_indent);
o->write_character('\"');
@ -144,8 +144,8 @@ class serializer
}
// last element
JSON_ASSERT(i != val.m_value.object->cend());
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
JSON_ASSERT(i != val.m_data.m_value.object->cend());
JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
o->write_characters(indent_string.c_str(), new_indent);
o->write_character('\"');
dump_escaped(i->first, ensure_ascii);
@ -161,8 +161,8 @@ class serializer
o->write_character('{');
// first n-1 elements
auto i = val.m_value.object->cbegin();
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
auto i = val.m_data.m_value.object->cbegin();
for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
{
o->write_character('\"');
dump_escaped(i->first, ensure_ascii);
@ -172,8 +172,8 @@ class serializer
}
// last element
JSON_ASSERT(i != val.m_value.object->cend());
JSON_ASSERT(std::next(i) == val.m_value.object->cend());
JSON_ASSERT(i != val.m_data.m_value.object->cend());
JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
o->write_character('\"');
dump_escaped(i->first, ensure_ascii);
o->write_characters("\":", 2);
@ -187,7 +187,7 @@ class serializer
case value_t::array:
{
if (val.m_value.array->empty())
if (val.m_data.m_value.array->empty())
{
o->write_characters("[]", 2);
return;
@ -205,8 +205,8 @@ class serializer
}
// first n-1 elements
for (auto i = val.m_value.array->cbegin();
i != val.m_value.array->cend() - 1; ++i)
for (auto i = val.m_data.m_value.array->cbegin();
i != val.m_data.m_value.array->cend() - 1; ++i)
{
o->write_characters(indent_string.c_str(), new_indent);
dump(*i, true, ensure_ascii, indent_step, new_indent);
@ -214,9 +214,9 @@ class serializer
}
// last element
JSON_ASSERT(!val.m_value.array->empty());
JSON_ASSERT(!val.m_data.m_value.array->empty());
o->write_characters(indent_string.c_str(), new_indent);
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
o->write_character('\n');
o->write_characters(indent_string.c_str(), current_indent);
@ -227,16 +227,16 @@ class serializer
o->write_character('[');
// first n-1 elements
for (auto i = val.m_value.array->cbegin();
i != val.m_value.array->cend() - 1; ++i)
for (auto i = val.m_data.m_value.array->cbegin();
i != val.m_data.m_value.array->cend() - 1; ++i)
{
dump(*i, false, ensure_ascii, indent_step, current_indent);
o->write_character(',');
}
// last element
JSON_ASSERT(!val.m_value.array->empty());
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
JSON_ASSERT(!val.m_data.m_value.array->empty());
dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
o->write_character(']');
}
@ -247,7 +247,7 @@ class serializer
case value_t::string:
{
o->write_character('\"');
dump_escaped(*val.m_value.string, ensure_ascii);
dump_escaped(*val.m_data.m_value.string, ensure_ascii);
o->write_character('\"');
return;
}
@ -269,24 +269,24 @@ class serializer
o->write_characters("\"bytes\": [", 10);
if (!val.m_value.binary->empty())
if (!val.m_data.m_value.binary->empty())
{
for (auto i = val.m_value.binary->cbegin();
i != val.m_value.binary->cend() - 1; ++i)
for (auto i = val.m_data.m_value.binary->cbegin();
i != val.m_data.m_value.binary->cend() - 1; ++i)
{
dump_integer(*i);
o->write_characters(", ", 2);
}
dump_integer(val.m_value.binary->back());
dump_integer(val.m_data.m_value.binary->back());
}
o->write_characters("],\n", 3);
o->write_characters(indent_string.c_str(), new_indent);
o->write_characters("\"subtype\": ", 11);
if (val.m_value.binary->has_subtype())
if (val.m_data.m_value.binary->has_subtype())
{
dump_integer(val.m_value.binary->subtype());
dump_integer(val.m_data.m_value.binary->subtype());
}
else
{
@ -300,21 +300,21 @@ class serializer
{
o->write_characters("{\"bytes\":[", 10);
if (!val.m_value.binary->empty())
if (!val.m_data.m_value.binary->empty())
{
for (auto i = val.m_value.binary->cbegin();
i != val.m_value.binary->cend() - 1; ++i)
for (auto i = val.m_data.m_value.binary->cbegin();
i != val.m_data.m_value.binary->cend() - 1; ++i)
{
dump_integer(*i);
o->write_character(',');
}
dump_integer(val.m_value.binary->back());
dump_integer(val.m_data.m_value.binary->back());
}
o->write_characters("],\"subtype\":", 12);
if (val.m_value.binary->has_subtype())
if (val.m_data.m_value.binary->has_subtype())
{
dump_integer(val.m_value.binary->subtype());
dump_integer(val.m_data.m_value.binary->subtype());
o->write_character('}');
}
else
@ -327,7 +327,7 @@ class serializer
case value_t::boolean:
{
if (val.m_value.boolean)
if (val.m_data.m_value.boolean)
{
o->write_characters("true", 4);
}
@ -340,19 +340,19 @@ class serializer
case value_t::number_integer:
{
dump_integer(val.m_value.number_integer);
dump_integer(val.m_data.m_value.number_integer);
return;
}
case value_t::number_unsigned:
{
dump_integer(val.m_value.number_unsigned);
dump_integer(val.m_data.m_value.number_unsigned);
return;
}
case value_t::number_float:
{
dump_float(val.m_value.number_float);
dump_float(val.m_data.m_value.number_float);
return;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -216,28 +216,28 @@ TEST_CASE("const_iterator class")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
@ -267,28 +267,28 @@ TEST_CASE("const_iterator class")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cbegin();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
@ -316,28 +316,28 @@ TEST_CASE("const_iterator class")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
@ -365,28 +365,28 @@ TEST_CASE("const_iterator class")
{
json const j({{"foo", "bar"}});
json::const_iterator it = j.cend();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json const j({1, 2, 3, 4});
json::const_iterator it = j.cend();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
}

View File

@ -206,28 +206,28 @@ TEST_CASE("iterator class")
{
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
it++;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it++;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
@ -257,28 +257,28 @@ TEST_CASE("iterator class")
{
json j({{"foo", "bar"}});
json::iterator it = j.begin();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
++it;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.begin();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
++it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
}
}
@ -306,28 +306,28 @@ TEST_CASE("iterator class")
{
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
it--;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
it--;
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
@ -355,28 +355,28 @@ TEST_CASE("iterator class")
{
json j({{"foo", "bar"}});
json::iterator it = j.end();
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->end()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
--it;
CHECK((it.m_it.object_iterator == it.m_object->m_value.object->begin()));
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
}
SECTION("array")
{
json j({1, 2, 3, 4});
json::iterator it = j.end();
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
--it;
CHECK((it.m_it.array_iterator == it.m_object->m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_value.array->end()));
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
CHECK((it.m_it.array_iterator != it.m_object->m_data.m_value.array->end()));
}
}
}

View File

@ -872,7 +872,7 @@ TEST_CASE("constructors")
float const n = 42.23f;
json const j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
SECTION("double")
@ -880,7 +880,7 @@ TEST_CASE("constructors")
double const n = 42.23;
json const j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
SECTION("long double")
@ -888,28 +888,28 @@ TEST_CASE("constructors")
long double const n = 42.23L;
json const j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
SECTION("floating-point literal without suffix")
{
json const j(42.23);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
SECTION("integer literal with f suffix")
{
json const j(42.23f);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
SECTION("integer literal with l suffix")
{
json const j(42.23L);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
CHECK(j.m_data.m_value.number_float == Approx(j_reference.m_data.m_value.number_float));
}
}

View File

@ -1076,19 +1076,19 @@ TEST_CASE("value conversion")
SECTION("number_float_t")
{
auto n = j.get<json::number_float_t>();
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
SECTION("float")
{
auto n = j.get<float>();
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
SECTION("double")
{
auto n = j.get<double>();
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
SECTION("exception in case of a non-string type")
@ -1126,19 +1126,19 @@ TEST_CASE("value conversion")
SECTION("number_float_t")
{
json::number_float_t const n = j;
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
SECTION("float")
{
float const n = j;
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
SECTION("double")
{
double const n = j;
CHECK(json(n).m_value.number_float == Approx(j.m_value.number_float));
CHECK(json(n).m_data.m_value.number_float == Approx(j.m_data.m_value.number_float));
}
}
#endif
@ -1151,7 +1151,7 @@ TEST_CASE("value conversion")
SECTION("binary_t")
{
json::binary_t const b = j.get<json::binary_t>();
CHECK(*json(b).m_value.binary == *j.m_value.binary);
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("get_binary()")
@ -1159,14 +1159,14 @@ TEST_CASE("value conversion")
SECTION("non-const")
{
auto& b = j.get_binary();
CHECK(*json(b).m_value.binary == *j.m_value.binary);
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
SECTION("non-const")
{
const json j_const = j;
const auto& b = j_const.get_binary();
CHECK(*json(b).m_value.binary == *j.m_value.binary);
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
@ -1258,7 +1258,7 @@ TEST_CASE("value conversion")
SECTION("binary_t")
{
json::binary_t const b = j;
CHECK(*json(b).m_value.binary == *j.m_value.binary);
CHECK(*json(b).m_data.m_value.binary == *j.m_data.m_value.binary);
}
}
#endif

View File

@ -0,0 +1,86 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++ (supporting code)
// | | |__ | | | | | | version 3.11.2
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#include "doctest_compatibility.h"
#include <nlohmann/json.hpp>
#include <exception>
#include <iostream>
struct Foo
{
int a;
int b;
};
namespace nlohmann
{
template <>
struct adl_serializer<Foo>
{
static void to_json(json& j, Foo const& f)
{
switch (f.b)
{
case 0:
j["a"] = f.a;
break;
case 1:
j[0] = f.a;
break;
default:
j = "test";
}
if (f.a == 1)
{
throw std::runtime_error("b is invalid");
}
}
};
} // namespace nlohmann
TEST_CASE("check_for_mem_leak_on_adl_to_json-1")
{
try
{
const nlohmann::json j = Foo {1, 0};
std::cout << j.dump() << "\n";
}
catch (...)
{
// just ignore the exception in this POC
}
}
TEST_CASE("check_for_mem_leak_on_adl_to_json-2")
{
try
{
const nlohmann::json j = Foo {1, 1};
std::cout << j.dump() << "\n";
}
catch (...)
{
// just ignore the exception in this POC
}
}
TEST_CASE("check_for_mem_leak_on_adl_to_json-2")
{
try
{
const nlohmann::json j = Foo {1, 2};
std::cout << j.dump() << "\n";
}
catch (...)
{
// just ignore the exception in this POC
}
}