From 4e765596f7656fa4687b442e9f6d420f6a901a3c Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sat, 27 Oct 2018 18:31:03 +0200 Subject: [PATCH] :hammer: small improvements --- .../nlohmann/detail/input/binary_reader.hpp | 16 +- .../nlohmann/detail/input/input_adapters.hpp | 6 +- .../nlohmann/detail/output/binary_writer.hpp | 272 +++++++++------- .../detail/output/output_adapters.hpp | 12 +- single_include/nlohmann/json.hpp | 306 ++++++++++-------- test/src/unit-bson.cpp | 36 +-- 6 files changed, 339 insertions(+), 309 deletions(-) diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 7d278736..ed2d66fd 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -68,6 +68,10 @@ class binary_reader switch (format) { + case input_format_t::bson: + result = parse_bson_internal(); + break; + case input_format_t::cbor: result = parse_cbor_internal(); break; @@ -80,10 +84,6 @@ class binary_reader result = parse_ubjson_internal(); break; - case input_format_t::bson: - result = parse_bson_internal(); - break; - // LCOV_EXCL_START default: assert(false); @@ -135,8 +135,8 @@ class binary_reader */ bool parse_bson_internal() { - std::int32_t documentSize; - get_number(input_format_t::bson, documentSize); + std::int32_t document_size; + get_number(input_format_t::bson, document_size); if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) { @@ -315,8 +315,8 @@ class binary_reader */ bool parse_bson_array() { - std::int32_t documentSize; - get_number(input_format_t::bson, documentSize); + std::int32_t document_size; + get_number(input_format_t::bson, document_size); if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) { diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index 8b7852b8..79a19c17 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -92,7 +92,7 @@ class input_stream_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol { 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) {} @@ -240,7 +240,9 @@ template class wide_string_input_adapter : public input_adapter_protocol { 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::int_type get_character() noexcept override { diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 7c0e6939..f54e2485 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -23,6 +23,8 @@ namespace detail template class binary_writer { + using string_t = typename BasicJsonType::string_t; + public: /*! @brief create a binary writer @@ -48,11 +50,6 @@ class binary_writer break; } - case value_t::discarded: - { - break; - } - default: { 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: { - oa->write_character(static_cast(0xF6)); + oa->write_character(to_char_type(0xF6)); break; } case value_t::boolean: { oa->write_character(j.m_value.boolean - ? static_cast(0xF5) - : static_cast(0xF4)); + ? to_char_type(0xF5) + : to_char_type(0xF4)); break; } @@ -94,22 +91,22 @@ class binary_writer } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x18)); + oa->write_character(to_char_type(0x18)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x19)); + oa->write_character(to_char_type(0x19)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1A)); + oa->write_character(to_char_type(0x1A)); write_number(static_cast(j.m_value.number_integer)); } else { - oa->write_character(static_cast(0x1B)); + oa->write_character(to_char_type(0x1B)); write_number(static_cast(j.m_value.number_integer)); } } @@ -124,22 +121,22 @@ class binary_writer } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x38)); + oa->write_character(to_char_type(0x38)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x39)); + oa->write_character(to_char_type(0x39)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x3A)); + oa->write_character(to_char_type(0x3A)); write_number(static_cast(positive_number)); } else { - oa->write_character(static_cast(0x3B)); + oa->write_character(to_char_type(0x3B)); write_number(static_cast(positive_number)); } } @@ -154,22 +151,22 @@ class binary_writer } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x18)); + oa->write_character(to_char_type(0x18)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x19)); + oa->write_character(to_char_type(0x19)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1A)); + oa->write_character(to_char_type(0x1A)); write_number(static_cast(j.m_value.number_unsigned)); } else { - oa->write_character(static_cast(0x1B)); + oa->write_character(to_char_type(0x1B)); write_number(static_cast(j.m_value.number_unsigned)); } break; @@ -192,23 +189,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x78)); + oa->write_character(to_char_type(0x78)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x79)); + oa->write_character(to_char_type(0x79)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x7A)); + oa->write_character(to_char_type(0x7A)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x7B)); + oa->write_character(to_char_type(0x7B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -230,23 +227,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x98)); + oa->write_character(to_char_type(0x98)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x99)); + oa->write_character(to_char_type(0x99)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x9A)); + oa->write_character(to_char_type(0x9A)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x9B)); + oa->write_character(to_char_type(0x9B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -269,23 +266,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xB8)); + oa->write_character(to_char_type(0xB8)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xB9)); + oa->write_character(to_char_type(0xB9)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xBA)); + oa->write_character(to_char_type(0xBA)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xBB)); + oa->write_character(to_char_type(0xBB)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -313,15 +310,15 @@ class binary_writer { case value_t::null: // nil { - oa->write_character(static_cast(0xC0)); + oa->write_character(to_char_type(0xC0)); break; } case value_t::boolean: // true and false { oa->write_character(j.m_value.boolean - ? static_cast(0xC3) - : static_cast(0xC2)); + ? to_char_type(0xC3) + : to_char_type(0xC2)); break; } @@ -340,25 +337,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xCC)); + oa->write_character(to_char_type(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xCD)); + oa->write_character(to_char_type(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xCE)); + oa->write_character(to_char_type(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xCF)); + oa->write_character(to_char_type(0xCF)); write_number(static_cast(j.m_value.number_integer)); } } @@ -373,28 +370,28 @@ class binary_writer j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 - oa->write_character(static_cast(0xD0)); + oa->write_character(to_char_type(0xD0)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 - oa->write_character(static_cast(0xD1)); + oa->write_character(to_char_type(0xD1)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 - oa->write_character(static_cast(0xD2)); + oa->write_character(to_char_type(0xD2)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 - oa->write_character(static_cast(0xD3)); + oa->write_character(to_char_type(0xD3)); write_number(static_cast(j.m_value.number_integer)); } } @@ -411,25 +408,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xCC)); + oa->write_character(to_char_type(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xCD)); + oa->write_character(to_char_type(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xCE)); + oa->write_character(to_char_type(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xCF)); + oa->write_character(to_char_type(0xCF)); write_number(static_cast(j.m_value.number_integer)); } break; @@ -454,19 +451,19 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // str 8 - oa->write_character(static_cast(0xD9)); + oa->write_character(to_char_type(0xD9)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // str 16 - oa->write_character(static_cast(0xDA)); + oa->write_character(to_char_type(0xDA)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // str 32 - oa->write_character(static_cast(0xDB)); + oa->write_character(to_char_type(0xDB)); write_number(static_cast(N)); } @@ -489,13 +486,13 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // array 16 - oa->write_character(static_cast(0xDC)); + oa->write_character(to_char_type(0xDC)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // array 32 - oa->write_character(static_cast(0xDD)); + oa->write_character(to_char_type(0xDD)); write_number(static_cast(N)); } @@ -519,13 +516,13 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // map 16 - oa->write_character(static_cast(0xDE)); + oa->write_character(to_char_type(0xDE)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // map 32 - oa->write_character(static_cast(0xDF)); + oa->write_character(to_char_type(0xDF)); write_number(static_cast(N)); } @@ -558,7 +555,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('Z')); + oa->write_character(to_char_type('Z')); } break; } @@ -568,8 +565,8 @@ class binary_writer if (add_prefix) { oa->write_character(j.m_value.boolean - ? static_cast('T') - : static_cast('F')); + ? to_char_type('T') + : to_char_type('F')); } break; } @@ -596,7 +593,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('S')); + oa->write_character(to_char_type('S')); } write_number_with_ubjson_prefix(j.m_value.string->size(), true); oa->write_characters( @@ -609,7 +606,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('[')); + oa->write_character(to_char_type('[')); } bool prefix_required = true; @@ -626,14 +623,14 @@ class binary_writer if (same_prefix) { prefix_required = false; - oa->write_character(static_cast('$')); + oa->write_character(to_char_type('$')); oa->write_character(first_prefix); } } if (use_count) { - oa->write_character(static_cast('#')); + oa->write_character(to_char_type('#')); write_number_with_ubjson_prefix(j.m_value.array->size(), true); } @@ -644,7 +641,7 @@ class binary_writer if (not use_count) { - oa->write_character(static_cast(']')); + oa->write_character(to_char_type(']')); } break; @@ -654,7 +651,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('{')); + oa->write_character(to_char_type('{')); } bool prefix_required = true; @@ -671,14 +668,14 @@ class binary_writer if (same_prefix) { prefix_required = false; - oa->write_character(static_cast('$')); + oa->write_character(to_char_type('$')); oa->write_character(first_prefix); } } if (use_count) { - oa->write_character(static_cast('#')); + oa->write_character(to_char_type('#')); write_number_with_ubjson_prefix(j.m_value.object->size(), true); } @@ -693,7 +690,7 @@ class binary_writer if (not use_count) { - oa->write_character(static_cast('}')); + oa->write_character(to_char_type('}')); } break; @@ -713,9 +710,9 @@ class binary_writer @return The size of a BSON document entry header, including the id marker 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(0)); + const auto it = name.find(static_cast(0)); if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos)) { 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 */ - void write_bson_entry_header(const typename BasicJsonType::string_t& name, - std::uint8_t element_type) + void write_bson_entry_header(const string_t& name, + const std::uint8_t element_type) { - oa->write_character(static_cast(element_type)); // boolean + oa->write_character(to_char_type(element_type)); // boolean oa->write_characters( reinterpret_cast(name.c_str()), name.size() + 1u); @@ -740,17 +737,17 @@ class binary_writer /*! @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) { write_bson_entry_header(name, 0x08); - oa->write_character(value ? static_cast(0x01) : static_cast(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 */ - void write_bson_double(const typename BasicJsonType::string_t& name, + void write_bson_double(const string_t& name, const double value) { write_bson_entry_header(name, 0x01); @@ -760,7 +757,7 @@ class binary_writer /*! @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; } @@ -768,8 +765,8 @@ class binary_writer /*! @brief Writes a BSON element with key @a name and string value @a value */ - void write_bson_string(const typename BasicJsonType::string_t& name, - const typename BasicJsonType::string_t& value) + void write_bson_string(const string_t& name, + const string_t& value) { 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 */ - void write_bson_null(const typename BasicJsonType::string_t& name) + void write_bson_null(const string_t& name) { 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 */ - void write_bson_integer(const typename BasicJsonType::string_t& name, + void write_bson_integer(const string_t& name, const std::int64_t value) { if ((std::numeric_limits::min)() <= value and value <= (std::numeric_limits::max)()) @@ -823,45 +820,39 @@ class binary_writer /*! @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::numeric_limits::max)())) - { - return sizeof(std::int32_t); - } - else - { - return sizeof(std::int64_t); - } + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); } /*! @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) { if (value <= static_cast((std::numeric_limits::max)())) { - write_bson_entry_header(name, 0x10); // int32 + write_bson_entry_header(name, 0x10 /* int32 */); write_number(static_cast(value)); } else if (value <= static_cast((std::numeric_limits::max)())) { - write_bson_entry_header(name, 0x12); // int64 + write_bson_entry_header(name, 0x12 /* int64 */); write_number(static_cast(value)); } 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 */ - 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) { 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 */ - void write_bson_array(const typename BasicJsonType::string_t& name, + void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value) { write_bson_entry_header(name, 0x04); // array @@ -900,22 +891,19 @@ class binary_writer write_bson_element(std::to_string(array_index++), el); } - oa->write_character(static_cast(0x00)); + oa->write_character(to_char_type(0x00)); } /*! @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. */ - 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 auto header_size = calc_bson_entry_header_size(name); switch (j.type()) { - case value_t::discarded: - return 0ul; - case value_t::object: return header_size + calc_bson_object_size(*j.m_value.object); @@ -955,14 +943,11 @@ class binary_writer current BSON document @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) { switch (j.type()) { - case value_t::discarded: - return; - case value_t::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) { - std::size_t document_size = 0; - - for (const auto& el : value) + std::size_t document_size = std::accumulate(value.begin(), value.end(), 0, + [](size_t result, const typename BasicJsonType::object_t::value_type & el) { - 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; } @@ -1026,7 +1010,7 @@ class binary_writer write_bson_element(el.first, el.second); } - oa->write_character(static_cast(0x00)); + oa->write_character(to_char_type(0x00)); } ////////// @@ -1035,12 +1019,12 @@ class binary_writer static constexpr CharType get_cbor_float_prefix(float /*unused*/) { - return static_cast(0xFA); // Single-Precision Float + return to_char_type(0xFA); // Single-Precision Float } static constexpr CharType get_cbor_float_prefix(double /*unused*/) { - return static_cast(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*/) { - return static_cast(0xCA); // float 32 + return to_char_type(0xCA); // float 32 } static constexpr CharType get_msgpack_float_prefix(double /*unused*/) { - return static_cast(0xCB); // float 64 + return to_char_type(0xCB); // float 64 } //////////// @@ -1084,7 +1068,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('i')); // int8 + oa->write_character(to_char_type('i')); // int8 } write_number(static_cast(n)); } @@ -1092,7 +1076,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('U')); // uint8 + oa->write_character(to_char_type('U')); // uint8 } write_number(static_cast(n)); } @@ -1100,7 +1084,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('I')); // int16 + oa->write_character(to_char_type('I')); // int16 } write_number(static_cast(n)); } @@ -1108,7 +1092,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('l')); // int32 + oa->write_character(to_char_type('l')); // int32 } write_number(static_cast(n)); } @@ -1116,7 +1100,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('L')); // int64 + oa->write_character(to_char_type('L')); // int64 } write_number(static_cast(n)); } @@ -1137,7 +1121,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('i')); // int8 + oa->write_character(to_char_type('i')); // int8 } write_number(static_cast(n)); } @@ -1145,7 +1129,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('U')); // uint8 + oa->write_character(to_char_type('U')); // uint8 } write_number(static_cast(n)); } @@ -1153,7 +1137,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('I')); // int16 + oa->write_character(to_char_type('I')); // int16 } write_number(static_cast(n)); } @@ -1161,7 +1145,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('l')); // int32 + oa->write_character(to_char_type('l')); // int32 } write_number(static_cast(n)); } @@ -1169,7 +1153,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('L')); // int64 + oa->write_character(to_char_type('L')); // int64 } write_number(static_cast(n)); } @@ -1304,6 +1288,46 @@ class binary_writer 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 for a discussion. + template < typename C = CharType, + enable_if_t < std::is_signed::value and std::is_signed::value > * = nullptr > + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return *reinterpret_cast(&x); + } + + template < typename C = CharType, + enable_if_t < std::is_signed::value and std::is_unsigned::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::value, "CharType must be POD"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } + + template::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::value and + std::is_signed::value and + std::is_same::type>::value + > * = nullptr > + static constexpr CharType to_char_type(InputCharType x) noexcept + { + return x; + } + private: /// whether we can assume little endianess const bool is_little_endian = binary_reader::little_endianess(); diff --git a/include/nlohmann/detail/output/output_adapters.hpp b/include/nlohmann/detail/output/output_adapters.hpp index 0a37715c..699757d6 100644 --- a/include/nlohmann/detail/output/output_adapters.hpp +++ b/include/nlohmann/detail/output/output_adapters.hpp @@ -30,7 +30,9 @@ template class output_vector_adapter : public output_adapter_protocol { public: - explicit output_vector_adapter(std::vector& vec) : v(vec) {} + explicit output_vector_adapter(std::vector& vec) noexcept + : v(vec) + {} void write_character(CharType c) override { @@ -51,7 +53,9 @@ template class output_stream_adapter : public output_adapter_protocol { public: - explicit output_stream_adapter(std::basic_ostream& s) : stream(s) {} + explicit output_stream_adapter(std::basic_ostream& s) noexcept + : stream(s) + {} void write_character(CharType c) override { @@ -72,7 +76,9 @@ template> class output_string_adapter : public output_adapter_protocol { public: - explicit output_string_adapter(StringType& s) : str(s) {} + explicit output_string_adapter(StringType& s) noexcept + : str(s) + {} void write_character(CharType c) override { diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 79f74e4c..848329e7 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2115,7 +2115,7 @@ class input_stream_adapter : public input_adapter_protocol class input_buffer_adapter : public input_adapter_protocol { 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) {} @@ -2263,7 +2263,9 @@ template class wide_string_input_adapter : public input_adapter_protocol { 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::int_type get_character() noexcept override { @@ -6210,7 +6212,9 @@ template class output_vector_adapter : public output_adapter_protocol { public: - explicit output_vector_adapter(std::vector& vec) : v(vec) {} + explicit output_vector_adapter(std::vector& vec) noexcept + : v(vec) + {} void write_character(CharType c) override { @@ -6231,7 +6235,9 @@ template class output_stream_adapter : public output_adapter_protocol { public: - explicit output_stream_adapter(std::basic_ostream& s) : stream(s) {} + explicit output_stream_adapter(std::basic_ostream& s) noexcept + : stream(s) + {} void write_character(CharType c) override { @@ -6252,7 +6258,9 @@ template> class output_string_adapter : public output_adapter_protocol { public: - explicit output_string_adapter(StringType& s) : str(s) {} + explicit output_string_adapter(StringType& s) noexcept + : str(s) + {} void write_character(CharType c) override { @@ -6369,6 +6377,10 @@ class binary_reader switch (format) { + case input_format_t::bson: + result = parse_bson_internal(); + break; + case input_format_t::cbor: result = parse_cbor_internal(); break; @@ -6381,10 +6393,6 @@ class binary_reader result = parse_ubjson_internal(); break; - case input_format_t::bson: - result = parse_bson_internal(); - break; - // LCOV_EXCL_START default: assert(false); @@ -6436,8 +6444,8 @@ class binary_reader */ bool parse_bson_internal() { - std::int32_t documentSize; - get_number(input_format_t::bson, documentSize); + std::int32_t document_size; + get_number(input_format_t::bson, document_size); if (JSON_UNLIKELY(not sax->start_object(std::size_t(-1)))) { @@ -6616,8 +6624,8 @@ class binary_reader */ bool parse_bson_array() { - std::int32_t documentSize; - get_number(input_format_t::bson, documentSize); + std::int32_t document_size; + get_number(input_format_t::bson, document_size); if (JSON_UNLIKELY(not sax->start_array(std::size_t(-1)))) { @@ -8303,6 +8311,8 @@ namespace detail template class binary_writer { + using string_t = typename BasicJsonType::string_t; + public: /*! @brief create a binary writer @@ -8328,11 +8338,6 @@ class binary_writer break; } - case value_t::discarded: - { - break; - } - default: { 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: { - oa->write_character(static_cast(0xF6)); + oa->write_character(to_char_type(0xF6)); break; } case value_t::boolean: { oa->write_character(j.m_value.boolean - ? static_cast(0xF5) - : static_cast(0xF4)); + ? to_char_type(0xF5) + : to_char_type(0xF4)); break; } @@ -8374,22 +8379,22 @@ class binary_writer } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x18)); + oa->write_character(to_char_type(0x18)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x19)); + oa->write_character(to_char_type(0x19)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1A)); + oa->write_character(to_char_type(0x1A)); write_number(static_cast(j.m_value.number_integer)); } else { - oa->write_character(static_cast(0x1B)); + oa->write_character(to_char_type(0x1B)); write_number(static_cast(j.m_value.number_integer)); } } @@ -8404,22 +8409,22 @@ class binary_writer } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x38)); + oa->write_character(to_char_type(0x38)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x39)); + oa->write_character(to_char_type(0x39)); write_number(static_cast(positive_number)); } else if (positive_number <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x3A)); + oa->write_character(to_char_type(0x3A)); write_number(static_cast(positive_number)); } else { - oa->write_character(static_cast(0x3B)); + oa->write_character(to_char_type(0x3B)); write_number(static_cast(positive_number)); } } @@ -8434,22 +8439,22 @@ class binary_writer } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x18)); + oa->write_character(to_char_type(0x18)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x19)); + oa->write_character(to_char_type(0x19)); write_number(static_cast(j.m_value.number_unsigned)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x1A)); + oa->write_character(to_char_type(0x1A)); write_number(static_cast(j.m_value.number_unsigned)); } else { - oa->write_character(static_cast(0x1B)); + oa->write_character(to_char_type(0x1B)); write_number(static_cast(j.m_value.number_unsigned)); } break; @@ -8472,23 +8477,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x78)); + oa->write_character(to_char_type(0x78)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x79)); + oa->write_character(to_char_type(0x79)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x7A)); + oa->write_character(to_char_type(0x7A)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x7B)); + oa->write_character(to_char_type(0x7B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -8510,23 +8515,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x98)); + oa->write_character(to_char_type(0x98)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x99)); + oa->write_character(to_char_type(0x99)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x9A)); + oa->write_character(to_char_type(0x9A)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0x9B)); + oa->write_character(to_char_type(0x9B)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -8549,23 +8554,23 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xB8)); + oa->write_character(to_char_type(0xB8)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xB9)); + oa->write_character(to_char_type(0xB9)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xBA)); + oa->write_character(to_char_type(0xBA)); write_number(static_cast(N)); } // LCOV_EXCL_START else if (N <= (std::numeric_limits::max)()) { - oa->write_character(static_cast(0xBB)); + oa->write_character(to_char_type(0xBB)); write_number(static_cast(N)); } // LCOV_EXCL_STOP @@ -8593,15 +8598,15 @@ class binary_writer { case value_t::null: // nil { - oa->write_character(static_cast(0xC0)); + oa->write_character(to_char_type(0xC0)); break; } case value_t::boolean: // true and false { oa->write_character(j.m_value.boolean - ? static_cast(0xC3) - : static_cast(0xC2)); + ? to_char_type(0xC3) + : to_char_type(0xC2)); break; } @@ -8620,25 +8625,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xCC)); + oa->write_character(to_char_type(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xCD)); + oa->write_character(to_char_type(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xCE)); + oa->write_character(to_char_type(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xCF)); + oa->write_character(to_char_type(0xCF)); write_number(static_cast(j.m_value.number_integer)); } } @@ -8653,28 +8658,28 @@ class binary_writer j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 - oa->write_character(static_cast(0xD0)); + oa->write_character(to_char_type(0xD0)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 - oa->write_character(static_cast(0xD1)); + oa->write_character(to_char_type(0xD1)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 - oa->write_character(static_cast(0xD2)); + oa->write_character(to_char_type(0xD2)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_integer >= (std::numeric_limits::min)() and j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 - oa->write_character(static_cast(0xD3)); + oa->write_character(to_char_type(0xD3)); write_number(static_cast(j.m_value.number_integer)); } } @@ -8691,25 +8696,25 @@ class binary_writer else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 - oa->write_character(static_cast(0xCC)); + oa->write_character(to_char_type(0xCC)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 - oa->write_character(static_cast(0xCD)); + oa->write_character(to_char_type(0xCD)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 - oa->write_character(static_cast(0xCE)); + oa->write_character(to_char_type(0xCE)); write_number(static_cast(j.m_value.number_integer)); } else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 - oa->write_character(static_cast(0xCF)); + oa->write_character(to_char_type(0xCF)); write_number(static_cast(j.m_value.number_integer)); } break; @@ -8734,19 +8739,19 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // str 8 - oa->write_character(static_cast(0xD9)); + oa->write_character(to_char_type(0xD9)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // str 16 - oa->write_character(static_cast(0xDA)); + oa->write_character(to_char_type(0xDA)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // str 32 - oa->write_character(static_cast(0xDB)); + oa->write_character(to_char_type(0xDB)); write_number(static_cast(N)); } @@ -8769,13 +8774,13 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // array 16 - oa->write_character(static_cast(0xDC)); + oa->write_character(to_char_type(0xDC)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // array 32 - oa->write_character(static_cast(0xDD)); + oa->write_character(to_char_type(0xDD)); write_number(static_cast(N)); } @@ -8799,13 +8804,13 @@ class binary_writer else if (N <= (std::numeric_limits::max)()) { // map 16 - oa->write_character(static_cast(0xDE)); + oa->write_character(to_char_type(0xDE)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { // map 32 - oa->write_character(static_cast(0xDF)); + oa->write_character(to_char_type(0xDF)); write_number(static_cast(N)); } @@ -8838,7 +8843,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('Z')); + oa->write_character(to_char_type('Z')); } break; } @@ -8848,8 +8853,8 @@ class binary_writer if (add_prefix) { oa->write_character(j.m_value.boolean - ? static_cast('T') - : static_cast('F')); + ? to_char_type('T') + : to_char_type('F')); } break; } @@ -8876,7 +8881,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('S')); + oa->write_character(to_char_type('S')); } write_number_with_ubjson_prefix(j.m_value.string->size(), true); oa->write_characters( @@ -8889,7 +8894,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('[')); + oa->write_character(to_char_type('[')); } bool prefix_required = true; @@ -8906,14 +8911,14 @@ class binary_writer if (same_prefix) { prefix_required = false; - oa->write_character(static_cast('$')); + oa->write_character(to_char_type('$')); oa->write_character(first_prefix); } } if (use_count) { - oa->write_character(static_cast('#')); + oa->write_character(to_char_type('#')); write_number_with_ubjson_prefix(j.m_value.array->size(), true); } @@ -8924,7 +8929,7 @@ class binary_writer if (not use_count) { - oa->write_character(static_cast(']')); + oa->write_character(to_char_type(']')); } break; @@ -8934,7 +8939,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('{')); + oa->write_character(to_char_type('{')); } bool prefix_required = true; @@ -8951,14 +8956,14 @@ class binary_writer if (same_prefix) { prefix_required = false; - oa->write_character(static_cast('$')); + oa->write_character(to_char_type('$')); oa->write_character(first_prefix); } } if (use_count) { - oa->write_character(static_cast('#')); + oa->write_character(to_char_type('#')); write_number_with_ubjson_prefix(j.m_value.object->size(), true); } @@ -8973,7 +8978,7 @@ class binary_writer if (not use_count) { - oa->write_character(static_cast('}')); + oa->write_character(to_char_type('}')); } break; @@ -8993,9 +8998,9 @@ class binary_writer @return The size of a BSON document entry header, including the id marker 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(0)); + const auto it = name.find(static_cast(0)); if (JSON_UNLIKELY(it != BasicJsonType::string_t::npos)) { 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 */ - void write_bson_entry_header(const typename BasicJsonType::string_t& name, - std::uint8_t element_type) + void write_bson_entry_header(const string_t& name, + const std::uint8_t element_type) { - oa->write_character(static_cast(element_type)); // boolean + oa->write_character(to_char_type(element_type)); // boolean oa->write_characters( reinterpret_cast(name.c_str()), name.size() + 1u); @@ -9020,17 +9025,17 @@ class binary_writer /*! @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) { write_bson_entry_header(name, 0x08); - oa->write_character(value ? static_cast(0x01) : static_cast(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 */ - void write_bson_double(const typename BasicJsonType::string_t& name, + void write_bson_double(const string_t& name, const double value) { write_bson_entry_header(name, 0x01); @@ -9040,7 +9045,7 @@ class binary_writer /*! @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; } @@ -9048,8 +9053,8 @@ class binary_writer /*! @brief Writes a BSON element with key @a name and string value @a value */ - void write_bson_string(const typename BasicJsonType::string_t& name, - const typename BasicJsonType::string_t& value) + void write_bson_string(const string_t& name, + const string_t& value) { 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 */ - void write_bson_null(const typename BasicJsonType::string_t& name) + void write_bson_null(const string_t& name) { 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 */ - void write_bson_integer(const typename BasicJsonType::string_t& name, + void write_bson_integer(const string_t& name, const std::int64_t value) { if ((std::numeric_limits::min)() <= value and value <= (std::numeric_limits::max)()) @@ -9103,45 +9108,39 @@ class binary_writer /*! @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::numeric_limits::max)())) - { - return sizeof(std::int32_t); - } - else - { - return sizeof(std::int64_t); - } + return (value <= static_cast((std::numeric_limits::max)())) + ? sizeof(std::int32_t) + : sizeof(std::int64_t); } /*! @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) { if (value <= static_cast((std::numeric_limits::max)())) { - write_bson_entry_header(name, 0x10); // int32 + write_bson_entry_header(name, 0x10 /* int32 */); write_number(static_cast(value)); } else if (value <= static_cast((std::numeric_limits::max)())) { - write_bson_entry_header(name, 0x12); // int64 + write_bson_entry_header(name, 0x12 /* int64 */); write_number(static_cast(value)); } 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 */ - 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) { 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 */ - void write_bson_array(const typename BasicJsonType::string_t& name, + void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value) { write_bson_entry_header(name, 0x04); // array @@ -9180,22 +9179,19 @@ class binary_writer write_bson_element(std::to_string(array_index++), el); } - oa->write_character(static_cast(0x00)); + oa->write_character(to_char_type(0x00)); } /*! @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. */ - 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 auto header_size = calc_bson_entry_header_size(name); switch (j.type()) { - case value_t::discarded: - return 0ul; - case value_t::object: return header_size + calc_bson_object_size(*j.m_value.object); @@ -9235,14 +9231,11 @@ class binary_writer current BSON document @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) { switch (j.type()) { - case value_t::discarded: - return; - case value_t::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) { - std::size_t document_size = 0; - - for (const auto& el : value) + std::size_t document_size = std::accumulate(value.begin(), value.end(), 0, + [](size_t result, const typename BasicJsonType::object_t::value_type & el) { - 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; } @@ -9306,7 +9298,7 @@ class binary_writer write_bson_element(el.first, el.second); } - oa->write_character(static_cast(0x00)); + oa->write_character(to_char_type(0x00)); } ////////// @@ -9315,12 +9307,12 @@ class binary_writer static constexpr CharType get_cbor_float_prefix(float /*unused*/) { - return static_cast(0xFA); // Single-Precision Float + return to_char_type(0xFA); // Single-Precision Float } static constexpr CharType get_cbor_float_prefix(double /*unused*/) { - return static_cast(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*/) { - return static_cast(0xCA); // float 32 + return to_char_type(0xCA); // float 32 } static constexpr CharType get_msgpack_float_prefix(double /*unused*/) { - return static_cast(0xCB); // float 64 + return to_char_type(0xCB); // float 64 } //////////// @@ -9364,7 +9356,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('i')); // int8 + oa->write_character(to_char_type('i')); // int8 } write_number(static_cast(n)); } @@ -9372,7 +9364,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('U')); // uint8 + oa->write_character(to_char_type('U')); // uint8 } write_number(static_cast(n)); } @@ -9380,7 +9372,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('I')); // int16 + oa->write_character(to_char_type('I')); // int16 } write_number(static_cast(n)); } @@ -9388,7 +9380,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('l')); // int32 + oa->write_character(to_char_type('l')); // int32 } write_number(static_cast(n)); } @@ -9396,7 +9388,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('L')); // int64 + oa->write_character(to_char_type('L')); // int64 } write_number(static_cast(n)); } @@ -9417,7 +9409,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('i')); // int8 + oa->write_character(to_char_type('i')); // int8 } write_number(static_cast(n)); } @@ -9425,7 +9417,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('U')); // uint8 + oa->write_character(to_char_type('U')); // uint8 } write_number(static_cast(n)); } @@ -9433,7 +9425,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('I')); // int16 + oa->write_character(to_char_type('I')); // int16 } write_number(static_cast(n)); } @@ -9441,7 +9433,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('l')); // int32 + oa->write_character(to_char_type('l')); // int32 } write_number(static_cast(n)); } @@ -9449,7 +9441,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(static_cast('L')); // int64 + oa->write_character(to_char_type('L')); // int64 } write_number(static_cast(n)); } @@ -9584,6 +9576,46 @@ class binary_writer 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 for a discussion. + template < typename C = CharType, + enable_if_t < std::is_signed::value and std::is_signed::value > * = nullptr > + static constexpr CharType to_char_type(std::uint8_t x) noexcept + { + return *reinterpret_cast(&x); + } + + template < typename C = CharType, + enable_if_t < std::is_signed::value and std::is_unsigned::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::value, "CharType must be POD"); + CharType result; + std::memcpy(&result, &x, sizeof(x)); + return result; + } + + template::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::value and + std::is_signed::value and + std::is_same::type>::value + > * = nullptr > + static constexpr CharType to_char_type(InputCharType x) noexcept + { + return x; + } + private: /// whether we can assume little endianess const bool is_little_endian = binary_reader::little_endianess(); diff --git a/test/src/unit-bson.cpp b/test/src/unit-bson.cpp index aeb7b898..d88a03e2 100644 --- a/test/src/unit-bson.cpp +++ b/test/src/unit-bson.cpp @@ -37,14 +37,6 @@ TEST_CASE("BSON") { 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") { json j = nullptr; @@ -392,32 +384,6 @@ TEST_CASE("BSON") 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 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") { json j = @@ -1136,7 +1102,7 @@ TEST_CASE("BSON numerical data") }; 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"); } }