diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 07f25c441..98f6de247 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -456,11 +456,11 @@ CurlStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow) } gcc_pure -static const char * +static std::string_view UriPathOrSlash(const char *uri) noexcept { - const char *path = uri_get_path(uri); - if (path == nullptr) + auto path = uri_get_path(uri); + if (path.data() == nullptr) path = "/"; return path; } @@ -495,7 +495,7 @@ private: */ gcc_pure StringView HrefToEscapedName(const char *href) const noexcept { - const char *path = uri_get_path(href); + StringView path = uri_get_path(href); if (path == nullptr) return nullptr; @@ -504,16 +504,16 @@ private: case in hex digits in escaped characters; TODO: implement properly */ path = StringAfterPrefixIgnoreCase(path, base_path.c_str()); - if (path == nullptr || *path == 0) + if (path == nullptr || path.empty()) return nullptr; - const char *slash = strchr(path, '/'); + const char *slash = path.Find('/'); if (slash == nullptr) /* regular file */ return path; - else if (slash[1] == 0) + else if (slash == &path.back()) /* trailing slash: collection; strip the slash */ - return {path, slash}; + return {path.data, slash}; else /* strange, better ignore it */ return nullptr; diff --git a/src/util/UriExtract.cxx b/src/util/UriExtract.cxx index 4e45040ce..c78bd9e8f 100644 --- a/src/util/UriExtract.cxx +++ b/src/util/UriExtract.cxx @@ -48,12 +48,12 @@ IsValidSchemeChar(char ch) gcc_pure static bool -IsValidScheme(StringView p) noexcept +IsValidScheme(std::string_view p) noexcept { if (p.empty() || !IsValidSchemeStart(p.front())) return false; - for (size_t i = 1; i < p.size; ++i) + for (size_t i = 1; i < p.size(); ++i) if (!IsValidSchemeChar(p[i])) return false; @@ -65,18 +65,23 @@ IsValidScheme(StringView p) noexcept * double slash). */ gcc_pure -static const char * -uri_after_scheme(const char *uri) noexcept +static std::string_view +uri_after_scheme(std::string_view uri) noexcept { - if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/') - return uri + 2; + if (uri.length() > 2 && + uri[0] == '/' && uri[1] == '/' && uri[2] != '/') + return uri.substr(2); - const char *colon = strchr(uri, ':'); - return colon != nullptr && - IsValidScheme({uri, colon}) && - colon[1] == '/' && colon[2] == '/' - ? colon + 3 - : nullptr; + auto colon = uri.find(':'); + if (colon == std::string_view::npos || + !IsValidScheme(uri.substr(0, colon))) + return {}; + + uri = uri.substr(colon + 1); + if (uri[0] != '/' || uri[1] != '/') + return {}; + + return uri.substr(2); } bool @@ -101,12 +106,16 @@ uri_is_relative_path(const char *uri) noexcept return !uri_has_scheme(uri) && *uri != '/'; } -const char * -uri_get_path(const char *uri) noexcept +std::string_view +uri_get_path(std::string_view uri) noexcept { - const char *ap = uri_after_scheme(uri); - if (ap != nullptr) - return strchr(ap, '/'); + auto ap = uri_after_scheme(uri); + if (ap.data() != nullptr) { + auto slash = ap.find('/'); + if (slash == std::string_view::npos) + return {}; + return ap.substr(slash); + } return uri; } diff --git a/src/util/UriExtract.hxx b/src/util/UriExtract.hxx index a47cf2cd0..05e288b30 100644 --- a/src/util/UriExtract.hxx +++ b/src/util/UriExtract.hxx @@ -57,9 +57,9 @@ uri_is_relative_path(const char *uri) noexcept; * Returns the URI path (including the query string) or nullptr if the * given URI has no path. */ -gcc_pure gcc_nonnull_all -const char * -uri_get_path(const char *uri) noexcept; +gcc_pure +std::string_view +uri_get_path(std::string_view uri) noexcept; gcc_pure const char * diff --git a/src/util/UriRelative.cxx b/src/util/UriRelative.cxx index 619afa812..507861a46 100644 --- a/src/util/UriRelative.cxx +++ b/src/util/UriRelative.cxx @@ -163,8 +163,8 @@ uri_apply_relative(const std::string &relative_uri, return base_uri.substr(0, i) + relative_uri; } - const char *_base_path = uri_get_path(base_uri.c_str()); - if (_base_path == nullptr) { + const auto _base_path = uri_get_path(base_uri); + if (_base_path.data() == nullptr) { std::string result(base_uri); if (relative_uri.front() != '/') result.push_back('/'); @@ -183,7 +183,7 @@ uri_apply_relative(const std::string &relative_uri, if (!ConsumeSpecial(relative_path, base_path)) return {}; - std::string result(base_uri.c_str(), _base_path); + std::string result(base_uri.data(), _base_path.data()); result.append(base_path.data, base_path.size); result.append(relative_path); return result;