update nlohmann:json to v3.12.0

This commit is contained in:
Green Sky
2025-05-21 11:51:08 +02:00
parent 2ea7a1529a
commit 7e76d6116f
50 changed files with 4863 additions and 2641 deletions

View File

@ -1,9 +1,9 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.2
// | | |__ | | | | | | version 3.12.0
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#pragma once
@ -28,6 +28,13 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{
/// how to encode BJData
enum class bjdata_version_t
{
draft2,
draft3,
};
///////////////////
// binary writer //
///////////////////
@ -63,7 +70,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 +105,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 +113,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 +178,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 +231,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 +261,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 +298,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 +307,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 +362,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 +371,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 +400,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 +429,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 +437,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 +513,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 +581,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 +609,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);
}
@ -612,11 +619,11 @@ class binary_writer
case value_t::binary:
{
// 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();
// determine whether to use the ext or fixext types
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{};
@ -661,18 +668,18 @@ class binary_writer
}
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
std::uint8_t output_type = use_ext
? 0xC8 // ext 16
: 0xC5; // bin 16
const std::uint8_t output_type = use_ext
? 0xC8 // ext 16
: 0xC5; // bin 16
oa->write_character(to_char_type(output_type));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
std::uint8_t output_type = use_ext
? 0xC9 // ext 32
: 0xC6; // bin 32
const std::uint8_t output_type = use_ext
? 0xC9 // ext 32
: 0xC6; // bin 32
oa->write_character(to_char_type(output_type));
write_number(static_cast<std::uint32_t>(N));
@ -681,12 +688,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 +702,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 +722,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);
@ -735,11 +742,14 @@ class binary_writer
@param[in] use_type whether to use '$' prefixes (optimized format)
@param[in] add_prefix whether prefixes need to be used for this value
@param[in] use_bjdata whether write in BJData format, default is false
@param[in] bjdata_version which BJData version to use, default is draft2
*/
void write_ubjson(const BasicJsonType& j, const bool use_count,
const bool use_type, const bool add_prefix = true,
const bool use_bjdata = false)
const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
{
const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
switch (j.type())
{
case value_t::null:
@ -755,7 +765,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 +774,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 +796,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 +811,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,12 +834,12 @@ 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);
write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
}
if (!use_count)
@ -847,31 +857,31 @@ class binary_writer
oa->write_character(to_char_type('['));
}
if (use_type && !j.m_value.binary->empty())
if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
{
JSON_ASSERT(use_count);
oa->write_character(to_char_type('$'));
oa->write_character('U');
oa->write_character(bjdata_draft3 ? 'B' : 'U');
}
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(to_char_type(bjdata_draft3 ? 'B' : 'U'));
oa->write_character(j.m_data.m_value.binary->data()[i]);
}
}
@ -885,9 +895,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, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
{
break;
}
@ -899,7 +909,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,16 +932,16 @@ 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(
reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size());
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
}
if (!use_count)
@ -1075,19 +1085,20 @@ 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));
write_bson_entry_header(name, 0x11 /* uint64 */);
write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
}
}
@ -1168,13 +1179,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 +1194,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 +1226,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);
@ -1258,8 +1269,8 @@ class binary_writer
*/
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
{
std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
{
return result += calc_bson_element_size(el.first, el.second);
});
@ -1509,35 +1520,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 +1558,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 +1595,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';
@ -1615,10 +1626,11 @@ class binary_writer
/*!
@return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
*/
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
{
std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
{"char", 'C'}, {"byte", 'B'}
};
string_t key = "_ArrayType_";
@ -1633,7 +1645,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_";
@ -1648,77 +1660,77 @@ class binary_writer
oa->write_character('#');
key = "_ArraySize_";
write_ubjson(value.at(key), use_count, use_type, true, true);
write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
key = "_ArrayData_";
if (dtype == 'U' || dtype == 'C')
if (dtype == 'U' || dtype == 'C' || dtype == 'B')
{
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;