SongFilter: move code from SongFilter to AndSongFilter
This commit is contained in:
parent
2da5b7cb65
commit
1b5faf5cbf
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user