Files
brightstone/Common/Std/any.c
T
2026-10-12 21:12:47 +03:00

139 lines
3.1 KiB
C

/*
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);
}