move is_bjdata to an optional param to write_ubjson

This commit is contained in:
Qianqian Fang 2022-02-21 10:35:13 -05:00
parent 53855c14d4
commit 7589b604aa
3 changed files with 114 additions and 112 deletions

View File

@ -39,7 +39,7 @@ class binary_writer
@param[in] adapter output adapter to write to @param[in] adapter output adapter to write to
@param[in] is_bjdata_ a boolean, if true, output is BJData format, default is false @param[in] is_bjdata_ a boolean, if true, output is BJData format, default is false
*/ */
explicit binary_writer(output_adapter_t<CharType> adapter, const bool is_bjdata_ = false) : oa(std::move(adapter)), is_bjdata(is_bjdata_) explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
{ {
JSON_ASSERT(oa); JSON_ASSERT(oa);
} }
@ -727,7 +727,8 @@ class binary_writer
@param[in] add_prefix whether prefixes need to be used for this value @param[in] add_prefix whether prefixes need to be used for this value
*/ */
void write_ubjson(const BasicJsonType& j, const bool use_count, void write_ubjson(const BasicJsonType& j, const bool use_count,
const bool use_type, const bool add_prefix = true) const bool use_type, const bool add_prefix = true,
const bool use_bjdata = false)
{ {
switch (j.type()) switch (j.type())
{ {
@ -753,19 +754,19 @@ class binary_writer
case value_t::number_integer: case value_t::number_integer:
{ {
write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
break; break;
} }
case value_t::number_unsigned: case value_t::number_unsigned:
{ {
write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
break; break;
} }
case value_t::number_float: case value_t::number_float:
{ {
write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
break; break;
} }
@ -775,7 +776,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('S')); oa->write_character(to_char_type('S'));
} }
write_number_with_ubjson_prefix(j.m_value.string->size(), true); write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()), reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size()); j.m_value.string->size());
@ -793,11 +794,11 @@ class binary_writer
if (use_type && !j.m_value.array->empty()) if (use_type && !j.m_value.array->empty())
{ {
JSON_ASSERT(use_count); JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front()); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin() + 1, j.end(), const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix](const BasicJsonType & v) [this, first_prefix, use_bjdata](const BasicJsonType & v)
{ {
return ubjson_prefix(v) == first_prefix; return ubjson_prefix(v, use_bjdata) == first_prefix;
}); });
if (same_prefix) if (same_prefix)
@ -811,7 +812,7 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.array->size(), true); write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
} }
for (const auto& el : *j.m_value.array) for (const auto& el : *j.m_value.array)
@ -844,7 +845,7 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.binary->size(), true); write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
} }
if (use_type) if (use_type)
@ -881,11 +882,11 @@ class binary_writer
if (use_type && !j.m_value.object->empty()) if (use_type && !j.m_value.object->empty())
{ {
JSON_ASSERT(use_count); JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front()); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin(), j.end(), const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix](const BasicJsonType & v) [this, first_prefix, use_bjdata](const BasicJsonType & v)
{ {
return ubjson_prefix(v) == first_prefix; return ubjson_prefix(v, use_bjdata) == first_prefix;
}); });
if (same_prefix) if (same_prefix)
@ -899,12 +900,12 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.object->size(), true); write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
} }
for (const auto& el : *j.m_value.object) for (const auto& el : *j.m_value.object)
{ {
write_number_with_ubjson_prefix(el.first.size(), true); write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(el.first.c_str()), reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size()); el.first.size());
@ -1296,20 +1297,22 @@ class binary_writer
template<typename NumberType, typename std::enable_if< template<typename NumberType, typename std::enable_if<
std::is_floating_point<NumberType>::value, int>::type = 0> std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(get_ubjson_float_prefix(n)); oa->write_character(get_ubjson_float_prefix(n));
} }
write_number(n); write_number(n, use_bjdata);
} }
// UBJSON: write number (unsigned integer) // UBJSON: write number (unsigned integer)
template<typename NumberType, typename std::enable_if< template<typename NumberType, typename std::enable_if<
std::is_unsigned<NumberType>::value, int>::type = 0> std::is_unsigned<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{ {
@ -1317,7 +1320,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if (n <= (std::numeric_limits<std::uint8_t>::max)()) else if (n <= (std::numeric_limits<std::uint8_t>::max)())
{ {
@ -1325,7 +1328,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{ {
@ -1333,15 +1336,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<std::int16_t>(n)); write_number(static_cast<std::int16_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('u')); // uint16 - bjdata only oa->write_character(to_char_type('u')); // uint16 - bjdata only
} }
write_number(static_cast<std::uint16_t>(n)); write_number(static_cast<std::uint16_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ {
@ -1349,15 +1352,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<std::int32_t>(n)); write_number(static_cast<std::int32_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('m')); // uint32 - bjdata only oa->write_character(to_char_type('m')); // uint32 - bjdata only
} }
write_number(static_cast<std::uint32_t>(n)); write_number(static_cast<std::uint32_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{ {
@ -1365,15 +1368,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<std::int64_t>(n)); write_number(static_cast<std::int64_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('M')); // uint64 - bjdata only oa->write_character(to_char_type('M')); // uint64 - bjdata only
} }
write_number(static_cast<std::uint64_t>(n)); write_number(static_cast<std::uint64_t>(n), use_bjdata);
} }
else else
{ {
@ -1383,7 +1386,7 @@ class binary_writer
} }
const auto number = BasicJsonType(n).dump(); const auto number = BasicJsonType(n).dump();
write_number_with_ubjson_prefix(number.size(), true); write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i) for (std::size_t i = 0; i < number.size(); ++i)
{ {
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@ -1396,7 +1399,8 @@ class binary_writer
std::is_signed<NumberType>::value&& std::is_signed<NumberType>::value&&
!std::is_floating_point<NumberType>::value, int >::type = 0 > !std::is_floating_point<NumberType>::value, int >::type = 0 >
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
{ {
@ -1404,7 +1408,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<std::int8_t>(n)); write_number(static_cast<std::int8_t>(n), use_bjdata);
} }
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
{ {
@ -1412,7 +1416,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
{ {
@ -1420,15 +1424,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<std::int16_t>(n)); write_number(static_cast<std::int16_t>(n), use_bjdata);
} }
else if (is_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)()))) else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('u')); // uint16 - bjdata only oa->write_character(to_char_type('u')); // uint16 - bjdata only
} }
write_number(static_cast<uint16_t>(n)); write_number(static_cast<uint16_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
{ {
@ -1436,15 +1440,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<std::int32_t>(n)); write_number(static_cast<std::int32_t>(n), use_bjdata);
} }
else if (is_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)()))) else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('m')); // uint32 - bjdata only oa->write_character(to_char_type('m')); // uint32 - bjdata only
} }
write_number(static_cast<uint32_t>(n)); write_number(static_cast<uint32_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
{ {
@ -1452,7 +1456,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<std::int64_t>(n)); write_number(static_cast<std::int64_t>(n), use_bjdata);
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else else
@ -1463,7 +1467,7 @@ class binary_writer
} }
const auto number = BasicJsonType(n).dump(); const auto number = BasicJsonType(n).dump();
write_number_with_ubjson_prefix(number.size(), true); write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i) for (std::size_t i = 0; i < number.size(); ++i)
{ {
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@ -1475,7 +1479,7 @@ class binary_writer
/*! /*!
@brief determine the type prefix of container values @brief determine the type prefix of container values
*/ */
CharType ubjson_prefix(const BasicJsonType& j) const noexcept CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata = false) const noexcept
{ {
switch (j.type()) switch (j.type())
{ {
@ -1499,7 +1503,7 @@ class binary_writer
{ {
return 'I'; return 'I';
} }
if (is_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_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
{ {
return 'u'; return 'u';
} }
@ -1507,7 +1511,7 @@ class binary_writer
{ {
return 'l'; return 'l';
} }
if (is_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_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
{ {
return 'm'; return 'm';
} }
@ -1533,7 +1537,7 @@ class binary_writer
{ {
return 'I'; return 'I';
} }
if (is_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
{ {
return 'u'; return 'u';
} }
@ -1541,7 +1545,7 @@ class binary_writer
{ {
return 'l'; return 'l';
} }
if (is_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
{ {
return 'm'; return 'm';
} }
@ -1549,7 +1553,7 @@ class binary_writer
{ {
return 'L'; return 'L';
} }
if (is_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{ {
return 'M'; return 'M';
} }
@ -1604,14 +1608,14 @@ class binary_writer
on big endian systems. on big endian systems.
*/ */
template<typename NumberType, bool OutputIsLittleEndian = false> template<typename NumberType, bool OutputIsLittleEndian = false>
void write_number(const NumberType n) void write_number(const NumberType n, const bool use_bjdata = false)
{ {
// step 1: write number to array of length NumberType // step 1: write number to array of length NumberType
std::array<CharType, sizeof(NumberType)> vec{}; std::array<CharType, sizeof(NumberType)> vec{};
std::memcpy(vec.data(), &n, sizeof(NumberType)); std::memcpy(vec.data(), &n, sizeof(NumberType));
// step 2: write array to output (with possible reordering) // step 2: write array to output (with possible reordering)
if (is_little_endian != (OutputIsLittleEndian || is_bjdata)) if (is_little_endian != (OutputIsLittleEndian || use_bjdata))
{ {
// reverse byte order prior to conversion if necessary // reverse byte order prior to conversion if necessary
std::reverse(vec.begin(), vec.end()); std::reverse(vec.begin(), vec.end());
@ -1692,9 +1696,6 @@ class binary_writer
/// whether we can assume little endianness /// whether we can assume little endianness
const bool is_little_endian = little_endianness(); const bool is_little_endian = little_endianness();
/// whether to write in bjdata format
const bool is_bjdata = false;
/// the output /// the output
output_adapter_t<CharType> oa = nullptr; output_adapter_t<CharType> oa = nullptr;
}; };

View File

@ -3970,20 +3970,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool use_type = false) const bool use_type = false)
{ {
std::vector<std::uint8_t> result; std::vector<std::uint8_t> result;
to_bjdata(j, result, use_size, use_type); to_bjdata(j, result, use_size, use_type, true);
return result; return result;
} }
static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false)
{ {
binary_writer<std::uint8_t>(o, true).write_ubjson(j, use_size, use_type); binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true);
} }
static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false)
{ {
binary_writer<char>(o, true).write_ubjson(j, use_size, use_type); binary_writer<char>(o).write_ubjson(j, use_size, use_type, true);
} }
/// @brief create a BSON serialization of a given JSON value /// @brief create a BSON serialization of a given JSON value

View File

@ -13863,7 +13863,7 @@ class binary_writer
@param[in] adapter output adapter to write to @param[in] adapter output adapter to write to
@param[in] is_bjdata_ a boolean, if true, output is BJData format, default is false @param[in] is_bjdata_ a boolean, if true, output is BJData format, default is false
*/ */
explicit binary_writer(output_adapter_t<CharType> adapter, const bool is_bjdata_ = false) : oa(std::move(adapter)), is_bjdata(is_bjdata_) explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
{ {
JSON_ASSERT(oa); JSON_ASSERT(oa);
} }
@ -14551,7 +14551,8 @@ class binary_writer
@param[in] add_prefix whether prefixes need to be used for this value @param[in] add_prefix whether prefixes need to be used for this value
*/ */
void write_ubjson(const BasicJsonType& j, const bool use_count, void write_ubjson(const BasicJsonType& j, const bool use_count,
const bool use_type, const bool add_prefix = true) const bool use_type, const bool add_prefix = true,
const bool use_bjdata = false)
{ {
switch (j.type()) switch (j.type())
{ {
@ -14577,19 +14578,19 @@ class binary_writer
case value_t::number_integer: case value_t::number_integer:
{ {
write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
break; break;
} }
case value_t::number_unsigned: case value_t::number_unsigned:
{ {
write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
break; break;
} }
case value_t::number_float: case value_t::number_float:
{ {
write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
break; break;
} }
@ -14599,7 +14600,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('S')); oa->write_character(to_char_type('S'));
} }
write_number_with_ubjson_prefix(j.m_value.string->size(), true); write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(j.m_value.string->c_str()), reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
j.m_value.string->size()); j.m_value.string->size());
@ -14617,11 +14618,11 @@ class binary_writer
if (use_type && !j.m_value.array->empty()) if (use_type && !j.m_value.array->empty())
{ {
JSON_ASSERT(use_count); JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front()); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin() + 1, j.end(), const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
[this, first_prefix](const BasicJsonType & v) [this, first_prefix, use_bjdata](const BasicJsonType & v)
{ {
return ubjson_prefix(v) == first_prefix; return ubjson_prefix(v, use_bjdata) == first_prefix;
}); });
if (same_prefix) if (same_prefix)
@ -14635,7 +14636,7 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.array->size(), true); write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
} }
for (const auto& el : *j.m_value.array) for (const auto& el : *j.m_value.array)
@ -14668,7 +14669,7 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.binary->size(), true); write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
} }
if (use_type) if (use_type)
@ -14705,11 +14706,11 @@ class binary_writer
if (use_type && !j.m_value.object->empty()) if (use_type && !j.m_value.object->empty())
{ {
JSON_ASSERT(use_count); JSON_ASSERT(use_count);
const CharType first_prefix = ubjson_prefix(j.front()); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
const bool same_prefix = std::all_of(j.begin(), j.end(), const bool same_prefix = std::all_of(j.begin(), j.end(),
[this, first_prefix](const BasicJsonType & v) [this, first_prefix, use_bjdata](const BasicJsonType & v)
{ {
return ubjson_prefix(v) == first_prefix; return ubjson_prefix(v, use_bjdata) == first_prefix;
}); });
if (same_prefix) if (same_prefix)
@ -14723,12 +14724,12 @@ class binary_writer
if (use_count) if (use_count)
{ {
oa->write_character(to_char_type('#')); oa->write_character(to_char_type('#'));
write_number_with_ubjson_prefix(j.m_value.object->size(), true); write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
} }
for (const auto& el : *j.m_value.object) for (const auto& el : *j.m_value.object)
{ {
write_number_with_ubjson_prefix(el.first.size(), true); write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(el.first.c_str()), reinterpret_cast<const CharType*>(el.first.c_str()),
el.first.size()); el.first.size());
@ -15120,20 +15121,22 @@ class binary_writer
template<typename NumberType, typename std::enable_if< template<typename NumberType, typename std::enable_if<
std::is_floating_point<NumberType>::value, int>::type = 0> std::is_floating_point<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(get_ubjson_float_prefix(n)); oa->write_character(get_ubjson_float_prefix(n));
} }
write_number(n); write_number(n, use_bjdata);
} }
// UBJSON: write number (unsigned integer) // UBJSON: write number (unsigned integer)
template<typename NumberType, typename std::enable_if< template<typename NumberType, typename std::enable_if<
std::is_unsigned<NumberType>::value, int>::type = 0> std::is_unsigned<NumberType>::value, int>::type = 0>
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)())) if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{ {
@ -15141,7 +15144,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if (n <= (std::numeric_limits<std::uint8_t>::max)()) else if (n <= (std::numeric_limits<std::uint8_t>::max)())
{ {
@ -15149,7 +15152,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{ {
@ -15157,15 +15160,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<std::int16_t>(n)); write_number(static_cast<std::int16_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)())) else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('u')); // uint16 - bjdata only oa->write_character(to_char_type('u')); // uint16 - bjdata only
} }
write_number(static_cast<std::uint16_t>(n)); write_number(static_cast<std::uint16_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ {
@ -15173,15 +15176,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<std::int32_t>(n)); write_number(static_cast<std::int32_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('m')); // uint32 - bjdata only oa->write_character(to_char_type('m')); // uint32 - bjdata only
} }
write_number(static_cast<std::uint32_t>(n)); write_number(static_cast<std::uint32_t>(n), use_bjdata);
} }
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{ {
@ -15189,15 +15192,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<std::int64_t>(n)); write_number(static_cast<std::int64_t>(n), use_bjdata);
} }
else if (is_bjdata && n <= (std::numeric_limits<uint64_t>::max)()) else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('M')); // uint64 - bjdata only oa->write_character(to_char_type('M')); // uint64 - bjdata only
} }
write_number(static_cast<std::uint64_t>(n)); write_number(static_cast<std::uint64_t>(n), use_bjdata);
} }
else else
{ {
@ -15207,7 +15210,7 @@ class binary_writer
} }
const auto number = BasicJsonType(n).dump(); const auto number = BasicJsonType(n).dump();
write_number_with_ubjson_prefix(number.size(), true); write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i) for (std::size_t i = 0; i < number.size(); ++i)
{ {
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@ -15220,7 +15223,8 @@ class binary_writer
std::is_signed<NumberType>::value&& std::is_signed<NumberType>::value&&
!std::is_floating_point<NumberType>::value, int >::type = 0 > !std::is_floating_point<NumberType>::value, int >::type = 0 >
void write_number_with_ubjson_prefix(const NumberType n, void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix) const bool add_prefix,
const bool use_bjdata = false)
{ {
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)()) if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
{ {
@ -15228,7 +15232,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<std::int8_t>(n)); write_number(static_cast<std::int8_t>(n), use_bjdata);
} }
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)())) else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
{ {
@ -15236,7 +15240,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<std::uint8_t>(n)); write_number(static_cast<std::uint8_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)()) else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
{ {
@ -15244,15 +15248,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<std::int16_t>(n)); write_number(static_cast<std::int16_t>(n), use_bjdata);
} }
else if (is_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)()))) else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('u')); // uint16 - bjdata only oa->write_character(to_char_type('u')); // uint16 - bjdata only
} }
write_number(static_cast<uint16_t>(n)); write_number(static_cast<uint16_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)()) else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
{ {
@ -15260,15 +15264,15 @@ class binary_writer
{ {
oa->write_character(to_char_type('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<std::int32_t>(n)); write_number(static_cast<std::int32_t>(n), use_bjdata);
} }
else if (is_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)()))) else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(to_char_type('m')); // uint32 - bjdata only oa->write_character(to_char_type('m')); // uint32 - bjdata only
} }
write_number(static_cast<uint32_t>(n)); write_number(static_cast<uint32_t>(n), use_bjdata);
} }
else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)()) else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
{ {
@ -15276,7 +15280,7 @@ class binary_writer
{ {
oa->write_character(to_char_type('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<std::int64_t>(n)); write_number(static_cast<std::int64_t>(n), use_bjdata);
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else else
@ -15287,7 +15291,7 @@ class binary_writer
} }
const auto number = BasicJsonType(n).dump(); const auto number = BasicJsonType(n).dump();
write_number_with_ubjson_prefix(number.size(), true); write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
for (std::size_t i = 0; i < number.size(); ++i) for (std::size_t i = 0; i < number.size(); ++i)
{ {
oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i]))); oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
@ -15299,7 +15303,7 @@ class binary_writer
/*! /*!
@brief determine the type prefix of container values @brief determine the type prefix of container values
*/ */
CharType ubjson_prefix(const BasicJsonType& j) const noexcept CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata = false) const noexcept
{ {
switch (j.type()) switch (j.type())
{ {
@ -15323,7 +15327,7 @@ class binary_writer
{ {
return 'I'; return 'I';
} }
if (is_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_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
{ {
return 'u'; return 'u';
} }
@ -15331,7 +15335,7 @@ class binary_writer
{ {
return 'l'; return 'l';
} }
if (is_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_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
{ {
return 'm'; return 'm';
} }
@ -15357,7 +15361,7 @@ class binary_writer
{ {
return 'I'; return 'I';
} }
if (is_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)())) if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
{ {
return 'u'; return 'u';
} }
@ -15365,7 +15369,7 @@ class binary_writer
{ {
return 'l'; return 'l';
} }
if (is_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)())) if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
{ {
return 'm'; return 'm';
} }
@ -15373,7 +15377,7 @@ class binary_writer
{ {
return 'L'; return 'L';
} }
if (is_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)()) if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{ {
return 'M'; return 'M';
} }
@ -15428,14 +15432,14 @@ class binary_writer
on big endian systems. on big endian systems.
*/ */
template<typename NumberType, bool OutputIsLittleEndian = false> template<typename NumberType, bool OutputIsLittleEndian = false>
void write_number(const NumberType n) void write_number(const NumberType n, const bool use_bjdata = false)
{ {
// step 1: write number to array of length NumberType // step 1: write number to array of length NumberType
std::array<CharType, sizeof(NumberType)> vec{}; std::array<CharType, sizeof(NumberType)> vec{};
std::memcpy(vec.data(), &n, sizeof(NumberType)); std::memcpy(vec.data(), &n, sizeof(NumberType));
// step 2: write array to output (with possible reordering) // step 2: write array to output (with possible reordering)
if (is_little_endian != (OutputIsLittleEndian || is_bjdata)) if (is_little_endian != (OutputIsLittleEndian || use_bjdata))
{ {
// reverse byte order prior to conversion if necessary // reverse byte order prior to conversion if necessary
std::reverse(vec.begin(), vec.end()); std::reverse(vec.begin(), vec.end());
@ -15516,9 +15520,6 @@ class binary_writer
/// whether we can assume little endianness /// whether we can assume little endianness
const bool is_little_endian = little_endianness(); const bool is_little_endian = little_endianness();
/// whether to write in bjdata format
const bool is_bjdata = false;
/// the output /// the output
output_adapter_t<CharType> oa = nullptr; output_adapter_t<CharType> oa = nullptr;
}; };
@ -21740,20 +21741,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool use_type = false) const bool use_type = false)
{ {
std::vector<std::uint8_t> result; std::vector<std::uint8_t> result;
to_bjdata(j, result, use_size, use_type); to_bjdata(j, result, use_size, use_type, true);
return result; return result;
} }
static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o, static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false)
{ {
binary_writer<std::uint8_t>(o, true).write_ubjson(j, use_size, use_type); binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true);
} }
static void to_bjdata(const basic_json& j, detail::output_adapter<char> o, static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
const bool use_size = false, const bool use_type = false) const bool use_size = false, const bool use_type = false)
{ {
binary_writer<char>(o, true).write_ubjson(j, use_size, use_type); binary_writer<char>(o).write_ubjson(j, use_size, use_type, true);
} }
/// @brief create a BSON serialization of a given JSON value /// @brief create a BSON serialization of a given JSON value