From 1d361e2f8cd66c00635fb1cbc7aacdaf087abf78 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 20 Sep 2026 17:30:11 -0700 Subject: [PATCH] Simplify printf handling of a zero value with a zero precision Reuse getsign instead of mapping the sign to a string and let write_bytes' default_align handle align::none. Also drop the presentation type check: printf only produces dec, oct and hex for a non-char integral argument because 'c' converts the argument to the char type. --- include/fmt/printf.h | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/include/fmt/printf.h b/include/fmt/printf.h index 0caeae0c..e25e6fba 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -250,13 +250,9 @@ class printf_arg_formatter : public arg_formatter { // zero, so only the sign and the padding remain. void write_zero_with_zero_precision() { auto s = this->specs; - const char* sign_str = s.sign() == sign::plus ? "+" - : s.sign() == sign::space ? " " - : ""; s.set_type(presentation_type::none); - if (s.align() == align::none || s.align() == align::numeric) - s.set_align(align::right); - write_bytes(this->out, sign_str, s); + char sign_str[] = {getsign(s.sign()), '\0'}; + write_bytes(this->out, sign_str, s); } public: @@ -271,15 +267,9 @@ class printf_arg_formatter : public arg_formatter { // MSVC2013 fails to compile separate overloads for bool and Char so use // std::is_same instead. if (!std::is_same::value) { - auto t = this->specs.type(); - if (value == 0 && this->specs.precision == 0 && - (t == presentation_type::dec || t == presentation_type::oct || - t == presentation_type::hex)) { - write_zero_with_zero_precision(); - return; - } - write(value); - return; + if (value == 0 && this->specs.precision == 0) + return write_zero_with_zero_precision(); + return write(value); } format_specs s = this->specs; if (s.type() != presentation_type::none && @@ -569,13 +559,13 @@ void vprintf(buffer& buf, basic_string_view format, if (specs.type() == presentation_type::none) report_error("invalid format specifier"); if (upper) specs.set_upper(); - // For '#o', C requires a single '0' when the value and the precision are - // both zero. - bool alt_zero = specs.alt() && arg.visit(is_zero_int()); - if (alt_zero) specs.clear_alt(); - if (alt_zero && specs.type() == presentation_type::oct && - specs.precision == 0) - specs.precision = 1; + // C requires no '0x' prefix for a zero value and, for '#o', a single '0' + // when the value and the precision are both zero. + if (specs.alt() && arg.visit(is_zero_int())) { + specs.clear_alt(); + if (specs.type() == presentation_type::oct && specs.precision == 0) + specs.precision = 1; + } start = it;