util/UriExtract: uri_get_suffix() returns std::string_view
No need to copy it to a buffer.
This commit is contained in:
parent
19dd1a25d7
commit
35a232105e
@ -36,10 +36,10 @@
|
||||
gcc_pure
|
||||
static bool
|
||||
CheckDecoderPlugin(const DecoderPlugin &plugin,
|
||||
const char *suffix, const char *mime) noexcept
|
||||
std::string_view suffix, const char *mime) noexcept
|
||||
{
|
||||
return (mime != nullptr && plugin.SupportsMimeType(mime)) ||
|
||||
(suffix != nullptr && plugin.SupportsSuffix(suffix));
|
||||
(!suffix.empty() && plugin.SupportsSuffix(suffix));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -47,11 +47,10 @@ tag_stream_scan(InputStream &is, TagHandler &handler)
|
||||
{
|
||||
assert(is.IsReady());
|
||||
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *const suffix = uri_get_suffix(is.GetURI(), suffix_buffer);
|
||||
const auto suffix = uri_get_suffix(is.GetURI());
|
||||
const char *mime = is.GetMimeType();
|
||||
|
||||
if (suffix == nullptr && mime == nullptr)
|
||||
if (suffix.empty() && mime == nullptr)
|
||||
return false;
|
||||
|
||||
std::string mime_base;
|
||||
|
@ -72,12 +72,12 @@ protected:
|
||||
|
||||
private:
|
||||
void DecodeStream(InputStream &is, const DecoderPlugin &plugin);
|
||||
bool DecodeStream(InputStream &is, const char *suffix,
|
||||
bool DecodeStream(InputStream &is, std::string_view suffix,
|
||||
const DecoderPlugin &plugin);
|
||||
void DecodeStream(InputStream &is);
|
||||
bool DecodeContainer(const char *suffix, const DecoderPlugin &plugin);
|
||||
bool DecodeContainer(const char *suffix);
|
||||
bool DecodeFile(const char *suffix, InputStream &is,
|
||||
bool DecodeContainer(std::string_view suffix, const DecoderPlugin &plugin);
|
||||
bool DecodeContainer(std::string_view suffix);
|
||||
bool DecodeFile(std::string_view suffix, InputStream &is,
|
||||
const DecoderPlugin &plugin);
|
||||
void DecodeFile();
|
||||
|
||||
@ -130,17 +130,17 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin,
|
||||
gcc_pure
|
||||
static bool
|
||||
decoder_check_plugin_suffix(const DecoderPlugin &plugin,
|
||||
const char *suffix) noexcept
|
||||
std::string_view suffix) noexcept
|
||||
{
|
||||
assert(plugin.stream_decode != nullptr);
|
||||
|
||||
return suffix != nullptr && plugin.SupportsSuffix(suffix);
|
||||
return !suffix.empty() && plugin.SupportsSuffix(suffix);
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static bool
|
||||
decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
|
||||
const char *suffix) noexcept
|
||||
std::string_view suffix) noexcept
|
||||
{
|
||||
return plugin.stream_decode != nullptr &&
|
||||
(decoder_check_plugin_mime(plugin, is) ||
|
||||
@ -149,7 +149,7 @@ decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
|
||||
|
||||
inline bool
|
||||
GetChromaprintCommand::DecodeStream(InputStream &is,
|
||||
const char *suffix,
|
||||
std::string_view suffix,
|
||||
const DecoderPlugin &plugin)
|
||||
{
|
||||
if (!decoder_check_plugin(plugin, is, suffix))
|
||||
@ -164,8 +164,7 @@ GetChromaprintCommand::DecodeStream(InputStream &is,
|
||||
inline void
|
||||
GetChromaprintCommand::DecodeStream(InputStream &is)
|
||||
{
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *const suffix = uri_get_suffix(uri.c_str(), suffix_buffer);
|
||||
const auto suffix = uri_get_suffix(uri.c_str());
|
||||
|
||||
decoder_plugins_try([this, &is, suffix](const DecoderPlugin &plugin){
|
||||
return DecodeStream(is, suffix, plugin);
|
||||
@ -173,7 +172,7 @@ GetChromaprintCommand::DecodeStream(InputStream &is)
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetChromaprintCommand::DecodeContainer(const char *suffix,
|
||||
GetChromaprintCommand::DecodeContainer(std::string_view suffix,
|
||||
const DecoderPlugin &plugin)
|
||||
{
|
||||
if (plugin.container_scan == nullptr ||
|
||||
@ -188,7 +187,7 @@ GetChromaprintCommand::DecodeContainer(const char *suffix,
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetChromaprintCommand::DecodeContainer(const char *suffix)
|
||||
GetChromaprintCommand::DecodeContainer(std::string_view suffix)
|
||||
{
|
||||
return decoder_plugins_try([this, suffix](const DecoderPlugin &plugin){
|
||||
return DecodeContainer(suffix, plugin);
|
||||
@ -196,7 +195,7 @@ GetChromaprintCommand::DecodeContainer(const char *suffix)
|
||||
}
|
||||
|
||||
inline bool
|
||||
GetChromaprintCommand::DecodeFile(const char *suffix, InputStream &is,
|
||||
GetChromaprintCommand::DecodeFile(std::string_view suffix, InputStream &is,
|
||||
const DecoderPlugin &plugin)
|
||||
{
|
||||
if (!plugin.SupportsSuffix(suffix))
|
||||
@ -223,8 +222,8 @@ GetChromaprintCommand::DecodeFile(const char *suffix, InputStream &is,
|
||||
inline void
|
||||
GetChromaprintCommand::DecodeFile()
|
||||
{
|
||||
const char *suffix = uri_get_suffix(uri.c_str());
|
||||
if (suffix == nullptr)
|
||||
const auto suffix = uri_get_suffix(uri.c_str());
|
||||
if (suffix.empty())
|
||||
return;
|
||||
|
||||
InputStreamPtr input_stream;
|
||||
|
@ -157,7 +157,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, std::string_view name,
|
||||
|
||||
bool
|
||||
UpdateWalk::UpdateArchiveFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept
|
||||
{
|
||||
const ArchivePlugin *plugin = archive_plugin_from_suffix(suffix);
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
bool
|
||||
UpdateWalk::UpdateContainerFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept
|
||||
{
|
||||
const DecoderPlugin *_plugin = decoder_plugins_find([suffix](const DecoderPlugin &plugin){
|
||||
|
@ -88,7 +88,7 @@ UpdateWalk::UpdatePlaylistFile(Directory &parent, std::string_view name,
|
||||
|
||||
bool
|
||||
UpdateWalk::UpdatePlaylistFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept
|
||||
{
|
||||
const auto *const plugin = FindPlaylistPluginBySuffix(suffix);
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
inline void
|
||||
UpdateWalk::UpdateSongFile2(Directory &directory,
|
||||
const char *name, const char *suffix,
|
||||
const char *name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept
|
||||
try {
|
||||
Song *song;
|
||||
@ -98,7 +98,7 @@ try {
|
||||
|
||||
bool
|
||||
UpdateWalk::UpdateSongFile(Directory &directory,
|
||||
const char *name, const char *suffix,
|
||||
const char *name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept
|
||||
{
|
||||
if (!decoder_plugins_supports_suffix(suffix))
|
||||
|
@ -189,8 +189,8 @@ UpdateWalk::UpdateRegularFile(Directory &directory,
|
||||
const char *name,
|
||||
const StorageFileInfo &info) noexcept
|
||||
{
|
||||
const char *suffix = uri_get_suffix(name);
|
||||
if (suffix == nullptr)
|
||||
const auto suffix = uri_get_suffix(name);
|
||||
if (suffix.empty())
|
||||
return false;
|
||||
|
||||
return UpdateSongFile(directory, name, suffix, info) ||
|
||||
|
@ -86,15 +86,15 @@ private:
|
||||
void PurgeDeletedFromDirectory(Directory &directory) noexcept;
|
||||
|
||||
void UpdateSongFile2(Directory &directory,
|
||||
const char *name, const char *suffix,
|
||||
const char *name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
bool UpdateSongFile(Directory &directory,
|
||||
const char *name, const char *suffix,
|
||||
const char *name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
bool UpdateContainerFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ private:
|
||||
const char *name) noexcept;
|
||||
|
||||
bool UpdateArchiveFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
void UpdateArchiveFile(Directory &directory, std::string_view name,
|
||||
@ -114,7 +114,7 @@ private:
|
||||
#else
|
||||
bool UpdateArchiveFile([[maybe_unused]] Directory &directory,
|
||||
[[maybe_unused]] const char *name,
|
||||
[[maybe_unused]] const char *suffix,
|
||||
[[maybe_unused]] std::string_view suffix,
|
||||
[[maybe_unused]] const StorageFileInfo &info) noexcept {
|
||||
return false;
|
||||
}
|
||||
@ -125,7 +125,7 @@ private:
|
||||
const PlaylistPlugin &plugin) noexcept;
|
||||
|
||||
bool UpdatePlaylistFile(Directory &directory,
|
||||
std::string_view name, const char *suffix,
|
||||
std::string_view name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
bool UpdateRegularFile(Directory &directory,
|
||||
|
@ -178,17 +178,17 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin,
|
||||
gcc_pure
|
||||
static bool
|
||||
decoder_check_plugin_suffix(const DecoderPlugin &plugin,
|
||||
const char *suffix) noexcept
|
||||
std::string_view suffix) noexcept
|
||||
{
|
||||
assert(plugin.stream_decode != nullptr);
|
||||
|
||||
return suffix != nullptr && plugin.SupportsSuffix(suffix);
|
||||
return !suffix.empty() && plugin.SupportsSuffix(suffix);
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
static bool
|
||||
decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
|
||||
const char *suffix) noexcept
|
||||
std::string_view suffix) noexcept
|
||||
{
|
||||
return plugin.stream_decode != nullptr &&
|
||||
(decoder_check_plugin_mime(plugin, is) ||
|
||||
@ -198,7 +198,7 @@ decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
|
||||
static bool
|
||||
decoder_run_stream_plugin(DecoderBridge &bridge, InputStream &is,
|
||||
std::unique_lock<Mutex> &lock,
|
||||
const char *suffix,
|
||||
std::string_view suffix,
|
||||
const DecoderPlugin &plugin,
|
||||
bool &tried_r)
|
||||
{
|
||||
@ -216,8 +216,7 @@ decoder_run_stream_locked(DecoderBridge &bridge, InputStream &is,
|
||||
std::unique_lock<Mutex> &lock,
|
||||
const char *uri, bool &tried_r)
|
||||
{
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *const suffix = uri_get_suffix(uri, suffix_buffer);
|
||||
const auto suffix = uri_get_suffix(uri);
|
||||
|
||||
const auto f = [&,suffix](const auto &plugin)
|
||||
{ return decoder_run_stream_plugin(bridge, is, lock, suffix, plugin, tried_r); };
|
||||
@ -326,7 +325,7 @@ decoder_run_stream(DecoderBridge &bridge, const char *uri)
|
||||
* DecoderControl::mutex is not locked by caller.
|
||||
*/
|
||||
static bool
|
||||
TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||
TryDecoderFile(DecoderBridge &bridge, Path path_fs, std::string_view suffix,
|
||||
InputStream &input_stream,
|
||||
const DecoderPlugin &plugin)
|
||||
{
|
||||
@ -354,7 +353,8 @@ TryDecoderFile(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||
* DecoderControl::mutex is not locked by caller.
|
||||
*/
|
||||
static bool
|
||||
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||
TryContainerDecoder(DecoderBridge &bridge, Path path_fs,
|
||||
std::string_view suffix,
|
||||
const DecoderPlugin &plugin)
|
||||
{
|
||||
if (plugin.container_scan == nullptr ||
|
||||
@ -375,7 +375,8 @@ TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix,
|
||||
* DecoderControl::mutex is not locked by caller.
|
||||
*/
|
||||
static bool
|
||||
TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix)
|
||||
TryContainerDecoder(DecoderBridge &bridge, Path path_fs,
|
||||
std::string_view suffix)
|
||||
{
|
||||
return decoder_plugins_try([&bridge, path_fs,
|
||||
suffix](const DecoderPlugin &plugin){
|
||||
@ -394,8 +395,8 @@ TryContainerDecoder(DecoderBridge &bridge, Path path_fs, const char *suffix)
|
||||
static bool
|
||||
decoder_run_file(DecoderBridge &bridge, const char *uri_utf8, Path path_fs)
|
||||
{
|
||||
const char *suffix = uri_get_suffix(uri_utf8);
|
||||
if (suffix == nullptr)
|
||||
const auto suffix = uri_get_suffix(uri_utf8);
|
||||
if (suffix.empty())
|
||||
return false;
|
||||
|
||||
InputStreamPtr input_stream;
|
||||
|
@ -157,9 +157,8 @@ playlist_list_open_uri_suffix(const char *uri, Mutex &mutex,
|
||||
{
|
||||
assert(uri != nullptr);
|
||||
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *const suffix = uri_get_suffix(uri, suffix_buffer);
|
||||
if (suffix == nullptr)
|
||||
const auto suffix = uri_get_suffix(uri);
|
||||
if (suffix.empty())
|
||||
return nullptr;
|
||||
|
||||
for (unsigned i = 0; playlist_plugins[i] != nullptr; ++i) {
|
||||
@ -272,15 +271,14 @@ playlist_list_open_stream(InputStreamPtr &&is, const char *uri)
|
||||
return playlist;
|
||||
}
|
||||
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *suffix = uri != nullptr
|
||||
? uri_get_suffix(uri, suffix_buffer)
|
||||
: nullptr;
|
||||
if (suffix != nullptr) {
|
||||
auto playlist = playlist_list_open_stream_suffix(std::move(is),
|
||||
suffix);
|
||||
if (playlist != nullptr)
|
||||
return playlist;
|
||||
if (uri != nullptr) {
|
||||
const auto suffix = uri_get_suffix(uri);
|
||||
if (!suffix.empty()) {
|
||||
auto playlist = playlist_list_open_stream_suffix(std::move(is),
|
||||
suffix);
|
||||
if (playlist != nullptr)
|
||||
return playlist;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -121,37 +121,21 @@ uri_get_path(std::string_view uri) noexcept
|
||||
}
|
||||
|
||||
/* suffixes should be ascii only characters */
|
||||
const char *
|
||||
std::string_view
|
||||
uri_get_suffix(const char *uri) noexcept
|
||||
{
|
||||
const char *suffix = std::strrchr(uri, '.');
|
||||
if (suffix == nullptr || suffix == uri ||
|
||||
suffix[-1] == '/' || suffix[-1] == '\\')
|
||||
return nullptr;
|
||||
return {};
|
||||
|
||||
++suffix;
|
||||
|
||||
if (strpbrk(suffix, "/\\") != nullptr)
|
||||
return nullptr;
|
||||
return {};
|
||||
|
||||
return suffix;
|
||||
}
|
||||
|
||||
const char *
|
||||
uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept
|
||||
{
|
||||
const char *suffix = uri_get_suffix(uri);
|
||||
if (suffix == nullptr)
|
||||
return nullptr;
|
||||
|
||||
const char *q = std::strchr(suffix, '?');
|
||||
if (q != nullptr && size_t(q - suffix) < sizeof(buffer.data)) {
|
||||
memcpy(buffer.data, suffix, q - suffix);
|
||||
buffer.data[q - suffix] = 0;
|
||||
suffix = buffer.data;
|
||||
}
|
||||
|
||||
return suffix;
|
||||
/* remove the query string */
|
||||
return StringView(suffix).Split('?').first;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -62,20 +62,9 @@ std::string_view
|
||||
uri_get_path(std::string_view uri) noexcept;
|
||||
|
||||
gcc_pure
|
||||
const char *
|
||||
std::string_view
|
||||
uri_get_suffix(const char *uri) noexcept;
|
||||
|
||||
struct UriSuffixBuffer {
|
||||
char data[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the file name suffix, ignoring the query string.
|
||||
*/
|
||||
gcc_pure
|
||||
const char *
|
||||
uri_get_suffix(const char *uri, UriSuffixBuffer &buffer) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the URI fragment, i.e. the portion after the '#', but
|
||||
* without the '#'. If there is no '#', this function returns
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
static const DecoderPlugin *
|
||||
FindContainerDecoderPlugin(const char *suffix)
|
||||
FindContainerDecoderPlugin(std::string_view suffix)
|
||||
{
|
||||
return decoder_plugins_find([suffix](const DecoderPlugin &plugin){
|
||||
return plugin.container_scan != nullptr &&
|
||||
@ -48,10 +48,8 @@ FindContainerDecoderPlugin(const char *suffix)
|
||||
static const DecoderPlugin *
|
||||
FindContainerDecoderPlugin(Path path)
|
||||
{
|
||||
UriSuffixBuffer suffix_buffer;
|
||||
const char *const suffix = uri_get_suffix(path.ToUTF8Throw().c_str(),
|
||||
suffix_buffer);
|
||||
if (suffix == nullptr)
|
||||
const auto suffix = uri_get_suffix(path.ToUTF8Throw().c_str());
|
||||
if (suffix.empty())
|
||||
return nullptr;
|
||||
|
||||
return FindContainerDecoderPlugin(suffix);
|
||||
|
@ -6,28 +6,17 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using std::string_view_literals::operator""sv;
|
||||
|
||||
TEST(UriExtract, Suffix)
|
||||
{
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo/bar"));
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo.jpg/bar"));
|
||||
EXPECT_STREQ(uri_get_suffix("/foo/bar.jpg"), "jpg");
|
||||
EXPECT_STREQ(uri_get_suffix("/foo.png/bar.jpg"), "jpg");
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix(".jpg"));
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo/.jpg"));
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo/bar").data());
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo.jpg/bar").data());
|
||||
EXPECT_EQ(uri_get_suffix("/foo/bar.jpg"), "jpg"sv);
|
||||
EXPECT_EQ(uri_get_suffix("/foo.png/bar.jpg"), "jpg"sv);
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix(".jpg").data());
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo/.jpg").data());
|
||||
|
||||
/* the first overload does not eliminate the query
|
||||
string */
|
||||
EXPECT_STREQ(uri_get_suffix("/foo/bar.jpg?query_string"),
|
||||
"jpg?query_string");
|
||||
|
||||
/* ... but the second one does */
|
||||
UriSuffixBuffer buffer;
|
||||
EXPECT_STREQ(uri_get_suffix("/foo/bar.jpg?query_string", buffer),
|
||||
"jpg");
|
||||
|
||||
/* repeat some of the above tests with the second overload */
|
||||
EXPECT_EQ((const char *)nullptr, uri_get_suffix("/foo/bar", buffer));
|
||||
EXPECT_EQ((const char *)nullptr,
|
||||
uri_get_suffix("/foo.jpg/bar", buffer));
|
||||
EXPECT_STREQ(uri_get_suffix("/foo/bar.jpg", buffer), "jpg");
|
||||
/* eliminate the query string */
|
||||
EXPECT_EQ(uri_get_suffix("/foo/bar.jpg?query_string"), "jpg"sv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user