LCOV - code coverage report
Current view: top level - libs/url/src - authority_view.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 157 157 100.0 %
Date: 2024-04-08 19:38:36 Functions: 22 23 95.7 %

          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        2345 : url_impl::
      29             : construct_authority() const noexcept
      30             : {
      31        2345 :     return authority_view(*this);
      32             : }
      33             : 
      34             : } // detail
      35             : 
      36             : //------------------------------------------------
      37             : 
      38        2345 : authority_view::
      39             : authority_view(
      40        2345 :     detail::url_impl const& u) noexcept
      41        2345 :     : u_(u)
      42             : {
      43        2345 : }
      44             : 
      45             : //------------------------------------------------
      46             : 
      47       11663 : authority_view::
      48       11663 : ~authority_view()
      49             : {
      50       11663 : }
      51             : 
      52        3608 : authority_view::
      53        3608 : authority_view() noexcept
      54        3608 :     : u_(from::authority)
      55             : {
      56        3608 : }
      57             : 
      58           2 : authority_view::
      59             : authority_view(
      60           2 :     core::string_view s)
      61             :     : authority_view(
      62           2 :         parse_authority(s
      63           2 :             ).value(BOOST_URL_POS))
      64             : {
      65           2 : }
      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         568 : authority_view::
      84             : has_userinfo() const noexcept
      85             : {
      86         568 :     auto n = u_.len(id_pass);
      87         568 :     if(n == 0)
      88         476 :         return false;
      89          92 :     BOOST_ASSERT(u_.get(
      90             :         id_pass).ends_with('@'));
      91          92 :     return true;
      92             : }
      93             : 
      94             : pct_string_view
      95          52 : authority_view::
      96             : encoded_userinfo() const noexcept
      97             : {
      98             :     auto s = u_.get(
      99          52 :         id_user, id_host);
     100          52 :     if(s.empty())
     101           2 :         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           7 : authority_view::
     197             : encoded_host_address() const noexcept
     198             : {
     199           7 :     core::string_view s = u_.get(id_host);
     200             :     std::size_t n;
     201           7 :     switch(u_.host_type_)
     202             :     {
     203           5 :     case urls::host_type::name:
     204             :     case urls::host_type::ipv4:
     205           5 :         n = u_.decoded_[id_host];
     206           5 :         break;
     207             : 
     208           2 :     case urls::host_type::ipv6:
     209             :     case urls::host_type::ipvfuture:
     210             :     {
     211           2 :         BOOST_ASSERT(
     212             :             u_.decoded_[id_host] ==
     213             :                 s.size());
     214           2 :         BOOST_ASSERT(s.size() >= 2);
     215           2 :         BOOST_ASSERT(s.front() == '[');
     216           2 :         BOOST_ASSERT(s.back() == ']');
     217           2 :         s = s.substr(1, s.size() - 2);
     218           2 :         n = u_.decoded_[id_host] - 2;
     219           2 :         break;
     220             :     }
     221             :     // LCOV_EXCL_START
     222             :     default:
     223             :     case urls::host_type::none:
     224             :         /*
     225             :          * This condition is for correctness
     226             :          * only.
     227             :          * This should never happen, because
     228             :          * the `host_rule` will set the host
     229             :          * type to `name` when it's empty.
     230             :          * This is correct because `reg-name`
     231             :          * accepts empty strings.
     232             :          */
     233             :         BOOST_ASSERT(s.empty());
     234             :         n = 0;
     235             :         break;
     236             :     // LCOV_EXCL_STOP
     237             :     }
     238             :     return make_pct_string_view_unsafe(
     239           7 :         s.data(), s.size(), n);
     240             : }
     241             : 
     242             : urls::ipv4_address
     243           2 : authority_view::
     244             : host_ipv4_address() const noexcept
     245             : {
     246           2 :     if(u_.host_type_ !=
     247             :             urls::host_type::ipv4)
     248           1 :         return {};
     249           1 :     ipv4_address::bytes_type b{{}};
     250           1 :     std::memcpy(
     251           1 :         &b[0], &u_.ip_addr_[0], b.size());
     252           1 :     return urls::ipv4_address(b);
     253             : }
     254             : 
     255             : urls::ipv6_address
     256           2 : authority_view::
     257             : host_ipv6_address() const noexcept
     258             : {
     259           2 :     if(u_.host_type_ !=
     260             :             urls::host_type::ipv6)
     261           1 :         return {};
     262           1 :     ipv6_address::bytes_type b{{}};
     263           1 :     std::memcpy(
     264           1 :         &b[0], &u_.ip_addr_[0], b.size());
     265           1 :     return urls::ipv6_address(b);
     266             : }
     267             : 
     268             : core::string_view
     269           2 : authority_view::
     270             : host_ipvfuture() const noexcept
     271             : {
     272           2 :     if(u_.host_type_ !=
     273             :             urls::host_type::ipvfuture)
     274           1 :         return {};
     275           1 :     core::string_view s = u_.get(id_host);
     276           1 :     BOOST_ASSERT(s.size() >= 6);
     277           1 :     BOOST_ASSERT(s.front() == '[');
     278           1 :     BOOST_ASSERT(s.back() == ']');
     279           1 :     s = s.substr(1, s.size() - 2);
     280           1 :     return s;
     281             : }
     282             : 
     283             : pct_string_view
     284           3 : authority_view::
     285             : encoded_host_name() const noexcept
     286             : {
     287           3 :     if(u_.host_type_ !=
     288             :             urls::host_type::name)
     289           1 :         return {};
     290           2 :     return u_.pct_get(id_host);
     291             : }
     292             : 
     293             : //------------------------------------------------
     294             : //
     295             : // Port
     296             : //
     297             : //------------------------------------------------
     298             : 
     299             : bool
     300         567 : authority_view::
     301             : has_port() const noexcept
     302             : {
     303         567 :     auto const n = u_.len(id_port);
     304         567 :     if(n == 0)
     305         282 :         return false;
     306         285 :     BOOST_ASSERT(
     307             :         u_.get(id_port).starts_with(':'));
     308         285 :     return true;
     309             : }
     310             : 
     311             : core::string_view
     312         112 : authority_view::
     313             : port() const noexcept
     314             : {
     315         112 :     auto s = u_.get(id_port);
     316         112 :     if(s.empty())
     317           4 :         return s;
     318         108 :     BOOST_ASSERT(has_port());
     319         108 :     return s.substr(1);
     320             : }
     321             : 
     322             : std::uint16_t
     323          20 : authority_view::
     324             : port_number() const noexcept
     325             : {
     326          20 :     BOOST_ASSERT(
     327             :         has_port() ||
     328             :         u_.port_number_ == 0);
     329          20 :     return u_.port_number_;
     330             : }
     331             : 
     332             : pct_string_view
     333          10 : authority_view::
     334             : encoded_host_and_port() const noexcept
     335             : {
     336          10 :     return u_.get(id_host, id_end);
     337             : }
     338             : 
     339             : //------------------------------------------------
     340             : //
     341             : // Parsing
     342             : //
     343             : //------------------------------------------------
     344             : 
     345             : system::result<authority_view>
     346          44 : parse_authority(
     347             :     core::string_view s) noexcept
     348             : {
     349          44 :     return grammar::parse(s, authority_rule);
     350             : }
     351             : 
     352             : //------------------------------------------------
     353             : //
     354             : // Comparisons
     355             : //
     356             : //------------------------------------------------
     357             : 
     358             : int
     359         182 : authority_view::
     360             : compare(const authority_view& other) const noexcept
     361             : {
     362         182 :     auto comp = static_cast<int>(has_userinfo()) -
     363         182 :         static_cast<int>(other.has_userinfo());
     364         182 :     if ( comp != 0 )
     365           1 :         return comp;
     366             : 
     367         181 :     if (has_userinfo())
     368             :     {
     369          46 :         comp = detail::compare_encoded(
     370          23 :             encoded_user(),
     371          23 :             other.encoded_user());
     372          23 :         if ( comp != 0 )
     373           7 :             return comp;
     374             : 
     375          16 :         comp = static_cast<int>(has_password()) -
     376          16 :                static_cast<int>(other.has_password());
     377          16 :         if ( comp != 0 )
     378           1 :             return comp;
     379             : 
     380          15 :         if (has_password())
     381             :         {
     382          30 :             comp = detail::compare_encoded(
     383          15 :                 encoded_password(),
     384          15 :                 other.encoded_password());
     385          15 :             if ( comp != 0 )
     386          14 :                 return comp;
     387             :         }
     388             :     }
     389             : 
     390         318 :     comp = detail::ci_compare_encoded(
     391         159 :         encoded_host(),
     392         159 :         other.encoded_host());
     393         159 :     if ( comp != 0 )
     394          17 :         return comp;
     395             : 
     396         142 :     comp = static_cast<int>(has_port()) -
     397         142 :            static_cast<int>(other.has_port());
     398         142 :     if ( comp != 0 )
     399           7 :         return comp;
     400             : 
     401         135 :     if (has_port())
     402             :     {
     403          46 :         comp = detail::compare(
     404             :             port(),
     405             :             other.port());
     406          46 :         if ( comp != 0 )
     407          42 :             return comp;
     408             :     }
     409             : 
     410          93 :     return 0;
     411             : }
     412             : 
     413             : } // urls
     414             : } // boost
     415             : 

Generated by: LCOV version 1.15