add 64-bit formatting support

This commit is contained in:
Josh Holtrop 2020-10-23 00:46:40 -04:00
parent fa4ff5facf
commit cbd427b14b

View File

@ -3,7 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "string.h" #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; size_t sz = 0u;
bool printing = false; bool printing = false;
@ -12,9 +12,9 @@ static size_t format_dec(char * buffer, int v)
buffer[sz++] = '-'; buffer[sz++] = '-';
v = -v; 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; v %= div;
if ((digit != 0) || (div == 1)) if ((digit != 0) || (div == 1))
{ {
@ -28,12 +28,37 @@ static size_t format_dec(char * buffer, int v)
return sz; 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; 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; v %= div;
if ((digit != 0) || (sz > 0u) || (div == 1)) if ((digit != 0) || (sz > 0u) || (div == 1))
{ {
@ -43,7 +68,22 @@ static size_t format_udec(char * buffer, unsigned int v)
return sz; 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 upper_hex[] = "0123456789ABCDEF";
const char lower_hex[] = "0123456789abcdef"; const char lower_hex[] = "0123456789abcdef";
@ -60,6 +100,23 @@ static size_t format_hex(char * buffer, int v, bool upper)
return sz; 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) 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) if (left_just)
@ -88,10 +145,12 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
{ {
bool in_conv = false; bool in_conv = false;
char c; char c;
char buffer[12]; char buffer[22];
size_t width; size_t width;
bool leading_zero; bool leading_zero;
bool left_just; bool left_just;
bool long_flag;
size_t length;
while ((c = *fmt)) while ((c = *fmt))
{ {
if (in_conv) if (in_conv)
@ -103,8 +162,16 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
break; break;
case 'X': case 'X':
{ {
unsigned int v = va_arg(va, unsigned int); if (long_flag)
size_t length = format_hex(buffer, v, true); {
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); pad_write(stream, buffer, length, leading_zero, left_just, width);
} }
break; break;
@ -116,8 +183,16 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
break; break;
case 'd': case 'd':
{ {
int v = va_arg(va, int); if (long_flag)
size_t length = format_dec(buffer, v); {
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); pad_write(stream, buffer, length, leading_zero, left_just, width);
} }
break; break;
@ -129,15 +204,31 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
break; break;
case 'u': case 'u':
{ {
unsigned int v = va_arg(va, unsigned int); if (long_flag)
size_t length = format_udec(buffer, v); {
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); pad_write(stream, buffer, length, leading_zero, left_just, width);
} }
break; break;
case 'x': case 'x':
{ {
unsigned int v = va_arg(va, unsigned int); if (long_flag)
size_t length = format_hex(buffer, v, false); {
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); pad_write(stream, buffer, length, leading_zero, left_just, width);
} }
break; break;
@ -150,6 +241,7 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
width = 0u; width = 0u;
leading_zero = false; leading_zero = false;
left_just = false; left_just = false;
long_flag = false;
if (fmt[1] == '-') if (fmt[1] == '-')
{ {
left_just = true; left_just = true;
@ -166,6 +258,11 @@ void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
width += (fmt[1] - '0'); width += (fmt[1] - '0');
fmt++; fmt++;
} }
if (fmt[1] == 'l')
{
long_flag = true;
fmt++;
}
} }
else else
{ {