Use leak-on-purpose raw pointer for Fan-owned preset modes vector

Fan entities live for the entire program lifetime, so the preset
modes vector never needs to be freed. Use a raw pointer (null by
default, allocated on first set_supported_preset_modes() call)
instead of an inline std::vector member.

This saves 24 bytes of RAM per Fan instance for components that
don't use preset modes (binary, bedjet, tuya, etc.).
This commit is contained in:
J. Nick Koston
2026-03-26 13:24:58 -10:00
parent df58091d1d
commit 4ff0d30e07
2 changed files with 14 additions and 9 deletions
+5 -5
View File
@@ -148,9 +148,9 @@ const char *Fan::find_preset_mode_(const char *preset_mode) {
}
const char *Fan::find_preset_mode_(const char *preset_mode, size_t len) {
if (preset_mode == nullptr || len == 0)
if (preset_mode == nullptr || len == 0 || !this->supported_preset_modes_)
return nullptr;
for (const char *mode : this->supported_preset_modes_) {
for (const char *mode : *this->supported_preset_modes_) {
if (strncmp(mode, preset_mode, len) == 0 && mode[len] == '\0')
return mode;
}
@@ -274,10 +274,10 @@ void Fan::save_state_() {
state.direction = this->direction;
state.preset_mode = FanRestoreState::NO_PRESET;
if (this->has_preset_mode()) {
if (this->has_preset_mode() && this->supported_preset_modes_) {
// Find index of current preset mode (pointer comparison is safe since preset is from our vector)
for (size_t i = 0; i < this->supported_preset_modes_.size(); i++) {
if (this->supported_preset_modes_[i] == this->preset_mode_) {
for (size_t i = 0; i < this->supported_preset_modes_->size(); i++) {
if ((*this->supported_preset_modes_)[i] == this->preset_mode_) {
state.preset_mode = i;
break;
}
+9 -4
View File
@@ -132,10 +132,15 @@ class Fan : public EntityBase {
/// Set the supported preset modes (stored on Fan, referenced by FanTraits via pointer).
void set_supported_preset_modes(std::initializer_list<const char *> preset_modes) {
this->supported_preset_modes_ = preset_modes;
if (!this->supported_preset_modes_)
this->supported_preset_modes_ =
new std::vector<const char *>(); // NOLINT - intentional leak, entity lives forever
*this->supported_preset_modes_ = preset_modes;
}
void set_supported_preset_modes(const std::vector<const char *> &preset_modes) {
this->supported_preset_modes_ = preset_modes;
if (!this->supported_preset_modes_)
this->supported_preset_modes_ = new std::vector<const char *>(); // NOLINT
*this->supported_preset_modes_ = preset_modes;
}
/// Set the restore mode of this fan.
@@ -179,8 +184,8 @@ class Fan : public EntityBase {
ESPPreferenceObject rtc_;
FanRestoreMode restore_mode_;
/// Preset mode storage — owned by Fan, referenced by FanTraits via pointer.
std::vector<const char *> supported_preset_modes_;
/// Preset mode storage — allocated on first use, never freed (entity lives forever).
std::vector<const char *> *supported_preset_modes_{nullptr};
private:
const char *preset_mode_{nullptr};