db/simple/Directory: LookupDirectory() return remaining URI
Code can now be reused in LookupSong().
This commit is contained in:
parent
525789cd36
commit
69a42fc901
@ -120,38 +120,49 @@ Directory::PruneEmpty()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory *
|
Directory::LookupResult
|
||||||
Directory::LookupDirectory(const char *uri)
|
Directory::LookupDirectory(const char *uri)
|
||||||
{
|
{
|
||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(uri != nullptr);
|
assert(uri != nullptr);
|
||||||
|
|
||||||
if (isRootDirectory(uri))
|
if (isRootDirectory(uri))
|
||||||
return this;
|
return { this, nullptr };
|
||||||
|
|
||||||
char *duplicated = xstrdup(uri), *name = duplicated;
|
char *duplicated = xstrdup(uri), *name = duplicated;
|
||||||
|
|
||||||
Directory *d = this;
|
Directory *d = this;
|
||||||
while (1) {
|
while (true) {
|
||||||
char *slash = strchr(name, '/');
|
char *slash = strchr(name, '/');
|
||||||
if (slash == name) {
|
if (slash == name)
|
||||||
d = nullptr;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (slash != nullptr)
|
if (slash != nullptr)
|
||||||
*slash = '\0';
|
*slash = '\0';
|
||||||
|
|
||||||
d = d->FindChild(name);
|
Directory *tmp = d->FindChild(name);
|
||||||
if (d == nullptr || slash == nullptr)
|
if (tmp == nullptr)
|
||||||
|
/* not found */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
d = tmp;
|
||||||
|
|
||||||
|
if (slash == nullptr) {
|
||||||
|
/* found everything */
|
||||||
|
name = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
name = slash + 1;
|
name = slash + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(duplicated);
|
free(duplicated);
|
||||||
|
|
||||||
return d;
|
const char *rest = name == nullptr
|
||||||
|
? nullptr
|
||||||
|
: uri + (name - duplicated);
|
||||||
|
|
||||||
|
return { d, rest };
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -197,26 +208,16 @@ Directory::LookupSong(const char *uri)
|
|||||||
assert(holding_db_lock());
|
assert(holding_db_lock());
|
||||||
assert(uri != nullptr);
|
assert(uri != nullptr);
|
||||||
|
|
||||||
char *duplicated = xstrdup(uri);
|
auto r = LookupDirectory(uri);
|
||||||
char *base = strrchr(duplicated, '/');
|
if (r.uri == nullptr)
|
||||||
|
/* it's a directory */
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
Directory *d = this;
|
if (strchr(r.uri, '/') != nullptr)
|
||||||
if (base != nullptr) {
|
/* refers to a URI "below" the actual song */
|
||||||
*base++ = 0;
|
return nullptr;
|
||||||
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);
|
|
||||||
|
|
||||||
free(duplicated);
|
|
||||||
return song;
|
|
||||||
|
|
||||||
|
return r.directory->FindSong(r.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -149,6 +149,21 @@ public:
|
|||||||
return child;
|
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.
|
* Looks up a directory by its relative URI.
|
||||||
*
|
*
|
||||||
@ -156,7 +171,7 @@ public:
|
|||||||
* @return the Directory, or nullptr if none was found
|
* @return the Directory, or nullptr if none was found
|
||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
Directory *LookupDirectory(const char *uri);
|
LookupResult LookupDirectory(const char *uri);
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const {
|
||||||
|
@ -244,28 +244,33 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
{
|
{
|
||||||
ScopeDatabaseLock protect;
|
ScopeDatabaseLock protect;
|
||||||
|
|
||||||
const Directory *directory = root->LookupDirectory(selection.uri.c_str());
|
auto r = root->LookupDirectory(selection.uri.c_str());
|
||||||
if (directory == nullptr) {
|
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) {
|
if (visit_song) {
|
||||||
Song *song = root->LookupSong(selection.uri.c_str());
|
Song *song = r.directory->FindSong(r.uri);
|
||||||
if (song != nullptr) {
|
if (song != nullptr) {
|
||||||
const LightSong song2 = song->Export();
|
const LightSong song2 = song->Export();
|
||||||
return !selection.Match(song2) ||
|
return !selection.Match(song2) ||
|
||||||
visit_song(song2, error);
|
visit_song(song2, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error.Set(db_domain, DB_NOT_FOUND, "No such directory");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.recursive && visit_directory &&
|
error.Set(db_domain, DB_NOT_FOUND, "No such directory");
|
||||||
!visit_directory(directory->Export(), error))
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
return directory->Walk(selection.recursive, selection.filter,
|
|
||||||
visit_directory, visit_song, visit_playlist,
|
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
Loading…
Reference in New Issue
Block a user