From 88af7a915b29b484e4673ebff0da46c106650d3f Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 13:59:06 +0100 Subject: [PATCH] Start padding and alternate forms for integers --- luna/Format.h | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/luna/Format.h b/luna/Format.h index b2b47506..f3c38144 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -200,7 +200,7 @@ static bool is_integer_format_specifier(char c) return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); } -template static usize to_string(T value, T base, char* buf, usize max, bool uppercase) +static usize to_string(usize value, usize base, char* buf, usize max, bool uppercase) { usize i = 0; if (!value && max) @@ -217,8 +217,7 @@ template static usize to_string(T value, T base, char* buf, usize m return i; } -template -static int output_integer(char specifier, const conv_state& vstate, format_state& state, T value, bool negative) +static int output_integer(char specifier, conv_state& vstate, format_state& state, usize value, bool negative) { usize base = 10; bool uppercase = false; @@ -233,10 +232,37 @@ static int output_integer(char specifier, const conv_state& vstate, format_state } if (specifier == 'X') uppercase = true; - char buf[1024]; - usize buflen = to_string(value, (T)base, buf, sizeof(buf), uppercase); + if (base == 10) vstate.flags &= ~FLAG_ALTERNATE; // decimal doesn't have an alternate form - // FIXME: Start padding and alternate forms. + char buf[1024]; + usize buflen = to_string(value, base, buf, sizeof(buf), uppercase); + + if (!(vstate.flags & FLAG_LEFT_ALIGN) && + (vstate.flags & FLAG_ZERO_PAD)) // we're padding with zeroes from the beginning + { + bool extra_char = + negative || ((vstate.flags & FLAG_SIGN) || + (vstate.flags & FLAG_BLANK_SIGNED)); // are we adding an extra character after the buffer? + if (vstate.width && extra_char) vstate.width--; + + if (vstate.width && (vstate.flags & FLAG_ALTERNATE)) // fit in the characters we're using for the alternate form + { + vstate.width--; + if (vstate.width && (base == 2 || base == 16)) vstate.width--; + } + + while (buflen < vstate.width && buflen < sizeof(buf)) buf[buflen++] = '0'; + } + + while (buflen < vstate.precision && buflen < sizeof(buf)) buf[buflen++] = '0'; + + if (vstate.flags & FLAG_ALTERNATE) + { + if (base == 16 && !uppercase && buflen < sizeof(buf)) buf[buflen++] = 'x'; + if (base == 16 && uppercase && buflen < sizeof(buf)) buf[buflen++] = 'X'; + if (base == 2 && buflen < sizeof(buf)) buf[buflen++] = 'b'; + if (buflen < sizeof(buf)) buf[buflen++] = '0'; + } if (buflen < sizeof(buf)) { @@ -247,6 +273,8 @@ static int output_integer(char specifier, const conv_state& vstate, format_state buf[buflen++] = ' '; } + if (!(vstate.flags & FLAG_ZERO_PAD)) TRY_START_PAD(vstate, state, buflen); + usize i = buflen; while (i--) TRY_PUTCHAR(buf[i], state); @@ -256,7 +284,7 @@ static int output_integer(char specifier, const conv_state& vstate, format_state return 0; } -static int va_output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +static int va_output_integer(char specifier, conv_state& vstate, format_state& state, va_list ap) { bool is_signed = false; bool negative = false;