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 % 149 149
Test Date: 2026-02-25 21:00:01 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             593 : authority_view::
      73                 : has_userinfo() const noexcept
      74                 : {
      75             593 :     auto n = u_.len(id_pass);
      76             593 :     if(n == 0)
      77             501 :         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              74 : authority_view::
     106                 : encoded_user() const noexcept
     107                 : {
     108              74 :     auto s = u_.get(id_user);
     109              74 :     return make_pct_string_view_unsafe(
     110                 :         s.data(),
     111                 :         s.size(),
     112             148 :         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              58 : authority_view::
     137                 : encoded_password() const noexcept
     138                 : {
     139              58 :     auto s = u_.get(id_pass);
     140              58 :     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              50 :     default:
     151              50 :         break;
     152                 :     }
     153              50 :     BOOST_ASSERT(s.ends_with('@'));
     154              50 :     BOOST_ASSERT(s.starts_with(':'));
     155              50 :     return make_pct_string_view_unsafe(
     156              50 :         s.data() + 1,
     157              50 :         s.size() - 2,
     158             100 :         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             349 : authority_view::
     184                 : encoded_host() const noexcept
     185                 : {
     186             349 :     return u_.pct_get(id_host);
     187                 : }
     188                 : 
     189                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     190                 : pct_string_view
     191               7 : authority_view::
     192                 : encoded_host_address() const noexcept
     193                 : {
     194               7 :     core::string_view s = u_.get(id_host);
     195                 :     std::size_t n;
     196               7 :     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               2 :     case urls::host_type::ipv6:
     204                 :     case urls::host_type::ipvfuture:
     205                 :     {
     206               2 :         BOOST_ASSERT(
     207                 :             u_.decoded_[id_host] ==
     208                 :                 s.size());
     209               2 :         BOOST_ASSERT(s.size() >= 2);
     210               2 :         BOOST_ASSERT(s.front() == '[');
     211               2 :         BOOST_ASSERT(s.back() == ']');
     212               2 :         s = s.substr(1, s.size() - 2);
     213               2 :         n = u_.decoded_[id_host] - 2;
     214               2 :         break;
     215                 :     }
     216                 :     // LCOV_EXCL_START
     217                 :     default:
     218                 :     case urls::host_type::none:
     219                 :         /*
     220                 :          * This condition is for correctness
     221                 :          * only.
     222                 :          * This should never happen, because
     223                 :          * the `host_rule` will set the host
     224                 :          * type to `name` when it's empty.
     225                 :          * This is correct because `reg-name`
     226                 :          * accepts empty strings.
     227                 :          */
     228                 :         BOOST_ASSERT(s.empty());
     229                 :         n = 0;
     230                 :         break;
     231                 :     // LCOV_EXCL_STOP
     232                 :     }
     233               7 :     return make_pct_string_view_unsafe(
     234               7 :         s.data(), s.size(), n);
     235                 : }
     236                 : 
     237                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     238                 : ipv4_address
     239               2 : authority_view::
     240                 : host_ipv4_address() const noexcept
     241                 : {
     242               2 :     if(u_.host_type_ !=
     243                 :             urls::host_type::ipv4)
     244               1 :         return {};
     245               1 :     ipv4_address::bytes_type b{{}};
     246               1 :     detail::memcpy(
     247               1 :         &b[0], &u_.ip_addr_[0], b.size());
     248               1 :     return urls::ipv4_address(b);
     249                 : }
     250                 : 
     251                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     252                 : ipv6_address
     253               2 : authority_view::
     254                 : host_ipv6_address() const noexcept
     255                 : {
     256               2 :     if(u_.host_type_ !=
     257                 :             urls::host_type::ipv6)
     258               1 :         return {};
     259               1 :     ipv6_address::bytes_type b{{}};
     260               1 :     detail::memcpy(
     261               1 :         &b[0], &u_.ip_addr_[0], b.size());
     262               1 :     return urls::ipv6_address(b);
     263                 : }
     264                 : 
     265                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     266                 : core::string_view
     267               2 : authority_view::
     268                 : host_ipvfuture() const noexcept
     269                 : {
     270               2 :     if(u_.host_type_ !=
     271                 :             urls::host_type::ipvfuture)
     272               1 :         return {};
     273               1 :     core::string_view s = u_.get(id_host);
     274               1 :     BOOST_ASSERT(s.size() >= 6);
     275               1 :     BOOST_ASSERT(s.front() == '[');
     276               1 :     BOOST_ASSERT(s.back() == ']');
     277               1 :     s = s.substr(1, s.size() - 2);
     278               1 :     return s;
     279                 : }
     280                 : 
     281                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     282                 : pct_string_view
     283               3 : authority_view::
     284                 : encoded_host_name() const noexcept
     285                 : {
     286               3 :     if(u_.host_type_ !=
     287                 :             urls::host_type::name)
     288               1 :         return {};
     289               2 :     return u_.pct_get(id_host);
     290                 : }
     291                 : 
     292                 : //------------------------------------------------
     293                 : //
     294                 : // Port
     295                 : //
     296                 : //------------------------------------------------
     297                 : 
     298                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     299                 : bool
     300             593 : authority_view::
     301                 : has_port() const noexcept
     302                 : {
     303             593 :     auto const n = u_.len(id_port);
     304             593 :     if(n == 0)
     305             306 :         return false;
     306             287 :     BOOST_ASSERT(
     307                 :         u_.get(id_port).starts_with(':'));
     308             287 :     return true;
     309                 : }
     310                 : 
     311                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     312                 : core::string_view
     313             114 : authority_view::
     314                 : port() const noexcept
     315                 : {
     316             114 :     auto s = u_.get(id_port);
     317             114 :     if(s.empty())
     318               4 :         return s;
     319             110 :     BOOST_ASSERT(has_port());
     320             110 :     return s.substr(1);
     321                 : }
     322                 : 
     323                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     324                 : std::uint16_t
     325              20 : authority_view::
     326                 : port_number() const noexcept
     327                 : {
     328              20 :     BOOST_ASSERT(
     329                 :         has_port() ||
     330                 :         u_.port_number_ == 0);
     331              20 :     return u_.port_number_;
     332                 : }
     333                 : 
     334                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     335                 : pct_string_view
     336              10 : authority_view::
     337                 : encoded_host_and_port() const noexcept
     338                 : {
     339              10 :     return u_.pct_get(id_host, id_end);
     340                 : }
     341                 : 
     342                 : //------------------------------------------------
     343                 : //
     344                 : // Comparisons
     345                 : //
     346                 : //------------------------------------------------
     347                 : 
     348                 : inline
     349                 : int
     350             190 : authority_view::
     351                 : compare(const authority_view& other) const noexcept
     352                 : {
     353             190 :     auto comp = static_cast<int>(has_userinfo()) -
     354             190 :         static_cast<int>(other.has_userinfo());
     355             190 :     if ( comp != 0 )
     356               1 :         return comp;
     357                 : 
     358             189 :     if (has_userinfo())
     359                 :     {
     360              46 :         comp = detail::compare_encoded(
     361              23 :             encoded_user(),
     362              23 :             other.encoded_user());
     363              23 :         if ( comp != 0 )
     364               7 :             return comp;
     365                 : 
     366              16 :         comp = static_cast<int>(has_password()) -
     367              16 :                static_cast<int>(other.has_password());
     368              16 :         if ( comp != 0 )
     369               1 :             return comp;
     370                 : 
     371              15 :         if (has_password())
     372                 :         {
     373              30 :             comp = detail::compare_encoded(
     374              15 :                 encoded_password(),
     375              15 :                 other.encoded_password());
     376              15 :             if ( comp != 0 )
     377              14 :                 return comp;
     378                 :         }
     379                 :     }
     380                 : 
     381             334 :     comp = detail::ci_compare_encoded(
     382             167 :         encoded_host(),
     383             167 :         other.encoded_host());
     384             167 :     if ( comp != 0 )
     385              17 :         return comp;
     386                 : 
     387             150 :     comp = static_cast<int>(has_port()) -
     388             150 :            static_cast<int>(other.has_port());
     389             150 :     if ( comp != 0 )
     390               7 :         return comp;
     391                 : 
     392             143 :     if (has_port())
     393                 :     {
     394              46 :         comp = detail::compare(
     395                 :             port(),
     396                 :             other.port());
     397              46 :         if ( comp != 0 )
     398              42 :             return comp;
     399                 :     }
     400                 : 
     401             101 :     return 0;
     402                 : }
     403                 : 
     404                 : //------------------------------------------------
     405                 : 
     406                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     407                 : system::result<authority_view>
     408              46 : parse_authority(
     409                 :     core::string_view s) noexcept
     410                 : {
     411              46 :     return grammar::parse(s, authority_rule);
     412                 : }
     413                 : 
     414                 : } // urls
     415                 : } // boost
     416                 : 
     417                 : #endif
        

Generated by: LCOV version 2.3