db/simple/Directory: reimplement LookupDirectory() without allocations

Use std::string_view to avoid modifying the string for the temporary
null terminators.
This commit is contained in:
Max Kellermann 2020-04-02 19:26:12 +02:00
parent 6593b5998a
commit dadf054fbb

View File

@ -30,9 +30,9 @@
#include "song/Filter.hxx" #include "song/Filter.hxx"
#include "lib/icu/Collate.hxx" #include "lib/icu/Collate.hxx"
#include "fs/Traits.hxx" #include "fs/Traits.hxx"
#include "util/Alloc.hxx"
#include "util/DeleteDisposer.hxx" #include "util/DeleteDisposer.hxx"
#include "util/StringCompare.hxx" #include "util/StringCompare.hxx"
#include "util/StringView.hxx"
#include <cassert> #include <cassert>
@ -127,24 +127,24 @@ Directory::PruneEmpty() noexcept
} }
Directory::LookupResult Directory::LookupResult
Directory::LookupDirectory(const char *uri) noexcept Directory::LookupDirectory(const char *_uri) noexcept
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(uri != nullptr); assert(_uri != nullptr);
if (isRootDirectory(uri)) if (isRootDirectory(_uri))
return { this, nullptr }; return { this, nullptr };
char *duplicated = xstrdup(uri), *name = duplicated; StringView uri(_uri);
Directory *d = this; Directory *d = this;
while (true) { do {
char *slash = strchr(name, '/'); auto s = uri.Split(PathTraitsUTF8::SEPARATOR);
if (slash == name) if (s.first.empty())
break; break;
if (slash != nullptr) const auto name = s.first;
*slash = '\0'; const auto rest = s.second;
Directory *tmp = d->FindChild(name); Directory *tmp = d->FindChild(name);
if (tmp == nullptr) if (tmp == nullptr)
@ -153,22 +153,10 @@ Directory::LookupDirectory(const char *uri) noexcept
d = tmp; d = tmp;
if (slash == nullptr) { uri = rest;
/* found everything */ } while (uri != nullptr);
name = nullptr;
break;
}
name = slash + 1; return { d, uri.data };
}
free(duplicated);
const char *rest = name == nullptr
? nullptr
: uri + (name - duplicated);
return { d, rest };
} }
void void