ext-boost/boost/url/impl/authority_view.ipp
2023-05-22 18:45:02 +10:00

407 lines
8.4 KiB
C++

//
// 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/boostorg/url
//
#ifndef BOOST_URL_IMPL_AUTHORITY_VIEW_IPP
#define BOOST_URL_IMPL_AUTHORITY_VIEW_IPP
#include <boost/url/authority_view.hpp>
#include <boost/url/grammar/parse.hpp>
#include <boost/url/rfc/authority_rule.hpp>
#include <boost/url/rfc/pct_encoded_rule.hpp>
#include <array>
#include <ostream>
namespace boost {
namespace urls {
//------------------------------------------------
namespace detail {
authority_view
url_impl::
construct_authority() const noexcept
{
return authority_view(*this);
}
} // detail
//------------------------------------------------
authority_view::
authority_view(
detail::url_impl const& u) noexcept
: u_(u)
{
}
//------------------------------------------------
authority_view::
~authority_view()
{
}
authority_view::
authority_view() noexcept
: u_(from::authority)
{
}
authority_view::
authority_view(
string_view s)
: authority_view(
parse_authority(s
).value(BOOST_URL_POS))
{
}
authority_view::
authority_view(
authority_view const&) noexcept = default;
authority_view&
authority_view::
operator=(
authority_view const&) noexcept = default;
//------------------------------------------------
//
// Userinfo
//
//------------------------------------------------
bool
authority_view::
has_userinfo() const noexcept
{
auto n = u_.len(id_pass);
if(n == 0)
return false;
BOOST_ASSERT(u_.get(
id_pass).ends_with('@'));
return true;
}
pct_string_view
authority_view::
encoded_userinfo() const noexcept
{
auto s = u_.get(
id_user, id_host);
if(s.empty())
return s;
BOOST_ASSERT(
s.ends_with('@'));
s.remove_suffix(1);
return make_pct_string_view_unsafe(
s.data(),
s.size(),
u_.decoded_[id_user] +
u_.decoded_[id_pass] +
has_password());
}
pct_string_view
authority_view::
encoded_user() const noexcept
{
auto s = u_.get(id_user);
return make_pct_string_view_unsafe(
s.data(),
s.size(),
u_.decoded_[id_user]);
}
bool
authority_view::
has_password() const noexcept
{
auto const n = u_.len(id_pass);
if(n > 1)
{
BOOST_ASSERT(u_.get(id_pass
).starts_with(':'));
BOOST_ASSERT(u_.get(id_pass
).ends_with('@'));
return true;
}
BOOST_ASSERT(n == 0 || u_.get(
id_pass).ends_with('@'));
return false;
}
pct_string_view
authority_view::
encoded_password() const noexcept
{
auto s = u_.get(id_pass);
switch(s.size())
{
case 1:
BOOST_ASSERT(
s.starts_with('@'));
s.remove_prefix(1);
BOOST_FALLTHROUGH;
case 0:
return make_pct_string_view_unsafe(
s.data(), s.size(), 0);
default:
break;
}
BOOST_ASSERT(s.ends_with('@'));
BOOST_ASSERT(s.starts_with(':'));
return make_pct_string_view_unsafe(
s.data() + 1,
s.size() - 2,
u_.decoded_[id_pass]);
}
//------------------------------------------------
//
// Host
//
//------------------------------------------------
/*
host_type host_type() // ipv4, ipv6, ipvfuture, name
std::string host() // return encoded_host().decode()
pct_string_view encoded_host() // return host part, as-is
std::string host_address() // return encoded_host_address().decode()
pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets
ipv4_address host_ipv4_address() // return ipv4_address or {}
ipv6_address host_ipv6_address() // return ipv6_address or {}
string_view host_ipvfuture() // return ipvfuture or {}
std::string host_name() // return decoded name or ""
pct_string_view encoded_host_name() // return encoded host name or ""
*/
pct_string_view
authority_view::
encoded_host() const noexcept
{
return u_.pct_get(id_host);
}
pct_string_view
authority_view::
encoded_host_address() const noexcept
{
string_view s = u_.get(id_host);
std::size_t n;
switch(u_.host_type_)
{
default:
case urls::host_type::none:
BOOST_ASSERT(s.empty());
n = 0;
break;
case urls::host_type::name:
case urls::host_type::ipv4:
n = u_.decoded_[id_host];
break;
case urls::host_type::ipv6:
case urls::host_type::ipvfuture:
{
BOOST_ASSERT(
u_.decoded_[id_host] ==
s.size());
BOOST_ASSERT(s.size() >= 2);
BOOST_ASSERT(s.front() == '[');
BOOST_ASSERT(s.back() == ']');
s = s.substr(1, s.size() - 2);
n = u_.decoded_[id_host] - 2;
break;
}
}
return make_pct_string_view_unsafe(
s.data(), s.size(), n);
}
urls::ipv4_address
authority_view::
host_ipv4_address() const noexcept
{
if(u_.host_type_ !=
urls::host_type::ipv4)
return {};
ipv4_address::bytes_type b{{}};
std::memcpy(
&b[0], &u_.ip_addr_[0], b.size());
return urls::ipv4_address(b);
}
urls::ipv6_address
authority_view::
host_ipv6_address() const noexcept
{
if(u_.host_type_ !=
urls::host_type::ipv6)
return {};
ipv6_address::bytes_type b{{}};
std::memcpy(
&b[0], &u_.ip_addr_[0], b.size());
return urls::ipv6_address(b);
}
string_view
authority_view::
host_ipvfuture() const noexcept
{
if(u_.host_type_ !=
urls::host_type::ipvfuture)
return {};
string_view s = u_.get(id_host);
BOOST_ASSERT(s.size() >= 6);
BOOST_ASSERT(s.front() == '[');
BOOST_ASSERT(s.back() == ']');
s = s.substr(1, s.size() - 2);
return s;
}
pct_string_view
authority_view::
encoded_host_name() const noexcept
{
if(u_.host_type_ !=
urls::host_type::name)
return {};
return u_.pct_get(id_host);
}
//------------------------------------------------
//
// Port
//
//------------------------------------------------
bool
authority_view::
has_port() const noexcept
{
auto const n = u_.len(id_port);
if(n == 0)
return false;
BOOST_ASSERT(
u_.get(id_port).starts_with(':'));
return true;
}
string_view
authority_view::
port() const noexcept
{
auto s = u_.get(id_port);
if(s.empty())
return s;
BOOST_ASSERT(has_port());
return s.substr(1);
}
std::uint16_t
authority_view::
port_number() const noexcept
{
BOOST_ASSERT(
has_port() ||
u_.port_number_ == 0);
return u_.port_number_;
}
pct_string_view
authority_view::
encoded_host_and_port() const noexcept
{
return u_.get(id_host, id_end);
}
//------------------------------------------------
//
// Parsing
//
//------------------------------------------------
result<authority_view>
parse_authority(
string_view s) noexcept
{
return grammar::parse(s, authority_rule);
}
//------------------------------------------------
//
// Comparisons
//
//------------------------------------------------
int
authority_view::
compare(const authority_view& other) const noexcept
{
auto comp = static_cast<int>(has_userinfo()) -
static_cast<int>(other.has_userinfo());
if ( comp != 0 )
return comp;
if (has_userinfo())
{
comp = detail::compare_encoded(
encoded_user(),
other.encoded_user());
if ( comp != 0 )
return comp;
comp = static_cast<int>(has_password()) -
static_cast<int>(other.has_password());
if ( comp != 0 )
return comp;
if (has_password())
{
comp = detail::compare_encoded(
encoded_password(),
other.encoded_password());
if ( comp != 0 )
return comp;
}
}
comp = detail::ci_compare_encoded(
encoded_host(),
other.encoded_host());
if ( comp != 0 )
return comp;
comp = static_cast<int>(has_port()) -
static_cast<int>(other.has_port());
if ( comp != 0 )
return comp;
if (has_port())
{
comp = detail::compare(
port(),
other.port());
if ( comp != 0 )
return comp;
}
return 0;
}
} // urls
} // boost
#endif