mirror of
https://github.com/esphome/esphome.git
synced 2026-05-24 18:06:27 +08:00
Extract inline helpers: small_pow10, uint32_to_str, frac_to_str
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user