Add option to toggle exact match
This commit is contained in:
parent
539ea7aa27
commit
27ed96e13b
40
filters.cpp
40
filters.cpp
|
@ -46,8 +46,8 @@ bool IntegerFilter::match(const LogcatEntry& entry) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StringFilter::StringFilter(FilterKey key_, std::string other_, bool inverted_, bool disabled)
|
StringFilter::StringFilter(FilterKey key_, std::string other_, bool inverted_, bool exact_match_, bool disabled)
|
||||||
: key(key_), other(std::move(other_)), inverted(inverted_), _disabled(disabled) {
|
: key(key_), other(std::move(other_)), inverted(inverted_), exact_match(exact_match_), _disabled(disabled) {
|
||||||
if (key_ != FilterKey::User && key_ != FilterKey::Tag && key_ != FilterKey::Message) {
|
if (key_ != FilterKey::User && key_ != FilterKey::Tag && key_ != FilterKey::Message) {
|
||||||
throw std::runtime_error("StringFilter is passed a non-string key");
|
throw std::runtime_error("StringFilter is passed a non-string key");
|
||||||
}
|
}
|
||||||
|
@ -86,13 +86,33 @@ void StringFilter::disabled(bool disabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Filter> StringFilter::clone() const {
|
std::unique_ptr<Filter> StringFilter::clone() const {
|
||||||
return std::make_unique<StringFilter>(this->key, this->other, this->inverted, this->_disabled);
|
return std::make_unique<StringFilter>(this->key, this->other, this->inverted, this->exact_match, this->_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string* StringFilter::error() const {
|
const std::string* StringFilter::error() const {
|
||||||
return !this->_error.empty() ? &this->_error : nullptr;
|
return !this->_error.empty() ? &this->_error : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StringFilter::_match_no_regex(const LogcatEntry& entry) const {
|
||||||
|
bool matched;
|
||||||
|
if (this->exact_match) {
|
||||||
|
switch (this->key) {
|
||||||
|
case FilterKey::User: matched = entry.user.value_or("") == this->other; break;
|
||||||
|
case FilterKey::Tag: matched = entry.tag == this->other; break;
|
||||||
|
case FilterKey::Message: matched = entry.message == this->other; break;
|
||||||
|
default: throw std::runtime_error("StringFilter::match received unhandled key");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (this->key) {
|
||||||
|
case FilterKey::User: matched = entry.user.value_or("").find(this->other) != std::string::npos; break;
|
||||||
|
case FilterKey::Tag: matched = entry.tag.find(this->other) != std::string::npos; break;
|
||||||
|
case FilterKey::Message: matched = entry.message.find(this->other) != std::string::npos; break;
|
||||||
|
default: throw std::runtime_error("StringFilter::match received unhandled key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !this->inverted ? matched : !matched;
|
||||||
|
}
|
||||||
|
|
||||||
bool StringFilter::match(const LogcatEntry& entry) const {
|
bool StringFilter::match(const LogcatEntry& entry) const {
|
||||||
bool matched;
|
bool matched;
|
||||||
|
|
||||||
|
@ -101,13 +121,7 @@ bool StringFilter::match(const LogcatEntry& entry) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!this->other.starts_with("regex:")) {
|
if (!this->other.starts_with("regex:")) {
|
||||||
switch (this->key) {
|
return this->_match_no_regex(entry);
|
||||||
case FilterKey::User: matched = entry.user.value_or("") == this->other; break;
|
|
||||||
case FilterKey::Tag: matched = entry.tag == this->other; break;
|
|
||||||
case FilterKey::Message: matched = entry.message == this->other; break;
|
|
||||||
default: throw std::runtime_error("StringFilter::match received unhandled key");
|
|
||||||
}
|
|
||||||
return !this->inverted ? matched : !matched;
|
|
||||||
}
|
}
|
||||||
if (!this->_regex) {
|
if (!this->_regex) {
|
||||||
log("StringFilter::match called with a regex despite there being no regex");
|
log("StringFilter::match called with a regex despite there being no regex");
|
||||||
|
@ -125,8 +139,10 @@ bool StringFilter::match(const LogcatEntry& entry) const {
|
||||||
pmatch[0].rm_so = 0;
|
pmatch[0].rm_so = 0;
|
||||||
pmatch[0].rm_eo = static_cast<regoff_t>(str.size());
|
pmatch[0].rm_eo = static_cast<regoff_t>(str.size());
|
||||||
|
|
||||||
matched = this->_regex->match(str.data(), 1, pmatch, REG_STARTEND)
|
matched = this->_regex->match(str.data(), 1, pmatch, REG_STARTEND);
|
||||||
&& pmatch[0].rm_so == 0 && static_cast<size_t>(pmatch[0].rm_eo) == str.size();
|
if (this->exact_match) {
|
||||||
|
matched = matched && pmatch[0].rm_so == 0 && static_cast<size_t>(pmatch[0].rm_eo) == str.size();
|
||||||
|
}
|
||||||
return !this->inverted ? matched : !matched;
|
return !this->inverted ? matched : !matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public:
|
||||||
StringFilter(const StringFilter&) = delete;
|
StringFilter(const StringFilter&) = delete;
|
||||||
StringFilter& operator=(const StringFilter&) = delete;
|
StringFilter& operator=(const StringFilter&) = delete;
|
||||||
|
|
||||||
StringFilter(FilterKey key_, std::string other_, bool inverted_ = false, bool disabled = false);
|
StringFilter(FilterKey key_, std::string other_, bool inverted_ = false, bool exact_match_ = true, bool disabled = false);
|
||||||
|
|
||||||
void updated() override;
|
void updated() override;
|
||||||
bool disabled() const override;
|
bool disabled() const override;
|
||||||
|
@ -69,8 +69,11 @@ public:
|
||||||
FilterKey key;
|
FilterKey key;
|
||||||
std::string other;
|
std::string other;
|
||||||
bool inverted;
|
bool inverted;
|
||||||
|
bool exact_match;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool _match_no_regex(const LogcatEntry& entry) const;
|
||||||
|
|
||||||
std::string _error;
|
std::string _error;
|
||||||
std::optional<Pcre2Regex> _regex;
|
std::optional<Pcre2Regex> _regex;
|
||||||
bool _disabled;
|
bool _disabled;
|
||||||
|
|
|
@ -52,6 +52,10 @@ static void render_filter(Filter* filter, std::string* title, bool* request_remo
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("Inverted", sfilter ? &sfilter->inverted : &ifilter->inverted);
|
ImGui::Checkbox("Inverted", sfilter ? &sfilter->inverted : &ifilter->inverted);
|
||||||
}
|
}
|
||||||
|
if (sfilter) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Checkbox("Exact match", &sfilter->exact_match);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter->error()) {
|
if (filter->error()) {
|
||||||
|
@ -103,7 +107,9 @@ static inline void render_string_filter(StringFilter* filter) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
ImGui::Text("%s is%s", head, filter->inverted ? " not" : "");
|
ImGui::Text("%s %s", head, filter->exact_match
|
||||||
|
? (filter->inverted ? "is not" : "is")
|
||||||
|
: (filter->inverted ? "doesn't have" : "has"));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::InputText("##str", &filter->other)) {
|
if (ImGui::InputText("##str", &filter->other)) {
|
||||||
filter->updated();
|
filter->updated();
|
||||||
|
|
Loading…
Reference in New Issue