Commit 35a23210 authored by Max Kellermann's avatar Max Kellermann

util/UriExtract: uri_get_suffix() returns std::string_view

No need to copy it to a buffer.
parent 19dd1a25
......@@ -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 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 {};
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"));
/* 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");
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());
/* 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment