SongFilter: move code from SongFilter to AndSongFilter

This commit is contained in:
Max Kellermann 2018-07-29 18:39:47 +02:00
parent 2da5b7cb65
commit 1b5faf5cbf
2 changed files with 77 additions and 27 deletions

View File

@ -185,19 +185,19 @@ ModifiedSinceSongFilter::Match(const LightSong &song) const noexcept
return song.mtime >= value; return song.mtime >= value;
} }
SongFilter::SongFilter(TagType tag, const char *value, bool fold_case) ISongFilterPtr
AndSongFilter::Clone() const noexcept
{ {
items.emplace_back(std::make_unique<TagSongFilter>(tag, value, auto result = std::make_unique<AndSongFilter>();
fold_case, false));
}
SongFilter::~SongFilter() for (const auto &i : items)
{ result->items.emplace_back(i->Clone());
/* this destructor exists here just so it won't get inlined */
return result;
} }
std::string std::string
SongFilter::ToExpression() const noexcept AndSongFilter::ToExpression() const noexcept
{ {
auto i = items.begin(); auto i = items.begin();
const auto end = items.end(); const auto end = items.end();
@ -217,6 +217,33 @@ SongFilter::ToExpression() const noexcept
return e; return e;
} }
bool
AndSongFilter::Match(const LightSong &song) const noexcept
{
for (const auto &i : items)
if (!i->Match(song))
return false;
return true;
}
SongFilter::SongFilter(TagType tag, const char *value, bool fold_case)
{
and_filter.AddItem(std::make_unique<TagSongFilter>(tag, value,
fold_case, false));
}
SongFilter::~SongFilter()
{
/* this destructor exists here just so it won't get inlined */
}
std::string
SongFilter::ToExpression() const noexcept
{
return and_filter.ToExpression();
}
static std::chrono::system_clock::time_point static std::chrono::system_clock::time_point
ParseTimeStamp(const char *s) ParseTimeStamp(const char *s)
{ {
@ -352,15 +379,15 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case)
if (!uri_safe_local(value)) if (!uri_safe_local(value))
throw std::runtime_error("Bad URI"); throw std::runtime_error("Bad URI");
items.emplace_back(std::make_unique<BaseSongFilter>(value)); and_filter.AddItem(std::make_unique<BaseSongFilter>(value));
break; break;
case LOCATE_TAG_MODIFIED_SINCE: case LOCATE_TAG_MODIFIED_SINCE:
items.emplace_back(std::make_unique<ModifiedSinceSongFilter>(ParseTimeStamp(value))); and_filter.AddItem(std::make_unique<ModifiedSinceSongFilter>(ParseTimeStamp(value)));
break; break;
case LOCATE_TAG_FILE_TYPE: case LOCATE_TAG_FILE_TYPE:
items.emplace_back(std::make_unique<UriSongFilter>(value, and_filter.AddItem(std::make_unique<UriSongFilter>(value,
fold_case, fold_case,
false)); false));
break; break;
@ -369,7 +396,7 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case)
if (tag == LOCATE_TAG_ANY_TYPE) if (tag == LOCATE_TAG_ANY_TYPE)
tag = TAG_NUM_OF_ITEM_TYPES; tag = TAG_NUM_OF_ITEM_TYPES;
items.emplace_back(std::make_unique<TagSongFilter>(TagType(tag), and_filter.AddItem(std::make_unique<TagSongFilter>(TagType(tag),
value, value,
fold_case, fold_case,
false)); false));
@ -391,7 +418,7 @@ SongFilter::Parse(ConstBuffer<const char *> args, bool fold_case)
if (*end != 0) if (*end != 0)
throw std::runtime_error("Unparsed garbage after expression"); throw std::runtime_error("Unparsed garbage after expression");
items.emplace_back(std::move(f)); and_filter.AddItem(std::move(f));
continue; continue;
} }
@ -407,17 +434,13 @@ SongFilter::Parse(ConstBuffer<const char *> args, bool fold_case)
bool bool
SongFilter::Match(const LightSong &song) const noexcept SongFilter::Match(const LightSong &song) const noexcept
{ {
for (const auto &i : items) return and_filter.Match(song);
if (!i->Match(song))
return false;
return true;
} }
bool bool
SongFilter::HasFoldCase() const noexcept SongFilter::HasFoldCase() const noexcept
{ {
for (const auto &i : items) { for (const auto &i : and_filter.GetItems()) {
if (auto t = dynamic_cast<const TagSongFilter *>(i.get())) { if (auto t = dynamic_cast<const TagSongFilter *>(i.get())) {
if (t->GetFoldCase()) if (t->GetFoldCase())
return true; return true;
@ -433,7 +456,7 @@ SongFilter::HasFoldCase() const noexcept
bool bool
SongFilter::HasOtherThanBase() const noexcept SongFilter::HasOtherThanBase() const noexcept
{ {
for (const auto &i : items) { for (const auto &i : and_filter.GetItems()) {
const auto *f = dynamic_cast<const BaseSongFilter *>(i.get()); const auto *f = dynamic_cast<const BaseSongFilter *>(i.get());
if (f == nullptr) if (f == nullptr)
return true; return true;
@ -445,7 +468,7 @@ SongFilter::HasOtherThanBase() const noexcept
const char * const char *
SongFilter::GetBase() const noexcept SongFilter::GetBase() const noexcept
{ {
for (const auto &i : items) { for (const auto &i : and_filter.GetItems()) {
const auto *f = dynamic_cast<const BaseSongFilter *>(i.get()); const auto *f = dynamic_cast<const BaseSongFilter *>(i.get());
if (f != nullptr) if (f != nullptr)
return f->GetValue(); return f->GetValue();
@ -460,7 +483,7 @@ SongFilter::WithoutBasePrefix(const char *_prefix) const noexcept
const StringView prefix(_prefix); const StringView prefix(_prefix);
SongFilter result; SongFilter result;
for (const auto &i : items) { for (const auto &i : and_filter.GetItems()) {
const auto *f = dynamic_cast<const BaseSongFilter *>(i.get()); const auto *f = dynamic_cast<const BaseSongFilter *>(i.get());
if (f != nullptr) { if (f != nullptr) {
const char *s = StringAfterPrefix(f->GetValue(), prefix); const char *s = StringAfterPrefix(f->GetValue(), prefix);
@ -472,14 +495,14 @@ SongFilter::WithoutBasePrefix(const char *_prefix) const noexcept
++s; ++s;
if (*s != 0) if (*s != 0)
result.items.emplace_back(std::make_unique<BaseSongFilter>(s)); result.and_filter.AddItem(std::make_unique<BaseSongFilter>(s));
continue; continue;
} }
} }
} }
result.items.emplace_back(i->Clone()); result.and_filter.AddItem(i->Clone());
} }
return result; return result;

View File

@ -200,9 +200,36 @@ public:
bool Match(const LightSong &song) const noexcept override; bool Match(const LightSong &song) const noexcept override;
}; };
class SongFilter { /**
* Combine multiple #ISongFilter instances with logical "and".
*/
class AndSongFilter final : public ISongFilter {
std::list<ISongFilterPtr> items; std::list<ISongFilterPtr> items;
public:
const auto &GetItems() const noexcept {
return items;
}
template<typename I>
void AddItem(I &&_item) {
items.emplace_back(std::forward<I>(_item));
}
gcc_pure
bool IsEmpty() const noexcept {
return items.empty();
}
/* virtual methods from ISongFilter */
ISongFilterPtr Clone() const noexcept override;
std::string ToExpression() const noexcept override;
bool Match(const LightSong &song) const noexcept override;
};
class SongFilter {
AndSongFilter and_filter;
public: public:
SongFilter() = default; SongFilter() = default;
@ -236,12 +263,12 @@ public:
bool Match(const LightSong &song) const noexcept; bool Match(const LightSong &song) const noexcept;
const auto &GetItems() const noexcept { const auto &GetItems() const noexcept {
return items; return and_filter.GetItems();
} }
gcc_pure gcc_pure
bool IsEmpty() const noexcept { bool IsEmpty() const noexcept {
return items.empty(); return and_filter.IsEmpty();
} }
/** /**