diff --git a/srv/format.c b/srv/format.c index f3bc2c1..ec4de76 100644 --- a/srv/format.c +++ b/srv/format.c @@ -21,9 +21,9 @@ static uint32_t buffer_write(uint8_t byte, void* arg); static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va); static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base); + int32_t number, uint8_t base, uint8_t width, bool zero_padding); static uint32_t render_unsigned(FormatCallback callback, void* arg, - uint32_t number, uint8_t base); + uint32_t number, uint8_t base, uint8_t width, bool zero_padding); //--local variables------------------------------------------------------------- @@ -74,7 +74,9 @@ static uint32_t buffer_write(uint8_t byte, void* arg) static uint32_t render_format(FormatCallback callback, void* arg, const char* restrict format, va_list va) { + uint8_t width = 0; bool in_format = false; + bool zero_padding = false; for (const char* c = format; *c != '\0'; ++c) { @@ -97,22 +99,40 @@ static uint32_t render_format(FormatCallback callback, void* arg, } break; case 'i': - if (render_signed(callback, arg, va_arg(va, int32_t), 10)) { + if (render_signed(callback, arg, va_arg(va, int32_t), + 10, width, zero_padding)) { return 1; } break; case 'u': - if (render_unsigned(callback, arg, - va_arg(va, uint32_t), 10)) { + if (render_unsigned(callback, arg, va_arg(va, uint32_t), + 10, width, zero_padding)) { return 1; } break; case 'x': - if (render_unsigned(callback, arg, - va_arg(va, uint32_t), 16)) { + if (render_unsigned(callback, arg, va_arg(va, uint32_t), + 16, width, zero_padding)) { return 1; } break; + case '0': + if (width == 0) { + zero_padding = true; + continue; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + width *= 10; + width += (*c - '0'); + continue; default: //TODO manage error break; @@ -121,6 +141,8 @@ static uint32_t render_format(FormatCallback callback, void* arg, switch (*c) { case '%': in_format = true; + zero_padding = false; + width = 0; continue; default: if (callback(*c, arg)) return 1; @@ -135,23 +157,70 @@ static uint32_t render_format(FormatCallback callback, void* arg, } static uint32_t render_signed(FormatCallback callback, void* arg, - int32_t number, uint8_t base) + int32_t number, uint8_t base, uint8_t width, bool zero_padding) { + if (width > 0 && number < 0) { + --width; + } + + if (width > 0) { + uint32_t abs_number; + if (number < 0) { + abs_number = -number; + } else { + abs_number = number; + } + + uint32_t base_power = base; + while (width > 0 && base_power <= abs_number) { + base_power *= base; + --width; + } + if (width > 0) { + --width; + } + + while (width > 0) { + --width; + if (zero_padding) { + if (callback('0', arg)) return 1; + } else { + if (callback(' ', arg)) return 1; + } + } + } + if (number < 0) { callback('-', arg); number = -number; } - return render_unsigned(callback, arg, (uint32_t)number, base); + return render_unsigned(callback, arg, (uint32_t)number, base, 0, + zero_padding); } static uint32_t render_unsigned(FormatCallback callback, void* arg, - uint32_t number, uint8_t base) + uint32_t number, uint8_t base, uint8_t width, bool zero_padding) { uint32_t base_power = base; while (base_power <= number) { base_power *= base; + if (width > 0) { + --width; + } + } + if (width > 0) { + --width; + } + + while (width > 0) { + --width; + if (zero_padding) { + if (callback('0', arg)) return 1; + } else { + if (callback(' ', arg)) return 1; + } } while (base_power > 1) {