From ac0852b4e33033d73770c610154ddb242f6c1119 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 4 Nov 2018 13:57:34 +0100 Subject: [PATCH] song/Filter: operator "==" never searches substrings in filter expressions The protocol documentation says that the difference between `find` and `search` is that `search` is case insensitive, but that's only half the truth: `search` also searches for sub strings instead of matching the whole string. This part is undocumented and unfortunate, but at this point, we can't change it. However leaking this surprising behavior to the new filter expressions was a bad idea; the "==" operator should never match substrings. For people who need that, we should add a new operator. --- NEWS | 1 + src/song/Filter.cxx | 15 +++++++++++++-- src/song/StringFilter.hxx | 4 ++-- src/song/TagSongFilter.hxx | 5 +++-- src/song/UriSongFilter.hxx | 5 +++-- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index d09aad71a..b22b28b02 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.21.1 (not yet released) * protocol - allow escaping quotes in filter expressions + - operator "==" never searches substrings in filter expressions * decoder - ffmpeg: fix build failure with non-standard FFmpeg installation path - flac: fix linker failure when building without FLAC support diff --git a/src/song/Filter.cxx b/src/song/Filter.cxx index d873ea3bd..0723f3c9f 100644 --- a/src/song/Filter.cxx +++ b/src/song/Filter.cxx @@ -91,8 +91,11 @@ locate_parse_type(const char *str) noexcept SongFilter::SongFilter(TagType tag, const char *value, bool fold_case) { + /* for compatibility with MPD 0.20 and older, "fold_case" also + switches on "substring" */ and_filter.AddItem(std::make_unique(tag, value, - fold_case, false)); + fold_case, fold_case, + false)); } SongFilter::~SongFilter() @@ -296,11 +299,13 @@ SongFilter::ParseExpression(const char *&s, bool fold_case) if (type == LOCATE_TAG_FILE_TYPE) return std::make_unique(std::move(value), fold_case, + false, negated); return std::make_unique(TagType(type), std::move(value), - fold_case, negated); + fold_case, false, + negated); } } @@ -325,7 +330,10 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case) break; case LOCATE_TAG_FILE_TYPE: + /* for compatibility with MPD 0.20 and older, + "fold_case" also switches on "substring" */ and_filter.AddItem(std::make_unique(value, + fold_case, fold_case, false)); break; @@ -334,9 +342,12 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case) if (tag == LOCATE_TAG_ANY_TYPE) tag = TAG_NUM_OF_ITEM_TYPES; + /* for compatibility with MPD 0.20 and older, + "fold_case" also switches on "substring" */ and_filter.AddItem(std::make_unique(TagType(tag), value, fold_case, + fold_case, false)); break; } diff --git a/src/song/StringFilter.hxx b/src/song/StringFilter.hxx index dd21eb100..ae363da39 100644 --- a/src/song/StringFilter.hxx +++ b/src/song/StringFilter.hxx @@ -40,12 +40,12 @@ class StringFilter { public: template - StringFilter(V &&_value, bool _fold_case) + StringFilter(V &&_value, bool _fold_case, bool _substring) :value(std::forward(_value)), fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare()), - substring(_fold_case) {} + substring(_substring) {} bool empty() const noexcept { return value.empty(); diff --git a/src/song/TagSongFilter.hxx b/src/song/TagSongFilter.hxx index cf880ec50..df6b37965 100644 --- a/src/song/TagSongFilter.hxx +++ b/src/song/TagSongFilter.hxx @@ -42,9 +42,10 @@ class TagSongFilter final : public ISongFilter { public: template - TagSongFilter(TagType _type, V &&_value, bool fold_case, bool _negated) + TagSongFilter(TagType _type, V &&_value, bool fold_case, bool substring, + bool _negated) :type(_type), negated(_negated), - filter(std::forward(_value), fold_case) {} + filter(std::forward(_value), fold_case, substring) {} TagType GetTagType() const { return type; diff --git a/src/song/UriSongFilter.hxx b/src/song/UriSongFilter.hxx index 8d37e48f1..60de80a95 100644 --- a/src/song/UriSongFilter.hxx +++ b/src/song/UriSongFilter.hxx @@ -32,8 +32,9 @@ class UriSongFilter final : public ISongFilter { public: template - UriSongFilter(V &&_value, bool fold_case, bool _negated) - :filter(std::forward(_value), fold_case), + UriSongFilter(V &&_value, bool fold_case, bool substring, + bool _negated) + :filter(std::forward(_value), fold_case, substring), negated(_negated) {} const auto &GetValue() const noexcept {