From 0e709f25cd49484134bea2cfc56aa783f342c52d Mon Sep 17 00:00:00 2001 From: blankie Date: Fri, 17 Feb 2023 12:33:08 +0700 Subject: [PATCH] Avoid copying strings in StringFilter --- filters.cpp | 63 ++++++++++++++++++++++++++++++----------------------- filters.h | 1 + 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/filters.cpp b/filters.cpp index f5428e4..a06360b 100644 --- a/filters.cpp +++ b/filters.cpp @@ -94,55 +94,64 @@ const std::string* StringFilter::error() const { } 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; + case FilterKey::User: return entry.user && *entry.user == this->other; + case FilterKey::Tag: return entry.tag == this->other; + case FilterKey::Message: return entry.message == this->other; 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; + case FilterKey::User: return entry.user && entry.user->find(this->other) != std::string::npos; + case FilterKey::Tag: return entry.tag.find(this->other) != std::string::npos; + case FilterKey::Message: return entry.message.find(this->other) != std::string::npos; default: throw std::runtime_error("StringFilter::match received unhandled key"); } } - return !this->inverted ? matched : !matched; } -bool StringFilter::match(const LogcatEntry& entry) const { - bool matched; - - if (this->error()) { - log(std::string("StringFilter::match called despite there being an error: ") + *this->error()); - return true; - } - if (!this->other.starts_with("regex:")) { - return this->_match_no_regex(entry); - } +bool StringFilter::_match_regex(const LogcatEntry& entry) const { if (!this->_regex) { log("StringFilter::match called with a regex despite there being no regex"); return true; } - std::string str; + bool matched; + const std::string* str; regmatch_t pmatch[1]; + int eflags = REG_STARTEND; + switch (this->key) { - case FilterKey::User: str = entry.user.value_or(""); break; - case FilterKey::Tag: str = entry.tag; break; - case FilterKey::Message: str = entry.message; break; + case FilterKey::User: str = entry.user ? &*entry.user : nullptr; break; + case FilterKey::Tag: str = &entry.tag; break; + case FilterKey::Message: str = &entry.message; break; default: throw std::runtime_error("StringFilter::match received unhandled key"); } pmatch[0].rm_so = 0; - pmatch[0].rm_eo = static_cast(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(); + pmatch[0].rm_eo = str ? static_cast(str->size()) : 0; + if (!this->exact_match) { + eflags |= REG_NOSUB; } + + matched = this->_regex->match(str ? str->data() : "", 1, pmatch, eflags); + if (this->exact_match) { + matched = matched && pmatch[0].rm_so == 0 && str + ? static_cast(pmatch[0].rm_eo) == str->size() + : pmatch[0].rm_so == 0; + } + return matched; +} + +bool StringFilter::match(const LogcatEntry& entry) const { + if (this->error()) { + log(std::string("StringFilter::match called despite there being an error: ") + *this->error()); + return true; + } + + bool matched = !this->other.starts_with("regex:") + ? this->_match_no_regex(entry) + : this->_match_regex(entry); return !this->inverted ? matched : !matched; } diff --git a/filters.h b/filters.h index 3172e16..e96ec78 100644 --- a/filters.h +++ b/filters.h @@ -74,6 +74,7 @@ public: private: bool _match_no_regex(const LogcatEntry& entry) const; + bool _match_regex(const LogcatEntry& entry) const; std::string _error; std::optional _regex;