LCOV - code coverage report
Current view: top level - libs/url/src/authority_view.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 164 164
Test Date: 2024-08-20 16:05:53 Functions: 96.0 % 25 24

            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         2349 : url_impl::
      29              : construct_authority() const noexcept
      30              : {
      31         2349 :     return authority_view(*this);
      32              : }
      33              : 
      34              : } // detail
      35              : 
      36              : //------------------------------------------------
      37              : 
      38         2349 : authority_view::
      39              : authority_view(
      40         2349 :     detail::url_impl const& u) noexcept
      41         2349 :     : u_(u)
      42              : {
      43         2349 : }
      44              : 
      45              : //------------------------------------------------
      46              : 
      47        11679 : authority_view::
      48        11679 : ~authority_view()
      49              : {
      50        11679 : }
      51              : 
      52         3612 : authority_view::
      53         3612 : authority_view() noexcept
      54         3612 :     : u_(from::authority)
      55              : {
      56         3612 : }
      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         5718 : authority_view::
      68              : authority_view(
      69              :     authority_view const&) noexcept = default;
      70              : 
      71              : authority_view&
      72         1708 : 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           52 :     auto s = u_.get(
      99              :         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           50 :     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          100 :             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           73 :     return make_pct_string_view_unsafe(
     119              :         s.data(),
     120              :         s.size(),
     121          146 :         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            8 :         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           49 :     return make_pct_string_view_unsafe(
     163           49 :         s.data() + 1,
     164           49 :         s.size() - 2,
     165           98 :         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            7 :     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 2.1