diff --git a/src/storage/Registry.cxx b/src/storage/Registry.cxx index 8e9af3977..fb42f1760 100644 --- a/src/storage/Registry.cxx +++ b/src/storage/Registry.cxx @@ -58,13 +58,25 @@ GetStoragePluginByName(const char *name) noexcept return nullptr; } +const StoragePlugin * +GetStoragePluginByUri(const char *uri) noexcept +{ + for (auto i = storage_plugins; *i != nullptr; ++i) { + const StoragePlugin &plugin = **i; + if (plugin.SupportsUri(uri)) + return *i; + } + + return nullptr; +} + std::unique_ptr CreateStorageURI(EventLoop &event_loop, const char *uri) { for (auto i = storage_plugins; *i != nullptr; ++i) { const StoragePlugin &plugin = **i; - if (plugin.create_uri == nullptr) + if (plugin.create_uri == nullptr || !plugin.SupportsUri(uri)) continue; auto storage = plugin.create_uri(event_loop, uri); diff --git a/src/storage/Registry.hxx b/src/storage/Registry.hxx index 5fa8a825a..7a9179dba 100644 --- a/src/storage/Registry.hxx +++ b/src/storage/Registry.hxx @@ -38,6 +38,10 @@ gcc_nonnull_all gcc_pure const StoragePlugin * GetStoragePluginByName(const char *name) noexcept; +gcc_nonnull_all gcc_pure +const StoragePlugin * +GetStoragePluginByUri(const char *uri) noexcept; + gcc_nonnull_all std::unique_ptr CreateStorageURI(EventLoop &event_loop, const char *uri); diff --git a/src/storage/StoragePlugin.cxx b/src/storage/StoragePlugin.cxx new file mode 100644 index 000000000..adb6f9707 --- /dev/null +++ b/src/storage/StoragePlugin.cxx @@ -0,0 +1,34 @@ +/* + * Copyright 2003-2021 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "StoragePlugin.hxx" +#include "util/StringCompare.hxx" + +bool +StoragePlugin::SupportsUri(const char *uri) const noexcept +{ + if (prefixes == nullptr) + return false; + + for (auto i = prefixes; *i != nullptr; ++i) + if (StringStartsWithIgnoreCase(uri, *i)) + return true; + + return false; +} diff --git a/src/storage/StoragePlugin.hxx b/src/storage/StoragePlugin.hxx index 17dccf892..ac2d427b7 100644 --- a/src/storage/StoragePlugin.hxx +++ b/src/storage/StoragePlugin.hxx @@ -28,11 +28,20 @@ class EventLoop; struct StoragePlugin { const char *name; + /** + * A nullptr-terminated list of URI prefixes handled by this + * plugin. This is usually a string in the form "scheme://". + */ + const char *const*prefixes; + /** * Throws #std::runtime_error on error. */ std::unique_ptr (*create_uri)(EventLoop &event_loop, const char *uri); + + [[gnu::pure]] + bool SupportsUri(const char *uri) const noexcept; }; #endif diff --git a/src/storage/meson.build b/src/storage/meson.build index 5aa214f01..2fbddeb7d 100644 --- a/src/storage/meson.build +++ b/src/storage/meson.build @@ -1,6 +1,7 @@ storage_api = static_library( 'storage_api', 'StorageInterface.cxx', + 'StoragePlugin.cxx', include_directories: inc, ) diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index b2cb5c8fc..ef1d59853 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -570,14 +570,15 @@ CurlStorage::OpenDirectory(std::string_view uri_utf8) static std::unique_ptr CreateCurlStorageURI(EventLoop &event_loop, const char *uri) { - if (!StringStartsWithCaseASCII(uri, "http://") && - !StringStartsWithCaseASCII(uri, "https://")) - return nullptr; - return std::make_unique(event_loop, uri); } +static constexpr const char *curl_prefixes[] = { + "http://", "https://", nullptr +}; + const StoragePlugin curl_storage_plugin = { "curl", + curl_prefixes, CreateCurlStorageURI, }; diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx index fa1e48792..61137298e 100644 --- a/src/storage/plugins/LocalStorage.cxx +++ b/src/storage/plugins/LocalStorage.cxx @@ -173,4 +173,5 @@ CreateLocalStorage(Path base_fs) constexpr StoragePlugin local_storage_plugin = { "local", nullptr, + nullptr, }; diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx index 67b7ed856..2344495f6 100644 --- a/src/storage/plugins/NfsStorage.cxx +++ b/src/storage/plugins/NfsStorage.cxx @@ -425,7 +425,10 @@ CreateNfsStorageURI(EventLoop &event_loop, const char *base) server.c_str(), mount); } +static constexpr const char *nfs_prefixes[] = { "nfs://", nullptr }; + const StoragePlugin nfs_storage_plugin = { "nfs", + nfs_prefixes, CreateNfsStorageURI, }; diff --git a/src/storage/plugins/UdisksStorage.cxx b/src/storage/plugins/UdisksStorage.cxx index 97a3265d6..844d1d5dc 100644 --- a/src/storage/plugins/UdisksStorage.cxx +++ b/src/storage/plugins/UdisksStorage.cxx @@ -377,7 +377,10 @@ CreateUdisksStorageURI(EventLoop &event_loop, const char *base_uri) std::move(inside_path)); } +static constexpr const char *udisks_prefixes[] = { "udisks://", nullptr }; + const StoragePlugin udisks_storage_plugin = { "udisks", + udisks_prefixes, CreateUdisksStorageURI, };