templatized output adapters
This commit is contained in:
parent
7444c7fa25
commit
bf55a999c5
@ -23,11 +23,13 @@ namespace detail
|
||||
/*!
|
||||
@brief serialization to CBOR and MessagePack values
|
||||
*/
|
||||
template<typename BasicJsonType, typename CharType>
|
||||
template<typename BasicJsonType, typename OutputAdapterType>
|
||||
class binary_writer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using output_adapter_t = OutputAdapterType;
|
||||
using CharType = typename OutputAdapterType::char_type;
|
||||
|
||||
public:
|
||||
/*!
|
||||
@ -35,10 +37,8 @@ class binary_writer
|
||||
|
||||
@param[in] adapter output adapter to write to
|
||||
*/
|
||||
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(adapter)
|
||||
{
|
||||
assert(oa);
|
||||
}
|
||||
explicit binary_writer(OutputAdapterType adapter) : oa(std::move(adapter))
|
||||
{}
|
||||
|
||||
/*!
|
||||
@param[in] j JSON value to serialize
|
||||
@ -70,15 +70,15 @@ class binary_writer
|
||||
{
|
||||
case value_t::null:
|
||||
{
|
||||
oa->write_character(to_char_type(0xF6));
|
||||
oa.write_character(to_char_type(0xF6));
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean:
|
||||
{
|
||||
oa->write_character(j.m_value.boolean
|
||||
? to_char_type(0xF5)
|
||||
: to_char_type(0xF4));
|
||||
oa.write_character(j.m_value.boolean
|
||||
? to_char_type(0xF5)
|
||||
: to_char_type(0xF4));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -95,22 +95,22 @@ class binary_writer
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x18));
|
||||
oa.write_character(to_char_type(0x18));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x19));
|
||||
oa.write_character(to_char_type(0x19));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x1A));
|
||||
oa.write_character(to_char_type(0x1A));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x1B));
|
||||
oa.write_character(to_char_type(0x1B));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
@ -125,22 +125,22 @@ class binary_writer
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x38));
|
||||
oa.write_character(to_char_type(0x38));
|
||||
write_number(static_cast<std::uint8_t>(positive_number));
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x39));
|
||||
oa.write_character(to_char_type(0x39));
|
||||
write_number(static_cast<std::uint16_t>(positive_number));
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x3A));
|
||||
oa.write_character(to_char_type(0x3A));
|
||||
write_number(static_cast<std::uint32_t>(positive_number));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x3B));
|
||||
oa.write_character(to_char_type(0x3B));
|
||||
write_number(static_cast<std::uint64_t>(positive_number));
|
||||
}
|
||||
}
|
||||
@ -155,22 +155,22 @@ class binary_writer
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x18));
|
||||
oa.write_character(to_char_type(0x18));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x19));
|
||||
oa.write_character(to_char_type(0x19));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x1A));
|
||||
oa.write_character(to_char_type(0x1A));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x1B));
|
||||
oa.write_character(to_char_type(0x1B));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
break;
|
||||
@ -181,16 +181,16 @@ class binary_writer
|
||||
if (std::isnan(j.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));
|
||||
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))
|
||||
{
|
||||
// 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(to_char_type(0x00));
|
||||
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(to_char_type(0x00));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -198,12 +198,12 @@ class binary_writer
|
||||
static_cast<double>(j.m_value.number_float) <= static_cast<double>((std::numeric_limits<float>::max)()) and
|
||||
static_cast<double>(static_cast<float>(j.m_value.number_float)) == static_cast<double>(j.m_value.number_float))
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
|
||||
oa.write_character(get_cbor_float_prefix(static_cast<float>(j.m_value.number_float)));
|
||||
write_number(static_cast<float>(j.m_value.number_float));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(get_cbor_float_prefix(j.m_value.number_float));
|
||||
oa.write_character(get_cbor_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
}
|
||||
}
|
||||
@ -220,29 +220,29 @@ class binary_writer
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x78));
|
||||
oa.write_character(to_char_type(0x78));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x79));
|
||||
oa.write_character(to_char_type(0x79));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x7A));
|
||||
oa.write_character(to_char_type(0x7A));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x7B));
|
||||
oa.write_character(to_char_type(0x7B));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
// step 2: write the string
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
|
||||
j.m_value.string->size());
|
||||
break;
|
||||
@ -258,23 +258,23 @@ class binary_writer
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x98));
|
||||
oa.write_character(to_char_type(0x98));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x99));
|
||||
oa.write_character(to_char_type(0x99));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x9A));
|
||||
oa.write_character(to_char_type(0x9A));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x9B));
|
||||
oa.write_character(to_char_type(0x9B));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
@ -297,29 +297,29 @@ class binary_writer
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x58));
|
||||
oa.write_character(to_char_type(0x58));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x59));
|
||||
oa.write_character(to_char_type(0x59));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x5A));
|
||||
oa.write_character(to_char_type(0x5A));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x5B));
|
||||
oa.write_character(to_char_type(0x5B));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
// step 2: write each element
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
|
||||
N);
|
||||
|
||||
@ -336,23 +336,23 @@ class binary_writer
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xB8));
|
||||
oa.write_character(to_char_type(0xB8));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xB9));
|
||||
oa.write_character(to_char_type(0xB9));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xBA));
|
||||
oa.write_character(to_char_type(0xBA));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xBB));
|
||||
oa.write_character(to_char_type(0xBB));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
@ -380,15 +380,15 @@ class binary_writer
|
||||
{
|
||||
case value_t::null: // nil
|
||||
{
|
||||
oa->write_character(to_char_type(0xC0));
|
||||
oa.write_character(to_char_type(0xC0));
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean: // true and false
|
||||
{
|
||||
oa->write_character(j.m_value.boolean
|
||||
? to_char_type(0xC3)
|
||||
: to_char_type(0xC2));
|
||||
oa.write_character(j.m_value.boolean
|
||||
? to_char_type(0xC3)
|
||||
: to_char_type(0xC2));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -407,25 +407,25 @@ class binary_writer
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// uint 8
|
||||
oa->write_character(to_char_type(0xCC));
|
||||
oa.write_character(to_char_type(0xCC));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// uint 16
|
||||
oa->write_character(to_char_type(0xCD));
|
||||
oa.write_character(to_char_type(0xCD));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// uint 32
|
||||
oa->write_character(to_char_type(0xCE));
|
||||
oa.write_character(to_char_type(0xCE));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
// uint 64
|
||||
oa->write_character(to_char_type(0xCF));
|
||||
oa.write_character(to_char_type(0xCF));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
@ -440,28 +440,28 @@ class binary_writer
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
// int 8
|
||||
oa->write_character(to_char_type(0xD0));
|
||||
oa.write_character(to_char_type(0xD0));
|
||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
// int 16
|
||||
oa->write_character(to_char_type(0xD1));
|
||||
oa.write_character(to_char_type(0xD1));
|
||||
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
// int 32
|
||||
oa->write_character(to_char_type(0xD2));
|
||||
oa.write_character(to_char_type(0xD2));
|
||||
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
// int 64
|
||||
oa->write_character(to_char_type(0xD3));
|
||||
oa.write_character(to_char_type(0xD3));
|
||||
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
@ -478,25 +478,25 @@ class binary_writer
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// uint 8
|
||||
oa->write_character(to_char_type(0xCC));
|
||||
oa.write_character(to_char_type(0xCC));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// uint 16
|
||||
oa->write_character(to_char_type(0xCD));
|
||||
oa.write_character(to_char_type(0xCD));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// uint 32
|
||||
oa->write_character(to_char_type(0xCE));
|
||||
oa.write_character(to_char_type(0xCE));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
// uint 64
|
||||
oa->write_character(to_char_type(0xCF));
|
||||
oa.write_character(to_char_type(0xCF));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
break;
|
||||
@ -504,7 +504,7 @@ class binary_writer
|
||||
|
||||
case value_t::number_float:
|
||||
{
|
||||
oa->write_character(get_msgpack_float_prefix(j.m_value.number_float));
|
||||
oa.write_character(get_msgpack_float_prefix(j.m_value.number_float));
|
||||
write_number(j.m_value.number_float);
|
||||
break;
|
||||
}
|
||||
@ -521,24 +521,24 @@ class binary_writer
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa->write_character(to_char_type(0xD9));
|
||||
oa.write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa->write_character(to_char_type(0xDA));
|
||||
oa.write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// str 32
|
||||
oa->write_character(to_char_type(0xDB));
|
||||
oa.write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
|
||||
j.m_value.string->size());
|
||||
break;
|
||||
@ -556,13 +556,13 @@ class binary_writer
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// array 16
|
||||
oa->write_character(to_char_type(0xDC));
|
||||
oa.write_character(to_char_type(0xDC));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// array 32
|
||||
oa->write_character(to_char_type(0xDD));
|
||||
oa.write_character(to_char_type(0xDD));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
@ -618,7 +618,7 @@ class binary_writer
|
||||
fixed = false;
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
oa.write_character(to_char_type(output_type));
|
||||
if (not fixed)
|
||||
{
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
@ -636,7 +636,7 @@ class binary_writer
|
||||
output_type = 0xC5; // bin 16
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
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)())
|
||||
@ -651,7 +651,7 @@ class binary_writer
|
||||
output_type = 0xC6; // bin 32
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(output_type));
|
||||
oa.write_character(to_char_type(output_type));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
@ -662,7 +662,7 @@ class binary_writer
|
||||
}
|
||||
|
||||
// step 2: write the byte string
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
|
||||
N);
|
||||
|
||||
@ -681,13 +681,13 @@ class binary_writer
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// map 16
|
||||
oa->write_character(to_char_type(0xDE));
|
||||
oa.write_character(to_char_type(0xDE));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// map 32
|
||||
oa->write_character(to_char_type(0xDF));
|
||||
oa.write_character(to_char_type(0xDF));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
@ -720,7 +720,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('Z'));
|
||||
oa.write_character(to_char_type('Z'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -729,9 +729,9 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(j.m_value.boolean
|
||||
? to_char_type('T')
|
||||
: to_char_type('F'));
|
||||
oa.write_character(j.m_value.boolean
|
||||
? to_char_type('T')
|
||||
: to_char_type('F'));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -758,10 +758,10 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
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);
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
|
||||
j.m_value.string->size());
|
||||
break;
|
||||
@ -771,7 +771,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('['));
|
||||
oa.write_character(to_char_type('['));
|
||||
}
|
||||
|
||||
bool prefix_required = true;
|
||||
@ -788,14 +788,14 @@ class binary_writer
|
||||
if (same_prefix)
|
||||
{
|
||||
prefix_required = false;
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character(first_prefix);
|
||||
oa.write_character(to_char_type('$'));
|
||||
oa.write_character(first_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -806,7 +806,7 @@ class binary_writer
|
||||
|
||||
if (not use_count)
|
||||
{
|
||||
oa->write_character(to_char_type(']'));
|
||||
oa.write_character(to_char_type(']'));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -816,25 +816,25 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('['));
|
||||
oa.write_character(to_char_type('['));
|
||||
}
|
||||
|
||||
if (use_type and not j.m_value.binary->empty())
|
||||
{
|
||||
assert(use_count);
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character('U');
|
||||
oa.write_character(to_char_type('$'));
|
||||
oa.write_character('U');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (use_type)
|
||||
{
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(j.m_value.binary->data()),
|
||||
j.m_value.binary->size());
|
||||
}
|
||||
@ -842,14 +842,14 @@ class binary_writer
|
||||
{
|
||||
for (size_t i = 0; i < j.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('U'));
|
||||
oa.write_character(j.m_value.binary->data()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (not use_count)
|
||||
{
|
||||
oa->write_character(to_char_type(']'));
|
||||
oa.write_character(to_char_type(']'));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -859,7 +859,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('{'));
|
||||
oa.write_character(to_char_type('{'));
|
||||
}
|
||||
|
||||
bool prefix_required = true;
|
||||
@ -876,21 +876,21 @@ class binary_writer
|
||||
if (same_prefix)
|
||||
{
|
||||
prefix_required = false;
|
||||
oa->write_character(to_char_type('$'));
|
||||
oa->write_character(first_prefix);
|
||||
oa.write_character(to_char_type('$'));
|
||||
oa.write_character(first_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (const auto& el : *j.m_value.object)
|
||||
{
|
||||
write_number_with_ubjson_prefix(el.first.size(), true);
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(el.first.c_str()),
|
||||
el.first.size());
|
||||
write_ubjson(el.second, use_count, use_type, prefix_required);
|
||||
@ -898,7 +898,7 @@ class binary_writer
|
||||
|
||||
if (not use_count)
|
||||
{
|
||||
oa->write_character(to_char_type('}'));
|
||||
oa.write_character(to_char_type('}'));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -936,8 +936,8 @@ class binary_writer
|
||||
void write_bson_entry_header(const string_t& name,
|
||||
const std::uint8_t element_type)
|
||||
{
|
||||
oa->write_character(to_char_type(element_type)); // boolean
|
||||
oa->write_characters(
|
||||
oa.write_character(to_char_type(element_type)); // boolean
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(name.c_str()),
|
||||
name.size() + 1u);
|
||||
}
|
||||
@ -949,7 +949,7 @@ class binary_writer
|
||||
const bool value)
|
||||
{
|
||||
write_bson_entry_header(name, 0x08);
|
||||
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
|
||||
oa.write_character(value ? to_char_type(0x01) : to_char_type(0x00));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -979,7 +979,7 @@ class binary_writer
|
||||
write_bson_entry_header(name, 0x02);
|
||||
|
||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
|
||||
oa->write_characters(
|
||||
oa.write_characters(
|
||||
reinterpret_cast<const CharType*>(value.c_str()),
|
||||
value.size() + 1);
|
||||
}
|
||||
@ -1101,7 +1101,7 @@ class binary_writer
|
||||
write_bson_element(std::to_string(array_index++), el);
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(0x00));
|
||||
oa.write_character(to_char_type(0x00));
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1115,7 +1115,7 @@ class binary_writer
|
||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
|
||||
write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
|
||||
|
||||
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
||||
oa.write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1240,7 +1240,7 @@ class binary_writer
|
||||
write_bson_element(el.first, el.second);
|
||||
}
|
||||
|
||||
oa->write_character(to_char_type(0x00));
|
||||
oa.write_character(to_char_type(0x00));
|
||||
}
|
||||
|
||||
//////////
|
||||
@ -1283,7 +1283,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(get_ubjson_float_prefix(n));
|
||||
oa.write_character(get_ubjson_float_prefix(n));
|
||||
}
|
||||
write_number(n);
|
||||
}
|
||||
@ -1298,7 +1298,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('i')); // int8
|
||||
oa.write_character(to_char_type('i')); // int8
|
||||
}
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
@ -1306,7 +1306,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('U')); // uint8
|
||||
oa.write_character(to_char_type('U')); // uint8
|
||||
}
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
@ -1314,7 +1314,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('I')); // int16
|
||||
oa.write_character(to_char_type('I')); // int16
|
||||
}
|
||||
write_number(static_cast<std::int16_t>(n));
|
||||
}
|
||||
@ -1322,7 +1322,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('l')); // int32
|
||||
oa.write_character(to_char_type('l')); // int32
|
||||
}
|
||||
write_number(static_cast<std::int32_t>(n));
|
||||
}
|
||||
@ -1330,7 +1330,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('L')); // int64
|
||||
oa.write_character(to_char_type('L')); // int64
|
||||
}
|
||||
write_number(static_cast<std::int64_t>(n));
|
||||
}
|
||||
@ -1351,7 +1351,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('i')); // int8
|
||||
oa.write_character(to_char_type('i')); // int8
|
||||
}
|
||||
write_number(static_cast<std::int8_t>(n));
|
||||
}
|
||||
@ -1359,7 +1359,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('U')); // uint8
|
||||
oa.write_character(to_char_type('U')); // uint8
|
||||
}
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
@ -1367,7 +1367,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('I')); // int16
|
||||
oa.write_character(to_char_type('I')); // int16
|
||||
}
|
||||
write_number(static_cast<std::int16_t>(n));
|
||||
}
|
||||
@ -1375,7 +1375,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('l')); // int32
|
||||
oa.write_character(to_char_type('l')); // int32
|
||||
}
|
||||
write_number(static_cast<std::int32_t>(n));
|
||||
}
|
||||
@ -1383,7 +1383,7 @@ class binary_writer
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('L')); // int64
|
||||
oa.write_character(to_char_type('L')); // int64
|
||||
}
|
||||
write_number(static_cast<std::int64_t>(n));
|
||||
}
|
||||
@ -1515,7 +1515,7 @@ class binary_writer
|
||||
std::reverse(vec.begin(), vec.end());
|
||||
}
|
||||
|
||||
oa->write_characters(vec.data(), sizeof(NumberType));
|
||||
oa.write_characters(vec.data(), sizeof(NumberType));
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1564,7 +1564,7 @@ class binary_writer
|
||||
const bool is_little_endian = little_endianess();
|
||||
|
||||
/// the output
|
||||
output_adapter_t<CharType> oa = nullptr;
|
||||
output_adapter_t oa;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@ -14,110 +14,134 @@ namespace nlohmann
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// abstract output adapter interface
|
||||
template<typename CharType> struct output_adapter_protocol
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct output_adapter_impl;
|
||||
|
||||
// Output to a string, append() is faster than insert(str.end(),...) on some compilers,
|
||||
// so it's worth having a special override for it.
|
||||
template<typename StringType>
|
||||
struct string_output_adapter
|
||||
{
|
||||
virtual void write_character(CharType c) = 0;
|
||||
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
||||
virtual ~output_adapter_protocol() = default;
|
||||
};
|
||||
using char_type = typename StringType::value_type;
|
||||
|
||||
/// a type to simplify interfaces
|
||||
template<typename CharType>
|
||||
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
|
||||
string_output_adapter(StringType& dst) : dst_(dst) {}
|
||||
|
||||
/// output adapter for byte vectors
|
||||
template<typename CharType>
|
||||
class output_vector_adapter : public output_adapter_protocol<CharType>
|
||||
{
|
||||
public:
|
||||
explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
|
||||
: v(vec)
|
||||
{}
|
||||
|
||||
void write_character(CharType c) override
|
||||
void write_character(char_type c)
|
||||
{
|
||||
v.push_back(c);
|
||||
dst_.push_back(c);
|
||||
}
|
||||
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
void write_characters(const CharType* s, std::size_t length) override
|
||||
void write_characters(const char_type* str, std::size_t len)
|
||||
{
|
||||
std::copy(s, s + length, std::back_inserter(v));
|
||||
dst_.append(str, len);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<CharType>& v;
|
||||
StringType& dst_;
|
||||
};
|
||||
|
||||
/// output adapter for output streams
|
||||
template<typename CharType>
|
||||
class output_stream_adapter : public output_adapter_protocol<CharType>
|
||||
// Output to an iterator-like object
|
||||
template<class IteratorType>
|
||||
struct iterator_output_adapter
|
||||
{
|
||||
public:
|
||||
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
|
||||
: stream(s)
|
||||
{}
|
||||
using char_type = char; //?????????????????????????
|
||||
|
||||
void write_character(CharType c) override
|
||||
iterator_output_adapter(IteratorType dst) : dst_(dst) {}
|
||||
|
||||
void write_character(char_type c)
|
||||
{
|
||||
stream.put(c);
|
||||
*dst_++ = c;
|
||||
}
|
||||
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
void write_characters(const CharType* s, std::size_t length) override
|
||||
void write_characters(const char_type* str, std::size_t len)
|
||||
{
|
||||
stream.write(s, static_cast<std::streamsize>(length));
|
||||
std::copy(str, str + len, dst_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::basic_ostream<CharType>& stream;
|
||||
IteratorType dst_;
|
||||
};
|
||||
|
||||
/// output adapter for basic_string
|
||||
template<typename CharType, typename StringType = std::basic_string<CharType>>
|
||||
class output_string_adapter : public output_adapter_protocol<CharType>
|
||||
// Output to a stream-like object
|
||||
template<class StreamType>
|
||||
struct stream_output_adapter
|
||||
{
|
||||
public:
|
||||
explicit output_string_adapter(StringType& s) noexcept
|
||||
: str(s)
|
||||
{}
|
||||
using char_type = typename StreamType::char_type;
|
||||
|
||||
void write_character(CharType c) override
|
||||
stream_output_adapter(StreamType& dst) : dst_(dst) {}
|
||||
|
||||
void write_character(char_type c)
|
||||
{
|
||||
str.push_back(c);
|
||||
dst_.put(c);
|
||||
}
|
||||
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
void write_characters(const CharType* s, std::size_t length) override
|
||||
void write_characters(const char_type* str, std::size_t len)
|
||||
{
|
||||
str.append(s, length);
|
||||
dst_.write(str, len);
|
||||
}
|
||||
|
||||
private:
|
||||
StringType& str;
|
||||
StreamType& dst_;
|
||||
};
|
||||
|
||||
template<typename CharType, typename StringType = std::basic_string<CharType>>
|
||||
class output_adapter
|
||||
template<typename T, typename = void>
|
||||
struct is_output_iterator : public std::false_type {};
|
||||
|
||||
template<typename T>
|
||||
struct is_output_iterator<T,
|
||||
typename std::enable_if<
|
||||
std::is_same<
|
||||
typename std::iterator_traits<T>::iterator_category,
|
||||
std::output_iterator_tag>::value
|
||||
>::type> : public std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
constexpr auto has_push_back (int)
|
||||
-> decltype( std::declval<T>().push_back('a'),
|
||||
std::true_type() );
|
||||
|
||||
template <typename>
|
||||
constexpr std::false_type has_push_back (long);
|
||||
|
||||
// If the parameter is a basic_string
|
||||
template<typename CharT, typename Traits, typename Allocator>
|
||||
string_output_adapter<std::basic_string<CharT, Traits, Allocator>> output_adapter(std::basic_string<CharT, Traits, Allocator>& dst)
|
||||
{
|
||||
public:
|
||||
output_adapter(std::vector<CharType>& vec)
|
||||
: oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
|
||||
return string_output_adapter<std::basic_string<CharT, Traits, Allocator>>(dst);
|
||||
}
|
||||
|
||||
output_adapter(std::basic_ostream<CharType>& s)
|
||||
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
|
||||
// If the parameter is an output iterator
|
||||
template<typename IteratorType,
|
||||
typename std::enable_if<
|
||||
is_output_iterator<IteratorType>::value,
|
||||
int>::type = 0>
|
||||
auto output_adapter(IteratorType dst) -> iterator_output_adapter<IteratorType>
|
||||
{
|
||||
return iterator_output_adapter<IteratorType>(std::move(dst));
|
||||
}
|
||||
|
||||
output_adapter(StringType& s)
|
||||
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
|
||||
// Try to extract an output iterator from the parameter
|
||||
template<typename ContainerType,
|
||||
typename std::enable_if<
|
||||
decltype(has_push_back<ContainerType>(0))::value,
|
||||
int>::type = 0>
|
||||
auto output_adapter(ContainerType& dst) -> decltype(output_adapter(std::back_inserter(dst)))
|
||||
{
|
||||
return output_adapter(std::back_inserter(dst));
|
||||
}
|
||||
|
||||
operator output_adapter_t<CharType>()
|
||||
{
|
||||
return oa;
|
||||
}
|
||||
|
||||
private:
|
||||
output_adapter_t<CharType> oa = nullptr;
|
||||
};
|
||||
// If all else fails, treat it as a stream
|
||||
template<typename StreamType, typename std::enable_if<
|
||||
not is_output_iterator<StreamType>::value and
|
||||
not decltype(has_push_back<StreamType>(0))::value,
|
||||
int>::type = 0>
|
||||
stream_output_adapter<StreamType> output_adapter(StreamType& dst)
|
||||
{
|
||||
return stream_output_adapter<StreamType>(dst);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
||||
@ -38,7 +38,7 @@ enum class error_handler_t
|
||||
ignore ///< ignore invalid UTF-8 sequences
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
template<typename BasicJsonType, typename OutputAdapterType>
|
||||
class serializer
|
||||
{
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
@ -46,16 +46,19 @@ class serializer
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using binary_char_t = typename BasicJsonType::binary_t::value_type;
|
||||
using output_adapter_t = OutputAdapterType;
|
||||
|
||||
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
|
||||
static_assert(sizeof(typename output_adapter_t::char_type) == 1, "can only serialize to UTF-8");
|
||||
public:
|
||||
/*!
|
||||
@param[in] s output stream to serialize to
|
||||
@param[in] ichar indentation character to use
|
||||
@param[in] error_handler_ how to react on decoding errors
|
||||
*/
|
||||
serializer(output_adapter_t<char> s, const char ichar,
|
||||
serializer(output_adapter_t s, const char ichar,
|
||||
error_handler_t error_handler_ = error_handler_t::strict)
|
||||
: o(std::move(s))
|
||||
, loc(std::localeconv())
|
||||
@ -107,13 +110,13 @@ class serializer
|
||||
{
|
||||
if (val.m_value.object->empty())
|
||||
{
|
||||
o->write_characters("{}", 2);
|
||||
o.write_characters("{}", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pretty_print)
|
||||
{
|
||||
o->write_characters("{\n", 2);
|
||||
o.write_characters("{\n", 2);
|
||||
|
||||
// variable to hold indentation for recursive calls
|
||||
const auto new_indent = current_indent + indent_step;
|
||||
@ -126,51 +129,51 @@ class serializer
|
||||
auto i = val.m_value.object->cbegin();
|
||||
for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
||||
{
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o->write_character('\"');
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
o->write_characters("\": ", 3);
|
||||
o.write_characters("\": ", 3);
|
||||
dump(i->second, true, ensure_ascii, indent_step, new_indent);
|
||||
o->write_characters(",\n", 2);
|
||||
o.write_characters(",\n", 2);
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
assert(std::next(i) == val.m_value.object->cend());
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o->write_character('\"');
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
o->write_characters("\": ", 3);
|
||||
o.write_characters("\": ", 3);
|
||||
dump(i->second, true, ensure_ascii, indent_step, new_indent);
|
||||
|
||||
o->write_character('\n');
|
||||
o->write_characters(indent_string.c_str(), current_indent);
|
||||
o->write_character('}');
|
||||
o.write_character('\n');
|
||||
o.write_characters(indent_string.c_str(), current_indent);
|
||||
o.write_character('}');
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_character('{');
|
||||
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)
|
||||
{
|
||||
o->write_character('\"');
|
||||
o.write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
o->write_characters("\":", 2);
|
||||
o.write_characters("\":", 2);
|
||||
dump(i->second, false, ensure_ascii, indent_step, current_indent);
|
||||
o->write_character(',');
|
||||
o.write_character(',');
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
assert(std::next(i) == val.m_value.object->cend());
|
||||
o->write_character('\"');
|
||||
o.write_character('\"');
|
||||
dump_escaped(i->first, ensure_ascii);
|
||||
o->write_characters("\":", 2);
|
||||
o.write_characters("\":", 2);
|
||||
dump(i->second, false, ensure_ascii, indent_step, current_indent);
|
||||
|
||||
o->write_character('}');
|
||||
o.write_character('}');
|
||||
}
|
||||
|
||||
return;
|
||||
@ -180,13 +183,13 @@ class serializer
|
||||
{
|
||||
if (val.m_value.array->empty())
|
||||
{
|
||||
o->write_characters("[]", 2);
|
||||
o.write_characters("[]", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pretty_print)
|
||||
{
|
||||
o->write_characters("[\n", 2);
|
||||
o.write_characters("[\n", 2);
|
||||
|
||||
// variable to hold indentation for recursive calls
|
||||
const auto new_indent = current_indent + indent_step;
|
||||
@ -199,37 +202,37 @@ class serializer
|
||||
for (auto i = val.m_value.array->cbegin();
|
||||
i != val.m_value.array->cend() - 1; ++i)
|
||||
{
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
dump(*i, true, ensure_ascii, indent_step, new_indent);
|
||||
o->write_characters(",\n", 2);
|
||||
o.write_characters(",\n", 2);
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
|
||||
|
||||
o->write_character('\n');
|
||||
o->write_characters(indent_string.c_str(), current_indent);
|
||||
o->write_character(']');
|
||||
o.write_character('\n');
|
||||
o.write_characters(indent_string.c_str(), current_indent);
|
||||
o.write_character(']');
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_character('[');
|
||||
o.write_character('[');
|
||||
|
||||
// first n-1 elements
|
||||
for (auto i = val.m_value.array->cbegin();
|
||||
i != val.m_value.array->cend() - 1; ++i)
|
||||
{
|
||||
dump(*i, false, ensure_ascii, indent_step, current_indent);
|
||||
o->write_character(',');
|
||||
o.write_character(',');
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
|
||||
|
||||
o->write_character(']');
|
||||
o.write_character(']');
|
||||
}
|
||||
|
||||
return;
|
||||
@ -237,9 +240,9 @@ class serializer
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
o->write_character('\"');
|
||||
o.write_character('\"');
|
||||
dump_escaped(*val.m_value.string, ensure_ascii);
|
||||
o->write_character('\"');
|
||||
o.write_character('\"');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -247,7 +250,7 @@ class serializer
|
||||
{
|
||||
if (pretty_print)
|
||||
{
|
||||
o->write_characters("{\n", 2);
|
||||
o.write_characters("{\n", 2);
|
||||
|
||||
// variable to hold indentation for recursive calls
|
||||
const auto new_indent = current_indent + indent_step;
|
||||
@ -256,9 +259,9 @@ class serializer
|
||||
indent_string.resize(indent_string.size() * 2, ' ');
|
||||
}
|
||||
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
|
||||
o->write_characters("\"bytes\": [", 10);
|
||||
o.write_characters("\"bytes\": [", 10);
|
||||
|
||||
if (not val.m_value.binary->empty())
|
||||
{
|
||||
@ -266,30 +269,30 @@ class serializer
|
||||
i != val.m_value.binary->cend() - 1; ++i)
|
||||
{
|
||||
dump_integer(*i);
|
||||
o->write_characters(", ", 2);
|
||||
o.write_characters(", ", 2);
|
||||
}
|
||||
dump_integer(val.m_value.binary->back());
|
||||
}
|
||||
|
||||
o->write_characters("],\n", 3);
|
||||
o->write_characters(indent_string.c_str(), new_indent);
|
||||
o.write_characters("],\n", 3);
|
||||
o.write_characters(indent_string.c_str(), new_indent);
|
||||
|
||||
o->write_characters("\"subtype\": ", 11);
|
||||
o.write_characters("\"subtype\": ", 11);
|
||||
if (val.m_value.binary->has_subtype())
|
||||
{
|
||||
dump_integer(val.m_value.binary->subtype());
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_characters("null", 4);
|
||||
o.write_characters("null", 4);
|
||||
}
|
||||
o->write_character('\n');
|
||||
o->write_characters(indent_string.c_str(), current_indent);
|
||||
o->write_character('}');
|
||||
o.write_character('\n');
|
||||
o.write_characters(indent_string.c_str(), current_indent);
|
||||
o.write_character('}');
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_characters("{\"bytes\":[", 10);
|
||||
o.write_characters("{\"bytes\":[", 10);
|
||||
|
||||
if (not val.m_value.binary->empty())
|
||||
{
|
||||
@ -297,20 +300,20 @@ class serializer
|
||||
i != val.m_value.binary->cend() - 1; ++i)
|
||||
{
|
||||
dump_integer(*i);
|
||||
o->write_character(',');
|
||||
o.write_character(',');
|
||||
}
|
||||
dump_integer(val.m_value.binary->back());
|
||||
}
|
||||
|
||||
o->write_characters("],\"subtype\":", 12);
|
||||
o.write_characters("],\"subtype\":", 12);
|
||||
if (val.m_value.binary->has_subtype())
|
||||
{
|
||||
dump_integer(val.m_value.binary->subtype());
|
||||
o->write_character('}');
|
||||
o.write_character('}');
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_characters("null}", 5);
|
||||
o.write_characters("null}", 5);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -320,11 +323,11 @@ class serializer
|
||||
{
|
||||
if (val.m_value.boolean)
|
||||
{
|
||||
o->write_characters("true", 4);
|
||||
o.write_characters("true", 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_characters("false", 5);
|
||||
o.write_characters("false", 5);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -349,13 +352,13 @@ class serializer
|
||||
|
||||
case value_t::discarded:
|
||||
{
|
||||
o->write_characters("<discarded>", 11);
|
||||
o.write_characters("<discarded>", 11);
|
||||
return;
|
||||
}
|
||||
|
||||
case value_t::null:
|
||||
{
|
||||
o->write_characters("null", 4);
|
||||
o.write_characters("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -483,7 +486,7 @@ class serializer
|
||||
// written ("\uxxxx\uxxxx\0") for one code point
|
||||
if (string_buffer.size() - bytes < 13)
|
||||
{
|
||||
o->write_characters(string_buffer.data(), bytes);
|
||||
o.write_characters(string_buffer.data(), bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
@ -534,9 +537,9 @@ class serializer
|
||||
}
|
||||
else
|
||||
{
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, output_adapter_t>::to_char_type('\xEF');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, output_adapter_t>::to_char_type('\xBF');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, output_adapter_t>::to_char_type('\xBD');
|
||||
}
|
||||
|
||||
// write buffer and reset index; there must be 13 bytes
|
||||
@ -544,7 +547,7 @@ class serializer
|
||||
// written ("\uxxxx\uxxxx\0") for one code point
|
||||
if (string_buffer.size() - bytes < 13)
|
||||
{
|
||||
o->write_characters(string_buffer.data(), bytes);
|
||||
o.write_characters(string_buffer.data(), bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
@ -583,7 +586,7 @@ class serializer
|
||||
// write buffer
|
||||
if (bytes > 0)
|
||||
{
|
||||
o->write_characters(string_buffer.data(), bytes);
|
||||
o.write_characters(string_buffer.data(), bytes);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -601,22 +604,22 @@ class serializer
|
||||
case error_handler_t::ignore:
|
||||
{
|
||||
// write all accepted bytes
|
||||
o->write_characters(string_buffer.data(), bytes_after_last_accept);
|
||||
o.write_characters(string_buffer.data(), bytes_after_last_accept);
|
||||
break;
|
||||
}
|
||||
|
||||
case error_handler_t::replace:
|
||||
{
|
||||
// write all accepted bytes
|
||||
o->write_characters(string_buffer.data(), bytes_after_last_accept);
|
||||
o.write_characters(string_buffer.data(), bytes_after_last_accept);
|
||||
// add a replacement character
|
||||
if (ensure_ascii)
|
||||
{
|
||||
o->write_characters("\\ufffd", 6);
|
||||
o.write_characters("\\ufffd", 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
o->write_characters("\xEF\xBF\xBD", 3);
|
||||
o.write_characters("\xEF\xBF\xBD", 3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -696,7 +699,7 @@ class serializer
|
||||
// special case for "0"
|
||||
if (x == 0)
|
||||
{
|
||||
o->write_character('0');
|
||||
o.write_character('0');
|
||||
return;
|
||||
}
|
||||
|
||||
@ -750,7 +753,7 @@ class serializer
|
||||
*(--buffer_ptr) = static_cast<char>('0' + abs_value);
|
||||
}
|
||||
|
||||
o->write_characters(number_buffer.data(), n_chars);
|
||||
o.write_characters(number_buffer.data(), n_chars);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -766,7 +769,7 @@ class serializer
|
||||
// NaN / inf
|
||||
if (not std::isfinite(x))
|
||||
{
|
||||
o->write_characters("null", 4);
|
||||
o.write_characters("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -787,7 +790,7 @@ class serializer
|
||||
char* begin = number_buffer.data();
|
||||
char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
|
||||
|
||||
o->write_characters(begin, static_cast<size_t>(end - begin));
|
||||
o.write_characters(begin, static_cast<size_t>(end - begin));
|
||||
}
|
||||
|
||||
void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
|
||||
@ -823,7 +826,7 @@ class serializer
|
||||
}
|
||||
}
|
||||
|
||||
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
|
||||
o.write_characters(number_buffer.data(), static_cast<std::size_t>(len));
|
||||
|
||||
// determine if need to append ".0"
|
||||
const bool value_is_int_like =
|
||||
@ -835,7 +838,7 @@ class serializer
|
||||
|
||||
if (value_is_int_like)
|
||||
{
|
||||
o->write_characters(".0", 2);
|
||||
o.write_characters(".0", 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -922,7 +925,7 @@ class serializer
|
||||
|
||||
private:
|
||||
/// the output of the serializer
|
||||
output_adapter_t<char> o = nullptr;
|
||||
output_adapter_t o;
|
||||
|
||||
/// a (hopefully) large enough character buffer
|
||||
std::array<char, 64> number_buffer{{}};
|
||||
|
||||
@ -174,7 +174,8 @@ class basic_json
|
||||
|
||||
template<typename BasicJsonType, typename InputType>
|
||||
friend class ::nlohmann::detail::parser;
|
||||
friend ::nlohmann::detail::serializer<basic_json>;
|
||||
template<typename BasicJsonType, typename OutputAdapterType>
|
||||
friend class ::nlohmann::detail::serializer;
|
||||
template<typename BasicJsonType>
|
||||
friend class ::nlohmann::detail::iter_impl;
|
||||
template<typename BasicJsonType, typename CharType>
|
||||
@ -211,14 +212,12 @@ class basic_json
|
||||
using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
|
||||
template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
|
||||
|
||||
template<typename CharType>
|
||||
using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
|
||||
|
||||
template<typename InputType>
|
||||
using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
|
||||
template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
|
||||
|
||||
using serializer = ::nlohmann::detail::serializer<basic_json>;
|
||||
template<typename OutputAdapterType>
|
||||
using serializer = ::nlohmann::detail::serializer<basic_json, OutputAdapterType>;
|
||||
|
||||
public:
|
||||
using value_t = detail::value_t;
|
||||
@ -2269,7 +2268,23 @@ class basic_json
|
||||
const error_handler_t error_handler = error_handler_t::strict) const
|
||||
{
|
||||
string_t result;
|
||||
serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
|
||||
|
||||
dump_to(result, indent, indent_char, ensure_ascii, error_handler);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename OutputType>
|
||||
void dump_to(OutputType&& dst,
|
||||
const int indent = -1,
|
||||
const char indent_char = ' ',
|
||||
const bool ensure_ascii = false,
|
||||
const error_handler_t error_handler = error_handler_t::strict) const
|
||||
{
|
||||
auto oa = detail::output_adapter(std::forward<OutputType>(dst));
|
||||
using serializer_t = serializer<decltype(oa)>;
|
||||
serializer<decltype(oa)> s(std::move(oa), indent_char, error_handler);
|
||||
|
||||
if (indent >= 0)
|
||||
{
|
||||
@ -2279,10 +2294,7 @@ class basic_json
|
||||
{
|
||||
s.dump(*this, false, ensure_ascii, 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the type of the JSON value (explicit)
|
||||
|
||||
@ -6516,9 +6528,7 @@ class basic_json
|
||||
// reset width to 0 for subsequent calls to this stream
|
||||
o.width(0);
|
||||
|
||||
// do the actual serialization
|
||||
serializer s(detail::output_adapter<char>(o), o.fill());
|
||||
s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
|
||||
j.dump_to(o, indentation, ' ', false);
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -6976,14 +6986,11 @@ class basic_json
|
||||
return result;
|
||||
}
|
||||
|
||||
static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
|
||||
template<typename OutputType>
|
||||
static void to_cbor(const basic_json& j, OutputType&& o)
|
||||
{
|
||||
binary_writer<uint8_t>(o).write_cbor(j);
|
||||
}
|
||||
|
||||
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
|
||||
{
|
||||
binary_writer<char>(o).write_cbor(j);
|
||||
auto oa = detail::output_adapter(std::forward<OutputType>(o));
|
||||
binary_writer<decltype(oa)>(std::move(oa)).write_cbor(j);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -7073,15 +7080,13 @@ class basic_json
|
||||
return result;
|
||||
}
|
||||
|
||||
static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
|
||||
template<typename OutputType>
|
||||
static void to_msgpack(const basic_json& j, OutputType&& o)
|
||||
{
|
||||
binary_writer<uint8_t>(o).write_msgpack(j);
|
||||
auto oa = detail::output_adapter(std::forward<OutputType>(o));
|
||||
binary_writer<decltype(oa)>(std::move(oa)).write_msgpack(j);
|
||||
}
|
||||
|
||||
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
|
||||
{
|
||||
binary_writer<char>(o).write_msgpack(j);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a UBJSON serialization of a given JSON value
|
||||
@ -7174,23 +7179,18 @@ class basic_json
|
||||
const bool use_type = false)
|
||||
{
|
||||
std::vector<uint8_t> result;
|
||||
to_ubjson(j, result, use_size, use_type);
|
||||
to_ubjson(j, std::back_inserter(result), use_size, use_type);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
|
||||
template<typename OutputType>
|
||||
static void to_ubjson(const basic_json& j, OutputType&& o,
|
||||
const bool use_size = false, const bool use_type = false)
|
||||
{
|
||||
binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
|
||||
auto oa = detail::output_adapter(std::forward<OutputType>(o));
|
||||
binary_writer<decltype(oa)>(std::move(oa)).write_ubjson(j, use_size, use_type);
|
||||
}
|
||||
|
||||
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
|
||||
const bool use_size = false, const bool use_type = false)
|
||||
{
|
||||
binary_writer<char>(o).write_ubjson(j, use_size, use_type);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
@brief Serializes the given JSON object `j` to BSON and returns a vector
|
||||
containing the corresponding BSON-representation.
|
||||
@ -7262,17 +7262,11 @@ class basic_json
|
||||
@pre The input `j` shall be an object: `j.is_object() == true`
|
||||
@sa @ref to_bson(const basic_json&)
|
||||
*/
|
||||
static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
|
||||
template<typename OutputType>
|
||||
static void to_bson(const basic_json& j, OutputType&& o)
|
||||
{
|
||||
binary_writer<uint8_t>(o).write_bson(j);
|
||||
}
|
||||
|
||||
/*!
|
||||
@copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
|
||||
*/
|
||||
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
|
||||
{
|
||||
binary_writer<char>(o).write_bson(j);
|
||||
auto oa = detail::output_adapter(std::forward<OutputType>(o));
|
||||
binary_writer<decltype(oa)>(std::move(oa)).write_bson(j);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1587,7 +1587,7 @@ TEST_CASE("parser class")
|
||||
CHECK (j_filtered1.size() == 2);
|
||||
CHECK (j_filtered1 == json({1, {{"qux", "baz"}}}));
|
||||
|
||||
json j_filtered2 = json::parse(structured_array, [](int, json::parse_event_t e, const json & /*parsed*/)
|
||||
json j_filtered2 = json::parse(structured_array, [](int, json::parse_event_t e, const json& /*parsed*/)
|
||||
{
|
||||
if (e == json::parse_event_t::object_end)
|
||||
{
|
||||
|
||||
@ -42,7 +42,8 @@ void check_escaped(const char* original, const char* escaped = "", const bool en
|
||||
void check_escaped(const char* original, const char* escaped, const bool ensure_ascii)
|
||||
{
|
||||
std::stringstream ss;
|
||||
json::serializer s(nlohmann::detail::output_adapter<char>(ss), ' ');
|
||||
auto oa = nlohmann::detail::output_adapter(ss);
|
||||
json::serializer<decltype(oa)> s(std::move(oa), ' ');
|
||||
s.dump_escaped(original, ensure_ascii);
|
||||
CHECK(ss.str() == escaped);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user