mirror of
https://github.com/boostorg/url.git
synced 2026-02-14 01:02:17 +00:00
url work
This commit is contained in:
@@ -124,7 +124,7 @@ parse_string(
|
||||
Tn&&... tn)
|
||||
{
|
||||
error_code ec;
|
||||
if(parse(s, ec,
|
||||
if(parse_string(s, ec,
|
||||
std::forward<T0>(t0),
|
||||
std::forward<Tn>(tn)...))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define BOOST_URL_DETAIL_PARTS_HPP
|
||||
|
||||
#include <boost/url/host_type.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
@@ -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<std::size_t>(n);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 "<unknown>";
|
||||
}
|
||||
|
||||
} // urls
|
||||
|
||||
@@ -12,11 +12,16 @@
|
||||
|
||||
#include <boost/url/url.hpp>
|
||||
#include <boost/url/error.hpp>
|
||||
#include <boost/url/pct_encoding.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/url_view.hpp>
|
||||
#include <boost/url/bnf/parse.hpp>
|
||||
#include <boost/url/detail/except.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
#include <boost/url/rfc/char_sets.hpp>
|
||||
#include <boost/url/rfc/scheme_bnf.hpp>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
@@ -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<char*>(
|
||||
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<char*>(
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-2.1">
|
||||
2.1. Percent-Encoding (rfc3986)</a>
|
||||
|
||||
@@ -33,7 +33,7 @@ parse(
|
||||
pct_encoded_bnf<
|
||||
masked_char_set<
|
||||
unsub_char_mask>>{
|
||||
t.username}))
|
||||
t.user}))
|
||||
return false;
|
||||
if( it != end &&
|
||||
*it == ':')
|
||||
|
||||
@@ -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<pct_encoded_str> password;
|
||||
|
||||
BOOST_URL_DECL
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <boost/url/detail/config.hpp>
|
||||
#include <boost/url/url.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace urls {
|
||||
@@ -73,6 +74,9 @@ class static_url
|
||||
{
|
||||
char buf_[Capacity + 1];
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
Capacity < max_size());
|
||||
|
||||
public:
|
||||
~static_url()
|
||||
{
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
#include <boost/url/ipv6_address.hpp>
|
||||
#include <boost/url/path_view.hpp>
|
||||
#include <boost/url/query_params_view.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/detail/parts.hpp>
|
||||
#include <boost/url/detail/pct_encoding.hpp>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -46,7 +48,9 @@ class url_view;
|
||||
@li Functions which throw offer the strong
|
||||
exception safety guarantee.
|
||||
|
||||
@see @li <a href="https://tools.ietf.org/html/rfc3986">Uniform Resource Identifier (URI): Generic Syntax</a>
|
||||
@par Specification
|
||||
@li <a href="https://tools.ietf.org/html/rfc3986">
|
||||
Uniform Resource Identifier (URI): Generic Syntax (rfc3986)</a>
|
||||
*/
|
||||
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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
has_scheme() const noexcept;
|
||||
|
||||
/** Return the scheme
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
string_view
|
||||
scheme() const noexcept;
|
||||
|
||||
/** Return a known-scheme constant if a scheme is present
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
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<char>>
|
||||
string_type<Allocator>
|
||||
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
|
||||
<em>URI-reference</em>.
|
||||
|
||||
@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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
|
||||
3.2.1. User Information (rfc3986)</a>
|
||||
*/
|
||||
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 <em>userinfo</em> 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 <em>userinfo-part</em> 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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
|
||||
3.2.1. User Information (rfc3986)</a>
|
||||
*/
|
||||
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 <em>user</em> 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 <em>password-part</em> otherwise an exception is
|
||||
of <em>userinfo</em> 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 <em>port</em> otherwise an exception is
|
||||
thrown.
|
||||
|
||||
@par ABNF
|
||||
@par BNF
|
||||
@code
|
||||
port = *DIGIT
|
||||
@endcode
|
||||
@@ -1254,7 +1278,7 @@ public:
|
||||
of <em>port-part</em> 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 <em>query</em> otherwise an exception is
|
||||
thrown.
|
||||
|
||||
@par ABNF
|
||||
@par BNF
|
||||
@code
|
||||
query = *( pchar / "/" / "?" )
|
||||
@endcode
|
||||
@@ -1433,7 +1457,7 @@ public:
|
||||
of <em>query-part</em> otherwise an exception
|
||||
is thrown.
|
||||
|
||||
@par ABNF
|
||||
@par BNF
|
||||
@code
|
||||
query-part = [ "#" *( pchar / "/" / "?" ) ]
|
||||
@endcode
|
||||
@@ -1519,7 +1543,7 @@ public:
|
||||
of <em>fragment</em> otherwise an exception is
|
||||
thrown.
|
||||
|
||||
@par ABNF
|
||||
@par BNF
|
||||
@code
|
||||
fragment = *( pchar / "/" / "?" )
|
||||
@endcode
|
||||
@@ -1555,7 +1579,7 @@ public:
|
||||
of <em>fragment-part</em> 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
|
||||
|
||||
|
||||
@@ -35,4 +35,34 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="boost::urls::url">
|
||||
<DisplayString>{s_,[pt_.offset[detail::part::id_end]]s}</DisplayString>
|
||||
<Expand>
|
||||
<Synthetic Name="scheme">
|
||||
<DisplayString>{s_,[pt_.offset[detail::part::id_user]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="user">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_user],[pt_.offset[detail::part::id_pass]-pt_.offset[detail::part::id_user]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="pass">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_pass],[pt_.offset[detail::part::id_host]-pt_.offset[detail::part::id_pass]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="host">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_host],[pt_.offset[detail::part::id_port]-pt_.offset[detail::part::id_host]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="port">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_port],[pt_.offset[detail::part::id_path]-pt_.offset[detail::part::id_port]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="path">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_path],[pt_.offset[detail::part::id_query]-pt_.offset[detail::part::id_path]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="query">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_query],[pt_.offset[detail::part::id_frag]-pt_.offset[detail::part::id_query]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
<Synthetic Name="frag">
|
||||
<DisplayString>{s_+pt_.offset[detail::id_frag],[pt_.offset[detail::part::id_end]-pt_.offset[detail::part::id_frag]]s}</DisplayString>
|
||||
</Synthetic>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <boost/url/ipv6_address.hpp>
|
||||
#include <boost/url/path_view.hpp>
|
||||
#include <boost/url/query_params_view.hpp>
|
||||
#include <boost/url/scheme.hpp>
|
||||
#include <boost/url/detail/parts.hpp>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
@@ -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 <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
bool
|
||||
has_scheme() const noexcept;
|
||||
|
||||
/** Return the scheme
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
BOOST_URL_DECL
|
||||
string_view
|
||||
scheme() const noexcept;
|
||||
|
||||
/** Return a known-scheme constant if a scheme is present
|
||||
|
||||
@par Specification
|
||||
@li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
|
||||
3.1. Scheme (rfc3986)</a>
|
||||
*/
|
||||
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<char>>
|
||||
string_type<Allocator>
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user