[text_sensor] Use std::array in SubstituteFilter

This commit is contained in:
J. Nick Koston
2026-03-27 13:33:39 -10:00
parent a075f63b59
commit a2856cf87b
3 changed files with 28 additions and 19 deletions
+3 -1
View File
@@ -123,7 +123,9 @@ async def substitute_filter_to_code(config, filter_id):
)
for conf in config
]
return cg.new_Pvariable(filter_id, substitutions)
return cg.new_Pvariable(
filter_id, cg.TemplateArguments(len(substitutions)), substitutions
)
@FILTER_REGISTRY.register("map", MapFilter, cv.ensure_list(validate_mapping))
+7 -13
View File
@@ -73,20 +73,14 @@ bool PrependFilter::new_value(std::string &value) {
return true;
}
// Substitute
SubstituteFilter::SubstituteFilter(const std::initializer_list<Substitution> &substitutions)
: substitutions_(substitutions) {}
bool SubstituteFilter::new_value(std::string &value) {
for (const auto &sub : this->substitutions_) {
// Compute lengths once per substitution (strlen is fast, called infrequently)
const size_t from_len = strlen(sub.from);
const size_t to_len = strlen(sub.to);
// Substitute — non-template helper
bool substitute_filter_apply(const Substitution *substitutions, size_t count, std::string &value) {
for (size_t i = 0; i < count; i++) {
const size_t from_len = strlen(substitutions[i].from);
const size_t to_len = strlen(substitutions[i].to);
std::size_t pos = 0;
while ((pos = value.find(sub.from, pos, from_len)) != std::string::npos) {
value.replace(pos, from_len, sub.to, to_len);
// Advance past the replacement to avoid infinite loop when
// the replacement contains the search pattern (e.g., f -> foo)
while ((pos = value.find(substitutions[i].from, pos, from_len)) != std::string::npos) {
value.replace(pos, from_len, substitutions[i].to, to_len);
pos += to_len;
}
}
+18 -5
View File
@@ -3,6 +3,8 @@
#include "esphome/core/defines.h"
#ifdef USE_TEXT_SENSOR_FILTER
#include <array>
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
@@ -121,14 +123,25 @@ struct Substitution {
const char *to;
};
/// A simple filter that replaces a substring with another substring
class SubstituteFilter : public Filter {
/// Non-template helper (implementation in filter.cpp)
bool substitute_filter_apply(const Substitution *substitutions, size_t count, std::string &value);
/// A simple filter that replaces a substring with another substring.
/// N is set by code generation to match the exact number of substitutions configured in YAML.
template<size_t N> class SubstituteFilter : public Filter {
public:
explicit SubstituteFilter(const std::initializer_list<Substitution> &substitutions);
bool new_value(std::string &value) override;
explicit SubstituteFilter(const std::initializer_list<Substitution> &substitutions) {
size_t i = 0;
for (const auto &s : substitutions) {
if (i >= N)
break;
this->substitutions_[i++] = s;
}
}
bool new_value(std::string &value) override { return substitute_filter_apply(this->substitutions_.data(), N, value); }
protected:
FixedVector<Substitution> substitutions_;
std::array<Substitution, N> substitutions_{};
};
/** A filter that maps values from one set to another