mirror of
https://github.com/esphome/esphome.git
synced 2026-05-23 03:06:05 +08:00
Split uint32_to_str/frac_to_str into internal and public API
- uint32_to_str_(): raw pointer, internal use - uint32_to_str(): template with compile-time buffer size check - frac_to_str_(): raw pointer, internal use - small_pow10(): simplify to ternary chain
This commit is contained in:
@@ -539,10 +539,10 @@ static size_t value_accuracy_to_buf_fast(char *buf, float value, int8_t accuracy
|
||||
// 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));
|
||||
p = uint32_to_str(p, scaled / mult);
|
||||
p = uint32_to_str_(p, scaled / mult);
|
||||
if (accuracy_decimals > 0) {
|
||||
*p++ = '.';
|
||||
p = frac_to_str(p, scaled % mult, mult / 10);
|
||||
p = frac_to_str_(p, scaled % mult, mult / 10);
|
||||
}
|
||||
*p = '\0';
|
||||
return static_cast<size_t>(p - buf);
|
||||
|
||||
+18
-15
@@ -1311,20 +1311,14 @@ inline char *buf_append_sep_str(char *buf, size_t remaining, char separator, con
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
inline uint32_t small_pow10(int8_t n) { return n == 3 ? 1000 : n == 2 ? 100 : n == 1 ? 10 : 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) {
|
||||
/// Minimum buffer size for uint32_to_str: 10 digits + null terminator.
|
||||
static constexpr size_t UINT32_MAX_STR_SIZE = 11;
|
||||
|
||||
/// Write unsigned 32-bit integer to buffer (internal, no size check).
|
||||
/// Buffer must have at least 10 bytes free. Returns pointer past last char written.
|
||||
inline char *uint32_to_str_(char *buf, uint32_t val) {
|
||||
if (val == 0) {
|
||||
*buf++ = '0';
|
||||
return buf;
|
||||
@@ -1338,10 +1332,19 @@ inline char *uint32_to_str(char *buf, uint32_t val) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/// Write fractional digits with leading zeros to buffer.
|
||||
/// Write unsigned 32-bit integer to buffer with compile-time size check.
|
||||
/// Null-terminates the output. Returns number of chars written (excluding null).
|
||||
template<size_t N> inline size_t uint32_to_str(char (&buf)[N], uint32_t val) {
|
||||
static_assert(N >= UINT32_MAX_STR_SIZE, "Buffer too small for uint32 (need 11 bytes)");
|
||||
char *end = uint32_to_str_(buf, val);
|
||||
*end = '\0';
|
||||
return static_cast<size_t>(end - buf);
|
||||
}
|
||||
|
||||
/// Write fractional digits with leading zeros to buffer (internal, no size check).
|
||||
/// 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) {
|
||||
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;
|
||||
|
||||
@@ -16,7 +16,7 @@ TEST(SmallPow10, Three) { EXPECT_EQ(small_pow10(3), 1000u); }
|
||||
|
||||
TEST(Uint32ToStr, Zero) {
|
||||
char buf[12];
|
||||
char *end = uint32_to_str(buf, 0);
|
||||
char *end = uint32_to_str_(buf, 0);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "0");
|
||||
EXPECT_EQ(end - buf, 1);
|
||||
@@ -24,14 +24,14 @@ TEST(Uint32ToStr, Zero) {
|
||||
|
||||
TEST(Uint32ToStr, SingleDigit) {
|
||||
char buf[12];
|
||||
char *end = uint32_to_str(buf, 7);
|
||||
char *end = uint32_to_str_(buf, 7);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "7");
|
||||
}
|
||||
|
||||
TEST(Uint32ToStr, MultiDigit) {
|
||||
char buf[12];
|
||||
char *end = uint32_to_str(buf, 12345);
|
||||
char *end = uint32_to_str_(buf, 12345);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "12345");
|
||||
EXPECT_EQ(end - buf, 5);
|
||||
@@ -39,7 +39,7 @@ TEST(Uint32ToStr, MultiDigit) {
|
||||
|
||||
TEST(Uint32ToStr, Large) {
|
||||
char buf[12];
|
||||
char *end = uint32_to_str(buf, 4294967295u);
|
||||
char *end = uint32_to_str_(buf, 4294967295u);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "4294967295");
|
||||
EXPECT_EQ(end - buf, 10);
|
||||
@@ -49,24 +49,36 @@ TEST(Uint32ToStr, PowersOfTen) {
|
||||
char buf[12];
|
||||
char *end;
|
||||
|
||||
end = uint32_to_str(buf, 10);
|
||||
end = uint32_to_str_(buf, 10);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "10");
|
||||
|
||||
end = uint32_to_str(buf, 100);
|
||||
end = uint32_to_str_(buf, 100);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "100");
|
||||
|
||||
end = uint32_to_str(buf, 1000);
|
||||
end = uint32_to_str_(buf, 1000);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "1000");
|
||||
}
|
||||
|
||||
// --- frac_to_str() ---
|
||||
// --- uint32_to_str() (public, template with size check) ---
|
||||
|
||||
TEST(Uint32ToStr, PublicApi) {
|
||||
char buf[UINT32_MAX_STR_SIZE];
|
||||
EXPECT_EQ(uint32_to_str(buf, 0), 1u);
|
||||
EXPECT_STREQ(buf, "0");
|
||||
EXPECT_EQ(uint32_to_str(buf, 12345), 5u);
|
||||
EXPECT_STREQ(buf, "12345");
|
||||
EXPECT_EQ(uint32_to_str(buf, 4294967295u), 10u);
|
||||
EXPECT_STREQ(buf, "4294967295");
|
||||
}
|
||||
|
||||
// --- frac_to_str_() ---
|
||||
|
||||
TEST(FracToStr, OneDigit) {
|
||||
char buf[8];
|
||||
char *end = frac_to_str(buf, 5, 1);
|
||||
char *end = frac_to_str_(buf, 5, 1);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "5");
|
||||
EXPECT_EQ(end - buf, 1);
|
||||
@@ -74,14 +86,14 @@ TEST(FracToStr, OneDigit) {
|
||||
|
||||
TEST(FracToStr, TwoDigits) {
|
||||
char buf[8];
|
||||
char *end = frac_to_str(buf, 46, 10);
|
||||
char *end = frac_to_str_(buf, 46, 10);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "46");
|
||||
}
|
||||
|
||||
TEST(FracToStr, ThreeDigits) {
|
||||
char buf[8];
|
||||
char *end = frac_to_str(buf, 456, 100);
|
||||
char *end = frac_to_str_(buf, 456, 100);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "456");
|
||||
EXPECT_EQ(end - buf, 3);
|
||||
@@ -89,22 +101,22 @@ TEST(FracToStr, ThreeDigits) {
|
||||
|
||||
TEST(FracToStr, LeadingZeros) {
|
||||
char buf[8];
|
||||
char *end = frac_to_str(buf, 1, 100);
|
||||
char *end = frac_to_str_(buf, 1, 100);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "001");
|
||||
|
||||
end = frac_to_str(buf, 5, 10);
|
||||
end = frac_to_str_(buf, 5, 10);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "05");
|
||||
}
|
||||
|
||||
TEST(FracToStr, AllZeros) {
|
||||
char buf[8];
|
||||
char *end = frac_to_str(buf, 0, 100);
|
||||
char *end = frac_to_str_(buf, 0, 100);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "000");
|
||||
|
||||
end = frac_to_str(buf, 0, 1);
|
||||
end = frac_to_str_(buf, 0, 1);
|
||||
*end = '\0';
|
||||
EXPECT_STREQ(buf, "0");
|
||||
}
|
||||
@@ -112,7 +124,7 @@ TEST(FracToStr, AllZeros) {
|
||||
TEST(FracToStr, ZeroDivisor) {
|
||||
char buf[8];
|
||||
buf[0] = 'X';
|
||||
char *end = frac_to_str(buf, 0, 0);
|
||||
char *end = frac_to_str_(buf, 0, 0);
|
||||
EXPECT_EQ(end, buf); // writes nothing
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user