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)
|
||||
{
|
||||
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);
|
||||
auto r = LookupDirectory(uri);
|
||||
if (r.uri == nullptr)
|
||||
/* it's a directory */
|
||||
return nullptr;
|
||||
}
|
||||
} else
|
||||
base = duplicated;
|
||||
|
||||
Song *song = d->FindSong(base);
|
||||
assert(song == nullptr || song->parent == d);
|
||||
|
||||
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
|
||||
|
@ -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 {
|
||||
|
@ -244,30 +244,35 @@ 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);
|
||||
}
|
||||
|
||||
bool
|
||||
SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||
TagType tag_type,
|
||||
|
Loading…
Reference in New Issue
Block a user