From 35a3b0f3dee78116f2066e9c27886bc400464c8f Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Wed, 30 Sep 2026 18:13:26 +0200 Subject: [PATCH] Deduplicate the MessagePack unsigned-integer writer ladder The number_integer (non-negative branch) and number_unsigned cases in write_msgpack() each held their own copy of the fixint/uint8/16/32/64 ladder, kept in lockstep only by a comment ("we used the code from the value_t::number_unsigned case here"). Both copies mixed union members: the signed copy compared number_unsigned but wrote number_integer, and vice versa. Extract write_msgpack_unsigned(std::uint64_t), mirroring how write_cbor_head() already avoids the same duplication for CBOR, and call it from both cases. Each case now reads only its own active union member. Output bytes are unchanged for the default 64-bit number types. #5710 item 3 Signed-off-by: Niels Lohmann --- .../nlohmann/detail/output/binary_writer.hpp | 100 +++++++----------- single_include/nlohmann/json.hpp | 100 +++++++----------- 2 files changed, 80 insertions(+), 120 deletions(-) diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 36798ec84..ac3832a11 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -316,6 +316,43 @@ class binary_writer return static_cast(length); } + /*! + @brief write a non-negative integer using the MessagePack fixint/uint ladder + @param[in] n the value to write, already known to be non-negative + */ + void write_msgpack_unsigned(const std::uint64_t n) + { + if (n < 128) + { + // positive fixnum + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 8 + oa.write_character(to_char_type(0xCC)); + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 16 + oa.write_character(to_char_type(0xCD)); + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 32 + oa.write_character(to_char_type(0xCE)); + write_number(static_cast(n)); + } + else + { + // uint 64 + oa.write_character(to_char_type(0xCF)); + write_number(n); + } + } + /*! @param[in] j JSON value to serialize */ @@ -342,37 +379,8 @@ class binary_writer if (j.m_data.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa.write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa.write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa.write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else - { - // uint 64 - oa.write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } + // signed integers and unsigned integers. + write_msgpack_unsigned(static_cast(j.m_data.m_value.number_integer)); } else { @@ -414,35 +422,7 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa.write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa.write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa.write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else - { - // uint 64 - oa.write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } + write_msgpack_unsigned(static_cast(j.m_data.m_value.number_unsigned)); break; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 45e794178..cc542156c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -20609,6 +20609,43 @@ class binary_writer return static_cast(length); } + /*! + @brief write a non-negative integer using the MessagePack fixint/uint ladder + @param[in] n the value to write, already known to be non-negative + */ + void write_msgpack_unsigned(const std::uint64_t n) + { + if (n < 128) + { + // positive fixnum + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 8 + oa.write_character(to_char_type(0xCC)); + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 16 + oa.write_character(to_char_type(0xCD)); + write_number(static_cast(n)); + } + else if (n <= (std::numeric_limits::max)()) + { + // uint 32 + oa.write_character(to_char_type(0xCE)); + write_number(static_cast(n)); + } + else + { + // uint 64 + oa.write_character(to_char_type(0xCF)); + write_number(n); + } + } + /*! @param[in] j JSON value to serialize */ @@ -20635,37 +20672,8 @@ class binary_writer if (j.m_data.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa.write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa.write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa.write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else - { - // uint 64 - oa.write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } + // signed integers and unsigned integers. + write_msgpack_unsigned(static_cast(j.m_data.m_value.number_integer)); } else { @@ -20707,35 +20715,7 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa.write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa.write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa.write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } - else - { - // uint 64 - oa.write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); - } + write_msgpack_unsigned(static_cast(j.m_data.m_value.number_unsigned)); break; }