diff --git a/filters.cpp b/filters.cpp index 520cb70..e5c8b1e 100644 --- a/filters.cpp +++ b/filters.cpp @@ -46,8 +46,8 @@ bool IntegerFilter::match(const LogcatEntry& entry) const { } -StringFilter::StringFilter(FilterKey key_, std::string other_, bool inverted_, bool disabled) - : key(key_), other(std::move(other_)), inverted(inverted_), _disabled(disabled) { +StringFilter::StringFilter(FilterKey key_, std::string other_, bool inverted_, bool exact_match_, bool 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) { throw std::runtime_error("StringFilter is passed a non-string key"); } @@ -86,13 +86,33 @@ void StringFilter::disabled(bool disabled) { } std::unique_ptr StringFilter::clone() const { - return std::make_unique(this->key, this->other, this->inverted, this->_disabled); + return std::make_unique(this->key, this->other, this->inverted, this->exact_match, this->_disabled); } const std::string* StringFilter::error() const { 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 matched; @@ -101,13 +121,7 @@ bool StringFilter::match(const LogcatEntry& entry) const { return true; } if (!this->other.starts_with("regex:")) { - 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"); - } - return !this->inverted ? matched : !matched; + return this->_match_no_regex(entry); } if (!this->_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_eo = static_cast(str.size()); - matched = this->_regex->match(str.data(), 1, pmatch, REG_STARTEND) - && pmatch[0].rm_so == 0 && static_cast(pmatch[0].rm_eo) == str.size(); + matched = this->_regex->match(str.data(), 1, pmatch, REG_STARTEND); + if (this->exact_match) { + matched = matched && pmatch[0].rm_so == 0 && static_cast(pmatch[0].rm_eo) == str.size(); + } return !this->inverted ? matched : !matched; } diff --git a/filters.h b/filters.h index ba34099..5f9bf19 100644 --- a/filters.h +++ b/filters.h @@ -57,7 +57,7 @@ public: StringFilter(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; bool disabled() const override; @@ -69,8 +69,11 @@ public: FilterKey key; std::string other; bool inverted; + bool exact_match; private: + bool _match_no_regex(const LogcatEntry& entry) const; + std::string _error; std::optional _regex; bool _disabled; diff --git a/windows/filters.cpp b/windows/filters.cpp index a0cfe46..fbffd15 100644 --- a/windows/filters.cpp +++ b/windows/filters.cpp @@ -52,6 +52,10 @@ static void render_filter(Filter* filter, std::string* title, bool* request_remo ImGui::SameLine(); ImGui::Checkbox("Inverted", sfilter ? &sfilter->inverted : &ifilter->inverted); } + if (sfilter) { + ImGui::SameLine(); + ImGui::Checkbox("Exact match", &sfilter->exact_match); + } } if (filter->error()) { @@ -103,7 +107,9 @@ static inline void render_string_filter(StringFilter* filter) { }; 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(); if (ImGui::InputText("##str", &filter->other)) { filter->updated();