From 7549d031fdd3ccb52f1cef8c5457fbba8ccafcdf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 15 Sep 2025 21:40:30 -0500 Subject: [PATCH] cleanup --- esphome/components/json/json_util.cpp | 46 +++------------------------ esphome/components/json/json_util.h | 23 +++++++++++--- 2 files changed, 24 insertions(+), 45 deletions(-) diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index a9cf383a18..166fbcd167 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -8,32 +8,6 @@ namespace json { static const char *const TAG = "json"; -#ifdef USE_PSRAM -// Build an allocator for the JSON Library using the RAMAllocator class -// This is only compiled when PSRAM is enabled -struct SpiRamAllocator : ArduinoJson::Allocator { - void *allocate(size_t size) override { return this->allocator_.allocate(size); } - - void deallocate(void *pointer) override { - // ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate. - // RAMAllocator::deallocate() requires the size, which we don't have access to here. - // RAMAllocator::deallocate implementation just calls free() regardless of whether - // the memory was allocated with heap_caps_malloc or malloc. - // This is safe because ESP-IDF's heap implementation internally tracks the memory region - // and routes free() to the appropriate heap. - free(pointer); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) - } - - void *reallocate(void *ptr, size_t new_size) override { - return this->allocator_.reallocate(static_cast(ptr), new_size); - } - - protected: - RAMAllocator allocator_{RAMAllocator(RAMAllocator::NONE)}; -}; - -#endif - std::string build_json(const json_build_t &f) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson JsonBuilder builder; @@ -71,24 +45,14 @@ bool parse_json(const std::string &data, const json_parse_t &f) { } // JsonBuilder implementation -JsonBuilder::JsonBuilder() { +JsonBuilder::JsonBuilder() + : doc_( #ifdef USE_PSRAM - // Verify our storage is large enough (and log the actual size for reference) - static_assert(sizeof(SpiRamAllocator) <= sizeof(allocator_storage_), "allocator_storage_ too small"); - // Note: sizeof(SpiRamAllocator) is typically around 24-32 bytes on ESP32 - // Use placement new to construct SpiRamAllocator in the pre-allocated storage - auto *allocator = new (allocator_storage_) SpiRamAllocator(); - doc_ = JsonDocument(allocator); + &allocator_ #else - doc_ = JsonDocument(); -#endif -} - -JsonBuilder::~JsonBuilder() { -#ifdef USE_PSRAM - // Explicitly call destructor for placement-new allocated object - reinterpret_cast(allocator_storage_)->~SpiRamAllocator(); + nullptr #endif + ) { } std::string JsonBuilder::serialize() { diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index de76ca53da..9699955133 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -13,6 +13,24 @@ namespace esphome { namespace json { +#ifdef USE_PSRAM +// Allocator for JSON that uses PSRAM on supported devices +struct SpiRamAllocator : ArduinoJson::Allocator { + void *allocate(size_t size) override { return allocator_.allocate(size); } + + void deallocate(void *ptr) override { + free(ptr); // NOLINT(cppcoreguidelines-owning-memory,cppcoreguidelines-no-malloc) + } + + void *reallocate(void *ptr, size_t new_size) override { + return allocator_.reallocate(static_cast(ptr), new_size); + } + + protected: + RAMAllocator allocator_{RAMAllocator::NONE}; +}; +#endif + /// Callback function typedef for parsing JsonObjects. using json_parse_t = std::function; @@ -29,7 +47,6 @@ bool parse_json(const std::string &data, const json_parse_t &f); class JsonBuilder { public: JsonBuilder(); - ~JsonBuilder(); JsonObject root() { if (!root_created_) { @@ -43,9 +60,7 @@ class JsonBuilder { private: #ifdef USE_PSRAM - // Storage for SpiRamAllocator - typically around 24-32 bytes on ESP32 - // Static assert in .cpp file ensures this is large enough - std::aligned_storage<32, alignof(void *)>::type allocator_storage_; + SpiRamAllocator allocator_; // Just a regular member on the stack! #endif JsonDocument doc_; JsonObject root_;