Extract inline helpers: small_pow10, uint32_to_str, frac_to_str

This commit is contained in:
J. Nick Koston
2026-04-08 20:50:03 -10:00
parent 5ac1f10b28
commit ff1f0a0d46
2 changed files with 44 additions and 28 deletions
+4 -28
View File
@@ -534,39 +534,15 @@ static size_t value_accuracy_to_buf_fast(char *buf, float value, int8_t accuracy
*p++ = '-';
value = -value;
}
uint32_t mult = 1;
if (accuracy_decimals == 1) {
mult = 10;
} else if (accuracy_decimals == 2) {
mult = 100;
} else if (accuracy_decimals == 3) {
mult = 1000;
}
// Cast to double for the multiply to match snprintf's precision.
uint32_t mult = small_pow10(accuracy_decimals);
// Cast to double for the multiply to match snprintf's rounding precision.
// float*int loses bits at exact-half boundaries (e.g. 23.45f*10 = 234.5 in float,
// but snprintf sees 234.500007... via double promotion and rounds differently).
uint32_t scaled = static_cast<uint32_t>(lrint(static_cast<double>(value) * mult));
uint32_t int_part = scaled / mult;
// Write integer part in reverse, then flip
char *start = p;
if (int_part == 0) {
*p++ = '0';
} else {
while (int_part > 0) {
*p++ = '0' + (int_part % 10);
int_part /= 10;
}
std::reverse(start, p);
}
p = uint32_to_str(p, scaled / mult);
if (accuracy_decimals > 0) {
*p++ = '.';
uint32_t frac = scaled % mult;
uint32_t d = mult / 10;
while (d > 0) {
*p++ = '0' + static_cast<char>(frac / d);
frac %= d;
d /= 10;
}
p = frac_to_str(p, scaled % mult, mult / 10);
}
*p = '\0';
return static_cast<size_t>(p - buf);
+40
View File
@@ -1295,6 +1295,46 @@ inline char *int8_to_str(char *buf, int8_t val) {
return buf;
}
/// Return 10^n for small non-negative n (0-3) as uint32_t, avoiding float.
inline uint32_t small_pow10(int8_t n) {
if (n == 1) {
return 10;
} else if (n == 2) {
return 100;
} else if (n == 3) {
return 1000;
}
return 1;
}
/// Write unsigned 32-bit integer to buffer. Returns pointer past last char written.
/// Buffer must have at least 10 bytes free (max uint32 is 4294967295).
inline char *uint32_to_str(char *buf, uint32_t val) {
if (val == 0) {
*buf++ = '0';
return buf;
}
char *start = buf;
while (val > 0) {
*buf++ = '0' + (val % 10);
val /= 10;
}
std::reverse(start, buf);
return buf;
}
/// Write fractional digits with leading zeros to buffer.
/// frac is the fractional value, divisor is the highest place value (e.g. 100 for 3 digits).
/// Returns pointer past last char written.
inline char *frac_to_str(char *buf, uint32_t frac, uint32_t divisor) {
while (divisor > 0) {
*buf++ = '0' + static_cast<char>(frac / divisor);
frac %= divisor;
divisor /= 10;
}
return buf;
}
/// Format byte array as lowercase hex to buffer (base implementation).
char *format_hex_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length);