From b726efcfd9462255d1ff2eedb9e9cdcb9f85b8b2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 3 Mar 2018 17:44:29 +0200 Subject: Add url::traits::find(), checks whether string looks like URL --- libbutl/url.mxx | 11 +++++++++++ libbutl/url.txx | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) 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 + std::size_t url_traits:: + 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 @@ -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) -- cgit v1.1