aboutsummaryrefslogtreecommitdiffstats
path: root/src/SongFilter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/SongFilter.cxx')
-rw-r--r--src/SongFilter.cxx73
1 files changed, 41 insertions, 32 deletions
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index 235dfe7a0..7a8e6fd12 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -19,12 +19,13 @@
#include "config.h"
#include "SongFilter.hxx"
-#include "Song.hxx"
+#include "db/LightSong.hxx"
+#include "DetachedSong.hxx"
#include "tag/Tag.hxx"
+#include "util/ConstBuffer.hxx"
#include "util/ASCII.hxx"
#include "util/UriUtil.hxx"
-
-#include <glib.h>
+#include "lib/icu/Collate.hxx"
#include <assert.h>
#include <string.h>
@@ -52,20 +53,10 @@ locate_parse_type(const char *str)
gcc_pure
static std::string
-CaseFold(const char *p)
-{
- char *q = g_utf8_casefold(p, -1);
- std::string result(q);
- g_free(q);
- return result;
-}
-
-gcc_pure
-static std::string
ImportString(const char *p, bool fold_case)
{
return fold_case
- ? CaseFold(p)
+ ? IcuCaseFold(p)
: std::string(p);
}
@@ -81,10 +72,8 @@ SongFilter::Item::StringMatch(const char *s) const
assert(s != nullptr);
if (fold_case) {
- char *p = g_utf8_casefold(s, -1);
- const bool result = strstr(p, value.c_str()) != NULL;
- g_free(p);
- return result;
+ const std::string folded = IcuCaseFold(s);
+ return folded.find(value) != folded.npos;
} else {
return s == value;
}
@@ -103,10 +92,10 @@ SongFilter::Item::Match(const Tag &_tag) const
bool visited_types[TAG_NUM_OF_ITEM_TYPES];
std::fill_n(visited_types, size_t(TAG_NUM_OF_ITEM_TYPES), false);
- for (unsigned i = 0; i < _tag.num_items; i++) {
- visited_types[_tag.items[i]->type] = true;
+ for (const auto &i : _tag) {
+ visited_types[i.type] = true;
- if (Match(*_tag.items[i]))
+ if (Match(i))
return true;
}
@@ -123,12 +112,10 @@ SongFilter::Item::Match(const Tag &_tag) const
if (tag == TAG_ALBUM_ARTIST && visited_types[TAG_ARTIST]) {
/* if we're looking for "album artist", but
only "artist" exists, use that */
- for (unsigned i = 0; i < _tag.num_items; i++) {
- const TagItem &item = *_tag.items[i];
+ for (const auto &item : _tag)
if (item.type == TAG_ARTIST &&
StringMatch(item.value))
return true;
- }
}
}
@@ -136,7 +123,19 @@ SongFilter::Item::Match(const Tag &_tag) const
}
bool
-SongFilter::Item::Match(const Song &song) const
+SongFilter::Item::Match(const DetachedSong &song) const
+{
+ if (tag == LOCATE_TAG_BASE_TYPE)
+ return uri_is_child_or_same(value.c_str(), song.GetURI());
+
+ if (tag == LOCATE_TAG_FILE_TYPE)
+ return StringMatch(song.GetURI());
+
+ return Match(song.GetTag());
+}
+
+bool
+SongFilter::Item::Match(const LightSong &song) const
{
if (tag == LOCATE_TAG_BASE_TYPE) {
const auto uri = song.GetURI();
@@ -148,7 +147,7 @@ SongFilter::Item::Match(const Song &song) const
return StringMatch(uri.c_str());
}
- return song.tag != NULL && Match(*song.tag);
+ return Match(*song.tag);
}
SongFilter::SongFilter(unsigned tag, const char *value, bool fold_case)
@@ -181,20 +180,30 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case)
}
bool
-SongFilter::Parse(unsigned argc, char *argv[], bool fold_case)
+SongFilter::Parse(ConstBuffer<const char *> args, bool fold_case)
{
- if (argc == 0 || argc % 2 != 0)
+ if (args.size == 0 || args.size % 2 != 0)
return false;
- for (unsigned i = 0; i < argc; i += 2)
- if (!Parse(argv[i], argv[i + 1], fold_case))
+ for (unsigned i = 0; i < args.size; i += 2)
+ if (!Parse(args[i], args[i + 1], fold_case))
+ return false;
+
+ return true;
+}
+
+bool
+SongFilter::Match(const DetachedSong &song) const
+{
+ for (const auto &i : items)
+ if (!i.Match(song))
return false;
return true;
}
bool
-SongFilter::Match(const Song &song) const
+SongFilter::Match(const LightSong &song) const
{
for (const auto &i : items)
if (!i.Match(song))