Commit 060908d5 authored by Max Kellermann's avatar Max Kellermann

song/Filter: add operator "contains"

Closes #410
parent 0b0f4c61
ver 0.21.2 (not yet released) ver 0.21.2 (not yet released)
* protocol * protocol
- operator "=~" matches a regular expression - operator "=~" matches a regular expression
- operator "contains" matches substrings
* decoder * decoder
- ffmpeg: require FFmpeg 3.1 or later - ffmpeg: require FFmpeg 3.1 or later
- ffmpeg: fix broken sound with certain codecs - ffmpeg: fix broken sound with certain codecs
......
...@@ -154,6 +154,9 @@ of: ...@@ -154,6 +154,9 @@ of:
``AlbumArtist`` does not exist. ``AlbumArtist`` does not exist.
``VALUE`` is what to find. ``VALUE`` is what to find.
- ``(TAG contains 'VALUE')`` checks if the given value is a substring
of the tag value.
- ``(TAG =~ 'VALUE')`` and ``(TAG !~ 'VALUE')`` use a Perl-compatible - ``(TAG =~ 'VALUE')`` and ``(TAG !~ 'VALUE')`` use a Perl-compatible
regular expression instead of doing a simple string comparison. regular expression instead of doing a simple string comparison.
(This feature is only available if :program:`MPD` was compiled with (This feature is only available if :program:`MPD` was compiled with
......
...@@ -206,6 +206,20 @@ ExpectQuoted(const char *&s) ...@@ -206,6 +206,20 @@ ExpectQuoted(const char *&s)
static StringFilter static StringFilter
ParseStringFilter(const char *&s, bool fold_case) ParseStringFilter(const char *&s, bool fold_case)
{ {
if (auto after_contains = StringAfterPrefixIgnoreCase(s, "contains ")) {
s = StripLeft(after_contains);
auto value = ExpectQuoted(s);
return StringFilter(std::move(value),
fold_case, true, false);
}
if (auto after_not_contains = StringAfterPrefixIgnoreCase(s, "!contains ")) {
s = StripLeft(after_not_contains);
auto value = ExpectQuoted(s);
return StringFilter(std::move(value),
fold_case, true, true);
}
bool negated = false; bool negated = false;
#ifdef HAVE_PCRE #ifdef HAVE_PCRE
......
...@@ -96,7 +96,9 @@ public: ...@@ -96,7 +96,9 @@ public:
const char *GetOperator() const noexcept { const char *GetOperator() const noexcept {
return IsRegex() return IsRegex()
? (negated ? "!~" : "=~") ? (negated ? "!~" : "=~")
: (negated ? "!=" : "=="); : (substring
? (negated ? "!contains" : "contains")
: (negated ? "!=" : "=="));
} }
gcc_pure gcc_pure
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment