From 8d0ce49eb4b6d25761d59442f890e95705641527 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 16:34:15 +0100 Subject: [PATCH] [api] Eliminate intermediate buffers in protobuf dump helpers (#13742) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_pb2_dump.cpp | 27 ++++++------------------- esphome/components/api/proto.h | 14 +++++++++++++ script/api_protobuf/api_protobuf.py | 27 ++++++------------------- 3 files changed, 26 insertions(+), 42 deletions(-) diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 29121f05e0..e9db36ae21 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -23,15 +23,8 @@ static inline void append_field_prefix(DumpBuffer &out, const char *field_name, out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(DumpBuffer &out, const char *str) { - out.append(str); - out.append("\n"); -} - static inline void append_uint(DumpBuffer &out, uint32_t value) { - char buf[16]; - snprintf(buf, sizeof(buf), "%" PRIu32, value); - out.append(buf); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32, value)); } // RAII helper for message dump formatting @@ -49,31 +42,23 @@ class MessageDumpHelper { // Helper functions to reduce code duplication in dump methods static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRId32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%g", value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%g\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu64, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu64 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { @@ -112,7 +97,7 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); - append_with_newline(out, hex_buf); + out.append(hex_buf).append("\n"); } template<> const char *proto_enum_to_string(enums::EntityCategory value) { diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 2e0df297c3..552b4a4625 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -402,6 +402,20 @@ class DumpBuffer { const char *c_str() const { return buf_; } size_t size() const { return pos_; } + /// Get writable buffer pointer for use with buf_append_printf + char *data() { return buf_; } + /// Get current position for use with buf_append_printf + size_t pos() const { return pos_; } + /// Update position after buf_append_printf call + void set_pos(size_t pos) { + if (pos >= CAPACITY) { + pos_ = CAPACITY - 1; + } else { + pos_ = pos; + } + buf_[pos_] = '\0'; + } + private: void append_impl_(const char *str, size_t len) { size_t space = CAPACITY - 1 - pos_; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 7625458f9f..72103285e8 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2599,15 +2599,8 @@ static inline void append_field_prefix(DumpBuffer &out, const char *field_name, out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(DumpBuffer &out, const char *str) { - out.append(str); - out.append("\\n"); -} - static inline void append_uint(DumpBuffer &out, uint32_t value) { - char buf[16]; - snprintf(buf, sizeof(buf), "%" PRIu32, value); - out.append(buf); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32, value)); } // RAII helper for message dump formatting @@ -2625,31 +2618,23 @@ class MessageDumpHelper { // Helper functions to reduce code duplication in dump methods static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRId32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%g", value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%g\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu64, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu64 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { @@ -2689,7 +2674,7 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); - append_with_newline(out, hex_buf); + out.append(hex_buf).append("\\n"); } """