aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/url.mxx11
-rw-r--r--libbutl/url.txx36
2 files changed, 46 insertions, 1 deletions
diff --git a/libbutl/url.mxx b/libbutl/url.mxx
index fe091f1..577434f 100644
--- a/libbutl/url.mxx
+++ b/libbutl/url.mxx
@@ -216,6 +216,17 @@ LIBBUTL_MODEXPORT namespace butl
//
static string_type
translate_path (const path_type& path) {return string_type (path);}
+
+ // Check whether a string looks like a URL by searching for the first ':'
+ // (unless its position is specified with the second argument) and then
+ // making sure it's followed by '/' (e.g., http:// or file:/) and preceded
+ // by the scheme at least 2 characters long (so we don't confuse it with
+ // an absolute Windows path, e.g., c:/).
+ //
+ // Return the start of the URL substring or string_type::npos.
+ //
+ static std::size_t
+ find (const string_type&, std::size_t pos = string_type::npos);
};
template <typename H, // scheme
diff --git a/libbutl/url.txx b/libbutl/url.txx
index e511bed..3a2c387 100644
--- a/libbutl/url.txx
+++ b/libbutl/url.txx
@@ -182,6 +182,40 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
return r;
}
+ // url_traits
+ //
+ template <typename H, typename S, typename P>
+ std::size_t url_traits<H, S, P>::
+ find (const string_type& s, std::size_t p)
+ {
+ if (p == string_type::npos)
+ p = s.find (':');
+
+ if (p == string_type::npos ||
+ p < 2 ||
+ p + 1 == s.size () || s[p + 1] != '/')
+ return string_type::npos;
+
+ // Scan backwards for as long as it is a valid scheme.
+ //
+ std::size_t i (p);
+
+ for (; i != 0; --i)
+ {
+ auto c (s[i - 1]);
+ if (!(alnum (c) || c == '+' || c == '-' || c == '.'))
+ break;
+ }
+
+ if (i != p && !alpha (s[i])) // First must be alpha.
+ ++i;
+
+ if (p - i < 2)
+ return string_type::npos;
+
+ return i;
+ }
+
// basic_url
//
template <typename S, typename T>
@@ -209,7 +243,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
// Extract scheme.
//
- for(char_type c; i != e && (c = *i) != ':'; ++i)
+ for (char_type c; i != e && (c = *i) != ':'; ++i)
{
if (!(i == b
? alpha (c)