BSON: Reworked the binary_writer such that it precomputes the size of the BSON-output.
				
					
				
			This way, the output_adapter can work on simple output iterators and no longer requires random access iterators.
This commit is contained in:
		
							parent
							
								
									81f4b34e06
								
							
						
					
					
						commit
						062aeaf7b6
					
				
					 5 changed files with 488 additions and 384 deletions
				
			
		|  | @ -9,6 +9,7 @@ | |||
| #include <nlohmann/detail/input/binary_reader.hpp> | ||||
| #include <nlohmann/detail/output/output_adapters.hpp> | ||||
| 
 | ||||
| 
 | ||||
| namespace nlohmann | ||||
| { | ||||
| namespace detail | ||||
|  | @ -676,187 +677,278 @@ class binary_writer | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_boolean(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @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) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x08)); // boolean
 | ||||
|         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @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) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(element_type)); // boolean
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
|         oa->write_character(j.m_value.boolean ? static_cast<CharType>(0x01) : static_cast<CharType>(0x00)); | ||||
|         return /*id*/ 1ul + name.size() + 1u + /*boolean value*/ 1u; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_double(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and boolean value @a value | ||||
|     */ | ||||
|     void write_bson_boolean(const typename BasicJsonType::string_t& name, const bool value) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x01)); // double
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
|         write_number<decltype(j.m_value.number_float), true>(j.m_value.number_float); | ||||
|         return /*id*/ 1ul + name.size() + 1u + /*double value*/ 8u; | ||||
|         write_bson_entry_header(name, 0x08); | ||||
|         oa->write_character(value ? static_cast<CharType>(0x01) : static_cast<CharType>(0x00)); | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_string(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and double value @a value | ||||
|     */ | ||||
|     void write_bson_double(const typename BasicJsonType::string_t& name, const double value) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x02)); // string (UTF-8)
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
| 
 | ||||
|         write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.string->size() + 1ul)); | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(j.m_value.string->c_str()), | ||||
|             j.m_value.string->size() + 1); | ||||
| 
 | ||||
|         return /*id*/ 1ul + name.size() + 1ul + sizeof(std::int32_t) + j.m_value.string->size() + 1ul; | ||||
|         write_bson_entry_header(name, 0x01); | ||||
|         write_number<double, true>(value); | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_null(const typename BasicJsonType::string_t& name, const BasicJsonType&) | ||||
|     /*!
 | ||||
|     @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) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x0A)); // null
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
| 
 | ||||
|         return /*id*/ 1ul + name.size() + 1ul; | ||||
|         return sizeof(std::int32_t) + value.size() + 1ul; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_integer(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @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) | ||||
|     { | ||||
|         auto n = j.m_value.number_integer; | ||||
|         if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)()) | ||||
|         write_bson_entry_header(name, 0x02); | ||||
| 
 | ||||
|         write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul)); | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(value.c_str()), | ||||
|             value.size() + 1); | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and null value | ||||
|     */ | ||||
|     void write_bson_null(const typename BasicJsonType::string_t& name) | ||||
|     { | ||||
|         write_bson_entry_header(name, 0x0A); | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @return The size of the BSON-encoded integer @a value | ||||
|     */ | ||||
|     static std::size_t calc_bson_integer_size(const std::int64_t value) | ||||
|     { | ||||
|         if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()) | ||||
|         { | ||||
|             oa->write_character(static_cast<CharType>(0x10)); // int32
 | ||||
|             oa->write_characters( | ||||
|                 reinterpret_cast<const CharType*>(name.c_str()), | ||||
|                 name.size() + 1u); | ||||
| 
 | ||||
|             write_number<std::int32_t, true>(static_cast<std::int32_t>(n)); | ||||
| 
 | ||||
|             return /*id*/ 1ul + name.size() + 1ul + sizeof(std::int32_t); | ||||
|             return sizeof(std::int32_t); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             oa->write_character(static_cast<CharType>(0x12)); // int64
 | ||||
|             oa->write_characters( | ||||
|                 reinterpret_cast<const CharType*>(name.c_str()), | ||||
|                 name.size() + 1u); | ||||
| 
 | ||||
|             write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_integer)); | ||||
| 
 | ||||
|             return /*id*/ 1ul + name.size() + 1ul + sizeof(std::int64_t); | ||||
|             return sizeof(std::int64_t); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_unsigned(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and integer @a value | ||||
|     */ | ||||
|     void write_bson_integer(const typename BasicJsonType::string_t& name, const std::int64_t value) | ||||
|     { | ||||
|         auto n = j.m_value.number_integer; | ||||
|         if (n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)())) | ||||
|         if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()) | ||||
|         { | ||||
|             oa->write_character(static_cast<CharType>(0x10)); // int32
 | ||||
|             oa->write_characters( | ||||
|                 reinterpret_cast<const CharType*>(name.c_str()), | ||||
|                 name.size() + 1u); | ||||
| 
 | ||||
|             write_number<std::int32_t, true>(static_cast<std::int32_t>(n)); | ||||
| 
 | ||||
|             return /*id*/ 1ul + name.size() + 1ul + sizeof(std::int32_t); | ||||
|             write_bson_entry_header(name, 0x10); // int32
 | ||||
|             write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             oa->write_character(static_cast<CharType>(0x12)); // int64
 | ||||
|             oa->write_characters( | ||||
|                 reinterpret_cast<const CharType*>(name.c_str()), | ||||
|                 name.size() + 1u); | ||||
| 
 | ||||
|             write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_integer)); | ||||
| 
 | ||||
|             return /*id*/ 1ul + name.size() + 1ul + sizeof(std::int64_t); | ||||
|             write_bson_entry_header(name, 0x12); // int64
 | ||||
|             write_number<std::int64_t, true>(static_cast<std::int64_t>(value)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_object_internal(const typename BasicJsonType::string_t& name, const BasicJsonType& 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) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x03)); // object
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
| 
 | ||||
|         auto const embedded_document_size = write_bson_object(j); | ||||
| 
 | ||||
|         return /*id*/ 1ul + name.size() + 1ul + embedded_document_size; | ||||
|         if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | ||||
|         { | ||||
|             return sizeof(std::int32_t); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return sizeof(std::int64_t); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_array(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and unsigned @a value | ||||
|     */ | ||||
|     void write_bson_unsigned(const typename BasicJsonType::string_t& name, const std::uint64_t value) | ||||
|     { | ||||
|         oa->write_character(static_cast<CharType>(0x04)); // object
 | ||||
|         oa->write_characters( | ||||
|             reinterpret_cast<const CharType*>(name.c_str()), | ||||
|             name.size() + 1u); | ||||
| 
 | ||||
| 
 | ||||
|         auto document_size_offset = oa->reserve_characters(4ul); | ||||
|         std::int32_t embedded_document_size = 5ul; | ||||
| 
 | ||||
|         for (const auto& el : *j.m_value.array) | ||||
|         if (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) | ||||
|         { | ||||
|             embedded_document_size += write_bson_object_entry("", el); | ||||
|             write_bson_entry_header(name, 0x10); // int32
 | ||||
|             write_number<std::int32_t, true>(static_cast<std::int32_t>(value)); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             write_bson_entry_header(name, 0x12); // int64
 | ||||
|             write_number<std::int64_t, true>(static_cast<std::int64_t>(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, const typename BasicJsonType::object_t& value) | ||||
|     { | ||||
|         write_bson_entry_header(name, 0x03); // object
 | ||||
|         write_bson_object(value); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /*!
 | ||||
|     @return The size of the BSON-encoded array @a value | ||||
|     */ | ||||
|     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) | ||||
|     { | ||||
|         std::size_t embedded_document_size = 0ul; | ||||
| 
 | ||||
|         for (const auto& el : value) | ||||
|         { | ||||
|             embedded_document_size += calc_bson_element_size("", el); | ||||
|         } | ||||
| 
 | ||||
|         return sizeof(std::int32_t) + embedded_document_size + 1ul; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @brief Writes a BSON element with key @a name and array @a value | ||||
|     */ | ||||
|     void write_bson_array(const typename BasicJsonType::string_t& name, const typename BasicJsonType::array_t& value) | ||||
|     { | ||||
|         write_bson_entry_header(name, 0x04); // array
 | ||||
|         write_number<std::int32_t, true>(calc_bson_array_size(value)); | ||||
| 
 | ||||
|         for (const auto& el : value) | ||||
|         { | ||||
|             write_bson_element("", el); | ||||
|         } | ||||
| 
 | ||||
|         oa->write_character(static_cast<CharType>(0x00)); | ||||
|         write_number_at<std::int32_t, true>(document_size_offset, embedded_document_size); | ||||
| 
 | ||||
|         return /*id*/ 1ul + name.size() + 1ul + embedded_document_size; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t write_bson_object_entry(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
| 
 | ||||
|     /*!
 | ||||
|     @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, const BasicJsonType& j) | ||||
|     { | ||||
|         const auto header_size = calc_bson_entry_header_size(name); | ||||
|         switch (j.type()) | ||||
|         { | ||||
|             // LCOV_EXCL_START
 | ||||
|             default: | ||||
|                 assert(false); | ||||
|                 return 0ul; | ||||
|             // LCOV_EXCL_STOP
 | ||||
|             case value_t::object: | ||||
|                 return header_size + calc_bson_object_size(*j.m_value.object); | ||||
|             case value_t::array: | ||||
|                 return header_size + calc_bson_array_size(*j.m_value.array); | ||||
|             case value_t::boolean: | ||||
|                 return header_size + 1ul; | ||||
|             case value_t::number_float: | ||||
|                 return header_size + 8ul; | ||||
|             case value_t::number_integer: | ||||
|                 return header_size + calc_bson_integer_size(j.m_value.number_integer); | ||||
|             case value_t::number_unsigned: | ||||
|                 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); | ||||
|             case value_t::string: | ||||
|                 return header_size + calc_bson_string_size(*j.m_value.string); | ||||
|             case value_t::null: | ||||
|                 return header_size + 0ul; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /*!
 | ||||
|     @brief Serializes the JSON value @a j to BSON and associates it with the key @a name. | ||||
|     @param name The name to associate with the JSON entity @a j within the current BSON document | ||||
|     @return The size of the bson entry | ||||
|     */ | ||||
|     void write_bson_element(const typename BasicJsonType::string_t& name, const BasicJsonType& j) | ||||
|     { | ||||
|         switch (j.type()) | ||||
|         { | ||||
|             // LCOV_EXCL_START
 | ||||
|             default: | ||||
|                 assert(false); | ||||
|                 break; | ||||
|                 return; | ||||
|             // LCOV_EXCL_STOP
 | ||||
|             case value_t::object: | ||||
|                 return write_bson_object_internal(name, j); | ||||
|                 return write_bson_object_entry(name, *j.m_value.object); | ||||
|             case value_t::array: | ||||
|                 return write_bson_array(name, j); | ||||
|                 return write_bson_array(name, *j.m_value.array); | ||||
|             case value_t::boolean: | ||||
|                 return write_bson_boolean(name, j); | ||||
|                 return write_bson_boolean(name, j.m_value.boolean); | ||||
|             case value_t::number_float: | ||||
|                 return write_bson_double(name, j); | ||||
|                 return write_bson_double(name, j.m_value.number_float); | ||||
|             case value_t::number_integer: | ||||
|                 return write_bson_integer(name, j); | ||||
|                 return write_bson_integer(name, j.m_value.number_integer); | ||||
|             case value_t::number_unsigned: | ||||
|                 return write_bson_unsigned(name, j); | ||||
|                 return write_bson_unsigned(name, j.m_value.number_unsigned); | ||||
|             case value_t::string: | ||||
|                 return write_bson_string(name, j); | ||||
|                 return write_bson_string(name, *j.m_value.string); | ||||
|             case value_t::null: | ||||
|                 return write_bson_null(name, j); | ||||
|                 return write_bson_null(name); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|         return 0ul; | ||||
|     /*!
 | ||||
|     @brief Calculates the size of the BSON serialization of the given | ||||
|            JSON-object @a j. | ||||
|     @param[in] j  JSON value to serialize | ||||
|     @pre       j.type() == value_t::object | ||||
|     */ | ||||
|     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) | ||||
|         { | ||||
|             document_size += calc_bson_element_size(el.first, el.second); | ||||
|         } | ||||
| 
 | ||||
|         return sizeof(std::int32_t) + document_size + 1ul; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|     @param[in] j  JSON value to serialize | ||||
|     @pre       j.type() == value_t::object | ||||
|     */ | ||||
|     std::size_t write_bson_object(const BasicJsonType& j) | ||||
|     void write_bson_object(const typename BasicJsonType::object_t& value) | ||||
|     { | ||||
|         assert(j.type() == value_t::object); | ||||
|         auto document_size_offset = oa->reserve_characters(4ul); | ||||
|         std::int32_t document_size = 5ul; | ||||
|         write_number<std::int32_t, true>(calc_bson_object_size(value)); | ||||
| 
 | ||||
|         for (const auto& el : *j.m_value.object) | ||||
|         for (const auto& el : value) | ||||
|         { | ||||
|             document_size += write_bson_object_entry(el.first, el.second); | ||||
|             write_bson_element(el.first, el.second); | ||||
|         } | ||||
| 
 | ||||
|         oa->write_character(static_cast<CharType>(0x00)); | ||||
|         write_number_at<std::int32_t, true>(document_size_offset, document_size); | ||||
|         return document_size; | ||||
|     } | ||||
| 
 | ||||
|     /*!
 | ||||
|  | @ -873,7 +965,7 @@ class binary_writer | |||
|             case value_t::discarded: | ||||
|                 break; | ||||
|             case value_t::object: | ||||
|                 write_bson_object(j); | ||||
|                 write_bson_object(*j.m_value.object); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | @ -909,35 +1001,6 @@ class binary_writer | |||
|         oa->write_characters(vec.data(), sizeof(NumberType)); | ||||
|     } | ||||
| 
 | ||||
|     /*
 | ||||
|     @brief write a number to output in little endian format | ||||
| 
 | ||||
|     @param[in] offset The offset where to start writing | ||||
|     @param[in] n number of type @a NumberType | ||||
|     @tparam NumberType the type of the number | ||||
|     @tparam OutputIsLittleEndian Set to true if output data is | ||||
|                                  required to be little endian | ||||
|     */ | ||||
|     template<typename NumberType, bool OutputIsLittleEndian = false> | ||||
|     void write_number_at(std::size_t offset, const NumberType n) | ||||
|     { | ||||
|         // step 1: write number to array of length NumberType
 | ||||
|         std::array<CharType, sizeof(NumberType)> vec; | ||||
|         std::memcpy(vec.data(), &n, sizeof(NumberType)); | ||||
| 
 | ||||
|         // step 2: write array to output (with possible reordering)
 | ||||
|         // LCOV_EXCL_START
 | ||||
|         if (is_little_endian && !OutputIsLittleEndian) | ||||
|         { | ||||
|             // reverse byte order prior to conversion if necessary
 | ||||
|             std::reverse(vec.begin(), vec.end()); | ||||
|         } | ||||
|         // LCOV_EXCL_STOP
 | ||||
| 
 | ||||
|         oa->write_characters_at(offset, vec.data(), sizeof(NumberType)); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // UBJSON: write number (floating point)
 | ||||
|     template<typename NumberType, typename std::enable_if< | ||||
|                  std::is_floating_point<NumberType>::value, int>::type = 0> | ||||
|  |  | |||
|  | @ -18,8 +18,6 @@ template<typename CharType> struct output_adapter_protocol | |||
| { | ||||
|     virtual void write_character(CharType c) = 0; | ||||
|     virtual void write_characters(const CharType* s, std::size_t length) = 0; | ||||
|     virtual void write_characters_at(std::size_t position, const CharType* s, std::size_t length) = 0; | ||||
|     virtual std::size_t reserve_characters(std::size_t length) = 0; | ||||
|     virtual ~output_adapter_protocol() = default; | ||||
| }; | ||||
| 
 | ||||
|  | @ -44,18 +42,6 @@ class output_vector_adapter : public output_adapter_protocol<CharType> | |||
|         std::copy(s, s + length, std::back_inserter(v)); | ||||
|     } | ||||
| 
 | ||||
|     void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         std::copy(s, s + length, std::begin(v) + position); | ||||
|     } | ||||
| 
 | ||||
|     std::size_t reserve_characters(std::size_t length) override | ||||
|     { | ||||
|         const auto position = v.size(); | ||||
|         std::fill_n(std::back_inserter(v), length, static_cast<CharType>(0x00)); | ||||
|         return position; | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     std::vector<CharType>& v; | ||||
| }; | ||||
|  | @ -77,22 +63,6 @@ class output_stream_adapter : public output_adapter_protocol<CharType> | |||
|         stream.write(s, static_cast<std::streamsize>(length)); | ||||
|     } | ||||
| 
 | ||||
|     void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         const auto orig_offset = stream.tellp(); | ||||
|         stream.seekp(static_cast<typename std::basic_ostream<CharType>::pos_type>(position)); | ||||
|         stream.write(s, static_cast<std::streamsize>(length)); | ||||
|         stream.seekp(orig_offset); | ||||
|     } | ||||
| 
 | ||||
|     std::size_t reserve_characters(std::size_t length) override | ||||
|     { | ||||
|         const auto position = stream.tellp(); | ||||
|         std::vector<CharType> empty(length, static_cast<CharType>(0)); | ||||
|         stream.write(empty.data(), length); | ||||
|         return static_cast<std::size_t>(position); | ||||
|     } | ||||
| 
 | ||||
|   private: | ||||
|     std::basic_ostream<CharType>& stream; | ||||
| }; | ||||
|  | @ -114,19 +84,6 @@ class output_string_adapter : public output_adapter_protocol<CharType> | |||
|         str.append(s, length); | ||||
|     } | ||||
| 
 | ||||
|     void write_characters_at(std::size_t position, const CharType* s, std::size_t length) override | ||||
|     { | ||||
|         std::copy(s, s + length, std::begin(str) + position); | ||||
|     } | ||||
| 
 | ||||
|     std::size_t reserve_characters(std::size_t length) override | ||||
|     { | ||||
|         const auto position = str.size(); | ||||
|         std::fill_n(std::back_inserter(str), length, static_cast<CharType>(0x00)); | ||||
|         return position; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|   private: | ||||
|     StringType& str; | ||||
| }; | ||||
|  |  | |||
|  | @ -6594,9 +6594,45 @@ class basic_json | |||
|     /*!
 | ||||
|     @brief Serializes the given JSON object `j` to BSON and returns a vector | ||||
|            containing the corresponding BSON-representation. | ||||
|     @param j The JSON object to convert to BSON. | ||||
|     @return The BSON representation of the JSON input `j`. | ||||
|     @pre The input `j` shall be an object: `j.is_object() == true` | ||||
| 
 | ||||
|     BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are | ||||
|     stored as a single entity (a so-called document). | ||||
| 
 | ||||
|     The library uses the following mapping from JSON values types to BSON types: | ||||
| 
 | ||||
|     JSON value type | value/range                       | BSON type   | marker | ||||
|     --------------- | --------------------------------- | ----------- | ------ | ||||
|     null            | `null`                            | null        | 0x0A | ||||
|     boolean         | `true`, `false`                   | boolean     | 0x08 | ||||
|     number_integer  | -9223372036854775808..-2147483649 | int64       | 0x12 | ||||
|     number_integer  | -2147483648..2147483647           | int32       | 0x10 | ||||
|     number_integer  | 2147483648..9223372036854775807   | int64       | 0x12 | ||||
|     number_unsigned | 0..2147483647                     | int32       | 0x10 | ||||
|     number_unsigned | 2147483648..9223372036854775807   | int64       | 0x12 | ||||
|     number_float    | *any value*                       | double      | 0x01 | ||||
|     string          | *any value*                       | string      | 0x02 | ||||
|     array           | *any value*                       | document    | 0x04 | ||||
|     object          | *any value*                       | document    | 0x03 | ||||
| 
 | ||||
|     @warning The mapping is **incomplete**, since only JSON-objects (and things | ||||
|     contained therein) can be serialized to BSON. | ||||
| 
 | ||||
|     @pre The input `j` is required to be an object: `j.is_object() == true` | ||||
| 
 | ||||
|     @note Any BSON output created via @ref to_bson can be successfully parsed | ||||
|           by @ref from_bson. | ||||
| 
 | ||||
|     @param[in] j  JSON value to serialize | ||||
|     @return BSON serialization as byte vector | ||||
| 
 | ||||
|     @complexity Linear in the size of the JSON value @a j. | ||||
| 
 | ||||
|     @sa http://bsonspec.org/spec.html
 | ||||
|     @sa @ref from_bson(detail::input_adapter, const bool strict) for the | ||||
|         analogous deserialization | ||||
|     @sa @ref to_ubjson(const basic_json&) for the related UBJSON format | ||||
|     @sa @ref to_cbor(const basic_json&) for the related CBOR format | ||||
|     @sa @ref to_msgpack(const basic_json&) for the related MessagePack format | ||||
|     */ | ||||
|     static std::vector<uint8_t> to_bson(const basic_json& j) | ||||
|     { | ||||
|  | @ -6611,6 +6647,7 @@ class basic_json | |||
|     @param j The JSON object to convert to BSON. | ||||
|     @param o The output adapter that receives the binary BSON representation. | ||||
|     @pre The input `j` shall be an object: `j.is_object() == true` | ||||
|     @sa @ref to_bson(const basic_json&) | ||||
|     */ | ||||
|     static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o) | ||||
|     { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue