🔨 small improvements

This commit is contained in:
Niels Lohmann 2018-10-27 18:31:03 +02:00
parent 037e93f5c0
commit 4e765596f7
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
6 changed files with 339 additions and 309 deletions

View file

@ -68,6 +68,10 @@ class binary_reader
switch (format) switch (format)
{ {
case input_format_t::bson:
result = parse_bson_internal();
break;
case input_format_t::cbor: case input_format_t::cbor:
result = parse_cbor_internal(); result = parse_cbor_internal();
break; break;
@ -80,10 +84,6 @@ class binary_reader
result = parse_ubjson_internal(); result = parse_ubjson_internal();
break; break;
case input_format_t::bson:
result = parse_bson_internal();
break;
// LCOV_EXCL_START // LCOV_EXCL_START
default: default:
assert(false); assert(false);
@ -135,8 +135,8 @@ class binary_reader
*/ */
bool parse_bson_internal() bool parse_bson_internal()
{ {
std::int32_t documentSize; std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, documentSize); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
{ {
@ -315,8 +315,8 @@ class binary_reader
*/ */
bool parse_bson_array() bool parse_bson_array()
{ {
std::int32_t documentSize; std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, documentSize); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
{ {

View file

@ -92,7 +92,7 @@ class input_stream_adapter : public input_adapter_protocol
class input_buffer_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol
{ {
public: public:
input_buffer_adapter(const char* b, const std::size_t l) input_buffer_adapter(const char* b, const std::size_t l) noexcept
: cursor(b), limit(b + l) : cursor(b), limit(b + l)
{} {}
@ -240,7 +240,9 @@ template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol class wide_string_input_adapter : public input_adapter_protocol
{ {
public: public:
explicit wide_string_input_adapter(const WideStringType& w) : str(w) {} explicit wide_string_input_adapter(const WideStringType& w) noexcept
: str(w)
{}
std::char_traits<char>::int_type get_character() noexcept override std::char_traits<char>::int_type get_character() noexcept override
{ {

View file

@ -23,6 +23,8 @@ namespace detail
template<typename BasicJsonType, typename CharType> template<typename BasicJsonType, typename CharType>
class binary_writer class binary_writer
{ {
using string_t = typename BasicJsonType::string_t;
public: public:
/*! /*!
@brief create a binary writer @brief create a binary writer
@ -48,11 +50,6 @@ class binary_writer
break; break;
} }
case value_t::discarded:
{
break;
}
default: default:
{ {
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
@ -69,15 +66,15 @@ class binary_writer
{ {
case value_t::null: case value_t::null:
{ {
oa->write_character(static_cast<CharType>(0xF6)); oa->write_character(to_char_type(0xF6));
break; break;
} }
case value_t::boolean: case value_t::boolean:
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xF5) ? to_char_type(0xF5)
: static_cast<CharType>(0xF4)); : to_char_type(0xF4));
break; break;
} }
@ -94,22 +91,22 @@ class binary_writer
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x18)); oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x19)); oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x1A)); oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x1B)); oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
} }
@ -124,22 +121,22 @@ class binary_writer
} }
else if (positive_number <= (std::numeric_limits<uint8_t>::max)()) else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x38)); oa->write_character(to_char_type(0x38));
write_number(static_cast<uint8_t>(positive_number)); write_number(static_cast<uint8_t>(positive_number));
} }
else if (positive_number <= (std::numeric_limits<uint16_t>::max)()) else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x39)); oa->write_character(to_char_type(0x39));
write_number(static_cast<uint16_t>(positive_number)); write_number(static_cast<uint16_t>(positive_number));
} }
else if (positive_number <= (std::numeric_limits<uint32_t>::max)()) else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x3A)); oa->write_character(to_char_type(0x3A));
write_number(static_cast<uint32_t>(positive_number)); write_number(static_cast<uint32_t>(positive_number));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x3B)); oa->write_character(to_char_type(0x3B));
write_number(static_cast<uint64_t>(positive_number)); write_number(static_cast<uint64_t>(positive_number));
} }
} }
@ -154,22 +151,22 @@ class binary_writer
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x18)); oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_unsigned)); write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x19)); oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_unsigned)); write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x1A)); oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_unsigned)); write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x1B)); oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_unsigned)); write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
} }
break; break;
@ -192,23 +189,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x78)); oa->write_character(to_char_type(0x78));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x79)); oa->write_character(to_char_type(0x79));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x7A)); oa->write_character(to_char_type(0x7A));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x7B)); oa->write_character(to_char_type(0x7B));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -230,23 +227,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x98)); oa->write_character(to_char_type(0x98));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x99)); oa->write_character(to_char_type(0x99));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x9A)); oa->write_character(to_char_type(0x9A));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x9B)); oa->write_character(to_char_type(0x9B));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -269,23 +266,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xB8)); oa->write_character(to_char_type(0xB8));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xB9)); oa->write_character(to_char_type(0xB9));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xBA)); oa->write_character(to_char_type(0xBA));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xBB)); oa->write_character(to_char_type(0xBB));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -313,15 +310,15 @@ class binary_writer
{ {
case value_t::null: // nil case value_t::null: // nil
{ {
oa->write_character(static_cast<CharType>(0xC0)); oa->write_character(to_char_type(0xC0));
break; break;
} }
case value_t::boolean: // true and false case value_t::boolean: // true and false
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xC3) ? to_char_type(0xC3)
: static_cast<CharType>(0xC2)); : to_char_type(0xC2));
break; break;
} }
@ -340,25 +337,25 @@ class binary_writer
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
// uint 8 // uint 8
oa->write_character(static_cast<CharType>(0xCC)); oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
// uint 16 // uint 16
oa->write_character(static_cast<CharType>(0xCD)); oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
// uint 32 // uint 32
oa->write_character(static_cast<CharType>(0xCE)); oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
{ {
// uint 64 // uint 64
oa->write_character(static_cast<CharType>(0xCF)); oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
} }
@ -373,28 +370,28 @@ class binary_writer
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
{ {
// int 8 // int 8
oa->write_character(static_cast<CharType>(0xD0)); oa->write_character(to_char_type(0xD0));
write_number(static_cast<int8_t>(j.m_value.number_integer)); write_number(static_cast<int8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
{ {
// int 16 // int 16
oa->write_character(static_cast<CharType>(0xD1)); oa->write_character(to_char_type(0xD1));
write_number(static_cast<int16_t>(j.m_value.number_integer)); write_number(static_cast<int16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
{ {
// int 32 // int 32
oa->write_character(static_cast<CharType>(0xD2)); oa->write_character(to_char_type(0xD2));
write_number(static_cast<int32_t>(j.m_value.number_integer)); write_number(static_cast<int32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
{ {
// int 64 // int 64
oa->write_character(static_cast<CharType>(0xD3)); oa->write_character(to_char_type(0xD3));
write_number(static_cast<int64_t>(j.m_value.number_integer)); write_number(static_cast<int64_t>(j.m_value.number_integer));
} }
} }
@ -411,25 +408,25 @@ class binary_writer
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
// uint 8 // uint 8
oa->write_character(static_cast<CharType>(0xCC)); oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
// uint 16 // uint 16
oa->write_character(static_cast<CharType>(0xCD)); oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
// uint 32 // uint 32
oa->write_character(static_cast<CharType>(0xCE)); oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
{ {
// uint 64 // uint 64
oa->write_character(static_cast<CharType>(0xCF)); oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
break; break;
@ -454,19 +451,19 @@ class binary_writer
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
// str 8 // str 8
oa->write_character(static_cast<CharType>(0xD9)); oa->write_character(to_char_type(0xD9));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// str 16 // str 16
oa->write_character(static_cast<CharType>(0xDA)); oa->write_character(to_char_type(0xDA));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// str 32 // str 32
oa->write_character(static_cast<CharType>(0xDB)); oa->write_character(to_char_type(0xDB));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -489,13 +486,13 @@ class binary_writer
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// array 16 // array 16
oa->write_character(static_cast<CharType>(0xDC)); oa->write_character(to_char_type(0xDC));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// array 32 // array 32
oa->write_character(static_cast<CharType>(0xDD)); oa->write_character(to_char_type(0xDD));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -519,13 +516,13 @@ class binary_writer
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// map 16 // map 16
oa->write_character(static_cast<CharType>(0xDE)); oa->write_character(to_char_type(0xDE));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// map 32 // map 32
oa->write_character(static_cast<CharType>(0xDF)); oa->write_character(to_char_type(0xDF));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -558,7 +555,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('Z')); oa->write_character(to_char_type('Z'));
} }
break; break;
} }
@ -568,8 +565,8 @@ class binary_writer
if (add_prefix) if (add_prefix)
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>('T') ? to_char_type('T')
: static_cast<CharType>('F')); : to_char_type('F'));
} }
break; break;
} }
@ -596,7 +593,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('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);
oa->write_characters( oa->write_characters(
@ -609,7 +606,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('[')); oa->write_character(to_char_type('['));
} }
bool prefix_required = true; bool prefix_required = true;
@ -626,14 +623,14 @@ class binary_writer
if (same_prefix) if (same_prefix)
{ {
prefix_required = false; prefix_required = false;
oa->write_character(static_cast<CharType>('$')); oa->write_character(to_char_type('$'));
oa->write_character(first_prefix); oa->write_character(first_prefix);
} }
} }
if (use_count) if (use_count)
{ {
oa->write_character(static_cast<CharType>('#')); 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);
} }
@ -644,7 +641,7 @@ class binary_writer
if (not use_count) if (not use_count)
{ {
oa->write_character(static_cast<CharType>(']')); oa->write_character(to_char_type(']'));
} }
break; break;
@ -654,7 +651,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('{')); oa->write_character(to_char_type('{'));
} }
bool prefix_required = true; bool prefix_required = true;
@ -671,14 +668,14 @@ class binary_writer
if (same_prefix) if (same_prefix)
{ {
prefix_required = false; prefix_required = false;
oa->write_character(static_cast<CharType>('$')); oa->write_character(to_char_type('$'));
oa->write_character(first_prefix); oa->write_character(first_prefix);
} }
} }
if (use_count) if (use_count)
{ {
oa->write_character(static_cast<CharType>('#')); 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);
} }
@ -693,7 +690,7 @@ class binary_writer
if (not use_count) if (not use_count)
{ {
oa->write_character(static_cast<CharType>('}')); oa->write_character(to_char_type('}'));
} }
break; break;
@ -713,9 +710,9 @@ class binary_writer
@return The size of a BSON document entry header, including the id marker @return The size of a BSON document entry header, including the id marker
and the entry name size (and its null-terminator). and the entry name size (and its null-terminator).
*/ */
static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name) static std::size_t calc_bson_entry_header_size(const string_t& name)
{ {
const auto it = name.find(static_cast<typename BasicJsonType::string_t::value_type>(0)); const auto it = name.find(static_cast<typename string_t::value_type>(0));
if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos)) if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
{ {
JSON_THROW(out_of_range::create(409, JSON_THROW(out_of_range::create(409,
@ -728,10 +725,10 @@ class binary_writer
/*! /*!
@brief Writes the given @a element_type and @a name to the output adapter @brief Writes the given @a element_type and @a name to the output adapter
*/ */
void write_bson_entry_header(const typename BasicJsonType::string_t& name, void write_bson_entry_header(const string_t& name,
std::uint8_t element_type) const std::uint8_t element_type)
{ {
oa->write_character(static_cast<CharType>(element_type)); // boolean oa->write_character(to_char_type(element_type)); // boolean
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(name.c_str()), reinterpret_cast<const CharType*>(name.c_str()),
name.size() + 1u); name.size() + 1u);
@ -740,17 +737,17 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and boolean value @a value @brief Writes a BSON element with key @a name and boolean value @a value
*/ */
void write_bson_boolean(const typename BasicJsonType::string_t& name, void write_bson_boolean(const string_t& name,
const bool value) const bool value)
{ {
write_bson_entry_header(name, 0x08); write_bson_entry_header(name, 0x08);
oa->write_character(value ? static_cast<CharType>(0x01) : static_cast<CharType>(0x00)); oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
} }
/*! /*!
@brief Writes a BSON element with key @a name and double value @a value @brief Writes a BSON element with key @a name and double value @a value
*/ */
void write_bson_double(const typename BasicJsonType::string_t& name, void write_bson_double(const string_t& name,
const double value) const double value)
{ {
write_bson_entry_header(name, 0x01); write_bson_entry_header(name, 0x01);
@ -760,7 +757,7 @@ class binary_writer
/*! /*!
@return The size of the BSON-encoded string in @a value @return The size of the BSON-encoded string in @a value
*/ */
static std::size_t calc_bson_string_size(const typename BasicJsonType::string_t& value) static std::size_t calc_bson_string_size(const string_t& value)
{ {
return sizeof(std::int32_t) + value.size() + 1ul; return sizeof(std::int32_t) + value.size() + 1ul;
} }
@ -768,8 +765,8 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and string value @a value @brief Writes a BSON element with key @a name and string value @a value
*/ */
void write_bson_string(const typename BasicJsonType::string_t& name, void write_bson_string(const string_t& name,
const typename BasicJsonType::string_t& value) const string_t& value)
{ {
write_bson_entry_header(name, 0x02); write_bson_entry_header(name, 0x02);
@ -782,7 +779,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and null value @brief Writes a BSON element with key @a name and null value
*/ */
void write_bson_null(const typename BasicJsonType::string_t& name) void write_bson_null(const string_t& name)
{ {
write_bson_entry_header(name, 0x0A); write_bson_entry_header(name, 0x0A);
} }
@ -805,7 +802,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and integer @a value @brief Writes a BSON element with key @a name and integer @a value
*/ */
void write_bson_integer(const typename BasicJsonType::string_t& name, void write_bson_integer(const string_t& name,
const std::int64_t value) const std::int64_t value)
{ {
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()) if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
@ -823,45 +820,39 @@ class binary_writer
/*! /*!
@return The size of the BSON-encoded unsigned integer in @a j @return The size of the BSON-encoded unsigned integer in @a j
*/ */
static std::size_t calc_bson_unsigned_size(const std::uint64_t value) static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
{ {
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ ? sizeof(std::int32_t)
return sizeof(std::int32_t); : sizeof(std::int64_t);
}
else
{
return sizeof(std::int64_t);
}
} }
/*! /*!
@brief Writes a BSON element with key @a name and unsigned @a value @brief Writes a BSON element with key @a name and unsigned @a value
*/ */
void write_bson_unsigned(const typename BasicJsonType::string_t& name, void write_bson_unsigned(const string_t& name,
const std::uint64_t value) const std::uint64_t value)
{ {
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ {
write_bson_entry_header(name, 0x10); // int32 write_bson_entry_header(name, 0x10 /* int32 */);
write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
} }
else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{ {
write_bson_entry_header(name, 0x12); // int64 write_bson_entry_header(name, 0x12 /* int64 */);
write_number<std::int64_t, true>(static_cast<std::int64_t>(value)); write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
} }
else else
{ {
JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(value))); JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
} }
} }
/*! /*!
@brief Writes a BSON element with key @a name and object @a value @brief Writes a BSON element with key @a name and object @a value
*/ */
void write_bson_object_entry(const typename BasicJsonType::string_t& name, void write_bson_object_entry(const string_t& name,
const typename BasicJsonType::object_t& value) const typename BasicJsonType::object_t& value)
{ {
write_bson_entry_header(name, 0x03); // object write_bson_entry_header(name, 0x03); // object
@ -887,7 +878,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and array @a value @brief Writes a BSON element with key @a name and array @a value
*/ */
void write_bson_array(const typename BasicJsonType::string_t& name, void write_bson_array(const string_t& name,
const typename BasicJsonType::array_t& value) const typename BasicJsonType::array_t& value)
{ {
write_bson_entry_header(name, 0x04); // array write_bson_entry_header(name, 0x04); // array
@ -900,22 +891,19 @@ class binary_writer
write_bson_element(std::to_string(array_index++), el); write_bson_element(std::to_string(array_index++), el);
} }
oa->write_character(static_cast<CharType>(0x00)); oa->write_character(to_char_type(0x00));
} }
/*! /*!
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
@return The calculated size for the BSON document entry for @a j with the given @a name. @return The calculated size for the BSON document entry for @a j with the given @a name.
*/ */
static std::size_t calc_bson_element_size(const typename BasicJsonType::string_t& name, static std::size_t calc_bson_element_size(const string_t& name,
const BasicJsonType& j) const BasicJsonType& j)
{ {
const auto header_size = calc_bson_entry_header_size(name); const auto header_size = calc_bson_entry_header_size(name);
switch (j.type()) switch (j.type())
{ {
case value_t::discarded:
return 0ul;
case value_t::object: case value_t::object:
return header_size + calc_bson_object_size(*j.m_value.object); return header_size + calc_bson_object_size(*j.m_value.object);
@ -955,14 +943,11 @@ class binary_writer
current BSON document current BSON document
@return The size of the BSON entry @return The size of the BSON entry
*/ */
void write_bson_element(const typename BasicJsonType::string_t& name, void write_bson_element(const string_t& name,
const BasicJsonType& j) const BasicJsonType& j)
{ {
switch (j.type()) switch (j.type())
{ {
case value_t::discarded:
return;
case value_t::object: case value_t::object:
return write_bson_object_entry(name, *j.m_value.object); return write_bson_object_entry(name, *j.m_value.object);
@ -1003,12 +988,11 @@ class binary_writer
*/ */
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
{ {
std::size_t document_size = 0; std::size_t document_size = std::accumulate(value.begin(), value.end(), 0,
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
for (const auto& el : value)
{ {
document_size += calc_bson_element_size(el.first, el.second); return result += calc_bson_element_size(el.first, el.second);
} });
return sizeof(std::int32_t) + document_size + 1ul; return sizeof(std::int32_t) + document_size + 1ul;
} }
@ -1026,7 +1010,7 @@ class binary_writer
write_bson_element(el.first, el.second); write_bson_element(el.first, el.second);
} }
oa->write_character(static_cast<CharType>(0x00)); oa->write_character(to_char_type(0x00));
} }
////////// //////////
@ -1035,12 +1019,12 @@ class binary_writer
static constexpr CharType get_cbor_float_prefix(float /*unused*/) static constexpr CharType get_cbor_float_prefix(float /*unused*/)
{ {
return static_cast<CharType>(0xFA); // Single-Precision Float return to_char_type(0xFA); // Single-Precision Float
} }
static constexpr CharType get_cbor_float_prefix(double /*unused*/) static constexpr CharType get_cbor_float_prefix(double /*unused*/)
{ {
return static_cast<CharType>(0xFB); // Double-Precision Float return to_char_type(0xFB); // Double-Precision Float
} }
///////////// /////////////
@ -1049,12 +1033,12 @@ class binary_writer
static constexpr CharType get_msgpack_float_prefix(float /*unused*/) static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
{ {
return static_cast<CharType>(0xCA); // float 32 return to_char_type(0xCA); // float 32
} }
static constexpr CharType get_msgpack_float_prefix(double /*unused*/) static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
{ {
return static_cast<CharType>(0xCB); // float 64 return to_char_type(0xCB); // float 64
} }
//////////// ////////////
@ -1084,7 +1068,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -1092,7 +1076,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -1100,7 +1084,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<int16_t>(n)); write_number(static_cast<int16_t>(n));
} }
@ -1108,7 +1092,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<int32_t>(n)); write_number(static_cast<int32_t>(n));
} }
@ -1116,7 +1100,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<int64_t>(n)); write_number(static_cast<int64_t>(n));
} }
@ -1137,7 +1121,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<int8_t>(n)); write_number(static_cast<int8_t>(n));
} }
@ -1145,7 +1129,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -1153,7 +1137,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<int16_t>(n)); write_number(static_cast<int16_t>(n));
} }
@ -1161,7 +1145,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<int32_t>(n)); write_number(static_cast<int32_t>(n));
} }
@ -1169,7 +1153,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<int64_t>(n)); write_number(static_cast<int64_t>(n));
} }
@ -1304,6 +1288,46 @@ class binary_writer
oa->write_characters(vec.data(), sizeof(NumberType)); oa->write_characters(vec.data(), sizeof(NumberType));
} }
// The following to_char_type functions are implement the conversion
// between uint8_t and CharType. In case CharType is not unsigned,
// such a conversion is required to allow values greater than 128.
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
template < typename C = CharType,
enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
static constexpr CharType to_char_type(std::uint8_t x) noexcept
{
return *reinterpret_cast<char*>(&x);
}
template < typename C = CharType,
enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
static CharType to_char_type(std::uint8_t x) noexcept
{
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
static_assert(std::is_pod<CharType>::value, "CharType must be POD");
CharType result;
std::memcpy(&result, &x, sizeof(x));
return result;
}
template<typename C = CharType,
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
static constexpr CharType to_char_type(std::uint8_t x) noexcept
{
return x;
}
template < typename InputCharType, typename C = CharType,
enable_if_t <
std::is_signed<C>::value and
std::is_signed<char>::value and
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
> * = nullptr >
static constexpr CharType to_char_type(InputCharType x) noexcept
{
return x;
}
private: private:
/// whether we can assume little endianess /// whether we can assume little endianess
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess(); const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();

View file

@ -30,7 +30,9 @@ template<typename CharType>
class output_vector_adapter : public output_adapter_protocol<CharType> class output_vector_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {} explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
: v(vec)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {
@ -51,7 +53,9 @@ template<typename CharType>
class output_stream_adapter : public output_adapter_protocol<CharType> class output_stream_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {} explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
: stream(s)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {
@ -72,7 +76,9 @@ template<typename CharType, typename StringType = std::basic_string<CharType>>
class output_string_adapter : public output_adapter_protocol<CharType> class output_string_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_string_adapter(StringType& s) : str(s) {} explicit output_string_adapter(StringType& s) noexcept
: str(s)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {

View file

@ -2115,7 +2115,7 @@ class input_stream_adapter : public input_adapter_protocol
class input_buffer_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol
{ {
public: public:
input_buffer_adapter(const char* b, const std::size_t l) input_buffer_adapter(const char* b, const std::size_t l) noexcept
: cursor(b), limit(b + l) : cursor(b), limit(b + l)
{} {}
@ -2263,7 +2263,9 @@ template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol class wide_string_input_adapter : public input_adapter_protocol
{ {
public: public:
explicit wide_string_input_adapter(const WideStringType& w) : str(w) {} explicit wide_string_input_adapter(const WideStringType& w) noexcept
: str(w)
{}
std::char_traits<char>::int_type get_character() noexcept override std::char_traits<char>::int_type get_character() noexcept override
{ {
@ -6210,7 +6212,9 @@ template<typename CharType>
class output_vector_adapter : public output_adapter_protocol<CharType> class output_vector_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_vector_adapter(std::vector<CharType>& vec) : v(vec) {} explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
: v(vec)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {
@ -6231,7 +6235,9 @@ template<typename CharType>
class output_stream_adapter : public output_adapter_protocol<CharType> class output_stream_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_stream_adapter(std::basic_ostream<CharType>& s) : stream(s) {} explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
: stream(s)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {
@ -6252,7 +6258,9 @@ template<typename CharType, typename StringType = std::basic_string<CharType>>
class output_string_adapter : public output_adapter_protocol<CharType> class output_string_adapter : public output_adapter_protocol<CharType>
{ {
public: public:
explicit output_string_adapter(StringType& s) : str(s) {} explicit output_string_adapter(StringType& s) noexcept
: str(s)
{}
void write_character(CharType c) override void write_character(CharType c) override
{ {
@ -6369,6 +6377,10 @@ class binary_reader
switch (format) switch (format)
{ {
case input_format_t::bson:
result = parse_bson_internal();
break;
case input_format_t::cbor: case input_format_t::cbor:
result = parse_cbor_internal(); result = parse_cbor_internal();
break; break;
@ -6381,10 +6393,6 @@ class binary_reader
result = parse_ubjson_internal(); result = parse_ubjson_internal();
break; break;
case input_format_t::bson:
result = parse_bson_internal();
break;
// LCOV_EXCL_START // LCOV_EXCL_START
default: default:
assert(false); assert(false);
@ -6436,8 +6444,8 @@ class binary_reader
*/ */
bool parse_bson_internal() bool parse_bson_internal()
{ {
std::int32_t documentSize; std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, documentSize); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1))))
{ {
@ -6616,8 +6624,8 @@ class binary_reader
*/ */
bool parse_bson_array() bool parse_bson_array()
{ {
std::int32_t documentSize; std::int32_t document_size;
get_number<std::int32_t, true>(input_format_t::bson, documentSize); get_number<std::int32_t, true>(input_format_t::bson, document_size);
if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1))))
{ {
@ -8303,6 +8311,8 @@ namespace detail
template<typename BasicJsonType, typename CharType> template<typename BasicJsonType, typename CharType>
class binary_writer class binary_writer
{ {
using string_t = typename BasicJsonType::string_t;
public: public:
/*! /*!
@brief create a binary writer @brief create a binary writer
@ -8328,11 +8338,6 @@ class binary_writer
break; break;
} }
case value_t::discarded:
{
break;
}
default: default:
{ {
JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name())));
@ -8349,15 +8354,15 @@ class binary_writer
{ {
case value_t::null: case value_t::null:
{ {
oa->write_character(static_cast<CharType>(0xF6)); oa->write_character(to_char_type(0xF6));
break; break;
} }
case value_t::boolean: case value_t::boolean:
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xF5) ? to_char_type(0xF5)
: static_cast<CharType>(0xF4)); : to_char_type(0xF4));
break; break;
} }
@ -8374,22 +8379,22 @@ class binary_writer
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x18)); oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x19)); oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x1A)); oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x1B)); oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
} }
@ -8404,22 +8409,22 @@ class binary_writer
} }
else if (positive_number <= (std::numeric_limits<uint8_t>::max)()) else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x38)); oa->write_character(to_char_type(0x38));
write_number(static_cast<uint8_t>(positive_number)); write_number(static_cast<uint8_t>(positive_number));
} }
else if (positive_number <= (std::numeric_limits<uint16_t>::max)()) else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x39)); oa->write_character(to_char_type(0x39));
write_number(static_cast<uint16_t>(positive_number)); write_number(static_cast<uint16_t>(positive_number));
} }
else if (positive_number <= (std::numeric_limits<uint32_t>::max)()) else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x3A)); oa->write_character(to_char_type(0x3A));
write_number(static_cast<uint32_t>(positive_number)); write_number(static_cast<uint32_t>(positive_number));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x3B)); oa->write_character(to_char_type(0x3B));
write_number(static_cast<uint64_t>(positive_number)); write_number(static_cast<uint64_t>(positive_number));
} }
} }
@ -8434,22 +8439,22 @@ class binary_writer
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x18)); oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_unsigned)); write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x19)); oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_unsigned)); write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x1A)); oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_unsigned)); write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
} }
else else
{ {
oa->write_character(static_cast<CharType>(0x1B)); oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_unsigned)); write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
} }
break; break;
@ -8472,23 +8477,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x78)); oa->write_character(to_char_type(0x78));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x79)); oa->write_character(to_char_type(0x79));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x7A)); oa->write_character(to_char_type(0x7A));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x7B)); oa->write_character(to_char_type(0x7B));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -8510,23 +8515,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x98)); oa->write_character(to_char_type(0x98));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x99)); oa->write_character(to_char_type(0x99));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x9A)); oa->write_character(to_char_type(0x9A));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0x9B)); oa->write_character(to_char_type(0x9B));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -8549,23 +8554,23 @@ class binary_writer
} }
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xB8)); oa->write_character(to_char_type(0xB8));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xB9)); oa->write_character(to_char_type(0xB9));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xBA)); oa->write_character(to_char_type(0xBA));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
// LCOV_EXCL_START // LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)()) else if (N <= (std::numeric_limits<uint64_t>::max)())
{ {
oa->write_character(static_cast<CharType>(0xBB)); oa->write_character(to_char_type(0xBB));
write_number(static_cast<uint64_t>(N)); write_number(static_cast<uint64_t>(N));
} }
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
@ -8593,15 +8598,15 @@ class binary_writer
{ {
case value_t::null: // nil case value_t::null: // nil
{ {
oa->write_character(static_cast<CharType>(0xC0)); oa->write_character(to_char_type(0xC0));
break; break;
} }
case value_t::boolean: // true and false case value_t::boolean: // true and false
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>(0xC3) ? to_char_type(0xC3)
: static_cast<CharType>(0xC2)); : to_char_type(0xC2));
break; break;
} }
@ -8620,25 +8625,25 @@ class binary_writer
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
// uint 8 // uint 8
oa->write_character(static_cast<CharType>(0xCC)); oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
// uint 16 // uint 16
oa->write_character(static_cast<CharType>(0xCD)); oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
// uint 32 // uint 32
oa->write_character(static_cast<CharType>(0xCE)); oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
{ {
// uint 64 // uint 64
oa->write_character(static_cast<CharType>(0xCF)); oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
} }
@ -8653,28 +8658,28 @@ class binary_writer
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
{ {
// int 8 // int 8
oa->write_character(static_cast<CharType>(0xD0)); oa->write_character(to_char_type(0xD0));
write_number(static_cast<int8_t>(j.m_value.number_integer)); write_number(static_cast<int8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
{ {
// int 16 // int 16
oa->write_character(static_cast<CharType>(0xD1)); oa->write_character(to_char_type(0xD1));
write_number(static_cast<int16_t>(j.m_value.number_integer)); write_number(static_cast<int16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
{ {
// int 32 // int 32
oa->write_character(static_cast<CharType>(0xD2)); oa->write_character(to_char_type(0xD2));
write_number(static_cast<int32_t>(j.m_value.number_integer)); write_number(static_cast<int32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)()) j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
{ {
// int 64 // int 64
oa->write_character(static_cast<CharType>(0xD3)); oa->write_character(to_char_type(0xD3));
write_number(static_cast<int64_t>(j.m_value.number_integer)); write_number(static_cast<int64_t>(j.m_value.number_integer));
} }
} }
@ -8691,25 +8696,25 @@ class binary_writer
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
{ {
// uint 8 // uint 8
oa->write_character(static_cast<CharType>(0xCC)); oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer)); write_number(static_cast<uint8_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
{ {
// uint 16 // uint 16
oa->write_character(static_cast<CharType>(0xCD)); oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer)); write_number(static_cast<uint16_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
{ {
// uint 32 // uint 32
oa->write_character(static_cast<CharType>(0xCE)); oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer)); write_number(static_cast<uint32_t>(j.m_value.number_integer));
} }
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)()) else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
{ {
// uint 64 // uint 64
oa->write_character(static_cast<CharType>(0xCF)); oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer)); write_number(static_cast<uint64_t>(j.m_value.number_integer));
} }
break; break;
@ -8734,19 +8739,19 @@ class binary_writer
else if (N <= (std::numeric_limits<uint8_t>::max)()) else if (N <= (std::numeric_limits<uint8_t>::max)())
{ {
// str 8 // str 8
oa->write_character(static_cast<CharType>(0xD9)); oa->write_character(to_char_type(0xD9));
write_number(static_cast<uint8_t>(N)); write_number(static_cast<uint8_t>(N));
} }
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// str 16 // str 16
oa->write_character(static_cast<CharType>(0xDA)); oa->write_character(to_char_type(0xDA));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// str 32 // str 32
oa->write_character(static_cast<CharType>(0xDB)); oa->write_character(to_char_type(0xDB));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -8769,13 +8774,13 @@ class binary_writer
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// array 16 // array 16
oa->write_character(static_cast<CharType>(0xDC)); oa->write_character(to_char_type(0xDC));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// array 32 // array 32
oa->write_character(static_cast<CharType>(0xDD)); oa->write_character(to_char_type(0xDD));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -8799,13 +8804,13 @@ class binary_writer
else if (N <= (std::numeric_limits<uint16_t>::max)()) else if (N <= (std::numeric_limits<uint16_t>::max)())
{ {
// map 16 // map 16
oa->write_character(static_cast<CharType>(0xDE)); oa->write_character(to_char_type(0xDE));
write_number(static_cast<uint16_t>(N)); write_number(static_cast<uint16_t>(N));
} }
else if (N <= (std::numeric_limits<uint32_t>::max)()) else if (N <= (std::numeric_limits<uint32_t>::max)())
{ {
// map 32 // map 32
oa->write_character(static_cast<CharType>(0xDF)); oa->write_character(to_char_type(0xDF));
write_number(static_cast<uint32_t>(N)); write_number(static_cast<uint32_t>(N));
} }
@ -8838,7 +8843,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('Z')); oa->write_character(to_char_type('Z'));
} }
break; break;
} }
@ -8848,8 +8853,8 @@ class binary_writer
if (add_prefix) if (add_prefix)
{ {
oa->write_character(j.m_value.boolean oa->write_character(j.m_value.boolean
? static_cast<CharType>('T') ? to_char_type('T')
: static_cast<CharType>('F')); : to_char_type('F'));
} }
break; break;
} }
@ -8876,7 +8881,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('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);
oa->write_characters( oa->write_characters(
@ -8889,7 +8894,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('[')); oa->write_character(to_char_type('['));
} }
bool prefix_required = true; bool prefix_required = true;
@ -8906,14 +8911,14 @@ class binary_writer
if (same_prefix) if (same_prefix)
{ {
prefix_required = false; prefix_required = false;
oa->write_character(static_cast<CharType>('$')); oa->write_character(to_char_type('$'));
oa->write_character(first_prefix); oa->write_character(first_prefix);
} }
} }
if (use_count) if (use_count)
{ {
oa->write_character(static_cast<CharType>('#')); 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);
} }
@ -8924,7 +8929,7 @@ class binary_writer
if (not use_count) if (not use_count)
{ {
oa->write_character(static_cast<CharType>(']')); oa->write_character(to_char_type(']'));
} }
break; break;
@ -8934,7 +8939,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('{')); oa->write_character(to_char_type('{'));
} }
bool prefix_required = true; bool prefix_required = true;
@ -8951,14 +8956,14 @@ class binary_writer
if (same_prefix) if (same_prefix)
{ {
prefix_required = false; prefix_required = false;
oa->write_character(static_cast<CharType>('$')); oa->write_character(to_char_type('$'));
oa->write_character(first_prefix); oa->write_character(first_prefix);
} }
} }
if (use_count) if (use_count)
{ {
oa->write_character(static_cast<CharType>('#')); 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);
} }
@ -8973,7 +8978,7 @@ class binary_writer
if (not use_count) if (not use_count)
{ {
oa->write_character(static_cast<CharType>('}')); oa->write_character(to_char_type('}'));
} }
break; break;
@ -8993,9 +8998,9 @@ class binary_writer
@return The size of a BSON document entry header, including the id marker @return The size of a BSON document entry header, including the id marker
and the entry name size (and its null-terminator). and the entry name size (and its null-terminator).
*/ */
static std::size_t calc_bson_entry_header_size(const typename BasicJsonType::string_t& name) static std::size_t calc_bson_entry_header_size(const string_t& name)
{ {
const auto it = name.find(static_cast<typename BasicJsonType::string_t::value_type>(0)); const auto it = name.find(static_cast<typename string_t::value_type>(0));
if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos)) if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos))
{ {
JSON_THROW(out_of_range::create(409, JSON_THROW(out_of_range::create(409,
@ -9008,10 +9013,10 @@ class binary_writer
/*! /*!
@brief Writes the given @a element_type and @a name to the output adapter @brief Writes the given @a element_type and @a name to the output adapter
*/ */
void write_bson_entry_header(const typename BasicJsonType::string_t& name, void write_bson_entry_header(const string_t& name,
std::uint8_t element_type) const std::uint8_t element_type)
{ {
oa->write_character(static_cast<CharType>(element_type)); // boolean oa->write_character(to_char_type(element_type)); // boolean
oa->write_characters( oa->write_characters(
reinterpret_cast<const CharType*>(name.c_str()), reinterpret_cast<const CharType*>(name.c_str()),
name.size() + 1u); name.size() + 1u);
@ -9020,17 +9025,17 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and boolean value @a value @brief Writes a BSON element with key @a name and boolean value @a value
*/ */
void write_bson_boolean(const typename BasicJsonType::string_t& name, void write_bson_boolean(const string_t& name,
const bool value) const bool value)
{ {
write_bson_entry_header(name, 0x08); write_bson_entry_header(name, 0x08);
oa->write_character(value ? static_cast<CharType>(0x01) : static_cast<CharType>(0x00)); oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
} }
/*! /*!
@brief Writes a BSON element with key @a name and double value @a value @brief Writes a BSON element with key @a name and double value @a value
*/ */
void write_bson_double(const typename BasicJsonType::string_t& name, void write_bson_double(const string_t& name,
const double value) const double value)
{ {
write_bson_entry_header(name, 0x01); write_bson_entry_header(name, 0x01);
@ -9040,7 +9045,7 @@ class binary_writer
/*! /*!
@return The size of the BSON-encoded string in @a value @return The size of the BSON-encoded string in @a value
*/ */
static std::size_t calc_bson_string_size(const typename BasicJsonType::string_t& value) static std::size_t calc_bson_string_size(const string_t& value)
{ {
return sizeof(std::int32_t) + value.size() + 1ul; return sizeof(std::int32_t) + value.size() + 1ul;
} }
@ -9048,8 +9053,8 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and string value @a value @brief Writes a BSON element with key @a name and string value @a value
*/ */
void write_bson_string(const typename BasicJsonType::string_t& name, void write_bson_string(const string_t& name,
const typename BasicJsonType::string_t& value) const string_t& value)
{ {
write_bson_entry_header(name, 0x02); write_bson_entry_header(name, 0x02);
@ -9062,7 +9067,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and null value @brief Writes a BSON element with key @a name and null value
*/ */
void write_bson_null(const typename BasicJsonType::string_t& name) void write_bson_null(const string_t& name)
{ {
write_bson_entry_header(name, 0x0A); write_bson_entry_header(name, 0x0A);
} }
@ -9085,7 +9090,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and integer @a value @brief Writes a BSON element with key @a name and integer @a value
*/ */
void write_bson_integer(const typename BasicJsonType::string_t& name, void write_bson_integer(const string_t& name,
const std::int64_t value) const std::int64_t value)
{ {
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()) if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
@ -9103,45 +9108,39 @@ class binary_writer
/*! /*!
@return The size of the BSON-encoded unsigned integer in @a j @return The size of the BSON-encoded unsigned integer in @a j
*/ */
static std::size_t calc_bson_unsigned_size(const std::uint64_t value) static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
{ {
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ ? sizeof(std::int32_t)
return sizeof(std::int32_t); : sizeof(std::int64_t);
}
else
{
return sizeof(std::int64_t);
}
} }
/*! /*!
@brief Writes a BSON element with key @a name and unsigned @a value @brief Writes a BSON element with key @a name and unsigned @a value
*/ */
void write_bson_unsigned(const typename BasicJsonType::string_t& name, void write_bson_unsigned(const string_t& name,
const std::uint64_t value) const std::uint64_t value)
{ {
if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{ {
write_bson_entry_header(name, 0x10); // int32 write_bson_entry_header(name, 0x10 /* int32 */);
write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
} }
else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)())) else if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{ {
write_bson_entry_header(name, 0x12); // int64 write_bson_entry_header(name, 0x12 /* int64 */);
write_number<std::int64_t, true>(static_cast<std::int64_t>(value)); write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
} }
else else
{ {
JSON_THROW(out_of_range::create(407, "number overflow serializing " + std::to_string(value))); JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64"));
} }
} }
/*! /*!
@brief Writes a BSON element with key @a name and object @a value @brief Writes a BSON element with key @a name and object @a value
*/ */
void write_bson_object_entry(const typename BasicJsonType::string_t& name, void write_bson_object_entry(const string_t& name,
const typename BasicJsonType::object_t& value) const typename BasicJsonType::object_t& value)
{ {
write_bson_entry_header(name, 0x03); // object write_bson_entry_header(name, 0x03); // object
@ -9167,7 +9166,7 @@ class binary_writer
/*! /*!
@brief Writes a BSON element with key @a name and array @a value @brief Writes a BSON element with key @a name and array @a value
*/ */
void write_bson_array(const typename BasicJsonType::string_t& name, void write_bson_array(const string_t& name,
const typename BasicJsonType::array_t& value) const typename BasicJsonType::array_t& value)
{ {
write_bson_entry_header(name, 0x04); // array write_bson_entry_header(name, 0x04); // array
@ -9180,22 +9179,19 @@ class binary_writer
write_bson_element(std::to_string(array_index++), el); write_bson_element(std::to_string(array_index++), el);
} }
oa->write_character(static_cast<CharType>(0x00)); oa->write_character(to_char_type(0x00));
} }
/*! /*!
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
@return The calculated size for the BSON document entry for @a j with the given @a name. @return The calculated size for the BSON document entry for @a j with the given @a name.
*/ */
static std::size_t calc_bson_element_size(const typename BasicJsonType::string_t& name, static std::size_t calc_bson_element_size(const string_t& name,
const BasicJsonType& j) const BasicJsonType& j)
{ {
const auto header_size = calc_bson_entry_header_size(name); const auto header_size = calc_bson_entry_header_size(name);
switch (j.type()) switch (j.type())
{ {
case value_t::discarded:
return 0ul;
case value_t::object: case value_t::object:
return header_size + calc_bson_object_size(*j.m_value.object); return header_size + calc_bson_object_size(*j.m_value.object);
@ -9235,14 +9231,11 @@ class binary_writer
current BSON document current BSON document
@return The size of the BSON entry @return The size of the BSON entry
*/ */
void write_bson_element(const typename BasicJsonType::string_t& name, void write_bson_element(const string_t& name,
const BasicJsonType& j) const BasicJsonType& j)
{ {
switch (j.type()) switch (j.type())
{ {
case value_t::discarded:
return;
case value_t::object: case value_t::object:
return write_bson_object_entry(name, *j.m_value.object); return write_bson_object_entry(name, *j.m_value.object);
@ -9283,12 +9276,11 @@ class binary_writer
*/ */
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
{ {
std::size_t document_size = 0; std::size_t document_size = std::accumulate(value.begin(), value.end(), 0,
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
for (const auto& el : value)
{ {
document_size += calc_bson_element_size(el.first, el.second); return result += calc_bson_element_size(el.first, el.second);
} });
return sizeof(std::int32_t) + document_size + 1ul; return sizeof(std::int32_t) + document_size + 1ul;
} }
@ -9306,7 +9298,7 @@ class binary_writer
write_bson_element(el.first, el.second); write_bson_element(el.first, el.second);
} }
oa->write_character(static_cast<CharType>(0x00)); oa->write_character(to_char_type(0x00));
} }
////////// //////////
@ -9315,12 +9307,12 @@ class binary_writer
static constexpr CharType get_cbor_float_prefix(float /*unused*/) static constexpr CharType get_cbor_float_prefix(float /*unused*/)
{ {
return static_cast<CharType>(0xFA); // Single-Precision Float return to_char_type(0xFA); // Single-Precision Float
} }
static constexpr CharType get_cbor_float_prefix(double /*unused*/) static constexpr CharType get_cbor_float_prefix(double /*unused*/)
{ {
return static_cast<CharType>(0xFB); // Double-Precision Float return to_char_type(0xFB); // Double-Precision Float
} }
///////////// /////////////
@ -9329,12 +9321,12 @@ class binary_writer
static constexpr CharType get_msgpack_float_prefix(float /*unused*/) static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
{ {
return static_cast<CharType>(0xCA); // float 32 return to_char_type(0xCA); // float 32
} }
static constexpr CharType get_msgpack_float_prefix(double /*unused*/) static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
{ {
return static_cast<CharType>(0xCB); // float 64 return to_char_type(0xCB); // float 64
} }
//////////// ////////////
@ -9364,7 +9356,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -9372,7 +9364,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -9380,7 +9372,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<int16_t>(n)); write_number(static_cast<int16_t>(n));
} }
@ -9388,7 +9380,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<int32_t>(n)); write_number(static_cast<int32_t>(n));
} }
@ -9396,7 +9388,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<int64_t>(n)); write_number(static_cast<int64_t>(n));
} }
@ -9417,7 +9409,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('i')); // int8 oa->write_character(to_char_type('i')); // int8
} }
write_number(static_cast<int8_t>(n)); write_number(static_cast<int8_t>(n));
} }
@ -9425,7 +9417,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('U')); // uint8 oa->write_character(to_char_type('U')); // uint8
} }
write_number(static_cast<uint8_t>(n)); write_number(static_cast<uint8_t>(n));
} }
@ -9433,7 +9425,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('I')); // int16 oa->write_character(to_char_type('I')); // int16
} }
write_number(static_cast<int16_t>(n)); write_number(static_cast<int16_t>(n));
} }
@ -9441,7 +9433,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('l')); // int32 oa->write_character(to_char_type('l')); // int32
} }
write_number(static_cast<int32_t>(n)); write_number(static_cast<int32_t>(n));
} }
@ -9449,7 +9441,7 @@ class binary_writer
{ {
if (add_prefix) if (add_prefix)
{ {
oa->write_character(static_cast<CharType>('L')); // int64 oa->write_character(to_char_type('L')); // int64
} }
write_number(static_cast<int64_t>(n)); write_number(static_cast<int64_t>(n));
} }
@ -9584,6 +9576,46 @@ class binary_writer
oa->write_characters(vec.data(), sizeof(NumberType)); oa->write_characters(vec.data(), sizeof(NumberType));
} }
// The following to_char_type functions are implement the conversion
// between uint8_t and CharType. In case CharType is not unsigned,
// such a conversion is required to allow values greater than 128.
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
template < typename C = CharType,
enable_if_t < std::is_signed<C>::value and std::is_signed<char>::value > * = nullptr >
static constexpr CharType to_char_type(std::uint8_t x) noexcept
{
return *reinterpret_cast<char*>(&x);
}
template < typename C = CharType,
enable_if_t < std::is_signed<C>::value and std::is_unsigned<char>::value > * = nullptr >
static CharType to_char_type(std::uint8_t x) noexcept
{
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
static_assert(std::is_pod<CharType>::value, "CharType must be POD");
CharType result;
std::memcpy(&result, &x, sizeof(x));
return result;
}
template<typename C = CharType,
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
static constexpr CharType to_char_type(std::uint8_t x) noexcept
{
return x;
}
template < typename InputCharType, typename C = CharType,
enable_if_t <
std::is_signed<C>::value and
std::is_signed<char>::value and
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
> * = nullptr >
static constexpr CharType to_char_type(InputCharType x) noexcept
{
return x;
}
private: private:
/// whether we can assume little endianess /// whether we can assume little endianess
const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess(); const bool is_little_endian = binary_reader<BasicJsonType>::little_endianess();

View file

@ -37,14 +37,6 @@ TEST_CASE("BSON")
{ {
SECTION("individual values not supported") SECTION("individual values not supported")
{ {
SECTION("discarded")
{
// discarded values are not serialized
json j = json::value_t::discarded;
const auto result = json::to_bson(j);
CHECK(result.empty());
}
SECTION("null") SECTION("null")
{ {
json j = nullptr; json j = nullptr;
@ -392,32 +384,6 @@ TEST_CASE("BSON")
CHECK(json::from_bson(result, true, false) == j); CHECK(json::from_bson(result, true, false) == j);
} }
SECTION("discarded values are not serialized")
{
json j = json::value_t::discarded;
const auto result = json::to_bson(j);
CHECK(result.empty());
}
SECTION("discarded members are not serialized")
{
json j =
{
{ "entry", json::value_t::discarded }
};
std::vector<uint8_t> expected =
{
0x05, 0x00, 0x00, 0x00, // size (little endian)
// no entries
0x00 // end marker
};
const auto result = json::to_bson(j);
CHECK(result == expected);
}
SECTION("non-empty object with object member") SECTION("non-empty object with object member")
{ {
json j = json j =
@ -1136,7 +1102,7 @@ TEST_CASE("BSON numerical data")
}; };
CHECK_THROWS_AS(json::to_bson(j), json::out_of_range&); CHECK_THROWS_AS(json::to_bson(j), json::out_of_range&);
CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.407] number overflow serializing " + std::to_string(i)); CHECK_THROWS_WITH(json::to_bson(j), "[json.exception.out_of_range.407] integer number " + std::to_string(i) + " cannot be represented by BSON as it does not fit int64");
} }
} }