[select] Refactor to index-based operations for immediate and future RAM savings (#11623)

This commit is contained in:
J. Nick Koston
2025-11-05 11:33:01 +13:00
committed by GitHub
parent c7ae424613
commit 6f7e54c3f3
44 changed files with 268 additions and 204 deletions
+34 -15
View File
@@ -7,24 +7,43 @@ namespace select {
static const char *const TAG = "select";
void Select::publish_state(const std::string &state) {
void Select::publish_state(const std::string &state) { this->publish_state(state.c_str()); }
void Select::publish_state(const char *state) {
auto index = this->index_of(state);
const auto *name = this->get_name().c_str();
if (index.has_value()) {
this->set_has_state(true);
this->state = state;
ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", name, state.c_str(), index.value());
this->state_callback_.call(state, index.value());
this->publish_state(index.value());
} else {
ESP_LOGE(TAG, "'%s': invalid state for publish_state(): %s", name, state.c_str());
ESP_LOGE(TAG, "'%s': Invalid option %s", this->get_name().c_str(), state);
}
}
void Select::publish_state(size_t index) {
if (!this->has_index(index)) {
ESP_LOGE(TAG, "'%s': Invalid index %zu", this->get_name().c_str(), index);
return;
}
const char *option = this->option_at(index);
this->set_has_state(true);
this->active_index_ = index;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
this->state = option; // Update deprecated member for backward compatibility
#pragma GCC diagnostic pop
ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", this->get_name().c_str(), option, index);
// Callback signature requires std::string, create temporary for compatibility
this->state_callback_.call(std::string(option), index);
}
const char *Select::current_option() const { return this->has_state() ? this->option_at(this->active_index_) : ""; }
void Select::add_on_state_callback(std::function<void(std::string, size_t)> &&callback) {
this->state_callback_.add(std::move(callback));
}
bool Select::has_option(const std::string &option) const { return this->index_of(option).has_value(); }
bool Select::has_option(const std::string &option) const { return this->index_of(option.c_str()).has_value(); }
bool Select::has_option(const char *option) const { return this->index_of(option).has_value(); }
bool Select::has_index(size_t index) const { return index < this->size(); }
@@ -33,10 +52,12 @@ size_t Select::size() const {
return options.size();
}
optional<size_t> Select::index_of(const std::string &option) const {
optional<size_t> Select::index_of(const std::string &option) const { return this->index_of(option.c_str()); }
optional<size_t> Select::index_of(const char *option) const {
const auto &options = traits.get_options();
for (size_t i = 0; i < options.size(); i++) {
if (strcmp(options[i], option.c_str()) == 0) {
if (strcmp(options[i], option) == 0) {
return i;
}
}
@@ -45,19 +66,17 @@ optional<size_t> Select::index_of(const std::string &option) const {
optional<size_t> Select::active_index() const {
if (this->has_state()) {
return this->index_of(this->state);
} else {
return {};
return this->active_index_;
}
return {};
}
optional<std::string> Select::at(size_t index) const {
if (this->has_index(index)) {
const auto &options = traits.get_options();
return std::string(options.at(index));
} else {
return {};
}
return {};
}
const char *Select::option_at(size_t index) const { return traits.get_options().at(index); }