From 7b187360e9641c8f664709d3ac50296e3a87b2e0 Mon Sep 17 00:00:00 2001 From: David Goldblatt Date: Wed, 5 Aug 2020 18:30:34 -0700 Subject: [PATCH] IO: Support 0-padding for unsigned numbers. --- src/malloc_io.c | 28 ++++++++++++++++++++++++++-- test/unit/malloc_io.c | 10 ++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/malloc_io.c b/src/malloc_io.c index f5004f0a..59a0cbfc 100644 --- a/src/malloc_io.c +++ b/src/malloc_io.c @@ -346,7 +346,11 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { if (!left_justify && pad_len != 0) { \ size_t j; \ for (j = 0; j < pad_len; j++) { \ - APPEND_C(' '); \ + if (pad_zero) { \ + APPEND_C('0'); \ + } else { \ + APPEND_C(' '); \ + } \ } \ } \ /* Value. */ \ @@ -418,6 +422,8 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { unsigned char len = '?'; char *s; size_t slen; + bool first_width_digit = true; + bool pad_zero = false; f++; /* Flags. */ @@ -454,7 +460,12 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { width = -width; } break; - case '0': case '1': case '2': case '3': case '4': + case '0': + if (first_width_digit) { + pad_zero = true; + } + JEMALLOC_FALLTHROUGH; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { uintmax_t uwidth; set_errno(0); @@ -462,6 +473,7 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { assert(uwidth != UINTMAX_MAX || get_errno() != ERANGE); width = (int)uwidth; + first_width_digit = false; break; } default: break; @@ -519,6 +531,18 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { intmax_t val JEMALLOC_CC_SILENCE_INIT(0); char buf[D2S_BUFSIZE]; + /* + * Outputting negative, zero-padded numbers + * would require a nontrivial rework of the + * interaction between the width and padding + * (since 0 padding goes between the '-' and the + * number, while ' ' padding goes either before + * the - or after the number. Since we + * currently don't ever need 0-padded negative + * numbers, just don't bother supporting it. + */ + assert(!pad_zero); + GET_ARG_NUMERIC(val, len); s = d2s(val, (plus_plus ? '+' : (plus_space ? ' ' : '-')), buf, &slen); diff --git a/test/unit/malloc_io.c b/test/unit/malloc_io.c index 1a6e5f63..385f7450 100644 --- a/test/unit/malloc_io.c +++ b/test/unit/malloc_io.c @@ -175,6 +175,7 @@ TEST_BEGIN(test_malloc_snprintf) { TEST("_1234_", "_%o_", 01234); TEST("_01234_", "_%#o_", 01234); TEST("_1234_", "_%u_", 1234); + TEST("01234", "%05u", 1234); TEST("_1234_", "_%d_", 1234); TEST("_ 1234_", "_% d_", 1234); @@ -183,6 +184,15 @@ TEST_BEGIN(test_malloc_snprintf) { TEST("_-1234_", "_% d_", -1234); TEST("_-1234_", "_%+d_", -1234); + /* + * Morally, we should test these too, but 0-padded signed types are not + * yet supported. + * + * TEST("01234", "%05", 1234); + * TEST("-1234", "%05d", -1234); + * TEST("-01234", "%06d", -1234); + */ + TEST("_-1234_", "_%d_", -1234); TEST("_1234_", "_%d_", 1234); TEST("_-1234_", "_%i_", -1234);