From e158b080bdc109628064a69944605b7f4c1c5d60 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 09:37:28 +0200 Subject: [PATCH] Fix stale and missing comments in binary_writer The doc block of write_number() ended up above the byte_swap() helpers added in #5286, about 80 lines from the function. It was also a plain comment that Doxygen skips, said "write a number to output input", and left BON8 out of the big-endian formats. Move it back onto write_number() as a /*! block and fix the text. write_bson() documented "@pre j.type() == value_t::object", but it throws type_error.317 for every other type, and to_bson() relies on that. Document the exception instead. Explain why the CBOR binary subtype is always written with a 0xD8..0xDB head and never in the one-byte tag form: binary_reader with cbor_tag_handler_t::store only keeps those heads as a subtype, so switching to write_cbor_head() would break round trips for subtypes 0..23. Also fix the grammar of the to_char_type comment. Comments only; no change in behavior, API or ABI. Part of #5710 Signed-off-by: Niels Lohmann --- .../nlohmann/detail/output/binary_writer.hpp | 37 +++++++++++-------- single_include/nlohmann/json.hpp | 37 +++++++++++-------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 9da4269a8..b39146a4f 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -115,7 +115,7 @@ class binary_writer /*! @param[in] j JSON value to serialize - @pre j.type() == value_t::object + @throw type_error.317 if @a j is not an object */ void write_bson(const BasicJsonType& j) { @@ -238,6 +238,13 @@ class binary_writer { if (j.m_data.m_value.binary->has_subtype()) { + // The subtype is always written as a tag with a 0xD8..0xDB + // head, never in the one-byte form 0xC0..0xD7 that CBOR + // allows for tags 0..23 (so this is not write_cbor_head). + // binary_reader with cbor_tag_handler_t::store only turns + // 0xD8..0xDB into a subtype and ignores the one-byte tags, + // so the shorter form would lose subtypes 0..23 on a round + // trip. if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); @@ -2408,19 +2415,6 @@ class binary_writer // Utility functions // /////////////////////// - /* - @brief write a number to output input - @param[in] n number of type @a NumberType - @param[in] OutputIsLittleEndian Set to true if output data is - required to be little endian - @tparam NumberType the type of the number - - @note This function needs to respect the system's endianness, because bytes - in CBOR, MessagePack, and UBJSON are stored in network order (big - endian) and therefore need reordering on little endian systems. - On the other hand, BSON and BJData use little endian and should reorder - on big endian systems. - */ // single-instruction byte swaps (compilers lower these to bswap/rev/movbe); // used to emit big-endian numbers without a per-byte std::reverse loop static std::uint16_t byte_swap(std::uint16_t x) noexcept @@ -2502,6 +2496,19 @@ class binary_writer std::reverse(a.begin(), a.end()); } + /*! + @brief write a number to the output + @param[in] n number of type @a NumberType + @param[in] OutputIsLittleEndian Set to true if output data is + required to be little endian + @tparam NumberType the type of the number + + @note This function needs to respect the system's endianness, because bytes + in CBOR, MessagePack, UBJSON, and BON8 are stored in network order + (big endian) and therefore need reordering on little endian systems. + On the other hand, BSON and BJData use little endian and should + reorder on big endian systems. + */ template void write_number(const NumberType n, const bool OutputIsLittleEndian = false) { @@ -2552,7 +2559,7 @@ class binary_writer } public: - // The following to_char_type functions are implement the conversion + // The following to_char_type functions 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. diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 576498738..63630a008 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20445,7 +20445,7 @@ class binary_writer /*! @param[in] j JSON value to serialize - @pre j.type() == value_t::object + @throw type_error.317 if @a j is not an object */ void write_bson(const BasicJsonType& j) { @@ -20568,6 +20568,13 @@ class binary_writer { if (j.m_data.m_value.binary->has_subtype()) { + // The subtype is always written as a tag with a 0xD8..0xDB + // head, never in the one-byte form 0xC0..0xD7 that CBOR + // allows for tags 0..23 (so this is not write_cbor_head). + // binary_reader with cbor_tag_handler_t::store only turns + // 0xD8..0xDB into a subtype and ignores the one-byte tags, + // so the shorter form would lose subtypes 0..23 on a round + // trip. if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); @@ -22738,19 +22745,6 @@ class binary_writer // Utility functions // /////////////////////// - /* - @brief write a number to output input - @param[in] n number of type @a NumberType - @param[in] OutputIsLittleEndian Set to true if output data is - required to be little endian - @tparam NumberType the type of the number - - @note This function needs to respect the system's endianness, because bytes - in CBOR, MessagePack, and UBJSON are stored in network order (big - endian) and therefore need reordering on little endian systems. - On the other hand, BSON and BJData use little endian and should reorder - on big endian systems. - */ // single-instruction byte swaps (compilers lower these to bswap/rev/movbe); // used to emit big-endian numbers without a per-byte std::reverse loop static std::uint16_t byte_swap(std::uint16_t x) noexcept @@ -22832,6 +22826,19 @@ class binary_writer std::reverse(a.begin(), a.end()); } + /*! + @brief write a number to the output + @param[in] n number of type @a NumberType + @param[in] OutputIsLittleEndian Set to true if output data is + required to be little endian + @tparam NumberType the type of the number + + @note This function needs to respect the system's endianness, because bytes + in CBOR, MessagePack, UBJSON, and BON8 are stored in network order + (big endian) and therefore need reordering on little endian systems. + On the other hand, BSON and BJData use little endian and should + reorder on big endian systems. + */ template void write_number(const NumberType n, const bool OutputIsLittleEndian = false) { @@ -22882,7 +22889,7 @@ class binary_writer } public: - // The following to_char_type functions are implement the conversion + // The following to_char_type functions 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.