diff --git a/src/db/Uri.hxx b/src/db/Uri.hxx index 37a2186f3..cb85d0ff2 100644 --- a/src/db/Uri.hxx +++ b/src/db/Uri.hxx @@ -20,10 +20,18 @@ #ifndef MPD_DB_URI_HXX #define MPD_DB_URI_HXX +#include + static inline bool isRootDirectory(const char *name) { return name[0] == 0 || (name[0] == '/' && name[1] == 0); } +static inline bool +isRootDirectory(std::string_view name) noexcept +{ + return name.empty() || (name.size() == 1 && name.front() == '/'); +} + #endif diff --git a/src/db/plugins/simple/Directory.cxx b/src/db/plugins/simple/Directory.cxx index 0b821fac4..e78b6e6fb 100644 --- a/src/db/plugins/simple/Directory.cxx +++ b/src/db/plugins/simple/Directory.cxx @@ -127,13 +127,12 @@ Directory::PruneEmpty() noexcept } Directory::LookupResult -Directory::LookupDirectory(const char *_uri) noexcept +Directory::LookupDirectory(std::string_view _uri) noexcept { assert(holding_db_lock()); - assert(_uri != nullptr); if (isRootDirectory(_uri)) - return { this, _uri, nullptr }; + return { this, _uri, {} }; StringView uri(_uri); @@ -156,7 +155,7 @@ Directory::LookupDirectory(const char *_uri) noexcept uri = rest; } while (uri != nullptr); - return { d, StringView(_uri, uri.data - 1), uri.data }; + return { d, _uri.substr(0, uri.data - _uri.data()), uri }; } void diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx index 49df25ee2..7062e609c 100644 --- a/src/db/plugins/simple/Directory.hxx +++ b/src/db/plugins/simple/Directory.hxx @@ -189,9 +189,9 @@ public: /** * The remaining URI part (without leading slash) or - * nullptr if the given URI was consumed completely. + * empty if the given URI was consumed completely. */ - const char *rest; + std::string_view rest; }; /** @@ -201,7 +201,7 @@ public: * @return the Directory, or nullptr if none was found */ gcc_pure - LookupResult LookupDirectory(const char *uri) noexcept; + LookupResult LookupDirectory(std::string_view uri) noexcept; gcc_pure bool IsEmpty() const noexcept { diff --git a/src/db/plugins/simple/SimpleDatabasePlugin.cxx b/src/db/plugins/simple/SimpleDatabasePlugin.cxx index f2a420fec..71c40c55e 100644 --- a/src/db/plugins/simple/SimpleDatabasePlugin.cxx +++ b/src/db/plugins/simple/SimpleDatabasePlugin.cxx @@ -211,8 +211,10 @@ SimpleDatabase::GetSong(const char *uri) const /* pass the request to the mounted database */ protect.unlock(); + /* note: r.rest.data() is actually null-terminated + because it points inside the "uri" parameter */ const LightSong *song = - r.directory->mounted_database->GetSong(r.rest); + r.directory->mounted_database->GetSong(r.rest.data()); if (song == nullptr) return nullptr; @@ -222,12 +224,12 @@ SimpleDatabase::GetSong(const char *uri) const return prefixed_light_song; } - if (r.rest == nullptr) + if (r.rest.data() == nullptr) /* it's a directory */ throw DatabaseError(DatabaseErrorCode::NOT_FOUND, "No such song"); - if (strchr(r.rest, '/') != nullptr) + if (r.rest.find('/') != std::string_view::npos) /* refers to a URI "below" the actual song */ throw DatabaseError(DatabaseErrorCode::NOT_FOUND, "No such song"); @@ -283,14 +285,15 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, { ScopeDatabaseLock protect; - auto r = root->LookupDirectory(selection.uri.c_str()); + auto r = root->LookupDirectory(selection.uri); if (r.directory->IsMount()) { /* pass the request and the remaining uri to the mounted database */ protect.unlock(); WalkMount(r.uri, *(r.directory->mounted_database), - (r.rest == nullptr)?"":r.rest, selection, + r.rest, + selection, visit_directory, visit_song, visit_playlist); return; @@ -298,7 +301,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, DatabaseVisitorHelper helper(CheckSelection(selection), visit_song); - if (r.rest == nullptr) { + if (r.rest.data() == nullptr) { /* it's a directory */ if (selection.recursive && visit_directory) @@ -311,7 +314,7 @@ SimpleDatabase::Visit(const DatabaseSelection &selection, return; } - if (strchr(r.rest, '/') == nullptr) { + if (r.rest.find('/') == std::string_view::npos) { if (visit_song) { Song *song = r.directory->FindSong(r.rest); if (song != nullptr) { @@ -402,11 +405,11 @@ SimpleDatabase::Mount(const char *uri, DatabasePtr db) ScopeDatabaseLock protect; auto r = root->LookupDirectory(uri); - if (r.rest == nullptr) + if (r.rest.data() == nullptr) throw DatabaseError(DatabaseErrorCode::CONFLICT, "Already exists"); - if (strchr(r.rest, '/') != nullptr) + if (r.rest.find('/') != std::string_view::npos) throw DatabaseError(DatabaseErrorCode::NOT_FOUND, "Parent not found"); @@ -461,7 +464,7 @@ SimpleDatabase::LockUmountSteal(const char *uri) noexcept ScopeDatabaseLock protect; auto r = root->LookupDirectory(uri); - if (r.rest != nullptr || !r.directory->IsMount()) + if (r.rest.data() != nullptr || !r.directory->IsMount()) return nullptr; auto db = std::move(r.directory->mounted_database); diff --git a/src/db/update/Service.cxx b/src/db/update/Service.cxx index dc09d79ad..2cc7e95eb 100644 --- a/src/db/update/Service.cxx +++ b/src/db/update/Service.cxx @@ -169,7 +169,7 @@ UpdateService::GenerateId() noexcept } unsigned -UpdateService::Enqueue(const char *path, bool discard) +UpdateService::Enqueue(const char *_path, bool discard) { assert(GetEventLoop().IsInside()); @@ -178,6 +178,8 @@ UpdateService::Enqueue(const char *path, bool discard) SimpleDatabase *db2; Storage *storage2; + std::string_view path(_path); + Directory::LookupResult lr; { const ScopeDatabaseLock protect; @@ -192,7 +194,7 @@ UpdateService::Enqueue(const char *path, bool discard) if (db2 == nullptr) throw std::runtime_error("Cannot update this type of database"); - if (lr.rest == nullptr) { + if (lr.rest.data() == nullptr) { storage2 = storage.GetMount(path); path = ""; } else {