add hos_printf and stream modules

This commit is contained in:
Josh Holtrop 2020-10-20 19:30:23 -04:00
parent c8db9fe905
commit 75491dd36b
3 changed files with 160 additions and 0 deletions

138
src/hos_printf.c Normal file
View File

@ -0,0 +1,138 @@
#include "hos_printf.h"
#include <stdint.h>
#include <stdbool.h>
#include "string.h"
static size_t format_dec(char * buffer, int v)
{
size_t sz = 0u;
bool printing = false;
if (v < 0)
{
buffer[sz++] = '-';
v = -v;
}
for (int div = 1000000000; div >= 1; div /= 10)
{
int 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, unsigned int v)
{
size_t sz = 0u;
for (unsigned int div = 1000000000u; div >= 1u; div /= 10u)
{
unsigned int 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, int v, bool upper)
{
const char upper_hex[] = "0123456789ABCDEF";
const char lower_hex[] = "0123456789abcdef";
size_t sz = 0u;
for (int i = 28; 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;
}
void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
{
bool in_conv = false;
char c;
char buffer[12];
while ((c = *fmt))
{
if (in_conv)
{
switch (c)
{
case '%':
stream->write1('%');
break;
case 'X':
{
unsigned int v = va_arg(va, unsigned int);
size_t length = format_hex(buffer, v, true);
stream->write(buffer, length);
}
break;
case 'c':
{
char ch = va_arg(va, int);
stream->write1(ch);
}
break;
case 'd':
{
int v = va_arg(va, int);
size_t length = format_dec(buffer, v);
stream->write(buffer, length);
}
break;
case 's':
{
const char * s = va_arg(va, const char *);
stream->write(s, strlen(s));
}
break;
case 'u':
{
unsigned int v = va_arg(va, unsigned int);
size_t length = format_udec(buffer, v);
stream->write(buffer, length);
}
break;
case 'x':
{
unsigned int v = va_arg(va, unsigned int);
size_t length = format_hex(buffer, v, false);
stream->write(buffer, length);
}
break;
}
in_conv = false;
}
else if (c == '%')
{
in_conv = true;
}
else
{
stream->write1(c);
}
fmt++;
}
}
void hos_printf(const stream_t * stream, const char * fmt, ...)
{
va_list va;
va_start(va, fmt);
hos_vprintf(stream, fmt, va);
va_end(va);
}

10
src/hos_printf.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef HOS_PRINTF_H
#define HOS_PRINTF_H
#include "stream.h"
#include <stdarg.h>
void hos_vprintf(const stream_t * stream, const char * fmt, va_list va);
void hos_printf(const stream_t * stream, const char * fmt, ...);
#endif

12
src/stream.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef STREAM_H
#define STREAM_H
#include <stddef.h>
#include <stdint.h>
typedef struct {
void (*write)(const uint8_t * src, size_t length);
void (*write1)(uint8_t c);
} stream_t;
#endif