From 6c6947b01fb043b7d4395b0253167b127f705665 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 8 Jan 2017 11:04:14 +0100 Subject: [PATCH] util/UriUtil: add uri_get_path() --- src/util/UriUtil.cxx | 57 ++++++++++++++++++++++++++++++++++++++++++++ src/util/UriUtil.hxx | 8 +++++++ 2 files changed, 65 insertions(+) diff --git a/src/util/UriUtil.cxx b/src/util/UriUtil.cxx index d6b369d9c..74f831513 100644 --- a/src/util/UriUtil.cxx +++ b/src/util/UriUtil.cxx @@ -19,10 +19,57 @@ #include "UriUtil.hxx" #include "StringCompare.hxx" +#include "CharUtil.hxx" #include #include +static constexpr bool +IsValidSchemeStart(char ch) +{ + return IsLowerAlphaASCII(ch); +} + +static constexpr bool +IsValidSchemeChar(char ch) +{ + return IsLowerAlphaASCII(ch) || IsDigitASCII(ch) || + ch == '+' || ch == '.' || ch == '-'; +} + +gcc_pure +static bool +IsValidScheme(StringView p) +{ + if (p.IsEmpty() || !IsValidSchemeStart(p.front())) + return false; + + for (size_t i = 1; i < p.size; ++i) + if (!IsValidSchemeChar(p[i])) + return false; + + return true; +} + +/** + * Return the URI part after the scheme specification (and after the + * double slash). + */ +gcc_pure +static const char * +uri_after_scheme(const char *uri) +{ + if (uri[0] == '/' && uri[1] == '/' && uri[2] != '/') + return uri + 2; + + const char *colon = strchr(uri, ':'); + return colon != nullptr && + IsValidScheme({uri, colon}) && + colon[1] == '/' && colon[2] == '/' + ? colon + 3 + : nullptr; +} + bool uri_has_scheme(const char *uri) { return strstr(uri, "://") != nullptr; @@ -38,6 +85,16 @@ uri_get_scheme(const char *uri) return std::string(uri, end); } +const char * +uri_get_path(const char *uri) +{ + const char *ap = uri_after_scheme(uri); + if (ap != nullptr) + return strchr(ap, '/'); + + return uri; +} + /* suffixes should be ascii only characters */ const char * uri_get_suffix(const char *uri) diff --git a/src/util/UriUtil.hxx b/src/util/UriUtil.hxx index 357027714..3f673ca7b 100644 --- a/src/util/UriUtil.hxx +++ b/src/util/UriUtil.hxx @@ -38,6 +38,14 @@ gcc_pure std::string uri_get_scheme(const char *uri); +/** + * 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); + gcc_pure const char * uri_get_suffix(const char *uri);