From 26b4716740b15145371a230af54399642dd2a79a Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 16 Oct 2026 23:23:09 +0200 Subject: [PATCH] Write the count of a UBJSON or BJData container in one reservation With use_size, a container is announced by the marker `#` and its element count as an integer, three small sink writes for the many containers of up to 127 elements (an empty array, an object with a few members). A count of up to 127 is now written as `#`, `i` and one byte in a single reservation. Instructions per call (Linux, GCC 13, thousands), to_ubjson with use_size and use_type: canada 25813 -> 22060, citm_catalog 10656 -> 9192, 20000 small objects 18178 -> 16798; to_bjdata with use_size and use_type: canada 26341 -> 22588, citm_catalog 10904 -> 9440. Signed-off-by: Niels Lohmann --- .../nlohmann/detail/output/binary_writer.hpp | 23 +++++++++++++++---- single_include/nlohmann/json.hpp | 23 +++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 2021278ab..7c5a60a9b 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -1173,8 +1173,7 @@ class binary_writer if (use_count) { - oa.write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); + write_ubjson_count(j.m_data.m_value.array->size(), use_bjdata); } return !use_count; @@ -1213,8 +1212,7 @@ class binary_writer if (use_count) { - oa.write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); + write_ubjson_count(j.m_data.m_value.object->size(), use_bjdata); } return !use_count; @@ -3410,6 +3408,23 @@ class binary_writer } } + /// write the count marker `#` and the number of elements of a container as + /// an integer; a count of up to 127, which is `i` and a byte, in one reservation + void write_ubjson_count(const std::size_t count, const bool use_bjdata) + { + if (JSON_HEDLEY_LIKELY(count <= 127)) + { + CharType* const out = oa.reserve(3); + out[0] = to_char_type('#'); + out[1] = to_char_type('i'); + out[2] = to_char_type(static_cast(count)); + oa.commit(3); + return; + } + oa.write_character(to_char_type('#')); + write_number_with_ubjson_prefix(count, true, use_bjdata); + } + /*! @brief write a UBJSON/BJData string or object key: the optional string marker `S`, the length as an integer with its marker, and the characters diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 087ce0032..e7aa00d78 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -26023,8 +26023,7 @@ class binary_writer if (use_count) { - oa.write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); + write_ubjson_count(j.m_data.m_value.array->size(), use_bjdata); } return !use_count; @@ -26063,8 +26062,7 @@ class binary_writer if (use_count) { - oa.write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); + write_ubjson_count(j.m_data.m_value.object->size(), use_bjdata); } return !use_count; @@ -28260,6 +28258,23 @@ class binary_writer } } + /// write the count marker `#` and the number of elements of a container as + /// an integer; a count of up to 127, which is `i` and a byte, in one reservation + void write_ubjson_count(const std::size_t count, const bool use_bjdata) + { + if (JSON_HEDLEY_LIKELY(count <= 127)) + { + CharType* const out = oa.reserve(3); + out[0] = to_char_type('#'); + out[1] = to_char_type('i'); + out[2] = to_char_type(static_cast(count)); + oa.commit(3); + return; + } + oa.write_character(to_char_type('#')); + write_number_with_ubjson_prefix(count, true, use_bjdata); + } + /*! @brief write a UBJSON/BJData string or object key: the optional string marker `S`, the length as an integer with its marker, and the characters