LCOV - code coverage report
Current view: top level - url/impl - authority_view.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 148 148
Test Date: 2026-10-16 04:17:11 Functions: 100.0 % 18 18

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

Generated by: LCOV version 2.3