IO: Support 0-padding for unsigned numbers.

This commit is contained in:
David Goldblatt 2020-08-05 18:30:34 -07:00 committed by David Goldblatt
parent 32d4673221
commit 7b187360e9
2 changed files with 36 additions and 2 deletions

View File

@ -346,9 +346,13 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (!left_justify && pad_len != 0) { \ if (!left_justify && pad_len != 0) { \
size_t j; \ size_t j; \
for (j = 0; j < pad_len; j++) { \ for (j = 0; j < pad_len; j++) { \
if (pad_zero) { \
APPEND_C('0'); \
} else { \
APPEND_C(' '); \ APPEND_C(' '); \
} \ } \
} \ } \
} \
/* Value. */ \ /* Value. */ \
APPEND_S(s, slen); \ APPEND_S(s, slen); \
/* Right padding. */ \ /* Right padding. */ \
@ -418,6 +422,8 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
unsigned char len = '?'; unsigned char len = '?';
char *s; char *s;
size_t slen; size_t slen;
bool first_width_digit = true;
bool pad_zero = false;
f++; f++;
/* Flags. */ /* Flags. */
@ -454,7 +460,12 @@ malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
width = -width; width = -width;
} }
break; 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': { case '5': case '6': case '7': case '8': case '9': {
uintmax_t uwidth; uintmax_t uwidth;
set_errno(0); 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() != assert(uwidth != UINTMAX_MAX || get_errno() !=
ERANGE); ERANGE);
width = (int)uwidth; width = (int)uwidth;
first_width_digit = false;
break; break;
} default: } default:
break; 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); intmax_t val JEMALLOC_CC_SILENCE_INIT(0);
char buf[D2S_BUFSIZE]; 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); GET_ARG_NUMERIC(val, len);
s = d2s(val, (plus_plus ? '+' : (plus_space ? s = d2s(val, (plus_plus ? '+' : (plus_space ?
' ' : '-')), buf, &slen); ' ' : '-')), buf, &slen);

View File

@ -175,6 +175,7 @@ TEST_BEGIN(test_malloc_snprintf) {
TEST("_1234_", "_%o_", 01234); TEST("_1234_", "_%o_", 01234);
TEST("_01234_", "_%#o_", 01234); TEST("_01234_", "_%#o_", 01234);
TEST("_1234_", "_%u_", 1234); TEST("_1234_", "_%u_", 1234);
TEST("01234", "%05u", 1234);
TEST("_1234_", "_%d_", 1234); TEST("_1234_", "_%d_", 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);
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_", "_%d_", 1234); TEST("_1234_", "_%d_", 1234);
TEST("_-1234_", "_%i_", -1234); TEST("_-1234_", "_%i_", -1234);