aboutsummaryrefslogtreecommitdiff
path: root/libbutl/url.txx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-09-29 00:12:26 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-10-09 21:07:02 +0300
commitec9c6f1bbdfd3d86fba493ea56473c0aaf9acad1 (patch)
tree85f063f5fa0ea307d0c8f67e39fdfdd93731cb89 /libbutl/url.txx
parent758b64bcf02d9269ae4765ab98d7d46396b3e69a (diff)
Add support for rootless URLs
Diffstat (limited to 'libbutl/url.txx')
-rw-r--r--libbutl/url.txx87
1 files changed, 39 insertions, 48 deletions
diff --git a/libbutl/url.txx b/libbutl/url.txx
index b520509..2a2a215 100644
--- a/libbutl/url.txx
+++ b/libbutl/url.txx
@@ -6,16 +6,6 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
{
// Convenience functions.
//
- template <typename C>
- inline bool
- url_path_char (C c)
- {
- using url = basic_url<std::basic_string<C>>;
-
- return c == '/' || c == ':' || url::unreserved (c) ||
- c == '@' || url::sub_delim (c);
- }
-
// basic_url_host
//
template <typename S>
@@ -224,7 +214,7 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
{
using namespace std;
- using iterator = typename string_type::const_iterator;
+ using iterator = typename string_type::const_iterator;
try
{
@@ -329,26 +319,23 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
// Extract path.
//
- if (i != e && *i == '/')
+ if (i != e && *i != '?' && *i != '#')
{
- ++i; // Skip '/'.
+ rootless = *i != '/';
- // Verify and URL-decode the path.
+ if (!rootless)
+ ++i;
+
+ // Verify and translate the path.
//
iterator j (i);
for(char_type c; j != e && (c = *j) != '?' && c != '#'; ++j)
{
- if (!(url_path_char (c) || c == '%'))
+ if (!(path_char (c) || c == '%'))
throw invalid_argument ("invalid path");
}
- // Note that encoding for non-ASCII path is not specified (in contrast
- // to the host name), and presumably is local to the referenced
- // authority.
- //
- string_type s;
- decode (i, j, back_inserter (s));
- path = traits::translate_path (move (s));
+ path = traits::translate_path (string_type (i, j));
i = j;
}
@@ -369,11 +356,6 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
i = qe;
}
- // We don't suppose to end up with an empty URL.
- //
- if (empty ())
- throw invalid_argument ("no authority, path or query");
-
// Parse fragment.
//
if (i != e)
@@ -390,16 +372,19 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
// Translate the scheme string representation to its type.
//
- scheme = traits::translate_scheme (u,
- move (sc),
- authority,
- path,
- query,
- fragment);
+ optional<scheme_type> s (traits::translate_scheme (u,
+ move (sc),
+ authority,
+ path,
+ query,
+ fragment,
+ rootless));
+ assert (s);
+ scheme = *s;
}
// If we fail to parse the URL, then delegate this job to
- // traits::translate_scheme(). If it also fails, leaving the components
- // absent, then we re-throw.
+ // traits::translate_scheme(). If it also fails, returning nullopt, then
+ // we re-throw.
//
catch (const invalid_argument&)
{
@@ -407,16 +392,20 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
path = nullopt;
query = nullopt;
fragment = nullopt;
-
- scheme = traits::translate_scheme (u,
- string_type () /* scheme */,
- authority,
- path,
- query,
- fragment);
-
- if (!authority && !path && !query && !fragment)
+ rootless = false;
+
+ optional<scheme_type> s (
+ traits::translate_scheme (u,
+ string_type () /* scheme */,
+ authority,
+ path,
+ query,
+ fragment,
+ rootless));
+ if (!s)
throw;
+
+ scheme = *s;
}
}
@@ -433,7 +422,8 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
authority,
path,
query,
- fragment));
+ fragment,
+ rootless));
// Return the custom URL pbject representation if provided.
//
@@ -454,9 +444,10 @@ LIBBUTL_MODEXPORT namespace butl //@@ MOD Clang needs this for some reason.
if (path)
{
- r += '/';
- r += encode (traits::translate_path (*path),
- [] (char_type& c) {return !url_path_char (c);});
+ if (!rootless)
+ r += '/';
+
+ r += traits::translate_path (*path);
}
if (query)