LCOV - code coverage report
Current view: top level - libs/url/src - authority_view.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 137 161 85.1 %
Date: 2024-03-12 19:37:18 Functions: 20 23 87.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3             : //
       4             : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5             : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6             : //
       7             : // Official repository: https://github.com/boostorg/url
       8             : //
       9             : 
      10             : 
      11             : #include <boost/url/detail/config.hpp>
      12             : #include <boost/url/authority_view.hpp>
      13             : #include "detail/normalize.hpp"
      14             : #include <boost/url/grammar/parse.hpp>
      15             : #include <boost/url/rfc/authority_rule.hpp>
      16             : #include <boost/url/rfc/pct_encoded_rule.hpp>
      17             : #include <array>
      18             : #include <ostream>
      19             : 
      20             : namespace boost {
      21             : namespace urls {
      22             : 
      23             : //------------------------------------------------
      24             : 
      25             : namespace detail {
      26             : 
      27             : authority_view
      28        2341 : url_impl::
      29             : construct_authority() const noexcept
      30             : {
      31        2341 :     return authority_view(*this);
      32             : }
      33             : 
      34             : } // detail
      35             : 
      36             : //------------------------------------------------
      37             : 
      38        2341 : authority_view::
      39             : authority_view(
      40        2341 :     detail::url_impl const& u) noexcept
      41        2341 :     : u_(u)
      42             : {
      43        2341 : }
      44             : 
      45             : //------------------------------------------------
      46             : 
      47       11645 : authority_view::
      48       11645 : ~authority_view()
      49             : {
      50       11645 : }
      51             : 
      52        3605 : authority_view::
      53        3605 : authority_view() noexcept
      54        3605 :     : u_(from::authority)
      55             : {
      56        3605 : }
      57             : 
      58           1 : authority_view::
      59             : authority_view(
      60           1 :     core::string_view s)
      61             :     : authority_view(
      62           1 :         parse_authority(s
      63           1 :             ).value(BOOST_URL_POS))
      64             : {
      65           1 : }
      66             : 
      67             : authority_view::
      68             : authority_view(
      69             :     authority_view const&) noexcept = default;
      70             : 
      71             : authority_view&
      72             : authority_view::
      73             : operator=(
      74             :     authority_view const&) noexcept = default;
      75             : 
      76             : //------------------------------------------------
      77             : //
      78             : // Userinfo
      79             : //
      80             : //------------------------------------------------
      81             : 
      82             : bool
      83         567 : authority_view::
      84             : has_userinfo() const noexcept
      85             : {
      86         567 :     auto n = u_.len(id_pass);
      87         567 :     if(n == 0)
      88         475 :         return false;
      89          92 :     BOOST_ASSERT(u_.get(
      90             :         id_pass).ends_with('@'));
      91          92 :     return true;
      92             : }
      93             : 
      94             : pct_string_view
      95          50 : authority_view::
      96             : encoded_userinfo() const noexcept
      97             : {
      98             :     auto s = u_.get(
      99          50 :         id_user, id_host);
     100          50 :     if(s.empty())
     101           0 :         return s;
     102          50 :     BOOST_ASSERT(
     103             :         s.ends_with('@'));
     104          50 :     s.remove_suffix(1);
     105             :     return make_pct_string_view_unsafe(
     106             :         s.data(),
     107             :         s.size(),
     108          50 :         u_.decoded_[id_user] +
     109          50 :             u_.decoded_[id_pass] +
     110          50 :             has_password());
     111             : }
     112             : 
     113             : pct_string_view
     114          73 : authority_view::
     115             : encoded_user() const noexcept
     116             : {
     117          73 :     auto s = u_.get(id_user);
     118             :     return make_pct_string_view_unsafe(
     119             :         s.data(),
     120             :         s.size(),
     121          73 :         u_.decoded_[id_user]);
     122             : }
     123             : 
     124             : bool
     125         112 : authority_view::
     126             : has_password() const noexcept
     127             : {
     128         112 :     auto const n = u_.len(id_pass);
     129         112 :     if(n > 1)
     130             :     {
     131          79 :         BOOST_ASSERT(u_.get(id_pass
     132             :             ).starts_with(':'));
     133          79 :         BOOST_ASSERT(u_.get(id_pass
     134             :             ).ends_with('@'));
     135          79 :         return true;
     136             :     }
     137          33 :     BOOST_ASSERT(n == 0 || u_.get(
     138             :         id_pass).ends_with('@'));
     139          33 :     return false;
     140             : }
     141             : 
     142             : pct_string_view
     143          57 : authority_view::
     144             : encoded_password() const noexcept
     145             : {
     146          57 :     auto s = u_.get(id_pass);
     147          57 :     switch(s.size())
     148             :     {
     149           8 :     case 1:
     150           8 :         BOOST_ASSERT(
     151             :             s.starts_with('@'));
     152           8 :         s.remove_prefix(1);
     153             :         BOOST_FALLTHROUGH;
     154           8 :     case 0:
     155             :         return make_pct_string_view_unsafe(
     156           8 :             s.data(), s.size(), 0);
     157          49 :     default:
     158          49 :         break;
     159             :     }
     160          49 :     BOOST_ASSERT(s.ends_with('@'));
     161          49 :     BOOST_ASSERT(s.starts_with(':'));
     162             :     return make_pct_string_view_unsafe(
     163          49 :         s.data() + 1,
     164          49 :         s.size() - 2,
     165          49 :         u_.decoded_[id_pass]);
     166             : }
     167             : 
     168             : //------------------------------------------------
     169             : //
     170             : // Host
     171             : //
     172             : //------------------------------------------------
     173             : /*
     174             : host_type       host_type()                 // ipv4, ipv6, ipvfuture, name
     175             : 
     176             : std::string     host()                      // return encoded_host().decode()
     177             : pct_string_view encoded_host()              // return host part, as-is
     178             : std::string     host_address()              // return encoded_host_address().decode()
     179             : pct_string_view encoded_host_address()      // ipv4, ipv6, ipvfut, or encoded name, no brackets
     180             : 
     181             : ipv4_address    host_ipv4_address()         // return ipv4_address or {}
     182             : ipv6_address    host_ipv6_address()         // return ipv6_address or {}
     183             : core::string_view     host_ipvfuture()            // return ipvfuture or {}
     184             : std::string     host_name()                 // return decoded name or ""
     185             : pct_string_view encoded_host_name()         // return encoded host name or ""
     186             : */
     187             : 
     188             : pct_string_view
     189         330 : authority_view::
     190             : encoded_host() const noexcept
     191             : {
     192         330 :     return u_.pct_get(id_host);
     193             : }
     194             : 
     195             : pct_string_view
     196           0 : authority_view::
     197             : encoded_host_address() const noexcept
     198             : {
     199           0 :     core::string_view s = u_.get(id_host);
     200             :     std::size_t n;
     201           0 :     switch(u_.host_type_)
     202             :     {
     203           0 :     default:
     204             :     case urls::host_type::none:
     205           0 :         BOOST_ASSERT(s.empty());
     206           0 :         n = 0;
     207           0 :         break;
     208             : 
     209           0 :     case urls::host_type::name:
     210             :     case urls::host_type::ipv4:
     211           0 :         n = u_.decoded_[id_host];
     212           0 :         break;
     213             : 
     214           0 :     case urls::host_type::ipv6:
     215             :     case urls::host_type::ipvfuture:
     216             :     {
     217           0 :         BOOST_ASSERT(
     218             :             u_.decoded_[id_host] ==
     219             :                 s.size());
     220           0 :         BOOST_ASSERT(s.size() >= 2);
     221           0 :         BOOST_ASSERT(s.front() == '[');
     222           0 :         BOOST_ASSERT(s.back() == ']');
     223           0 :         s = s.substr(1, s.size() - 2);
     224           0 :         n = u_.decoded_[id_host] - 2;
     225           0 :         break;
     226             :     }
     227             :     }
     228             :     return make_pct_string_view_unsafe(
     229           0 :         s.data(), s.size(), n);
     230             : }
     231             : 
     232             : urls::ipv4_address
     233           2 : authority_view::
     234             : host_ipv4_address() const noexcept
     235             : {
     236           2 :     if(u_.host_type_ !=
     237             :             urls::host_type::ipv4)
     238           1 :         return {};
     239           1 :     ipv4_address::bytes_type b{{}};
     240           1 :     std::memcpy(
     241           1 :         &b[0], &u_.ip_addr_[0], b.size());
     242           1 :     return urls::ipv4_address(b);
     243             : }
     244             : 
     245             : urls::ipv6_address
     246           2 : authority_view::
     247             : host_ipv6_address() const noexcept
     248             : {
     249           2 :     if(u_.host_type_ !=
     250             :             urls::host_type::ipv6)
     251           1 :         return {};
     252           1 :     ipv6_address::bytes_type b{{}};
     253           1 :     std::memcpy(
     254           1 :         &b[0], &u_.ip_addr_[0], b.size());
     255           1 :     return urls::ipv6_address(b);
     256             : }
     257             : 
     258             : core::string_view
     259           2 : authority_view::
     260             : host_ipvfuture() const noexcept
     261             : {
     262           2 :     if(u_.host_type_ !=
     263             :             urls::host_type::ipvfuture)
     264           1 :         return {};
     265           1 :     core::string_view s = u_.get(id_host);
     266           1 :     BOOST_ASSERT(s.size() >= 6);
     267           1 :     BOOST_ASSERT(s.front() == '[');
     268           1 :     BOOST_ASSERT(s.back() == ']');
     269           1 :     s = s.substr(1, s.size() - 2);
     270           1 :     return s;
     271             : }
     272             : 
     273             : pct_string_view
     274           0 : authority_view::
     275             : encoded_host_name() const noexcept
     276             : {
     277           0 :     if(u_.host_type_ !=
     278             :             urls::host_type::name)
     279           0 :         return {};
     280           0 :     return u_.pct_get(id_host);
     281             : }
     282             : 
     283             : //------------------------------------------------
     284             : //
     285             : // Port
     286             : //
     287             : //------------------------------------------------
     288             : 
     289             : bool
     290         567 : authority_view::
     291             : has_port() const noexcept
     292             : {
     293         567 :     auto const n = u_.len(id_port);
     294         567 :     if(n == 0)
     295         282 :         return false;
     296         285 :     BOOST_ASSERT(
     297             :         u_.get(id_port).starts_with(':'));
     298         285 :     return true;
     299             : }
     300             : 
     301             : core::string_view
     302         112 : authority_view::
     303             : port() const noexcept
     304             : {
     305         112 :     auto s = u_.get(id_port);
     306         112 :     if(s.empty())
     307           4 :         return s;
     308         108 :     BOOST_ASSERT(has_port());
     309         108 :     return s.substr(1);
     310             : }
     311             : 
     312             : std::uint16_t
     313          20 : authority_view::
     314             : port_number() const noexcept
     315             : {
     316          20 :     BOOST_ASSERT(
     317             :         has_port() ||
     318             :         u_.port_number_ == 0);
     319          20 :     return u_.port_number_;
     320             : }
     321             : 
     322             : pct_string_view
     323          10 : authority_view::
     324             : encoded_host_and_port() const noexcept
     325             : {
     326          10 :     return u_.get(id_host, id_end);
     327             : }
     328             : 
     329             : //------------------------------------------------
     330             : //
     331             : // Parsing
     332             : //
     333             : //------------------------------------------------
     334             : 
     335             : system::result<authority_view>
     336          42 : parse_authority(
     337             :     core::string_view s) noexcept
     338             : {
     339          42 :     return grammar::parse(s, authority_rule);
     340             : }
     341             : 
     342             : //------------------------------------------------
     343             : //
     344             : // Comparisons
     345             : //
     346             : //------------------------------------------------
     347             : 
     348             : int
     349         182 : authority_view::
     350             : compare(const authority_view& other) const noexcept
     351             : {
     352         182 :     auto comp = static_cast<int>(has_userinfo()) -
     353         182 :         static_cast<int>(other.has_userinfo());
     354         182 :     if ( comp != 0 )
     355           1 :         return comp;
     356             : 
     357         181 :     if (has_userinfo())
     358             :     {
     359          46 :         comp = detail::compare_encoded(
     360          23 :             encoded_user(),
     361          23 :             other.encoded_user());
     362          23 :         if ( comp != 0 )
     363           7 :             return comp;
     364             : 
     365          16 :         comp = static_cast<int>(has_password()) -
     366          16 :                static_cast<int>(other.has_password());
     367          16 :         if ( comp != 0 )
     368           1 :             return comp;
     369             : 
     370          15 :         if (has_password())
     371             :         {
     372          30 :             comp = detail::compare_encoded(
     373          15 :                 encoded_password(),
     374          15 :                 other.encoded_password());
     375          15 :             if ( comp != 0 )
     376          14 :                 return comp;
     377             :         }
     378             :     }
     379             : 
     380         318 :     comp = detail::ci_compare_encoded(
     381         159 :         encoded_host(),
     382         159 :         other.encoded_host());
     383         159 :     if ( comp != 0 )
     384          17 :         return comp;
     385             : 
     386         142 :     comp = static_cast<int>(has_port()) -
     387         142 :            static_cast<int>(other.has_port());
     388         142 :     if ( comp != 0 )
     389           7 :         return comp;
     390             : 
     391         135 :     if (has_port())
     392             :     {
     393          46 :         comp = detail::compare(
     394             :             port(),
     395             :             other.port());
     396          46 :         if ( comp != 0 )
     397          42 :             return comp;
     398             :     }
     399             : 
     400          93 :     return 0;
     401             : }
     402             : 
     403             : } // urls
     404             : } // boost
     405             : 

Generated by: LCOV version 1.15