diff --git a/doc/javadoc.hpp b/doc/javadoc.hpp
new file mode 100644
index 00000000..af8cf7ca
--- /dev/null
+++ b/doc/javadoc.hpp
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Official repository: https://github.com/CPPAllinace/url
+//
+
+/** {brief}
+
+ {description}
+
+ @par Example
+ {description}
+ @code
+ {statements}
+ @endcode
+
+ @par BNF
+ @code
+ ELEMENT = {ABNF}
+ @endcode
+
+ @note {text}
+
+ @par Exception Safety
+ Does not throw.
+ No-throw guarantee.
+ Strong guarantee.
+ Calls to allocate may throw.
+ Exceptions thrown on invalid input.
+
+ @return {description}.
+
+ @tparam {name} {description}.
+
+ @param {name} {description}.
+
+ @throw {condition}.
+
+ @par Specification
+ @li text (rfc#)
+
+ @par Thread Safety
+ {description}
+
+ @see @ref {refid}, @ref {refid}.
+*/
diff --git a/include/boost/url/bnf/impl/parse.hpp b/include/boost/url/bnf/impl/parse.hpp
index d7f2bd74..f75f5007 100644
--- a/include/boost/url/bnf/impl/parse.hpp
+++ b/include/boost/url/bnf/impl/parse.hpp
@@ -124,7 +124,7 @@ parse_string(
Tn&&... tn)
{
error_code ec;
- if(parse(s, ec,
+ if(parse_string(s, ec,
std::forward(t0),
std::forward(tn)...))
{
diff --git a/include/boost/url/detail/except.hpp b/include/boost/url/detail/except.hpp
index f4fa2396..debe5212 100644
--- a/include/boost/url/detail/except.hpp
+++ b/include/boost/url/detail/except.hpp
@@ -20,7 +20,7 @@ namespace detail {
BOOST_URL_DECL void BOOST_NORETURN throw_bad_alloc(source_location const& loc);
BOOST_URL_DECL void BOOST_NORETURN throw_invalid_argument(char const* what, source_location const& loc);
-//BOOST_URL_DECL void BOOST_NORETURN throw_length_error(char const* what, source_location const& loc);
+BOOST_URL_DECL void BOOST_NORETURN throw_length_error(char const* what, source_location const& loc);
BOOST_URL_DECL void BOOST_NORETURN throw_out_of_range(source_location const& loc);
BOOST_URL_DECL void BOOST_NORETURN throw_system_error(error_code const& ec, source_location const& loc);
//BOOST_URL_DECL void BOOST_NORETURN throw_system_error(error e, source_location const& loc);
diff --git a/include/boost/url/detail/impl/except.ipp b/include/boost/url/detail/impl/except.ipp
index 9d3e54fc..e1786bce 100644
--- a/include/boost/url/detail/impl/except.ipp
+++ b/include/boost/url/detail/impl/except.ipp
@@ -27,7 +27,6 @@ throw_bad_alloc(
std::bad_alloc(), loc);
}
-#if 0
void
throw_length_error(
char const* what,
@@ -36,7 +35,6 @@ throw_length_error(
throw_exception(
std::length_error(what), loc);
}
-#endif
void
throw_invalid_argument(
diff --git a/include/boost/url/detail/impl/parse.ipp b/include/boost/url/detail/impl/parse.ipp
index 6ef4659c..b1ea94ed 100644
--- a/include/boost/url/detail/impl/parse.ipp
+++ b/include/boost/url/detail/impl/parse.ipp
@@ -85,7 +85,7 @@ apply_authority(
// leading "//" for authority
p.resize(
part::id_user,
- u.username.str.size() + 2);
+ u.user.str.size() + 2);
if(u.password.has_value())
{
diff --git a/include/boost/url/detail/parts.hpp b/include/boost/url/detail/parts.hpp
index 8c6253fa..16469230 100644
--- a/include/boost/url/detail/parts.hpp
+++ b/include/boost/url/detail/parts.hpp
@@ -11,6 +11,7 @@
#define BOOST_URL_DETAIL_PARTS_HPP
#include
+#include
#include
#include
@@ -43,7 +44,17 @@ struct parts
std::uint16_t port_number = 0;
urls::host_type host_type =
urls::host_type::none;
+ urls::scheme scheme =
+ urls::scheme::none;
+ // size excluding null
+ std::size_t
+ len() const noexcept
+ {
+ return offset[id_end];
+ }
+
+ // size of id
std::size_t
len(int id) const noexcept
{
@@ -51,6 +62,7 @@ struct parts
offset[id];
}
+ // size of [begin, end)
std::size_t
len(
int begin,
@@ -62,6 +74,7 @@ struct parts
offset[begin];
}
+ // return id as string
string_view
get(int id,
char const* s) const noexcept
@@ -72,6 +85,7 @@ struct parts
offset[id] };
}
+ // return [begin, end) as string
string_view
get(int begin,
int end,
@@ -83,6 +97,7 @@ struct parts
offset[begin] };
}
+ // change id to size n
void
resize(
int id,
@@ -100,7 +115,8 @@ struct parts
int id,
std::size_t n) noexcept
{
- BOOST_ASSERT(id < detail::id_end - 1);
+ BOOST_ASSERT(
+ id < detail::id_end - 1);
BOOST_ASSERT(n <= len(id));
offset[id + 1] = offset[id] +
static_cast(n);
diff --git a/include/boost/url/detail/pct_encoding.hpp b/include/boost/url/detail/pct_encoding.hpp
index eef4731d..19ef2b1b 100644
--- a/include/boost/url/detail/pct_encoding.hpp
+++ b/include/boost/url/detail/pct_encoding.hpp
@@ -138,14 +138,9 @@ pct_decode_size(
++n;
continue;
}
- if(opt.non_normal_is_error)
- {
- // reserved character in input
- ec = error::illegal_reserved_char;
- break;
- }
- ++n;
- ++it;
+ // reserved character in input
+ ec = error::illegal_reserved_char;
+ break;
}
return n;
}
diff --git a/include/boost/url/impl/scheme.ipp b/include/boost/url/impl/scheme.ipp
index 087a9999..83f2f081 100644
--- a/include/boost/url/impl/scheme.ipp
+++ b/include/boost/url/impl/scheme.ipp
@@ -23,6 +23,9 @@ string_to_scheme(
using bnf::ascii_tolower;
switch(s.size())
{
+ case 0: // none
+ return scheme::none;
+
case 2: // ws
if( ascii_tolower(s[0]) == 'w' &&
ascii_tolower(s[1]) == 's')
@@ -97,11 +100,11 @@ to_string(scheme s) noexcept
case scheme::https: return "https";
case scheme::ws: return "ws";
case scheme::wss: return "wss";
-
+ case scheme::none: return {};
default:
break;
}
- return "unknown";
+ return "";
}
} // urls
diff --git a/include/boost/url/impl/url.ipp b/include/boost/url/impl/url.ipp
index 8d2152de..e87b6017 100644
--- a/include/boost/url/impl/url.ipp
+++ b/include/boost/url/impl/url.ipp
@@ -12,11 +12,16 @@
#include
#include
+#include
+#include
#include
#include
#include
+#include
+#include
#include
#include
+#include
#include
#include
@@ -70,21 +75,21 @@ copy(
char const* s,
detail::parts const& pt)
{
- auto n = pt.len(
- id_scheme, id_end);
+ auto n = pt.len();
if(n == 0 && ! s_)
return;
if(cap_ < n)
{
auto cap = growth_impl(
cap_, n);
- auto p = alloc_impl(cap);
+ auto s1 = alloc_impl(cap);
if(s_)
free_impl(s_);
- s_ = p;
+ s_ = s1;
cap_ = cap;
}
- std::memcpy(s_, s, n);
+ if(n != 0)
+ std::memcpy(s_, s, n);
s_[n] = 0;
pt_ = pt;
}
@@ -109,19 +114,24 @@ growth_impl(
std::size_t cap,
std::size_t new_size)
{
- if(new_size >= std::size_t(-1))
- detail::throw_bad_alloc(
+ if(new_size > max_size())
+ detail::throw_length_error(
+ "url::reserve",
BOOST_CURRENT_LOCATION);
BOOST_ASSERT(new_size > cap);
if(cap == 0)
+ {
+ // minimum
+ if( new_size < 24)
+ return 24;
return new_size;
+ }
// 50% growth factor
- auto n = cap + (cap >> 1);
+ auto n = cap + cap / 2;
if(n < cap)
{
// overflow
- return std::size_t(-1)
- - 1; // for null
+ return max_size();
}
if(n < new_size)
return new_size;
@@ -198,9 +208,7 @@ operator=(url_view const& u)
}
//------------------------------------------------
-//************************************************
-//************************************************
-//************************************************
+//------------------------------------------------
//------------------------------------------------
//------------------------------------------------
@@ -213,8 +221,7 @@ bool
url::
empty() const noexcept
{
- return len(
- id_scheme, id_end) == 0;
+ return pt_.len() == 0;
}
//------------------------------------------------
@@ -262,6 +269,13 @@ scheme() const noexcept
return s;
}
+urls::scheme
+url::
+scheme_id() const noexcept
+{
+ return pt_.scheme;
+}
+
//----------------------------------------------------------
//
// authority
@@ -329,7 +343,7 @@ encoded_userinfo() const noexcept
string_view
url::
-encoded_username() const noexcept
+encoded_user() const noexcept
{
auto s = get(id_user);
if(! s.empty())
@@ -585,9 +599,7 @@ encoded_fragment() const noexcept
}
//------------------------------------------------
-//************************************************
-//************************************************
-//************************************************
+//------------------------------------------------
//------------------------------------------------
string_view
@@ -688,36 +700,290 @@ set_encoded_origin(
//
//------------------------------------------------
+void
+url::
+assert_scheme() const noexcept
+{
+ BOOST_ASSERT(
+ (len(id_scheme) == 0) ||
+ (len(id_scheme) > 1 &&
+ get(id_scheme).ends_with(':')));
+}
+
url&
url::
-set_scheme(
- string_view s)
+set_scheme(string_view s)
{
-#if 0
- if(s.empty())
- {
- resize_impl(id_scheme, 0);
- return *this;
- }
-
- scheme_bnf b;
- bnf::parse(s, b);
- auto const n = s.size();
- auto const dest =
- resize_impl(id_scheme, n + 1);
- s.copy(dest, n);
- dest[n] = ':';
-#endif
+ set_scheme_impl(
+ s, string_to_scheme(s));
return *this;
}
-#if 0
+url&
+url::
+set_scheme(urls::scheme id)
+{
+ if(id == urls::scheme::unknown)
+ detail::throw_invalid_argument(
+ "url::set_scheme",
+ BOOST_CURRENT_LOCATION);
+ if(id == urls::scheme::none)
+ {
+ set_scheme_impl("", id);
+ return *this;
+ }
+ set_scheme_impl(
+ to_string(id), id);
+ return *this;
+}
+
+void
+url::
+set_scheme_impl(
+ string_view s,
+ urls::scheme id)
+{
+ assert_scheme();
+
+ if(s.empty())
+ {
+ if(len(id_scheme) == 0)
+ return;
+
+ // remove scheme
+ // The complicated case is changing
+ // path-rootless to path-noscheme
+ bool const need_dot = [this]
+ {
+ if(has_authority())
+ return false;
+ auto s = get(id_path);
+ if(s.empty())
+ return false;
+ if(s.starts_with('/'))
+ return false;
+ auto const p = static_cast<
+ url const*>(this)->path();
+ BOOST_ASSERT(! p.empty());
+ auto it = p.begin();
+ s = it->encoded_segment();
+ return s.find_first_of(':') !=
+ string_view::npos;
+ }();
+
+ if(! need_dot)
+ {
+ // just remove the scheme
+ resize_impl(id_scheme, 0);
+ pt_.scheme = id;
+ assert_scheme();
+ return;
+ }
+
+ // remove the scheme but add "./"
+ // to the beginning of the path
+ auto dest = resize_impl(
+ id_scheme, 2);
+ dest[0] = '.';
+ dest[1] = '/';
+ pt_.split(id_scheme, 0);
+ pt_.scheme = id;
+ assert_scheme();
+ return;
+ }
+
+ scheme_bnf b;
+ error_code ec;
+ bnf::parse_string(s, ec, b);
+ if(ec.failed())
+ detail::throw_invalid_argument(
+ "url::set_scheme",
+ BOOST_CURRENT_LOCATION);
+ auto n = s.size();
+ auto dest = resize_impl(
+ id_scheme, n + 1);
+ s.copy(dest, n);
+ dest[n] = ':';
+ pt_.scheme = id;
+ assert_scheme();
+ return;
+}
+
//------------------------------------------------
//
// authority
//
//------------------------------------------------
+void
+url::
+assert_userinfo() const noexcept
+{
+ BOOST_ASSERT(
+ len(id_user) == 0 ||
+ get(id_user).starts_with("//"));
+ BOOST_ASSERT(
+ len(id_pass) == 0 ||
+ get(id_user).starts_with("//"));
+ BOOST_ASSERT(
+ (len(id_pass) == 0) ||
+ (len(id_pass) == 1 &&
+ get(id_pass) == "@") ||
+ (len(id_pass) == 2 &&
+ get(id_pass) == ":@") ||
+ (len(id_pass) > 2 &&
+ get(id_pass).starts_with(':') &&
+ get(id_pass).ends_with('@')));
+}
+
+//------------------------------------------------
+
+char*
+url::
+set_user_impl(std::size_t n)
+{
+ assert_userinfo();
+ if(len(id_pass) != 0)
+ {
+ // keep "//"
+ auto dest = resize_impl(
+ id_user, 2 + n);
+ assert_userinfo();
+ return dest + 2;
+ }
+ // add authority
+ auto dest = resize_impl(
+ id_user, 2 + n + 1);
+ pt_.split(id_user, 2 + n);
+ dest[0] = '/';
+ dest[1] = '/';
+ dest[2 + n] = '@';
+ assert_userinfo();
+ return dest + 2;
+}
+
+url&
+url::
+clear_user() noexcept
+{
+ assert_userinfo();
+ if(len(id_user) == 0)
+ {
+ // no authority
+ }
+ else if(len(id_pass) == 1)
+ {
+ // no password, remove '@'
+ resize_impl(
+ id_user, id_host, 2);
+ }
+ else
+ {
+ // keep password
+ resize_impl(id_user, 2);
+ }
+ assert_userinfo();
+ return *this;
+ }
+
+url&
+url::
+set_user(string_view s)
+{
+ masked_char_set<
+ unsub_char_mask> cs;
+ auto const n =
+ pct_encode_size(s, cs);
+ auto dest = set_user_impl(n);
+ dest = detail::pct_encode(
+ dest, get(id_pass).data(),
+ s, {}, cs);
+ BOOST_ASSERT(dest ==
+ get(id_pass).data());
+ assert_userinfo();
+ return *this;
+}
+
+url&
+url::
+set_encoded_user(
+ string_view s)
+{
+ if(s.empty())
+ {
+ // remove user
+ set_user_impl(0);
+ return *this;
+ }
+ error_code ec;
+ masked_char_set<
+ unsub_char_mask> cs;
+ pct_decode_size(s, ec, cs);
+ if(ec)
+ detail::throw_invalid_argument(
+ "url::set_encoded_user",
+ BOOST_CURRENT_LOCATION);
+ auto dest = set_user_impl(s.size());
+ BOOST_ASSERT(dest != nullptr);
+ std::memcpy(dest, s.data(), s.size());
+ return *this;
+}
+
+//------------------------------------------------
+
+char*
+url::
+set_password_impl(
+ std::size_t n)
+{
+ assert_userinfo();
+ if(len(id_user) != 0)
+ {
+ // already have authority
+ auto const dest = resize_impl(
+ id_pass, 1 + n + 1);
+ dest[0] = ':';
+ dest[n + 1] = '@';
+ return dest + 1;
+ }
+ // add authority
+ auto const dest =
+ resize_impl(
+ id_user, id_host,
+ 2 + 1 + n + 1);
+ pt_.split(id_user, 2);
+ dest[0] = '/';
+ dest[1] = '/';
+ dest[2] = ':';
+ dest[2 + n + 1] = '@';
+ assert_userinfo();
+ return dest + 3;
+}
+
+url&
+url::
+clear_password() noexcept
+{
+ assert_userinfo();
+ auto const n =
+ len(id_pass);
+ if(n == 0)
+ return *this;
+ if(len(id_user) == 2)
+ {
+ // remove '@'
+ resize_impl(id_pass, 0);
+ return *this;
+ }
+ // retain '@'
+ auto dest =
+ resize_impl(id_pass, 1);
+ dest[0] = '@';
+ return *this;
+}
+
+#if 0
+
url&
url::
set_encoded_authority(
@@ -803,246 +1069,6 @@ set_encoded_userinfo(
return *this;
}
-url&
-url::
-set_userinfo_part(
- string_view s)
-{
- if(! s.empty())
- {
- if(s.back() != '@')
- invalid_part::raise();
- s.remove_suffix(1);
- }
- return set_encoded_userinfo(s);
-}
-
-url&
-url::
-set_user(
- string_view s)
-{
- if(s.empty())
- {
- if(pt_.len(
- id_user) == 0)
- return *this;
- BOOST_ASSERT(pt_.get(
- id_pass, s_).back() == '@');
- BOOST_ASSERT(pt_.get(
- id_user, s_).size() >= 2);
- BOOST_ASSERT(pt_.get(
- id_user, s_)[0] == '/');
- BOOST_ASSERT(pt_.get(
- id_user, s_)[1] == '/');
- if(pt_.len(
- id_pass) == 1)
- {
- // remove '@'
- resize_impl(
- id_user,
- id_host, 2);
- }
- else
- {
- resize_impl(id_user, 2);
- }
- return *this;
- }
-
- auto const e =
- detail::userinfo_nc_pct_set();
- if(pt_.len(
- id_pass) != 0)
- {
- BOOST_ASSERT(pt_.get(
- id_pass, s_).back() == '@');
- // preserve "//"
- auto const dest = resize_impl(
- id_user,
- 2 + e.encoded_size(s));
- e.encode(dest + 2, s);
- return *this;
- }
- auto const n = e.encoded_size(s);
- auto const dest = resize_impl(
- id_user, 2 + n + 1);
- dest[0] = '/';
- dest[1] = '/';
- dest[2 + n] = '@';
- pt_.split(
- id_user,
- 2 + n);
- e.encode(dest + 2, s);
- return *this;
-}
-
-url&
-url::
-set_encoded_user(
- string_view s)
-{
- if(s.empty())
- return set_user(s);
-
- auto const e =
- detail::userinfo_nc_pct_set();
- e.validate(s);
-
- auto const n = s.size();
- if(pt_.len(id_pass) != 0)
- {
- BOOST_ASSERT(pt_.get(
- id_pass, s_).back() == '@');
- // preserve "//"
- auto const dest = resize_impl(
- id_user, 2 + n);
- s.copy(dest + 2, n);
- return *this;
- }
-
- // add '@'
- auto const dest = resize_impl(
- id_user,
- 2 + n + 1);
- dest[0] = '/';
- dest[1] = '/';
- dest[2 + n] = '@';
- pt_.split(
- id_user,
- 2 + n);
- s.copy(dest + 2, n);
- return *this;
-}
-
-url&
-url::
-set_password(
- string_view s)
-{
- if(s.empty())
- {
- auto const n = pt_.len(
- id_pass);
- if(n == 0)
- return *this;
- BOOST_ASSERT(pt_.get(
- id_pass, s_).back() == '@');
- BOOST_ASSERT(pt_.get(
- id_user, s_).size() >= 2);
- BOOST_ASSERT(pt_.get(
- id_user, s_)[0] == '/');
- BOOST_ASSERT(pt_.get(
- id_user, s_)[1] == '/');
- if(pt_.len(id_user) == 2)
- {
- // remove '@'
- resize_impl(id_pass, 0);
- return *this;
- }
- // retain '@'
- *resize_impl(id_pass, 1) = '@';
- return *this;
- }
-
- auto const e =
- detail::userinfo_pct_set();
- auto const n =
- e.encoded_size(s);
- if(pt_.len(id_user) != 0)
- {
- auto const dest = resize_impl(
- id_pass, 1 + n + 1);
- dest[0] = ':';
- dest[n + 1] = '@';
- e.encode(dest + 1, s);
- return *this;
- }
- auto const dest = resize_impl(
- id_user,
- id_host,
- 2 + 1 + n + 1);
- dest[0] = '/';
- dest[1] = '/';
- dest[2] = ':';
- dest[2 + n + 1] = '@';
- e.encode(dest + 3, s);
- pt_.split(id_user, 2);
- return *this;
-}
-
-url&
-url::
-set_encoded_password(
- string_view s)
-{
- if(s.empty())
- return set_password(s);
-
- auto const e =
- detail::userinfo_pct_set();
- if(s[0] == ':')
- invalid_part::raise();
- e.validate(s);
-
- auto const n = s.size();
- if(pt_.len(id_user) != 0)
- {
- auto const dest = resize_impl(
- id_pass, 1 + n + 1);
- dest[0] = ':';
- dest[n + 1] = '@';
- s.copy(dest + 1, n);
- return *this;
- }
- auto const dest = resize_impl(
- id_user,
- id_host,
- 2 + 1 + n + 1);
- dest[0] = '/';
- dest[1] = '/';
- dest[2] = ':';
- dest[2 + n + 1] = '@';
- s.copy(dest + 3, n);
- pt_.split(id_user, 2);
- return *this;
-}
-
-url&
-url::
-set_password_part(
- string_view s)
-{
- if(s.empty())
- return set_password(s);
- if(s.size() == 1)
- {
- if(s.front() != ':')
- invalid_part::raise();
- if(pt_.len(
- id_user) != 0)
- {
- auto const dest = resize_impl(
- id_pass, 2);
- dest[0] = ':';
- dest[1] = '@';
- return *this;
- }
- auto const dest = resize_impl(
- id_user,
- id_host, 4);
- dest[0] = '/';
- dest[1] = '/';
- dest[2] = ':';
- dest[3] = '@';
- pt_.split(
- id_user, 2);
- }
- set_encoded_password(
- s.substr(1));
- return *this;
-}
-
//------------------------------------------------
//
// host
@@ -2060,6 +2086,7 @@ operator[](string_view key) const
}
//------------------------------------------------
+#endif
void
url::
@@ -2068,17 +2095,19 @@ resize_impl(
{
if(new_size > cap_)
{
+#if 0
// reallocate
auto p = static_cast(
sp_->allocate(new_size + 1));
if(s_)
{
BOOST_ASSERT(cap_ != 0);
- std::memcpy(p, s_, size() + 1);
+ std::memcpy(p, s_, pt_.len() + 1);
sp_->deallocate(s_, cap_ + 1, 1);
}
s_ = p;
cap_ = new_size;
+#endif
}
s_[new_size] = '\0';
@@ -2100,81 +2129,96 @@ resize_impl(
int last,
std::size_t new_len)
{
- auto const len =
+ auto const n0 =
pt_.len(first, last);
- if(new_len == 0 && len == 0)
+ if(new_len == 0 && n0 == 0)
{
// VFALCO This happens
- //BOOST_ASSERT(s_ != nullptr);
+ BOOST_ASSERT(s_ != nullptr);
return s_ + pt_.offset[first];
}
- if(new_len <= len)
+ if(new_len <= n0)
{
// shrinking
- auto const n = static_cast<
- std::size_t>(len - new_len);
- auto const pos = pt_.offset[last];
+ std::size_t n = n0 - new_len;
+ auto const pos =
+ pt_.offset[last];
+ // adjust chars
std::memmove(
s_ + pos - n,
s_ + pos,
pt_.offset[
id_end] - pos + 1);
+ // collapse [first, last)
for(auto i = first + 1;
- i < last; ++i)
+ i < last; ++i)
pt_.offset[i] =
pt_.offset[last] - n;
+ // shift [last, end) left
for(auto i = last;
- i <= id_end; ++i)
+ i <= id_end; ++i)
pt_.offset[i] -= n;
- s_[size()] = '\0';
+ s_[pt_.len()] = '\0';
return s_ + pt_.offset[first];
}
// growing
- auto const n = static_cast<
- std::size_t>(new_len - len);
+ std::size_t n = new_len - n0;
- // check for exceeding max size
- if(n > (
- (std::size_t)-1)/*max_size()*/ - size())
- too_large::raise();
+ if(n > max_size() - pt_.len())
+ detail::throw_length_error(
+ "url::resize",
+ BOOST_CURRENT_LOCATION);
- if(cap_ < size() + n)
+ if(cap_ < pt_.len() + n)
{
// reallocate
- auto p = static_cast(
- sp_->allocate(cap_ + n + 1));
+ auto new_cap = growth_impl(
+ cap_, pt_.len() + n);
+ auto s1 = alloc_impl(new_cap);
if(s_)
{
BOOST_ASSERT(cap_ != 0);
- std::memcpy(p, s_, size() + 1);
- sp_->deallocate(s_, cap_ + 1, 1);
+ std::memcpy(s1, s_, pt_.len() + 1);
+ free_impl(s_);
}
- s_ = p;
- cap_ = cap_ + n;
+ s_ = s1;
+ cap_ = new_cap;
}
auto const pos =
pt_.offset[last];
+ // adjust chars
std::memmove(
s_ + pos + n,
s_ + pos,
pt_.offset[id_end] -
pos + 1);
+ // collapse [first, last)
for(auto i = first + 1;
i < last; ++i)
pt_.offset[i] =
pt_.offset[last] + n;
+ // shift [last, end) right
for(auto i = last;
i <= id_end; ++i)
pt_.offset[i] += n;
-
- s_[size()] = '\0';
+ s_[pt_.len()] = '\0';
return s_ + pt_.offset[first];
}
-#endif
+//------------------------------------------------
+
+std::ostream&
+operator<<(
+ std::ostream& os,
+ url const& u)
+{
+ auto const s = u.str();
+ os.write(s.data(), s.size());
+ return os;
+}
} // urls
} // boost
diff --git a/include/boost/url/impl/url_view.ipp b/include/boost/url/impl/url_view.ipp
index 36739056..3a698855 100644
--- a/include/boost/url/impl/url_view.ipp
+++ b/include/boost/url/impl/url_view.ipp
@@ -96,19 +96,11 @@ bool
url_view::
empty() const noexcept
{
- return len(
- id_scheme, id_end) == 0;
+ return pt_.len() == 0;
}
//------------------------------------------------
-string_view
-url_view::
-str() const
-{
- return get(id_scheme, id_end);
-}
-
string_view
url_view::
encoded_origin() const noexcept
@@ -152,6 +144,13 @@ scheme() const noexcept
return s;
}
+urls::scheme
+url_view::
+scheme_id() const noexcept
+{
+ return pt_.scheme;
+}
+
//----------------------------------------------------------
//
// authority
@@ -219,7 +218,7 @@ encoded_userinfo() const noexcept
string_view
url_view::
-encoded_username() const noexcept
+encoded_user() const noexcept
{
auto s = get(id_user);
if(! s.empty())
@@ -472,6 +471,17 @@ encoded_fragment() const noexcept
return s.substr(1);
}
+//------------------------------------------------
+//------------------------------------------------
+//------------------------------------------------
+
+string_view
+url_view::
+str() const
+{
+ return get(id_scheme, id_end);
+}
+
//------------------------------------------------
url_view
@@ -487,6 +497,7 @@ parse_uri(
detail::parts p;
// scheme
+ p.scheme = t.scheme.id;
p.resize(
detail::part::id_scheme,
t.scheme.str.size() + 1);
diff --git a/include/boost/url/pct_encoding.hpp b/include/boost/url/pct_encoding.hpp
index 8b5f593f..a0016fd9 100644
--- a/include/boost/url/pct_encoding.hpp
+++ b/include/boost/url/pct_encoding.hpp
@@ -54,11 +54,6 @@ namespace urls {
parameter is omitted, the default options
will be used.
- @param a An optional allocator the returned
- string will use. If this parameter is omitted,
- the default allocator is used, and the return
- type of the function becomes `std::string`.
-
@par Specification
@li
2.1. Percent-Encoding (rfc3986)
diff --git a/include/boost/url/rfc/impl/userinfo_bnf.ipp b/include/boost/url/rfc/impl/userinfo_bnf.ipp
index bfa32d83..fc5b474e 100644
--- a/include/boost/url/rfc/impl/userinfo_bnf.ipp
+++ b/include/boost/url/rfc/impl/userinfo_bnf.ipp
@@ -33,7 +33,7 @@ parse(
pct_encoded_bnf<
masked_char_set<
unsub_char_mask>>{
- t.username}))
+ t.user}))
return false;
if( it != end &&
*it == ':')
diff --git a/include/boost/url/rfc/userinfo_bnf.hpp b/include/boost/url/rfc/userinfo_bnf.hpp
index 8b483c21..a847f01d 100644
--- a/include/boost/url/rfc/userinfo_bnf.hpp
+++ b/include/boost/url/rfc/userinfo_bnf.hpp
@@ -23,9 +23,9 @@ namespace urls {
@par BNF
@code
- userinfo = username [ ":" [ password ] ]
+ userinfo = user [ ":" [ password ] ]
- username = *( unreserved / pct-encoded / sub-delims )
+ user = *( unreserved / pct-encoded / sub-delims )
password = *( unreserved / pct-encoded / sub-delims / ":" )
@endcode
@@ -35,7 +35,7 @@ namespace urls {
struct userinfo_bnf
{
string_view str;
- pct_encoded_str username;
+ pct_encoded_str user;
optional password;
BOOST_URL_DECL
diff --git a/include/boost/url/scheme.hpp b/include/boost/url/scheme.hpp
index bf1f6733..21624c92 100644
--- a/include/boost/url/scheme.hpp
+++ b/include/boost/url/scheme.hpp
@@ -20,9 +20,13 @@ namespace urls {
*/
enum class scheme : unsigned char
{
+ /** Indicates that no scheme is present
+ */
+ none = 0,
+
/** Indicates the scheme is not a well-known scheme
*/
- unknown = 0,
+ unknown,
/** File Transfer Protocol (FTP)
diff --git a/include/boost/url/static_url.hpp b/include/boost/url/static_url.hpp
index 56a97972..5dd9fede 100644
--- a/include/boost/url/static_url.hpp
+++ b/include/boost/url/static_url.hpp
@@ -12,6 +12,7 @@
#include
#include
+#include
namespace boost {
namespace urls {
@@ -73,6 +74,9 @@ class static_url
{
char buf_[Capacity + 1];
+ BOOST_STATIC_ASSERT(
+ Capacity < max_size());
+
public:
~static_url()
{
diff --git a/include/boost/url/url.hpp b/include/boost/url/url.hpp
index 0162d054..4964d500 100644
--- a/include/boost/url/url.hpp
+++ b/include/boost/url/url.hpp
@@ -15,9 +15,11 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
@@ -46,7 +48,9 @@ class url_view;
@li Functions which throw offer the strong
exception safety guarantee.
- @see @li Uniform Resource Identifier (URI): Generic Syntax
+ @par Specification
+ @li
+ Uniform Resource Identifier (URI): Generic Syntax (rfc3986)
*/
class BOOST_SYMBOL_VISIBLE url
{
@@ -140,12 +144,26 @@ public:
url&
operator=(url_view const& u);
+ //--------------------------------------------
+ //--------------------------------------------
+ //--------------------------------------------
+
//--------------------------------------------
//
// classification
//
//--------------------------------------------
+ /** An integer for the maximum size string that can be represented
+ */
+ static
+ constexpr
+ std::size_t
+ max_size()
+ {
+ return 0x7ffffffe;
+ }
+
/** Return true if the URL is empty
An empty URL is a relative-ref with
@@ -170,17 +188,35 @@ public:
//--------------------------------------------
/** Return true if a scheme exists
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
*/
BOOST_URL_DECL
bool
has_scheme() const noexcept;
/** Return the scheme
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
*/
BOOST_URL_DECL
string_view
scheme() const noexcept;
+ /** Return a known-scheme constant if a scheme is present
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
+ */
+ BOOST_URL_DECL
+ urls::scheme
+ scheme_id() const noexcept;
+
//--------------------------------------------
//
// authority
@@ -222,7 +258,7 @@ public:
/** Return the userinfo if it exists, or an empty string
Returns the userinfo of the URL as an encoded
- string. The userinfo includes the username and
+ string. The userinfo includes the user and
password, with a colon separating the components
if the password is not empty.
@@ -263,11 +299,11 @@ public:
encoded_userinfo(), {}, a);
}
- /** Return the username if it exists, or an empty string
+ /** Return the user if it exists, or an empty string
- This function returns the username portion of
+ This function returns the user portion of
the userinfo if present, as an encoded string.
- The username portion is defined by all of the
+ The user portion is defined by all of the
characters in the userinfo up to but not
including the first colon (':"), or the
entire userinfo if no colon is present.
@@ -278,13 +314,13 @@ public:
*/
BOOST_URL_DECL
string_view
- encoded_username() const noexcept;
+ encoded_user() const noexcept;
- /** Return the username if it exists, or an empty string
+ /** Return the user if it exists, or an empty string
- This function returns the username portion of
+ This function returns the user portion of
the userinfo if present, as a decoded string.
- The username portion is defined by all of the
+ The user portion is defined by all of the
characters in the userinfo up to but not
including the first colon (':"), or the
entire userinfo if no colon is present.
@@ -306,11 +342,11 @@ public:
class Allocator =
std::allocator>
string_type
- username(
+ user(
Allocator const& a = {}) const
{
return detail::pct_decode_unchecked(
- encoded_username(), {}, a);
+ encoded_user(), {}, a);
}
/** Return true if a password exists
@@ -651,8 +687,6 @@ public:
pt_.decoded[id_frag], {}, a);
}
- //--------------------------------------------
- //--------------------------------------------
//--------------------------------------------
//--------------------------------------------
//--------------------------------------------
@@ -697,52 +731,16 @@ public:
void
reserve(std::size_t n);
- //------------------------------------------------------
-
- /** Set the URL.
-
- @par Exception Safety
-
- Strong guarantee.
- Calls to allocate may throw.
-
- @param s The URL to set. The contents must
- meet the syntactic requirements of a
- URI-reference.
-
- @throw std::exception parsing error.
- */
- BOOST_URL_DECL
- url&
- set_encoded_url(
- string_view s);
-
- /** Set the origin to the specified value.
-
- The origin consists of the everything from the
- beginning of the URL up to but not including
- the path.
-
- @par Exception Safety
-
- Strong guarantee.
- Calls to allocate may throw.
-
- @param s The origin to set. Special characters
- must be percent-encoded, or an exception is
- thrown.
- */
- BOOST_URL_DECL
- url&
- set_encoded_origin(
- string_view s);
-
//------------------------------------------------------
//
// scheme
//
//------------------------------------------------------
+private:
+ void assert_scheme() const noexcept;
+public:
+
/** Set the scheme.
This function sets the scheme to the specified
@@ -756,157 +754,137 @@ public:
contain a valid scheme. A trailing colon is
automatically added.
- @par ABNF
+ @par Example
+ @code
+ url u;
+ u.set_scheme( "http" ); // produces "http:"
+ u.set_scheme( "" ); // produces ""
+ u.set_scheme( "1forall"); // throws, invalid scheme
+ @endcode
+
+ @par BNF
@code
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
@endcode
@par Exception Safety
-
Strong guarantee.
Calls to allocate may throw.
+ @return A reference to the object, for chaining.
+
@param s The scheme to set. This string must
not include a trailing colon, otherwise an
exception is thrown.
- @throw std::exception invalid scheme.
+ @throw std::invalid_argument invalid scheme.
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
*/
BOOST_URL_DECL
url&
set_scheme(string_view s);
+ /** Set the scheme.
+
+ This function sets the scheme to the specified
+ string:
+
+ @li If `id` is @ref scheme::none, any existing
+ scheme is removed along with the trailing
+ colon (':'), otherwise:
+
+ @li The scheme is set to `id`, which must
+ not be equal to @ref scheme::unknown.
+
+ @par Example
+ @code
+ url u;
+ u.set_scheme( scheme::http ); // produces "http:"
+ u.set_scheme( scheme::none ); // produces ""
+ u.set_scheme( scheme::unknown); // throws, invalid scheme
+ @endcode
+
+ @par BNF
+ @code
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ @endcode
+
+ @par Exception Safety
+ Strong guarantee.
+ Calls to allocate may throw.
+
+ @return A reference to the object, for chaining.
+
+ @param id The scheme to set.
+
+ @throw std::invalid_argument `id == scheme::unknown`
+ */
+ BOOST_URL_DECL
+ url&
+ set_scheme(urls::scheme id);
+
+private:
+ void set_scheme_impl(string_view s, urls::scheme id);
+public:
+
//------------------------------------------------------
//
// authority
//
//------------------------------------------------------
- /** Set the authority.
+private:
+ void assert_userinfo() const noexcept;
+ char* set_user_impl(std::size_t n);
+public:
+
+ /** Clear the user.
+
+ If a user is present, it is removed. If the
+ user was the only component present in the
+ userinfo, then the userinfo is removed without
+ removing the authority.
@par Exception Safety
+ Does not throw.
- Strong guarantee.
- Calls to allocate may throw.
+ @return A reference to the object, for chaining.
- @param s The authority to set. This string
- must meed the syntactic requirements for
- the components of the authority, otherwise
- an exception is thrown.
-
- @throw std::exception invalid authority.
+ @par Specification
+ @li
+ 3.2.1. User Information (rfc3986)
*/
BOOST_URL_DECL
url&
- set_encoded_authority(
- string_view s);
-
- //------------------------------------------------------
- //
- // userinfo
- //
- //------------------------------------------------------
-
- /** Set the userinfo.
-
- Sets the userinfo of the URL to the given
- encoded string:
-
- @li If the string is empty, the userinfo is
- cleared, else
-
- @li If the string is not empty, then the userinfo
- is set to the given string. The user is set to
- the characters up to the first colon if any,
- while the password is set to the remaining
- characters if any.
- If the URL previously did not have an authority
- (@ref has_authority returns `false`), a double
- slash ("//") is prepended to the userinfo.
- The string must meet the syntactic requirements
- of userinfo otherwise an exception is
- thrown.
-
- @par ABNF
- @code
- userinfo = [ [ user ] [ ':' password ] ]
- user = *( unreserved / pct-encoded / sub-delims )
- password = *( unreserved / pct-encoded / sub-delims / ":" )
- @endcode
-
- @par Exception Safety
-
- Strong guarantee.
- Calls to allocate may throw.
-
- @param s The string to set.
- */
- BOOST_URL_DECL
- url&
- set_encoded_userinfo(
- string_view s);
-
- /** Set the userinfo.
-
- Sets the userinfo of the URL to the given
- encoded string:
-
- @li If the string is empty, the userinfo is
- cleared, else
-
- @li If the string is not empty, then the userinfo
- is set to the given string. The user is set to
- the characters up to the first colon if any,
- while the password is set to the remaining
- characters if any.
- If the URL previously did not have an authority
- (@ref has_authority returns `false`), a double
- slash ("//") is prepended to the userinfo.
- The string must meet the syntactic requirements
- of userinfo-part otherwise an exception
- is thrown.
-
- @par ABNF
- @code
- userinfo-part = [ [ user ] [ ':' password ] '@' ]
- user = *( unreserved / pct-encoded / sub-delims )
- password = *( unreserved / pct-encoded / sub-delims / ":" )
- @endcode
-
- @par Exception Safety
-
- Strong guarantee.
- Calls to allocate may throw.
-
- @param s The string to set.
- */
- BOOST_URL_DECL
- url&
- set_userinfo_part(
- string_view s);
+ clear_user() noexcept;
/** Set the user.
The user is set to the specified string,
- replacing any previous user:
+ replacing any previous user. If a userinfo
+ was not present it is added, even if the
+ user string is empty. The resulting URL
+ will have an authority if it did not have
+ one previously.
- @li If the string is empty, the user is cleared.
-
- @li If the string is not empty then the
- user is set to the new string.
Any special or reserved characters in the
string are automatically percent-encoded.
- If the URL previously did not have an authority
- (@ref has_authority returns `false`), a double
- slash ("//") is prepended to the userinfo.
@par Exception Safety
-
Strong guarantee.
Calls to allocate may throw.
+ @return A reference to the object, for chaining.
+
@param s The string to set. This string may
contain any characters, including nulls.
+
+ @par Specification
+ @li
+ 3.2.1. User Information (rfc3986)
*/
BOOST_URL_DECL
url&
@@ -915,28 +893,25 @@ public:
/** Set the user.
- The user is set to the specified encoded
- string, replacing any previous user:
+ The user is set to the specified string,
+ replacing any previous user. If a userinfo
+ was not present it is added, even if the
+ user string is empty. The resulting URL
+ will have an authority if it did not have
+ one previously.
- @li If the string is empty, the user is cleared.
+ The string must be a valid percent-encoded
+ string for the user field, otherwise an
+ exception is thrown.
- @li If the string is not empty then the
- user is set to the given string.
- If the URL previously did not have an authority
- (@ref has_authority returns `false`), a double
- slash ("//") is prepended to the userinfo.
- The string must meet the syntactic requirements
- of user otherwise an exception is
- thrown.
-
- @li
- @par ABNF
+ @par BNF
@code
user = *( unreserved / pct-encoded / sub-delims )
@endcode
- @par Exception Safety
+ @return A reference to the object, for chaining.
+ @par Exception Safety
Strong guarantee.
Calls to allocate may throw.
@@ -947,6 +922,14 @@ public:
set_encoded_user(
string_view s);
+private:
+ char* set_password_impl(std::size_t n);
+public:
+
+ BOOST_URL_DECL
+ url&
+ clear_password() noexcept;
+
/** Set the password.
This function sets the password to the specified
@@ -1012,28 +995,69 @@ public:
set_encoded_password(
string_view s);
- /** Set the password.
+ /** Set the origin to the specified value.
- The password part is set to the encoded string
- `s`, replacing any previous password:
+ The origin consists of the everything from the
+ beginning of the URL up to but not including
+ the path.
- @li If the string is empty, the password is
- cleared, and the first occurring colon (':') is
- removed from the userinfo if present, otherwise
+ @par Exception Safety
- @li If ths string is not empty then the password
- is set to the new string, which must include a
- leading colon.
+ Strong guarantee.
+ Calls to allocate may throw.
+
+ @param s The origin to set. Special characters
+ must be percent-encoded, or an exception is
+ thrown.
+ */
+ BOOST_URL_DECL
+ url&
+ set_encoded_origin(
+ string_view s);
+
+ /** Set the authority.
+
+ @par Exception Safety
+ Strong guarantee.
+ Calls to allocate may throw.
+
+ @param s The authority to set. This string
+ must meed the syntactic requirements for
+ the components of the authority, otherwise
+ an exception is thrown.
+
+ @throw std::invalid_argument invalid authority
+ */
+ BOOST_URL_DECL
+ url&
+ set_encoded_authority(
+ string_view s);
+
+ /** Set the userinfo.
+
+ Sets the userinfo of the URL to the given
+ encoded string:
+
+ @li If the string is empty, the userinfo is
+ cleared, else
+
+ @li If the string is not empty, then the userinfo
+ is set to the given string. The user is set to
+ the characters up to the first colon if any,
+ while the password is set to the remaining
+ characters if any.
If the URL previously did not have an authority
(@ref has_authority returns `false`), a double
slash ("//") is prepended to the userinfo.
The string must meet the syntactic requirements
- of password-part otherwise an exception is
+ of userinfo otherwise an exception is
thrown.
- @par ANBF
+ @par BNF
@code
- password-part = [ ':' *( unreserved / pct-encoded / sub-delims / ":" ) ]
+ userinfo = [ [ user ] [ ':' password ] ]
+ user = *( unreserved / pct-encoded / sub-delims )
+ password = *( unreserved / pct-encoded / sub-delims / ":" )
@endcode
@par Exception Safety
@@ -1045,7 +1069,7 @@ public:
*/
BOOST_URL_DECL
url&
- set_password_part(
+ set_encoded_userinfo(
string_view s);
//------------------------------------------------------
@@ -1089,7 +1113,7 @@ public:
and `s` is not empty, then the authority is added
including a leading double slash ("//").
- @par ABNF
+ @par BNF
@code
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
@@ -1139,7 +1163,7 @@ public:
then the authority is added including the
leading double slash ("//").
- @par ABNF
+ @par BNF
@code
host = IP-literal / IPv4address / reg-name
@@ -1217,7 +1241,7 @@ public:
of port otherwise an exception is
thrown.
- @par ABNF
+ @par BNF
@code
port = *DIGIT
@endcode
@@ -1254,7 +1278,7 @@ public:
of port-part otherwise an exception is
thrown.
- @par ABNF
+ @par BNF
@code
port-part = [ ':' *DIGIT ]
@endcode
@@ -1302,7 +1326,7 @@ public:
If the path does not meet the syntactic
requirements, an exception is thrown.
- @par ABNF
+ @par BNF
@code
path = path-abempty ; begins with "/" or is empty
/ path-absolute ; begins with "/" but not "//"
@@ -1399,7 +1423,7 @@ public:
of query otherwise an exception is
thrown.
- @par ABNF
+ @par BNF
@code
query = *( pchar / "/" / "?" )
@endcode
@@ -1433,7 +1457,7 @@ public:
of query-part otherwise an exception
is thrown.
- @par ABNF
+ @par BNF
@code
query-part = [ "#" *( pchar / "/" / "?" ) ]
@endcode
@@ -1519,7 +1543,7 @@ public:
of fragment otherwise an exception is
thrown.
- @par ABNF
+ @par BNF
@code
fragment = *( pchar / "/" / "?" )
@endcode
@@ -1555,7 +1579,7 @@ public:
of fragment-part otherwise an exception
is thrown.
- @par ABNF
+ @par BNF
@code
fragment-part = [ "#" *( pchar / "/" / "?" ) ]
@endcode
@@ -2159,6 +2183,10 @@ private:
parse() noexcept;
};
+BOOST_URL_DECL
+std::ostream&
+operator<<(std::ostream& os, url const& u);
+
} // urls
} // boost
diff --git a/include/boost/url/url.natvis b/include/boost/url/url.natvis
index 3437e6d9..7f42819c 100644
--- a/include/boost/url/url.natvis
+++ b/include/boost/url/url.natvis
@@ -35,4 +35,34 @@
+
+ {s_,[pt_.offset[detail::part::id_end]]s}
+
+
+ {s_,[pt_.offset[detail::part::id_user]]s}
+
+
+ {s_+pt_.offset[detail::id_user],[pt_.offset[detail::part::id_pass]-pt_.offset[detail::part::id_user]]s}
+
+
+ {s_+pt_.offset[detail::id_pass],[pt_.offset[detail::part::id_host]-pt_.offset[detail::part::id_pass]]s}
+
+
+ {s_+pt_.offset[detail::id_host],[pt_.offset[detail::part::id_port]-pt_.offset[detail::part::id_host]]s}
+
+
+ {s_+pt_.offset[detail::id_port],[pt_.offset[detail::part::id_path]-pt_.offset[detail::part::id_port]]s}
+
+
+ {s_+pt_.offset[detail::id_path],[pt_.offset[detail::part::id_query]-pt_.offset[detail::part::id_path]]s}
+
+
+ {s_+pt_.offset[detail::id_query],[pt_.offset[detail::part::id_frag]-pt_.offset[detail::part::id_query]]s}
+
+
+ {s_+pt_.offset[detail::id_frag],[pt_.offset[detail::part::id_end]-pt_.offset[detail::part::id_frag]]s}
+
+
+
+
diff --git a/include/boost/url/url_view.hpp b/include/boost/url/url_view.hpp
index ac24b2a5..2d656d62 100644
--- a/include/boost/url/url_view.hpp
+++ b/include/boost/url/url_view.hpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -106,12 +107,26 @@ public:
url_view const>
collect() const;
+ //--------------------------------------------
+ //--------------------------------------------
+ //--------------------------------------------
+
//--------------------------------------------
//
// classification
//
//--------------------------------------------
+ /** An integer for the maximum size string that can be represented
+ */
+ static
+ constexpr
+ std::size_t
+ max_size()
+ {
+ return 0x7ffffffe;
+ }
+
/** Return true if the URL is empty
An empty URL is a relative-ref with
@@ -123,12 +138,6 @@ public:
//--------------------------------------------
- /** Return the complete encoded URL
- */
- BOOST_URL_DECL
- string_view
- str() const;
-
/** Return the origin
*/
BOOST_URL_DECL
@@ -142,17 +151,35 @@ public:
//--------------------------------------------
/** Return true if a scheme exists
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
*/
BOOST_URL_DECL
bool
has_scheme() const noexcept;
/** Return the scheme
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
*/
BOOST_URL_DECL
string_view
scheme() const noexcept;
+ /** Return a known-scheme constant if a scheme is present
+
+ @par Specification
+ @li
+ 3.1. Scheme (rfc3986)
+ */
+ BOOST_URL_DECL
+ urls::scheme
+ scheme_id() const noexcept;
+
//--------------------------------------------
//
// authority
@@ -194,7 +221,7 @@ public:
/** Return the userinfo if it exists, or an empty string
Returns the userinfo of the URL as an encoded
- string. The userinfo includes the username and
+ string. The userinfo includes the user and
password, with a colon separating the components
if the password is not empty.
@@ -235,11 +262,11 @@ public:
encoded_userinfo(), {}, a);
}
- /** Return the username if it exists, or an empty string
+ /** Return the user if it exists, or an empty string
- This function returns the username portion of
+ This function returns the user portion of
the userinfo if present, as an encoded string.
- The username portion is defined by all of the
+ The user portion is defined by all of the
characters in the userinfo up to but not
including the first colon (':"), or the
entire userinfo if no colon is present.
@@ -250,13 +277,13 @@ public:
*/
BOOST_URL_DECL
string_view
- encoded_username() const noexcept;
+ encoded_user() const noexcept;
- /** Return the username if it exists, or an empty string
+ /** Return the user if it exists, or an empty string
- This function returns the username portion of
+ This function returns the user portion of
the userinfo if present, as a decoded string.
- The username portion is defined by all of the
+ The user portion is defined by all of the
characters in the userinfo up to but not
including the first colon (':"), or the
entire userinfo if no colon is present.
@@ -278,11 +305,11 @@ public:
class Allocator =
std::allocator>
string_type
- username(
+ user(
Allocator const& a = {}) const
{
return detail::pct_decode_unchecked(
- encoded_username(), {}, a);
+ encoded_user(), {}, a);
}
/** Return true if a password exists
@@ -623,6 +650,16 @@ public:
pt_.decoded[id_frag], {}, a);
}
+ //--------------------------------------------
+ //--------------------------------------------
+ //--------------------------------------------
+
+ /** Return the complete encoded URL
+ */
+ BOOST_URL_DECL
+ string_view
+ str() const;
+
//--------------------------------------------
//
// free functions
diff --git a/test/pct_encoding.cpp b/test/pct_encoding.cpp
index d8e21497..2a5370c4 100644
--- a/test/pct_encoding.cpp
+++ b/test/pct_encoding.cpp
@@ -122,7 +122,8 @@ public:
// null is reserved
opt.allow_null = true;
opt.non_normal_is_error = false;
- good_decode_size(1, string_view("\0", 1), opt);
+ bad_decode_size(string_view("\0", 1), opt);
+ good_decode_size(1, string_view("\0", 1), opt, test_chars_null{});
good_decode_size(1, "%00", opt);
opt.allow_null = false;
bad_decode_size(string_view("\0", 1), opt);
@@ -134,12 +135,14 @@ public:
pct_decode_opts opt;
good_decode_size(1, "A", opt);
- good_decode_size(2, "aA", opt);
- good_decode_size(3, "ab%41", opt);
+ good_decode_size(1, "%41", opt);
+ bad_decode_size("ab%41", opt);
+ bad_decode_size("aA", opt);
opt.non_normal_is_error = true;
good_decode_size(1, "A", opt);
good_decode_size(2, "A%20", opt);
+ bad_decode_size("%41", opt);
opt.plus_to_space = true;
good_decode_size(2, "A+", opt);
opt.plus_to_space = false;
@@ -228,7 +231,8 @@ public:
opt.non_normal_is_error = false;
good_decode(
string_view("\0", 1),
- string_view("\0", 1), opt);
+ string_view("\0", 1), opt,
+ test_chars_null{});
good_decode("%00",
string_view("\0", 1), opt);
opt.allow_null = false;
@@ -240,8 +244,9 @@ public:
pct_decode_opts opt;
good_decode("A", "A", opt);
- good_decode("aA", "aA", opt);
- good_decode("ab%41", "abA", opt);
+ good_decode("%42", "B", opt);
+ bad_decode("aA", opt);
+ bad_decode("ab%41", opt);
opt.non_normal_is_error = true;
good_decode("A", "A", opt);
diff --git a/test/rfc/authority_bnf.cpp b/test/rfc/authority_bnf.cpp
index 122aa281..6c7dce20 100644
--- a/test/rfc/authority_bnf.cpp
+++ b/test/rfc/authority_bnf.cpp
@@ -65,7 +65,7 @@ public:
if(BOOST_TEST(p.has_userinfo))
{
BOOST_TEST(p.userinfo.str == "x:y");
- BOOST_TEST(p.userinfo.username.str == "x");
+ BOOST_TEST(p.userinfo.user.str == "x");
if(BOOST_TEST(p.userinfo.password.has_value()))
BOOST_TEST(p.userinfo.password->str == "y");
}
diff --git a/test/rfc/userinfo_bnf.cpp b/test/rfc/userinfo_bnf.cpp
index c652a318..9fb942ae 100644
--- a/test/rfc/userinfo_bnf.cpp
+++ b/test/rfc/userinfo_bnf.cpp
@@ -37,7 +37,7 @@ public:
if(! BOOST_TEST(! ec))
return;
BOOST_TEST(p.str == s);
- BOOST_TEST(p.username.str == s1);
+ BOOST_TEST(p.user.str == s1);
if(s2.has_value())
BOOST_TEST(
p.password.has_value() &&
diff --git a/test/static_url.cpp b/test/static_url.cpp
index 077fa455..47627ef8 100644
--- a/test/static_url.cpp
+++ b/test/static_url.cpp
@@ -12,6 +12,7 @@
#include
#include "test_suite.hpp"
+#include
namespace boost {
namespace urls {
@@ -135,12 +136,12 @@ public:
{
url_view uv;
BOOST_TEST_NO_THROW( uv = parse_uri(
- "http://username:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag"));
+ "http://user:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag"));
url_t u(uv);
BOOST_TEST(u.encoded_origin() ==
- "http://username:pass@www.boost.org:8080");
+ "http://user:pass@www.boost.org:8080");
BOOST_TEST(u.scheme() == "http");
- BOOST_TEST(u.username() == "username");
+ BOOST_TEST(u.user() == "user");
BOOST_TEST(u.password() == "pass");
BOOST_TEST(u.host() == "www.boost.org");
BOOST_TEST(u.port() == "8080");
@@ -149,11 +150,41 @@ public:
BOOST_TEST(u.encoded_fragment() == "frag");
}
+ void
+ testSetScheme()
+ {
+ {
+ url_t u;
+ u = parse_uri("http://www.example.com");
+ u.set_scheme("");
+ BOOST_TEST(u.str() == "//www.example.com");
+ }
+ {
+ url_t u;
+ u = parse_uri("http:live/wire");
+ u.set_scheme("");
+ BOOST_TEST(u.str() == "live/wire");
+ }
+ {
+ url_t u;
+ u = parse_uri("http:my:adidas");
+ u.set_scheme("");
+ BOOST_TEST(u.str() == "./my:adidas");
+ }
+ {
+ url_t u;
+ u = parse_uri("http:my:adidas/");
+ u.set_scheme("");
+ BOOST_TEST(u.str() == "./my:adidas/");
+ }
+ }
+
void
run()
{
testSpecial();
testParts();
+ testSetScheme();
}
};
diff --git a/test/url.cpp b/test/url.cpp
index b97ac756..84c5911a 100644
--- a/test/url.cpp
+++ b/test/url.cpp
@@ -10,7 +10,7 @@
// Test that header file is self-contained.
#include
-#include
+#include
#include "test_suite.hpp"
@@ -30,7 +30,7 @@ public:
log <<
"href : " << u.str() << "\n"
"scheme : " << u.scheme() << "\n"
- "user : " << u.encoded_username() << "\n"
+ "user : " << u.encoded_user() << "\n"
"password : " << u.encoded_password() << "\n"
"hostname : " << u.encoded_host() << "\n"
"port : " << u.port() << "\n" <<
@@ -69,7 +69,7 @@ public:
BOOST_TEST(v.encoded_origin() == "http://user:pass@example.com:80");
BOOST_TEST(v.encoded_authority() == "user:pass@example.com:80");
BOOST_TEST(v.scheme() == "http");
- BOOST_TEST(v.encoded_username() == "user");
+ BOOST_TEST(v.encoded_user() == "user");
BOOST_TEST(v.encoded_password() == "pass");
BOOST_TEST(v.encoded_userinfo() == "user:pass");
BOOST_TEST(v.encoded_host() == "example.com");
@@ -78,7 +78,7 @@ public:
BOOST_TEST(v.encoded_query() == "k1=v1&k2=v2");
BOOST_TEST(v.encoded_fragment() == "");
- BOOST_TEST(v.username() == "user");
+ BOOST_TEST(v.user() == "user");
BOOST_TEST(v.password() == "pass");
BOOST_TEST(v.host() == "example.com");
BOOST_TEST(v.query() == "k1=v1&k2=v2");
@@ -94,24 +94,6 @@ public:
BOOST_TEST(url().str() == "");
}
- void
- testScheme()
- {
- BOOST_TEST(url().scheme() == "");
- BOOST_TEST(url("http:").scheme() == "http");
- BOOST_TEST(url("http:").str() == "http:");
- BOOST_TEST(url("http:").set_scheme("").scheme() == "");
- BOOST_TEST(url("http:").set_scheme("").str() == "");
- BOOST_TEST(url("http:").set_scheme("ftp").str() == "ftp:");
- BOOST_TEST(url("ws:").set_scheme("gopher").str() == "gopher:");
- BOOST_TEST(url("http://example.com").set_scheme("ftp").str() == "ftp://example.com");
- BOOST_TEST(url("ws://example.com").set_scheme("gopher").str() == "gopher://example.com");
-
- BOOST_TEST_THROWS(url().set_scheme("c@t"), invalid_part);
- BOOST_TEST_THROWS(url().set_scheme("1cat"), invalid_part);
- BOOST_TEST_THROWS(url().set_scheme("http:s"), invalid_part);
- }
-
void
testOrigin()
{
@@ -148,15 +130,15 @@ public:
void
testUsername()
{
- BOOST_TEST(url().username() == "");
- BOOST_TEST(url().encoded_username() == "");
- BOOST_TEST(url().set_user("").username() == "");
+ BOOST_TEST(url().user() == "");
+ BOOST_TEST(url().encoded_user() == "");
+ BOOST_TEST(url().set_user("").user() == "");
BOOST_TEST(url().set_user("user").str() == "//user@");
BOOST_TEST(url().set_encoded_user("user%20name").str() == "//user%20name@");
BOOST_TEST(url().set_encoded_user("user%3Aname").str() == "//user%3Aname@");
- BOOST_TEST(url().set_encoded_user("user%3Aname").username() == "user:name");
+ BOOST_TEST(url().set_encoded_user("user%3Aname").user() == "user:name");
BOOST_TEST(url().set_encoded_user("user%40name").str() == "//user%40name@");
- BOOST_TEST(url().set_encoded_user("user%40name").username() == "user@name");
+ BOOST_TEST(url().set_encoded_user("user%40name").user() == "user@name");
BOOST_TEST(url("http:").set_encoded_user("").str() == "http:");
BOOST_TEST(url("http://@").set_encoded_user("").str() == "http://");
@@ -170,31 +152,6 @@ public:
BOOST_TEST_THROWS(url().set_encoded_user("user name"), invalid_part);
}
- void
- testPassword()
- {
- BOOST_TEST(url().password() == "");
- BOOST_TEST(url().encoded_password() == "");
- BOOST_TEST(url().set_encoded_password("").password() == "");
- BOOST_TEST(url().set_password("pass").str() == "//:pass@");
- BOOST_TEST(url().set_encoded_password("%40pass").str() == "//:%40pass@");
- BOOST_TEST(url().set_encoded_password("pass%20word").str() == "//:pass%20word@");
- BOOST_TEST(url().set_encoded_password("pass%42word").str() == "//:pass%42word@");
-
- BOOST_TEST(url("http:").set_encoded_password("").str() == "http:");
- BOOST_TEST(url("http://@").set_encoded_password("").str() == "http://");
- BOOST_TEST(url("http://x@").set_encoded_password("").str() == "http://x@");
- BOOST_TEST(url("http://x@").set_encoded_password("y").str() == "http://x:y@");
- BOOST_TEST(url("http://:@").set_encoded_password("").str() == "http://");
- BOOST_TEST(url("http://:y@").set_password("pass").str() == "http://:pass@");
- BOOST_TEST(url("http://x:y@").set_password("pass").str() == "http://x:pass@");
- BOOST_TEST(url("http://x:pass@").set_password("y").str() == "http://x:y@");
- BOOST_TEST(url("http://x:pass@example.com").set_password("y").str() == "http://x:y@example.com");
-
- BOOST_TEST_THROWS(url().set_encoded_password("pass word"), invalid_part);
- BOOST_TEST_THROWS(url().set_encoded_password(":pass"), invalid_part);
- }
-
//------------------------------------------------------
void
@@ -232,41 +189,6 @@ public:
BOOST_TEST(url("http://x:y@z.com/").set_encoded_userinfo("").str() == "http://z.com/");
}
- void
- testUser()
- {
- BOOST_TEST(url().username() == "");
- BOOST_TEST(url("//x/").username() == "");
- BOOST_TEST(url("//x@/").username() == "x");
- BOOST_TEST(url("//x:@/").username() == "x");
- BOOST_TEST(url("//x:y@/").username() == "x");
- BOOST_TEST(url("//:y@/").username() == "");
- BOOST_TEST(url("//:@/").username() == "");
- BOOST_TEST(url("//@/").username() == "");
- BOOST_TEST(url("//%3A@/").username() == ":");
-
- BOOST_TEST(url().encoded_username() == "");
- BOOST_TEST(url("//x/").encoded_username() == "");
- BOOST_TEST(url("//x@/").encoded_username() == "x");
- BOOST_TEST(url("//x:@/").encoded_username() == "x");
- BOOST_TEST(url("//x:y@/").encoded_username() == "x");
- BOOST_TEST(url("//:y@/").encoded_username() == "");
- BOOST_TEST(url("//:@/").encoded_username() == "");
- BOOST_TEST(url("//@/").encoded_username() == "");
- BOOST_TEST(url("//%3A@/").encoded_username() == "%3A");
-
- BOOST_TEST(url("").set_user("").str() == "");
- BOOST_TEST(url("").set_user("x").str() == "//x@");
- BOOST_TEST(url("").set_user("x:").str() == "//x%3A@");
- BOOST_TEST(url("").set_user("x:y").str() == "//x%3Ay@");
- BOOST_TEST(url("//yy@").set_user("x").str() == "//x@");
- BOOST_TEST(url("//:@").set_user("x").str() == "//x:@");
- BOOST_TEST(url("//:p@").set_user("x").str() == "//x:p@");
- //BOOST_TEST(url("//yy@").set_user("").str() == "");
- BOOST_TEST(url("//:p@").set_user("x").str() == "//x:p@");
- BOOST_TEST(url("//yy:p@").set_user("x").str() == "//x:p@");
- }
-
//------------------------------------------------------
void
@@ -862,9 +784,238 @@ public:
//------------------------------------------------------
#endif
+ //--------------------------------------------
+
+ void
+ testScheme()
+ {
+ {
+ url u;
+ u.reserve(40);
+ BOOST_TEST(
+ u.set_scheme("http").str() == "http:");
+ }
+
+ url u;
+ BOOST_TEST(u.set_scheme("").str() == "");
+ BOOST_TEST(u.set_scheme(scheme::none).str() == "");
+ BOOST_TEST(u.set_scheme("http").str() == "http:");
+ BOOST_TEST(u.scheme_id() == scheme::http);
+ BOOST_TEST_THROWS(
+ u.set_scheme("http:"), std::invalid_argument);
+ BOOST_TEST(u.str() == "http:");
+ BOOST_TEST(u.scheme_id() == scheme::http);
+ BOOST_TEST_THROWS(
+ u.set_scheme("1http"), std::invalid_argument);
+ BOOST_TEST_THROWS(
+ u.set_scheme(scheme::unknown), std::invalid_argument);
+ BOOST_TEST(u.scheme_id() == scheme::http);
+ BOOST_TEST(u.str() == "http:");
+ BOOST_TEST(u.scheme_id() == scheme::http);
+ BOOST_TEST(u.set_scheme("ftp").str() == "ftp:");
+ BOOST_TEST(u.scheme_id() == scheme::ftp);
+ BOOST_TEST(u.set_scheme(scheme::none).str() == "");
+ BOOST_TEST(u.scheme_id() == scheme::none);
+ BOOST_TEST(u.set_scheme(scheme::ws).str() == "ws:");
+ BOOST_TEST(u.scheme_id() == scheme::ws);
+ BOOST_TEST(u.set_scheme("").str() == "");
+ BOOST_TEST(u.scheme_id() == scheme::none);
+ BOOST_TEST(u.set_scheme("x").str() == "x:");
+ BOOST_TEST(u.scheme_id() == scheme::unknown);
+ u = parse_uri("http:/path/to/file.txt");
+ BOOST_TEST(u.set_scheme("").str() == "/path/to/file.txt");
+ }
+
+ //--------------------------------------------
+
+ void
+ testUser()
+ {
+ auto const clear = [](
+ string_view s1, string_view s2)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).clear_user().str() == s2);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).clear_user().str() == s2);
+ };
+
+ auto const set = [](
+ string_view s1, string_view s2,
+ string_view s3)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).set_user(s2).str() == s3);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).set_user(s2).str() == s3);
+ };
+
+ auto const enc = [](
+ string_view s1, string_view s2,
+ string_view s3)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).set_encoded_user(s2).str() == s3);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).set_encoded_user(s2).str() == s3);
+ };
+
+ clear("", "");
+ clear("/x", "/x");
+ clear("//", "//");
+ clear("//x", "//x");
+ clear("//@", "//");
+ clear("//:@", "//:@");
+ clear("//x@", "//");
+ clear("//x@z", "//z");
+ clear("//x:@", "//:@");
+ clear("//x:y@", "//:y@");
+ clear("//x:y@z", "//:y@z");
+
+ clear("ws:", "ws:");
+ clear("ws:/x", "ws:/x");
+ clear("ws://", "ws://");
+ clear("ws://x", "ws://x");
+ clear("ws://@", "ws://");
+ clear("ws://:@", "ws://:@");
+ clear("ws://x@", "ws://");
+ clear("ws://x@z", "ws://z");
+ clear("ws://x:@", "ws://:@");
+ clear("ws://x:y@", "ws://:y@");
+ clear("ws://x:y@z", "ws://:y@z");
+
+ set("", "", "//@");
+ set("/y", "", "//@/y");
+ set("//", "", "//@");
+ set("//y", "", "//@y");
+ set("//@", "", "//@");
+ set("//:@", "", "//:@");
+ set("//y@", "", "//@");
+ set("//y@z", "", "//@z");
+ set("//y:@", "", "//:@");
+ set("//y:z@", "", "//:z@");
+ set("//a:b@c", "", "//:b@c");
+
+ set("ws:", "", "ws://@");
+ set("ws:/y", "", "ws://@/y");
+ set("ws://", "", "ws://@");
+ set("ws://y", "", "ws://@y");
+ set("ws://@", "", "ws://@");
+ set("ws://:@", "", "ws://:@");
+ set("ws://y@", "", "ws://@");
+ set("ws://y@z", "", "ws://@z");
+ set("ws://y:@", "", "ws://:@");
+ set("ws://y:z@", "", "ws://:z@");
+ set("ws://a:b@c", "", "ws://:b@c");
+
+ set("", "x", "//x@");
+ set("/y", "x", "//x@/y");
+ set("//", "x", "//x@");
+ set("//y", "x", "//x@y");
+ set("//@", "x", "//x@");
+ set("//:@", "x", "//x:@");
+ set("//y@", "x", "//x@");
+ set("//y@z", "x", "//x@z");
+ set("//y:@", "x", "//x:@");
+ set("//y:z@", "x", "//x:z@");
+ set("//a:b@c", "x", "//x:b@c");
+
+ set("ws:", "x", "ws://x@");
+ set("ws:/y", "x", "ws://x@/y");
+ set("ws://", "x", "ws://x@");
+ set("ws://y", "x", "ws://x@y");
+ set("ws://@", "x", "ws://x@");
+ set("ws://:@", "x", "ws://x:@");
+ set("ws://y@", "x", "ws://x@");
+ set("ws://y@z", "x", "ws://x@z");
+ set("ws://y:@", "x", "ws://x:@");
+ set("ws://y:z@", "x", "ws://x:z@");
+ set("ws://a:b@c", "x", "ws://x:b@c");
+
+ enc("", "%41", "//%41@");
+ enc("/y", "%41", "//%41@/y");
+ enc("//", "%41", "//%41@");
+ enc("//y", "%41", "//%41@y");
+ enc("//@", "%41", "//%41@");
+ enc("//:@", "%41", "//%41:@");
+ enc("//y@", "%41", "//%41@");
+ enc("//y@z", "%41", "//%41@z");
+ enc("//y:@", "%41", "//%41:@");
+ enc("//y:z@", "%41", "//%41:z@");
+ enc("//a:b@c", "%41", "//%41:b@c");
+
+ enc("ws:", "%41", "ws://%41@");
+ enc("ws:/y", "%41", "ws://%41@/y");
+ enc("ws://", "%41", "ws://%41@");
+ enc("ws://y", "%41", "ws://%41@y");
+ enc("ws://@", "%41", "ws://%41@");
+ enc("ws://:@", "%41", "ws://%41:@");
+ enc("ws://y@", "%41", "ws://%41@");
+ enc("ws://y@z", "%41", "ws://%41@z");
+ enc("ws://y:@", "%41", "ws://%41:@");
+ enc("ws://y:z@", "%41", "ws://%41:z@");
+ enc("ws://a:b@c", "%41", "ws://%41:b@c");
+
+ BOOST_TEST_THROWS(url().set_encoded_user(
+ "%2"), std::invalid_argument);
+ }
+
+ //--------------------------------------------
+
+ void
+ testPassword()
+ {
+ auto const clear = [](
+ string_view s1, string_view s2)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).clear_password().str() == s2);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).clear_password().str() == s2);
+ };
+
+ auto const set = [](
+ string_view s1, string_view s2,
+ string_view s3)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).set_password(s2).str() == s3);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).set_password(s2).str() == s3);
+ };
+
+ auto const enc = [](
+ string_view s1, string_view s2,
+ string_view s3)
+ {
+ if(s1.empty() || s1.starts_with('/'))
+ BOOST_TEST(url(parse_relative_ref(
+ s1)).set_encoded_password(s2).str() == s3);
+ else
+ BOOST_TEST(url(parse_uri(s1)
+ ).set_encoded_password(s2).str() == s3);
+ };
+ }
+
+ //--------------------------------------------
+
void
run()
{
+ testScheme();
+
+ testUser();
+ testPassword();
#if 0
testObservers();
@@ -878,7 +1029,6 @@ public:
testPassword();
testUserinfo();
- testUser();
testHostAndPort();
testHost();
testPort();
diff --git a/test/url_view.cpp b/test/url_view.cpp
index b570e26d..ae781c7b 100644
--- a/test/url_view.cpp
+++ b/test/url_view.cpp
@@ -36,14 +36,14 @@ public:
{
error_code ec;
auto const u = urls::parse_uri(
- "http://username:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag",
+ "http://user:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag",
ec);
if(! BOOST_TEST(! ec))
return;
BOOST_TEST(u.encoded_origin() ==
- "http://username:pass@www.boost.org:8080");
+ "http://user:pass@www.boost.org:8080");
BOOST_TEST(u.scheme() == "http");
- BOOST_TEST(u.username() == "username");
+ BOOST_TEST(u.user() == "user");
BOOST_TEST(u.password() == "pass");
BOOST_TEST(u.host() == "www.boost.org");
BOOST_TEST(u.port() == "8080");
@@ -84,12 +84,24 @@ public:
"http://");
BOOST_TEST(u.has_scheme());
BOOST_TEST(u.scheme() == "http");
+ BOOST_TEST(
+ u.scheme_id() == scheme::http);
+ }
+ {
+ auto u = parse_uri(
+ "ou812://");
+ BOOST_TEST(u.has_scheme());
+ BOOST_TEST(u.scheme() == "ou812");
+ BOOST_TEST(
+ u.scheme_id() == scheme::unknown);
}
{
auto u = parse_relative_ref(
"/x");
BOOST_TEST(! u.has_scheme());
BOOST_TEST(u.scheme() == "");
+ BOOST_TEST(
+ u.scheme_id() == scheme::none);
}
}
@@ -187,8 +199,8 @@ public:
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == "");
BOOST_TEST(u.userinfo() == "");
- BOOST_TEST(u.encoded_username() == "");
- BOOST_TEST(u.username() == "");
+ BOOST_TEST(u.encoded_user() == "");
+ BOOST_TEST(u.user() == "");
BOOST_TEST(u.has_password() == false);
BOOST_TEST(u.encoded_password() == "");
BOOST_TEST(u.password() == "");
@@ -198,8 +210,8 @@ public:
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == ":");
BOOST_TEST(u.userinfo() == ":");
- BOOST_TEST(u.encoded_username() == "");
- BOOST_TEST(u.username() == "");
+ BOOST_TEST(u.encoded_user() == "");
+ BOOST_TEST(u.user() == "");
BOOST_TEST(u.has_password() == true);
BOOST_TEST(u.encoded_password() == "");
BOOST_TEST(u.password() == "");
@@ -208,8 +220,8 @@ public:
auto u = parse_uri("x://a%41:@");
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == "a%41:");
- BOOST_TEST(u.encoded_username() == "a%41");
- BOOST_TEST(u.username() == "aA");
+ BOOST_TEST(u.encoded_user() == "a%41");
+ BOOST_TEST(u.user() == "aA");
BOOST_TEST(u.has_password() == true);
BOOST_TEST(u.encoded_password() == "");
BOOST_TEST(u.password() == "");
@@ -218,8 +230,8 @@ public:
auto u = parse_uri("x://:b%42@");
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == ":b%42");
- BOOST_TEST(u.encoded_username() == "");
- BOOST_TEST(u.username() == "");
+ BOOST_TEST(u.encoded_user() == "");
+ BOOST_TEST(u.user() == "");
BOOST_TEST(u.has_password() == true);
BOOST_TEST(u.encoded_password() == "b%42");
BOOST_TEST(u.password() == "bB");
@@ -228,7 +240,7 @@ public:
auto u = parse_uri("x://a:b@");
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == "a:b");
- BOOST_TEST(u.encoded_username() == "a");
+ BOOST_TEST(u.encoded_user() == "a");
BOOST_TEST(u.has_password() == true);
BOOST_TEST(u.encoded_password() == "b");
}
@@ -237,8 +249,8 @@ public:
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == "%3a:%3a");
BOOST_TEST(u.userinfo() == ":::");
- BOOST_TEST(u.encoded_username() == "%3a");
- BOOST_TEST(u.username() == ":");
+ BOOST_TEST(u.encoded_user() == "%3a");
+ BOOST_TEST(u.user() == ":");
BOOST_TEST(u.has_password() == true);
BOOST_TEST(u.encoded_password() == "%3a");
BOOST_TEST(u.password() == ":");
@@ -248,8 +260,8 @@ public:
BOOST_TEST(u.has_userinfo());
BOOST_TEST(u.encoded_userinfo() == "%2525");
BOOST_TEST(u.userinfo() == "%25");
- BOOST_TEST(u.encoded_username() == "%2525");
- BOOST_TEST(u.username() == "%25");
+ BOOST_TEST(u.encoded_user() == "%2525");
+ BOOST_TEST(u.user() == "%25");
BOOST_TEST(u.has_password() == false);
BOOST_TEST(u.encoded_password() == "");
BOOST_TEST(u.password() == "");
@@ -648,7 +660,7 @@ public:
testCollect()
{
string_view s =
- "http://username:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag";
+ "http://user:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag";
std::shared_ptr sp;
{
auto const u = urls::parse_uri(s);