From cbd427b14b75c859df14d36cb05dab0765616a52 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Fri, 23 Oct 2020 00:46:40 -0400 Subject: [PATCH] add 64-bit formatting support --- src/hos_printf.c | 129 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 113 insertions(+), 16 deletions(-) diff --git a/src/hos_printf.c b/src/hos_printf.c index 6013d53..aa1f899 100644 --- a/src/hos_printf.c +++ b/src/hos_printf.c @@ -3,7 +3,7 @@ #include #include "string.h" -static size_t format_dec(char * buffer, int v) +static size_t format_dec(char * buffer, int32_t v) { size_t sz = 0u; bool printing = false; @@ -12,9 +12,9 @@ static size_t format_dec(char * buffer, int v) buffer[sz++] = '-'; v = -v; } - for (int div = 1000000000; div >= 1; div /= 10) + for (int32_t div = 1000000000; div >= 1; div /= 10) { - int digit = v / div; + int32_t digit = v / div; v %= div; if ((digit != 0) || (div == 1)) { @@ -28,12 +28,37 @@ static size_t format_dec(char * buffer, int v) return sz; } -static size_t format_udec(char * buffer, unsigned int v) +static size_t format_dec64(char * buffer, int64_t v) { size_t sz = 0u; - for (unsigned int div = 1000000000u; div >= 1u; div /= 10u) + bool printing = false; + if (v < 0) { - unsigned int digit = v / div; + buffer[sz++] = '-'; + v = -v; + } + for (int64_t div = 1000000000000000000; div >= 1; div /= 10) + { + int64_t digit = v / div; + v %= div; + if ((digit != 0) || (div == 1)) + { + printing = true; + } + if (printing) + { + buffer[sz++] = digit + '0'; + } + } + return sz; +} + +static size_t format_udec(char * buffer, int32_t v) +{ + size_t sz = 0u; + for (int32_t div = 1000000000u; div >= 1u; div /= 10u) + { + int32_t digit = v / div; v %= div; if ((digit != 0) || (sz > 0u) || (div == 1)) { @@ -43,7 +68,22 @@ static size_t format_udec(char * buffer, unsigned int v) return sz; } -static size_t format_hex(char * buffer, int v, bool upper) +static size_t format_udec64(char * buffer, uint64_t v) +{ + size_t sz = 0u; + for (uint64_t div = 10000000000000000000u; div >= 1u; div /= 10u) + { + uint64_t digit = v / div; + v %= div; + if ((digit != 0) || (sz > 0u) || (div == 1)) + { + buffer[sz++] = digit + '0'; + } + } + return sz; +} + +static size_t format_hex(char * buffer, uint32_t v, bool upper) { const char upper_hex[] = "0123456789ABCDEF"; const char lower_hex[] = "0123456789abcdef"; @@ -60,6 +100,23 @@ static size_t format_hex(char * buffer, int v, bool upper) return sz; } +static size_t format_hex64(char * buffer, uint64_t v, bool upper) +{ + const char upper_hex[] = "0123456789ABCDEF"; + const char lower_hex[] = "0123456789abcdef"; + size_t sz = 0u; + for (int i = 60; i >= 0; i -= 4) + { + uint8_t n = (v >> i) & 0xFu; + if ((sz > 0u) || (n != 0u) || (i == 0)) + { + buffer[sz] = upper ? upper_hex[n] : lower_hex[n]; + sz++; + } + } + return sz; +} + static void pad_write(const stream_t * stream, const char * data, size_t length, bool leading_zero, bool left_just, size_t width) { if (left_just) @@ -88,10 +145,12 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) { bool in_conv = false; char c; - char buffer[12]; + char buffer[22]; size_t width; bool leading_zero; bool left_just; + bool long_flag; + size_t length; while ((c = *fmt)) { if (in_conv) @@ -103,8 +162,16 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) break; case 'X': { - unsigned int v = va_arg(va, unsigned int); - size_t length = format_hex(buffer, v, true); + if (long_flag) + { + uint64_t v = va_arg(va, uint64_t); + length = format_hex(buffer, v, true); + } + else + { + uint32_t v = va_arg(va, uint32_t); + length = format_hex(buffer, v, true); + } pad_write(stream, buffer, length, leading_zero, left_just, width); } break; @@ -116,8 +183,16 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) break; case 'd': { - int v = va_arg(va, int); - size_t length = format_dec(buffer, v); + if (long_flag) + { + int64_t v = va_arg(va, int64_t); + length = format_dec64(buffer, v); + } + else + { + int32_t v = va_arg(va, int32_t); + length = format_dec(buffer, v); + } pad_write(stream, buffer, length, leading_zero, left_just, width); } break; @@ -129,15 +204,31 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) break; case 'u': { - unsigned int v = va_arg(va, unsigned int); - size_t length = format_udec(buffer, v); + if (long_flag) + { + uint64_t v = va_arg(va, uint64_t); + length = format_udec64(buffer, v); + } + else + { + uint32_t v = va_arg(va, uint32_t); + length = format_udec(buffer, v); + } pad_write(stream, buffer, length, leading_zero, left_just, width); } break; case 'x': { - unsigned int v = va_arg(va, unsigned int); - size_t length = format_hex(buffer, v, false); + if (long_flag) + { + uint64_t v = va_arg(va, uint64_t); + length = format_hex64(buffer, v, false); + } + else + { + uint32_t v = va_arg(va, uint32_t); + length = format_hex(buffer, v, false); + } pad_write(stream, buffer, length, leading_zero, left_just, width); } break; @@ -150,6 +241,7 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) width = 0u; leading_zero = false; left_just = false; + long_flag = false; if (fmt[1] == '-') { left_just = true; @@ -166,6 +258,11 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va) width += (fmt[1] - '0'); fmt++; } + if (fmt[1] == 'l') + { + long_flag = true; + fmt++; + } } else {