diff --git a/src/song/OptimizeFilter.cxx b/src/song/OptimizeFilter.cxx index 471045b76..81ab26572 100644 --- a/src/song/OptimizeFilter.cxx +++ b/src/song/OptimizeFilter.cxx @@ -58,11 +58,11 @@ OptimizeSongFilter(ISongFilterPtr f) noexcept /* #TagSongFilter has its own "negated" flag, so we can drop the #NotSongFilter container */ - tf->negated = !tf->negated; + tf->ToggleNegated(); return child; } else if (auto *uf = dynamic_cast(child.get())) { /* same for #UriSongFilter */ - uf->negated = !uf->negated; + uf->ToggleNegated(); return child; } diff --git a/src/song/StringFilter.cxx b/src/song/StringFilter.cxx index a918d3c85..1e57b638f 100644 --- a/src/song/StringFilter.cxx +++ b/src/song/StringFilter.cxx @@ -23,8 +23,8 @@ #include -bool -StringFilter::Match(const char *s) const noexcept +inline bool +StringFilter::MatchWithoutNegation(const char *s) const noexcept { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ @@ -41,3 +41,9 @@ StringFilter::Match(const char *s) const noexcept : value == s; } } + +bool +StringFilter::Match(const char *s) const noexcept +{ + return MatchWithoutNegation(s) != negated; +} diff --git a/src/song/StringFilter.hxx b/src/song/StringFilter.hxx index ae363da39..1cc3f8998 100644 --- a/src/song/StringFilter.hxx +++ b/src/song/StringFilter.hxx @@ -38,14 +38,16 @@ class StringFilter { */ bool substring; + bool negated; + public: template - StringFilter(V &&_value, bool _fold_case, bool _substring) + StringFilter(V &&_value, bool _fold_case, bool _substring, bool _negated) :value(std::forward(_value)), fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare()), - substring(_substring) {} + substring(_substring), negated(_negated) {} bool empty() const noexcept { return value.empty(); @@ -59,8 +61,24 @@ public: return fold_case; } + bool IsNegated() const noexcept { + return negated; + } + + void ToggleNegated() noexcept { + negated = !negated; + } + + const char *GetOperator() const noexcept { + return negated ? "!=" : "=="; + } + gcc_pure bool Match(const char *s) const noexcept; + +private: + gcc_pure + bool MatchWithoutNegation(const char *s) const noexcept; }; #endif diff --git a/src/song/TagSongFilter.cxx b/src/song/TagSongFilter.cxx index a6578331b..99eb8252d 100644 --- a/src/song/TagSongFilter.cxx +++ b/src/song/TagSongFilter.cxx @@ -31,7 +31,8 @@ TagSongFilter::ToExpression() const noexcept ? "any" : tag_item_names[type]; - return std::string("(") + name + " " + (negated ? "!=" : "==") + " \"" + EscapeFilterString(filter.GetValue()) + "\")"; + return std::string("(") + name + " " + filter.GetOperator() + + " \"" + EscapeFilterString(filter.GetValue()) + "\")"; } bool @@ -89,5 +90,5 @@ TagSongFilter::MatchNN(const Tag &tag) const noexcept bool TagSongFilter::Match(const LightSong &song) const noexcept { - return MatchNN(song.tag) != negated; + return MatchNN(song.tag); } diff --git a/src/song/TagSongFilter.hxx b/src/song/TagSongFilter.hxx index df6b37965..b3e99a7f2 100644 --- a/src/song/TagSongFilter.hxx +++ b/src/song/TagSongFilter.hxx @@ -34,18 +34,15 @@ struct LightSong; class TagSongFilter final : public ISongFilter { TagType type; - bool negated; - StringFilter filter; - friend ISongFilterPtr OptimizeSongFilter(ISongFilterPtr) noexcept; - public: template TagSongFilter(TagType _type, V &&_value, bool fold_case, bool substring, - bool _negated) - :type(_type), negated(_negated), - filter(std::forward(_value), fold_case, substring) {} + bool negated) + :type(_type), + filter(std::forward(_value), fold_case, substring, + negated) {} TagType GetTagType() const { return type; @@ -60,7 +57,11 @@ public: } bool IsNegated() const noexcept { - return negated; + return filter.IsNegated(); + } + + void ToggleNegated() noexcept { + filter.ToggleNegated(); } ISongFilterPtr Clone() const noexcept override { diff --git a/src/song/UriSongFilter.cxx b/src/song/UriSongFilter.cxx index 584595b65..cd6ab84f2 100644 --- a/src/song/UriSongFilter.cxx +++ b/src/song/UriSongFilter.cxx @@ -25,11 +25,12 @@ std::string UriSongFilter::ToExpression() const noexcept { - return std::string("(file ") + (negated ? "!=" : "==") + " \"" + EscapeFilterString(filter.GetValue()) + "\")"; + return std::string("(file ") + filter.GetOperator() + + " \"" + EscapeFilterString(filter.GetValue()) + "\")"; } bool UriSongFilter::Match(const LightSong &song) const noexcept { - return filter.Match(song.GetURI().c_str()) != negated; + return filter.Match(song.GetURI().c_str()); } diff --git a/src/song/UriSongFilter.hxx b/src/song/UriSongFilter.hxx index 60de80a95..8ff979d66 100644 --- a/src/song/UriSongFilter.hxx +++ b/src/song/UriSongFilter.hxx @@ -26,16 +26,12 @@ class UriSongFilter final : public ISongFilter { StringFilter filter; - bool negated; - - friend ISongFilterPtr OptimizeSongFilter(ISongFilterPtr) noexcept; - public: template UriSongFilter(V &&_value, bool fold_case, bool substring, - bool _negated) - :filter(std::forward(_value), fold_case, substring), - negated(_negated) {} + bool negated) + :filter(std::forward(_value), fold_case, substring, + negated) {} const auto &GetValue() const noexcept { return filter.GetValue(); @@ -46,7 +42,11 @@ public: } bool IsNegated() const noexcept { - return negated; + return filter.IsNegated(); + } + + void ToggleNegated() noexcept { + filter.ToggleNegated(); } ISongFilterPtr Clone() const noexcept override {