[core] Add uint32_to_str helper and use in preferences (#15597)

This commit is contained in:
J. Nick Koston
2026-04-14 07:49:44 -10:00
committed by GitHub
parent 5ba8c644e4
commit cf01163c8c
6 changed files with 170 additions and 16 deletions
+56
View File
@@ -1,4 +1,6 @@
#include <benchmark/benchmark.h>
#include <cinttypes>
#include <cstdio>
#include "esphome/core/helpers.h"
@@ -307,4 +309,58 @@ static void Base64Decode_32Bytes(benchmark::State &state) {
}
BENCHMARK(Base64Decode_32Bytes);
// --- uint32_to_str() vs snprintf ---
static void Uint32ToStr_Small(benchmark::State &state) {
char buf[UINT32_MAX_STR_SIZE];
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uint32_to_str(buf, 12345);
benchmark::DoNotOptimize(buf);
benchmark::ClobberMemory();
}
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(Uint32ToStr_Small);
static void Snprintf_Uint32_Small(benchmark::State &state) {
char buf[UINT32_MAX_STR_SIZE];
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
snprintf(buf, sizeof(buf), "%" PRIu32, static_cast<uint32_t>(12345));
benchmark::DoNotOptimize(buf);
benchmark::ClobberMemory();
}
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(Snprintf_Uint32_Small);
static void Uint32ToStr_Large(benchmark::State &state) {
char buf[UINT32_MAX_STR_SIZE];
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
uint32_to_str(buf, 4294967295u);
benchmark::DoNotOptimize(buf);
benchmark::ClobberMemory();
}
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(Uint32ToStr_Large);
static void Snprintf_Uint32_Large(benchmark::State &state) {
char buf[UINT32_MAX_STR_SIZE];
for (auto _ : state) {
for (int i = 0; i < kInnerIterations; i++) {
snprintf(buf, sizeof(buf), "%" PRIu32, static_cast<uint32_t>(4294967295u));
benchmark::DoNotOptimize(buf);
benchmark::ClobberMemory();
}
}
state.SetItemsProcessed(state.iterations() * kInnerIterations);
}
BENCHMARK(Snprintf_Uint32_Large);
} // namespace esphome::benchmarks
@@ -0,0 +1,77 @@
#include <gtest/gtest.h>
#include "esphome/core/helpers.h"
namespace esphome::core::testing {
// --- uint32_to_str_unchecked() (internal, raw pointer) ---
TEST(Uint32ToStr, InternalZero) {
char buf[UINT32_MAX_STR_SIZE];
char *end = uint32_to_str_unchecked(buf, 0);
*end = '\0';
EXPECT_STREQ(buf, "0");
EXPECT_EQ(end - buf, 1);
}
TEST(Uint32ToStr, InternalSingleDigit) {
char buf[UINT32_MAX_STR_SIZE];
char *end = uint32_to_str_unchecked(buf, 7);
*end = '\0';
EXPECT_STREQ(buf, "7");
}
TEST(Uint32ToStr, InternalMultiDigit) {
char buf[UINT32_MAX_STR_SIZE];
char *end = uint32_to_str_unchecked(buf, 12345);
*end = '\0';
EXPECT_STREQ(buf, "12345");
EXPECT_EQ(end - buf, 5);
}
TEST(Uint32ToStr, InternalMaxValue) {
char buf[UINT32_MAX_STR_SIZE];
char *end = uint32_to_str_unchecked(buf, 4294967295u);
*end = '\0';
EXPECT_STREQ(buf, "4294967295");
EXPECT_EQ(end - buf, 10);
}
TEST(Uint32ToStr, InternalPowersOfTen) {
char buf[UINT32_MAX_STR_SIZE];
char *end;
end = uint32_to_str_unchecked(buf, 10);
*end = '\0';
EXPECT_STREQ(buf, "10");
end = uint32_to_str_unchecked(buf, 100);
*end = '\0';
EXPECT_STREQ(buf, "100");
end = uint32_to_str_unchecked(buf, 1000000);
*end = '\0';
EXPECT_STREQ(buf, "1000000");
}
// --- uint32_to_str() (public, span API) ---
TEST(Uint32ToStr, SpanZero) {
char buf[UINT32_MAX_STR_SIZE];
EXPECT_EQ(uint32_to_str(buf, 0), 1u);
EXPECT_STREQ(buf, "0");
}
TEST(Uint32ToStr, SpanMultiDigit) {
char buf[UINT32_MAX_STR_SIZE];
EXPECT_EQ(uint32_to_str(buf, 12345), 5u);
EXPECT_STREQ(buf, "12345");
}
TEST(Uint32ToStr, SpanMaxValue) {
char buf[UINT32_MAX_STR_SIZE];
EXPECT_EQ(uint32_to_str(buf, 4294967295u), 10u);
EXPECT_STREQ(buf, "4294967295");
}
} // namespace esphome::core::testing