many things, cosmo build!
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
Generic std parts, building on top of platform specifics.
|
||||
*/
|
||||
|
||||
#include "../fix.h"
|
||||
#include "../std.h"
|
||||
#include "../str.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static uint8_t com_std_any_format_u32(uint32_t v, char buf[10]) {
|
||||
uint8_t c = 0;
|
||||
if (v == 0) {
|
||||
buf[10 - (++c)] = '0';
|
||||
} else {
|
||||
while (v > 0) {
|
||||
buf[10 - (++c)] = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static uint8_t com_std_any_format_i32(int32_t v, char buf[11]) {
|
||||
bool neg = v < 0;
|
||||
uint8_t c = 0;
|
||||
if (v == 0) {
|
||||
buf[11 - (++c)] = '0';
|
||||
} else {
|
||||
while (v > 0) {
|
||||
buf[11 - (++c)] = '0' + (v % 10);
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
if (neg)
|
||||
buf[11 - (++c)] = '-';
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Just assume 5 points of precision. */
|
||||
static uint8_t com_std_any_format_f64(double v, char buf[11 + 1 + 5]) {
|
||||
bool neg = v < 0;
|
||||
uint8_t c = 0;
|
||||
double frac_part = v - (double)(int32_t)v;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
frac_part *= 10.0;
|
||||
uint8_t digit = (unsigned int)frac_part;
|
||||
buf[17 - (++c)] = digit + '0';
|
||||
frac_part -= digit;
|
||||
}
|
||||
buf[17 - (++c)] = '.';
|
||||
c += com_std_any_format_i32((int32_t)v, &buf[c]);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* We can make it buffered, but who cares, it's only for testing. */
|
||||
void com_std_print_(int32_t start, ...) {
|
||||
va_list args;
|
||||
va_start(args, start);
|
||||
|
||||
bool afterstring = false;
|
||||
char type = start;
|
||||
do {
|
||||
|
||||
/* Put space if not proceeding string. */
|
||||
if (!afterstring && type != 'c')
|
||||
com_std_write(COM_STD_OUTFD, " ", 1);
|
||||
|
||||
afterstring = false;
|
||||
|
||||
switch (type) {
|
||||
|
||||
/* uint32_t case. */
|
||||
case 'u': {
|
||||
uint32_t const v = va_arg(args, uint32_t);
|
||||
char buf[10];
|
||||
uint8_t c = com_std_any_format_u32(v, buf);
|
||||
com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c);
|
||||
break;
|
||||
}
|
||||
|
||||
/* null terminated string case. */
|
||||
case 'c': {
|
||||
char const *const v = va_arg(args, char *);
|
||||
com_std_write(COM_STD_OUTFD, v, com_str_ext_len(v));
|
||||
afterstring = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: FIX THIS */
|
||||
/* com_fix case. */
|
||||
case 'f': {
|
||||
com_fix_t const v = va_arg(args, com_fix_t);
|
||||
char buf[11];
|
||||
|
||||
int32_t const int_part = com_fix_int(v);
|
||||
uint8_t c = com_std_any_format_i32(int_part, buf);
|
||||
com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c);
|
||||
|
||||
uint32_t const decimal_val = (com_fix_frac(v) * 10000) >> 16;
|
||||
uint8_t cd = com_std_any_format_u32(decimal_val, buf);
|
||||
buf[sizeof buf - (++cd)] = '.';
|
||||
com_std_write(COM_STD_OUTFD, &buf[sizeof buf - cd], cd);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* double floating point case. */
|
||||
case 'd': {
|
||||
double const v = va_arg(args, double);
|
||||
char buf[17];
|
||||
|
||||
uint8_t c = com_std_any_format_f64(v, buf);
|
||||
com_std_write(COM_STD_OUTFD, &buf[sizeof buf - c], c);
|
||||
}
|
||||
|
||||
/* End of things. */
|
||||
case '.':
|
||||
break;
|
||||
|
||||
default:
|
||||
com_std_assert(false && "Unhandled format type");
|
||||
}
|
||||
|
||||
type = va_arg(args, int32_t);
|
||||
|
||||
} while (type != '.');
|
||||
|
||||
com_std_write(COM_STD_OUTFD, "\n", 1);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void com_std_print_str(char const *str, uint32_t len, bool newline) {
|
||||
com_std_write(COM_STD_OUTFD, str, len);
|
||||
if (newline)
|
||||
com_std_write(COM_STD_OUTFD, "\n", 1);
|
||||
}
|
||||
Reference in New Issue
Block a user