/* Generic std parts, building on top of platform specifics. */ #include "../fix.h" #include "../std.h" #include "../str.h" #include #include 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); }