SongFilter: basic support for negated items

Not yet wired to the protocol.
This commit is contained in:
Max Kellermann 2018-07-21 11:20:50 +02:00
parent 504776a10f
commit 7f1b134137
2 changed files with 39 additions and 19 deletions

View File

@ -74,7 +74,7 @@ SongFilter::Item::Item(unsigned _tag,
} }
bool bool
SongFilter::Item::StringMatch(const char *s) const noexcept SongFilter::Item::StringMatchNN(const char *s) const noexcept
{ {
#if !CLANG_CHECK_VERSION(3,6) #if !CLANG_CHECK_VERSION(3,6)
/* disabled on clang due to -Wtautological-pointer-compare */ /* disabled on clang due to -Wtautological-pointer-compare */
@ -91,14 +91,14 @@ SongFilter::Item::StringMatch(const char *s) const noexcept
} }
bool bool
SongFilter::Item::Match(const TagItem &item) const noexcept SongFilter::Item::MatchNN(const TagItem &item) const noexcept
{ {
return (tag == LOCATE_TAG_ANY_TYPE || (unsigned)item.type == tag) && return (tag == LOCATE_TAG_ANY_TYPE || (unsigned)item.type == tag) &&
StringMatch(item.value); StringMatchNN(item.value);
} }
bool bool
SongFilter::Item::Match(const Tag &_tag) const noexcept SongFilter::Item::MatchNN(const Tag &_tag) const noexcept
{ {
bool visited_types[TAG_NUM_OF_ITEM_TYPES]; bool visited_types[TAG_NUM_OF_ITEM_TYPES];
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false); std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
@ -106,7 +106,7 @@ SongFilter::Item::Match(const Tag &_tag) const noexcept
for (const auto &i : _tag) { for (const auto &i : _tag) {
visited_types[i.type] = true; visited_types[i.type] = true;
if (Match(i)) if (MatchNN(i))
return true; return true;
} }
@ -125,7 +125,7 @@ SongFilter::Item::Match(const Tag &_tag) const noexcept
only "artist" exists, use that */ only "artist" exists, use that */
for (const auto &item : _tag) for (const auto &item : _tag)
if (item.type == TAG_ARTIST && if (item.type == TAG_ARTIST &&
StringMatch(item.value)) StringMatchNN(item.value))
return true; return true;
} }
} }
@ -134,7 +134,7 @@ SongFilter::Item::Match(const Tag &_tag) const noexcept
} }
bool bool
SongFilter::Item::Match(const DetachedSong &song) const noexcept SongFilter::Item::MatchNN(const DetachedSong &song) const noexcept
{ {
if (tag == LOCATE_TAG_BASE_TYPE) if (tag == LOCATE_TAG_BASE_TYPE)
return uri_is_child_or_same(value.c_str(), song.GetURI()); return uri_is_child_or_same(value.c_str(), song.GetURI());
@ -143,13 +143,13 @@ SongFilter::Item::Match(const DetachedSong &song) const noexcept
return song.GetLastModified() >= time; return song.GetLastModified() >= time;
if (tag == LOCATE_TAG_FILE_TYPE) if (tag == LOCATE_TAG_FILE_TYPE)
return StringMatch(song.GetURI()); return StringMatchNN(song.GetURI());
return Match(song.GetTag()); return MatchNN(song.GetTag());
} }
bool bool
SongFilter::Item::Match(const LightSong &song) const noexcept SongFilter::Item::MatchNN(const LightSong &song) const noexcept
{ {
if (tag == LOCATE_TAG_BASE_TYPE) { if (tag == LOCATE_TAG_BASE_TYPE) {
const auto uri = song.GetURI(); const auto uri = song.GetURI();
@ -161,10 +161,10 @@ SongFilter::Item::Match(const LightSong &song) const noexcept
if (tag == LOCATE_TAG_FILE_TYPE) { if (tag == LOCATE_TAG_FILE_TYPE) {
const auto uri = song.GetURI(); const auto uri = song.GetURI();
return StringMatch(uri.c_str()); return StringMatchNN(uri.c_str());
} }
return Match(song.tag); return MatchNN(song.tag);
} }
SongFilter::SongFilter(unsigned tag, const char *value, bool fold_case) SongFilter::SongFilter(unsigned tag, const char *value, bool fold_case)

View File

@ -52,6 +52,8 @@ public:
class Item { class Item {
unsigned tag; unsigned tag;
bool negated = false;
std::string value; std::string value;
/** /**
@ -73,6 +75,14 @@ public:
return tag; return tag;
} }
bool IsNegated() const noexcept {
return negated;
}
void SetNegated(bool _negated=true) noexcept {
negated = _negated;
}
bool GetFoldCase() const { bool GetFoldCase() const {
return fold_case; return fold_case;
} }
@ -82,21 +92,31 @@ public:
} }
private: private:
/* note: the "NN" suffix means "no negation", i.e. the
method pretends negation is unset, and the caller
is responsibly for considering it */
gcc_pure gcc_nonnull(2) gcc_pure gcc_nonnull(2)
bool StringMatch(const char *s) const noexcept; bool StringMatchNN(const char *s) const noexcept;
gcc_pure gcc_pure
bool Match(const TagItem &tag_item) const noexcept; bool MatchNN(const TagItem &tag_item) const noexcept;
gcc_pure gcc_pure
bool Match(const Tag &tag) const noexcept; bool MatchNN(const Tag &tag) const noexcept;
gcc_pure
bool MatchNN(const DetachedSong &song) const noexcept;
gcc_pure
bool MatchNN(const LightSong &song) const noexcept;
public: public:
template<typename T>
gcc_pure gcc_pure
bool Match(const DetachedSong &song) const noexcept; bool Match(const T &t) const noexcept {
return MatchNN(t) != IsNegated();
gcc_pure }
bool Match(const LightSong &song) const noexcept;
}; };
private: private: