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

Generated by: LCOV version 1.15