aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2014-02-26 19:48:37 +0100
committerMax Kellermann <max@duempel.org>2014-02-26 19:50:46 +0100
commit69a42fc901d06af2f90d7046e153dc1273f19beb (patch)
tree672f869bd68f193343b98c10f5b946c031731410
parent525789cd36c0dcf5a9b8a9fe25944197e9fc19cf (diff)
downloadmpd-69a42fc901d06af2f90d7046e153dc1273f19beb.tar.gz
mpd-69a42fc901d06af2f90d7046e153dc1273f19beb.tar.xz
mpd-69a42fc901d06af2f90d7046e153dc1273f19beb.zip
db/simple/Directory: LookupDirectory() return remaining URI
Code can now be reused in LookupSong().
-rw-r--r--src/db/plugins/simple/Directory.cxx55
-rw-r--r--src/db/plugins/simple/Directory.hxx17
-rw-r--r--src/db/plugins/simple/SimpleDatabasePlugin.cxx31
3 files changed, 62 insertions, 41 deletions
diff --git a/src/db/plugins/simple/Directory.cxx b/src/db/plugins/simple/Directory.cxx
index 05de51963..a81021b47 100644
--- a/src/db/plugins/simple/Directory.cxx
+++ b/src/db/plugins/simple/Directory.cxx
@@ -120,38 +120,49 @@ Directory::PruneEmpty()
}
}
-Directory *
+Directory::LookupResult
Directory::LookupDirectory(const char *uri)
{
assert(holding_db_lock());
assert(uri != nullptr);
if (isRootDirectory(uri))
- return this;
+ return { this, nullptr };
char *duplicated = xstrdup(uri), *name = duplicated;
Directory *d = this;
- while (1) {
+ while (true) {
char *slash = strchr(name, '/');
- if (slash == name) {
- d = nullptr;
+ if (slash == name)
break;
- }
if (slash != nullptr)
*slash = '\0';
- d = d->FindChild(name);
- if (d == nullptr || slash == nullptr)
+ Directory *tmp = d->FindChild(name);
+ if (tmp == nullptr)
+ /* not found */
+ break;
+
+ d = tmp;
+
+ if (slash == nullptr) {
+ /* found everything */
+ name = nullptr;
break;
+ }
name = slash + 1;
}
free(duplicated);
- return d;
+ const char *rest = name == nullptr
+ ? nullptr
+ : uri + (name - duplicated);
+
+ return { d, rest };
}
void
@@ -197,26 +208,16 @@ Directory::LookupSong(const char *uri)
assert(holding_db_lock());
assert(uri != nullptr);
- char *duplicated = xstrdup(uri);
- char *base = strrchr(duplicated, '/');
-
- Directory *d = this;
- if (base != nullptr) {
- *base++ = 0;
- d = d->LookupDirectory(duplicated);
- if (d == nullptr) {
- free(duplicated);
- return nullptr;
- }
- } else
- base = duplicated;
-
- Song *song = d->FindSong(base);
- assert(song == nullptr || song->parent == d);
+ auto r = LookupDirectory(uri);
+ if (r.uri == nullptr)
+ /* it's a directory */
+ return nullptr;
- free(duplicated);
- return song;
+ if (strchr(r.uri, '/') != nullptr)
+ /* refers to a URI "below" the actual song */
+ return nullptr;
+ return r.directory->FindSong(r.uri);
}
static int
diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx
index 716afecea..ab03092f7 100644
--- a/src/db/plugins/simple/Directory.hxx
+++ b/src/db/plugins/simple/Directory.hxx
@@ -149,6 +149,21 @@ public:
return child;
}
+ struct LookupResult {
+ /**
+ * The last directory that was found. If the given
+ * URI could not be resolved at all, then this is the
+ * root directory.
+ */
+ Directory *directory;
+
+ /**
+ * The remaining URI part (without leading slash) or
+ * nullptr if the given URI was consumed completely.
+ */
+ const char *uri;
+ };
+
/**
* Looks up a directory by its relative URI.
*
@@ -156,7 +171,7 @@ public:
* @return the Directory, or nullptr if none was found
*/
gcc_pure
- Directory *LookupDirectory(const char *uri);
+ LookupResult LookupDirectory(const char *uri);
gcc_pure
bool IsEmpty() const {
diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
index 9911caa66..8ba6eef92 100644
--- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx
+++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx
@@ -244,28 +244,33 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
{
ScopeDatabaseLock protect;
- const Directory *directory = root->LookupDirectory(selection.uri.c_str());
- if (directory == nullptr) {
+ auto r = root->LookupDirectory(selection.uri.c_str());
+ if (r.uri == nullptr) {
+ /* it's a directory */
+
+ if (selection.recursive && visit_directory &&
+ !visit_directory(r.directory->Export(), error))
+ return false;
+
+ return r.directory->Walk(selection.recursive, selection.filter,
+ visit_directory, visit_song,
+ visit_playlist,
+ error);
+ }
+
+ if (strchr(r.uri, '/') == nullptr) {
if (visit_song) {
- Song *song = root->LookupSong(selection.uri.c_str());
+ Song *song = r.directory->FindSong(r.uri);
if (song != nullptr) {
const LightSong song2 = song->Export();
return !selection.Match(song2) ||
visit_song(song2, error);
}
}
-
- error.Set(db_domain, DB_NOT_FOUND, "No such directory");
- return false;
}
- if (selection.recursive && visit_directory &&
- !visit_directory(directory->Export(), error))
- return false;
-
- return directory->Walk(selection.recursive, selection.filter,
- visit_directory, visit_song, visit_playlist,
- error);
+ error.Set(db_domain, DB_NOT_FOUND, "No such directory");
+ return false;
}
bool