LCOV - code coverage report
Current view: top level - url/detail/impl - url_impl.hpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 97.4 % 229 223 6
Test Date: 2026-02-25 21:00:01 Functions: 100.0 % 35 35

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2022 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_DETAIL_IMPL_URL_IMPL_HPP
      12                 : #define BOOST_URL_DETAIL_IMPL_URL_IMPL_HPP
      13                 : 
      14                 : #include <boost/url/detail/config.hpp>
      15                 : #include <boost/url/detail/memcpy.hpp>
      16                 : #include <boost/url/detail/path.hpp>
      17                 : #include <boost/url/detail/url_impl.hpp>
      18                 : #include <boost/url/scheme.hpp>
      19                 : #include <boost/assert.hpp>
      20                 : #include <cstring>
      21                 : 
      22                 : namespace boost {
      23                 : namespace urls {
      24                 : namespace detail {
      25                 : 
      26                 : //------------------------------------------------
      27                 : //
      28                 : // url_impl
      29                 : //
      30                 : //------------------------------------------------
      31                 : 
      32                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
      33                 : void
      34 HIT        2432 : url_impl::
      35                 : apply_scheme(
      36                 :     core::string_view s) noexcept
      37                 : {
      38            2432 :     scheme_ = string_to_scheme(s);
      39            2432 :     set_size(id_scheme, s.size() + 1);
      40            2432 : }
      41                 : 
      42                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
      43                 : void
      44             405 : url_impl::
      45                 : apply_userinfo(
      46                 :     pct_string_view const& user,
      47                 :     pct_string_view const* pass) noexcept
      48                 : {
      49                 :     // this function is for
      50                 :     // authority_view_rule only
      51             405 :     BOOST_ASSERT(from_ == from::authority);
      52                 : 
      53                 :     // userinfo
      54             405 :     set_size(id_user, user.size());
      55             405 :     decoded_[id_user] =
      56             405 :         detail::to_size_type(
      57                 :             user.decoded_size());
      58             405 :     if(pass)
      59                 :     {
      60             270 :         set_size(id_pass,
      61             270 :             pass->size() + 2);
      62             270 :         decoded_[id_pass] =
      63             270 :             detail::to_size_type(
      64                 :                 pass->decoded_size());
      65                 :     }
      66                 :     else
      67                 :     {
      68                 :         // trailing '@'
      69             135 :         set_size(id_pass, 1 );
      70                 :     }
      71             405 : }
      72                 : 
      73                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
      74                 : void
      75            2022 : url_impl::
      76                 : apply_host(
      77                 :     host_type ht,
      78                 :     pct_string_view s,
      79                 :     unsigned char const* addr) noexcept
      80                 : {
      81                 :     // this function is for
      82                 :     // authority_view_rule only
      83            2022 :     BOOST_ASSERT(from_ == from::authority);
      84                 : 
      85                 :     // host, port
      86            2022 :     host_type_ = ht;
      87            2022 :     set_size(id_host, s.size());
      88            2022 :     decoded_[id_host] =
      89            2022 :         detail::to_size_type(
      90                 :             s.decoded_size());
      91                 :     detail::memcpy(
      92            2022 :         ip_addr_,
      93                 :         addr,
      94                 :         sizeof(ip_addr_));
      95            2022 : }
      96                 : 
      97                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
      98                 : void
      99             284 : url_impl::
     100                 : apply_port(
     101                 :     core::string_view s,
     102                 :     unsigned short pn) noexcept
     103                 : {
     104                 :     // this function is for
     105                 :     // authority_view_rule only
     106             284 :     BOOST_ASSERT(from_ == from::authority);
     107                 : 
     108             284 :     port_number_ = pn;
     109             284 :     set_size(id_port, 1 + s.size());
     110             284 : }
     111                 : 
     112                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     113                 : void
     114            1962 : url_impl::
     115                 : apply_authority(
     116                 :     url_impl const& a) noexcept
     117                 : {
     118            1962 :     BOOST_ASSERT(from_ != from::authority);
     119                 : 
     120                 :     // userinfo
     121            1962 :     set_size(id_user,
     122            1962 :         a.len(id_user) +
     123            1962 :         (from_ == from::authority ? 0 : 2));
     124            1962 :     set_size(id_pass, a.len(id_pass));
     125            1962 :     decoded_[id_user] = a.decoded_[id_user];
     126            1962 :     decoded_[id_pass] = a.decoded_[id_pass];
     127                 : 
     128                 :     // host, port
     129            1962 :     host_type_ = a.host_type_;
     130            1962 :     port_number_ = a.port_number_;
     131            1962 :     set_size(id_host, a.len(id_host));
     132            1962 :     set_size(id_port, a.len(id_port));
     133                 :     detail::memcpy(
     134            1962 :         ip_addr_,
     135            1962 :         a.ip_addr_,
     136                 :         sizeof(ip_addr_));
     137            1962 :     decoded_[id_host] = a.decoded_[id_host];
     138            1962 : }
     139                 : 
     140                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     141                 : void
     142            3748 : url_impl::
     143                 : apply_path(
     144                 :     pct_string_view s,
     145                 :     std::size_t nseg) noexcept
     146                 : {
     147            3748 :     set_size(id_path, s.size());
     148            3748 :     decoded_[id_path] =
     149            3748 :         detail::to_size_type(
     150                 :             s.decoded_size());
     151            3748 :     nseg_ = detail::to_size_type(
     152                 :         detail::path_segments(s, nseg));
     153            3748 : }
     154                 : 
     155                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     156                 : void
     157             504 : url_impl::
     158                 : apply_query(
     159                 :     pct_string_view s,
     160                 :     std::size_t n) noexcept
     161                 : {
     162             504 :     nparam_ = detail::to_size_type(n);
     163             504 :     set_size(id_query, 1 + s.size());
     164             504 :     decoded_[id_query] =
     165             504 :         detail::to_size_type(
     166                 :             s.decoded_size());
     167             504 : }
     168                 : 
     169                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     170                 : void
     171             244 : url_impl::
     172                 : apply_frag(
     173                 :     pct_string_view s) noexcept
     174                 : {
     175             244 :     set_size(id_frag, s.size() + 1);
     176             244 :     decoded_[id_frag] =
     177             244 :         detail::to_size_type(
     178                 :             s.decoded_size());
     179             244 : }
     180                 : 
     181                 : // return length of [first, last)
     182                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     183                 : std::size_t
     184           20955 : url_impl::
     185                 : len(
     186                 :     int first,
     187                 :     int last) const noexcept
     188                 : {
     189           20955 :     BOOST_ASSERT(first <= last);
     190           20955 :     BOOST_ASSERT(last <= id_end);
     191           20955 :     return offset(last) - offset(first);
     192                 : }
     193                 : 
     194                 : // return length of part
     195                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     196                 : std::size_t
     197          276636 : url_impl::
     198                 : len(int id) const noexcept
     199                 : {
     200                 :     return id == id_end
     201          553272 :         ? zero_
     202          276636 :         : ( offset(id + 1) -
     203          553272 :             offset(id) );
     204                 : }
     205                 : 
     206                 : // return offset of id
     207                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     208                 : std::size_t
     209          723724 : url_impl::
     210                 : offset(int id) const noexcept
     211                 : {
     212                 :     return
     213                 :         id == id_scheme
     214          723724 :         ? zero_
     215          723724 :         : offset_[id];
     216                 : }
     217                 : 
     218                 : // return id as string
     219                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     220                 : core::string_view
     221           49394 : url_impl::
     222                 : get(int id) const noexcept
     223                 : {
     224                 :     return {
     225           49394 :         cs_ + offset(id), len(id) };
     226                 : }
     227                 : 
     228                 : // return [first, last) as string
     229                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     230                 : core::string_view
     231             916 : url_impl::
     232                 : get(int first,
     233                 :     int last) const noexcept
     234                 : {
     235             916 :     return { cs_ + offset(first),
     236             916 :         offset(last) - offset(first) };
     237                 : }
     238                 : 
     239                 : // return id as pct-string
     240                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     241                 : pct_string_view
     242            2318 : url_impl::
     243                 : pct_get(
     244                 :     int id) const noexcept
     245                 : {
     246            2318 :     return make_pct_string_view_unsafe(
     247            2318 :         cs_ + offset(id),
     248                 :         len(id),
     249            4636 :         decoded_[id]);
     250                 : }
     251                 : 
     252                 : // return [first, last) as pct-string
     253                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     254                 : pct_string_view
     255             130 : url_impl::
     256                 : pct_get(
     257                 :     int first,
     258                 :     int last) const noexcept
     259                 : {
     260             130 :     auto const pos = offset(first);
     261             130 :     std::size_t n = 0;
     262             420 :     for(auto i = first; i < last;)
     263             290 :         n += decoded_[i++];
     264             130 :     return make_pct_string_view_unsafe(
     265             130 :         cs_ + pos,
     266             130 :         offset(last) - pos,
     267             130 :         n);
     268                 : }
     269                 : 
     270                 : //------------------------------------------------
     271                 : 
     272                 : // change id to size n
     273                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     274                 : void
     275           20675 : url_impl::
     276                 : set_size(
     277                 :     int id,
     278                 :     std::size_t n) noexcept
     279                 : {
     280           20675 :     auto const cur = len(id);
     281           20675 :     if(n >= cur)
     282                 :     {
     283           20310 :         auto const d = n - cur;
     284           20310 :         for(auto i = id + 1;
     285          123823 :             i <= id_end; ++i)
     286          103513 :             offset_[i] += detail::to_size_type(d);
     287           20310 :         return;
     288                 :     }
     289             365 :     auto const d = cur - n;
     290             365 :     for(auto i = id + 1;
     291            1794 :         i <= id_end; ++i)
     292            1429 :         offset_[i] -= detail::to_size_type(d);
     293                 : }
     294                 : 
     295                 : // trim id to size n,
     296                 : // moving excess into id+1
     297                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     298                 : void
     299             891 : url_impl::
     300                 : split(
     301                 :     int id,
     302                 :     std::size_t n) noexcept
     303                 : {
     304             891 :     BOOST_ASSERT(id < id_end - 1);
     305                 :     //BOOST_ASSERT(n <= len(id));
     306             891 :     offset_[id + 1] = detail::to_size_type(
     307             891 :         offset(id) + n);
     308             891 : }
     309                 : 
     310                 : // add n to [first, last]
     311                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     312                 : void
     313             979 : url_impl::
     314                 : adjust_right(
     315                 :     int first,
     316                 :     int last,
     317                 :     std::size_t n) noexcept
     318                 : {
     319             979 :     for(int i = first;
     320            5720 :             i <= last; ++i)
     321            4741 :         offset_[i] += detail::to_size_type(n);
     322             979 : }
     323                 : 
     324                 : // remove n from [first, last]
     325                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     326                 : void
     327             721 : url_impl::
     328                 : adjust_left(
     329                 :     int first,
     330                 :     int last,
     331                 :     std::size_t n) noexcept
     332                 : {
     333             721 :     for(int i = first;
     334            3558 :             i <= last; ++i)
     335            2837 :         offset_[i] -= detail::to_size_type(n);
     336             721 : }
     337                 : 
     338                 : // set [first, last) offset
     339                 : BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
     340                 : void
     341            1681 : url_impl::
     342                 : collapse(
     343                 :     int first,
     344                 :     int last,
     345                 :     std::size_t n) noexcept
     346                 : {
     347            1681 :     for(int i = first + 1;
     348            2228 :             i < last; ++i)
     349             547 :         offset_[i] = detail::to_size_type(n);
     350            1681 : }
     351                 : 
     352                 : 
     353                 : //------------------------------------------------
     354                 : //
     355                 : // path_ref
     356                 : //
     357                 : //------------------------------------------------
     358                 : 
     359                 : inline
     360            2097 : path_ref::
     361                 : path_ref(
     362            2097 :     url_impl const& impl) noexcept
     363                 : {
     364            2097 :     if(impl.from_ == url_impl::from::url)
     365                 :     {
     366            1594 :         impl_ = &impl;
     367                 :     }
     368                 :     else
     369                 :     {
     370             503 :         core::string_view s = impl.get(id_path);
     371             503 :         data_ = s.data();
     372             503 :         size_ = s.size();
     373             503 :         nseg_ = impl.nseg_;
     374             503 :         dn_ = impl.decoded_[id_path];
     375                 :     }
     376            2097 : }
     377                 : 
     378                 : inline
     379             181 : path_ref::
     380                 : path_ref(
     381                 :     core::string_view s,
     382                 :     std::size_t dn,
     383             181 :     std::size_t nseg) noexcept
     384             362 :     : data_(s.data())
     385             181 :     , size_(s.size())
     386             181 :     , nseg_(nseg)
     387             181 :     , dn_(dn)
     388                 : {
     389             181 : }
     390                 : 
     391                 : inline
     392                 : pct_string_view
     393            4739 : path_ref::
     394                 : buffer() const noexcept
     395                 : {
     396            4739 :     if(impl_)
     397            2392 :         return make_pct_string_view_unsafe(
     398            2392 :             impl_->cs_ +
     399            2392 :                 impl_->offset(id_path),
     400            2392 :             impl_->len(id_path),
     401            4784 :             impl_->decoded_[id_path]);
     402            2347 :     return make_pct_string_view_unsafe(
     403            2347 :         data_, size_, dn_);
     404                 : }
     405                 : 
     406                 : inline
     407                 : std::size_t
     408            4487 : path_ref::
     409                 : size() const noexcept
     410                 : {
     411            4487 :     if(impl_)
     412            3116 :         return impl_->len(id_path);
     413            1371 :     return size_;
     414                 : }
     415                 : 
     416                 : inline
     417                 : char const*
     418           12997 : path_ref::
     419                 : data() const noexcept
     420                 : {
     421           12997 :     if(impl_)
     422            7472 :         return impl_->cs_ +
     423            7472 :             impl_->offset(id_path);
     424            5525 :     return data_;
     425                 : }
     426                 : 
     427                 : inline
     428                 : char const*
     429            4461 : path_ref::
     430                 : end() const noexcept
     431                 : {
     432            4461 :     if(impl_)
     433            2842 :         return impl_->cs_ +
     434            2842 :             impl_->offset(id_query);
     435            1619 :     return data_ + size_;
     436                 : }
     437                 : 
     438                 : inline
     439                 : std::size_t
     440            9623 : path_ref::
     441                 : nseg() const noexcept
     442                 : {
     443            9623 :     if(impl_)
     444            6161 :         return impl_->nseg_;
     445            3462 :     return nseg_;
     446                 : }
     447                 : 
     448                 : inline
     449                 : std::size_t
     450            2040 : path_ref::
     451                 : decoded_size() const noexcept
     452                 : {
     453            2040 :     if(impl_)
     454            1359 :         return impl_->decoded_[id_path];
     455             681 :     return dn_;
     456                 : }
     457                 : 
     458                 : //------------------------------------------------
     459                 : //
     460                 : // query_ref
     461                 : //
     462                 : //------------------------------------------------
     463                 : 
     464                 : inline
     465             255 : query_ref::
     466                 : query_ref(
     467                 :     core::string_view s,
     468                 :     std::size_t dn,
     469             255 :     std::size_t nparam) noexcept
     470             510 :     : data_(s.data())
     471             255 :     , size_(s.size())
     472             255 :     , nparam_(nparam)
     473             255 :     , dn_(dn)
     474                 : {
     475             255 : }
     476                 : 
     477                 : inline
     478             493 : query_ref::
     479                 : query_ref(
     480             493 :     url_impl const& impl) noexcept
     481                 : {
     482             493 :     if(impl.from_ == url_impl::from::url)
     483                 :     {
     484             362 :         impl_ = &impl;
     485                 :     }
     486                 :     else
     487                 :     {
     488             131 :         core::string_view s = impl.get(id_query);
     489             131 :         if (!s.empty())
     490                 :         {
     491             125 :             s.remove_prefix(1);
     492             125 :             question_mark_ = true;
     493                 :         }
     494             131 :         data_ = s.data();
     495             131 :         size_ = s.size();
     496             131 :         nparam_ = impl.nparam_;
     497             131 :         dn_ = impl.decoded_[id_query];
     498                 :     }
     499             493 : }
     500                 : 
     501                 : inline
     502                 : pct_string_view
     503              24 : query_ref::
     504                 : buffer() const noexcept
     505                 : {
     506              24 :     if(impl_)
     507                 :     {
     508               2 :         auto pos = impl_->offset_[id_query];
     509               2 :         auto pos1 = impl_->offset_[id_frag];
     510               2 :         if(pos < pos1)
     511                 :         {
     512 MIS           0 :             ++pos; // no '?'
     513               0 :             return make_pct_string_view_unsafe(
     514               0 :                 impl_->cs_ + pos,
     515               0 :                 pos1 - pos,
     516               0 :                 impl_->decoded_[id_query]);
     517                 :         }
     518                 :         // empty
     519 HIT           2 :         return make_pct_string_view_unsafe(
     520               2 :             impl_->cs_ + pos,
     521                 :             0,
     522               2 :             0);
     523                 :     }
     524                 :     // no '?'
     525              22 :     return make_pct_string_view_unsafe(
     526              22 :         data_, size_, dn_);
     527                 : }
     528                 : 
     529                 : // with '?'
     530                 : inline
     531                 : std::size_t
     532            5650 : query_ref::
     533                 : size() const noexcept
     534                 : {
     535            5650 :     if(impl_)
     536            2029 :         return impl_->len(id_query);
     537            3621 :     if(size_ > 0)
     538            3584 :         return size_ + 1;
     539              37 :     return question_mark_;
     540                 : }
     541                 : 
     542                 : // no '?'
     543                 : inline
     544                 : char const*
     545            6152 : query_ref::
     546                 : begin() const noexcept
     547                 : {
     548            6152 :     if(impl_)
     549                 :     {
     550                 :         // using the offset array here
     551            2288 :         auto pos = impl_->offset_[id_query];
     552            2288 :         auto pos1 = impl_->offset_[id_frag];
     553            2288 :         if(pos < pos1)
     554            2288 :             return impl_->cs_ + pos + 1; // no '?'
     555                 :         // empty
     556 MIS           0 :         return impl_->cs_ + pos;
     557                 :     }
     558 HIT        3864 :     return data_;
     559                 : 
     560                 : }
     561                 : 
     562                 : inline
     563                 : char const*
     564            2410 : query_ref::
     565                 : end() const noexcept
     566                 : {
     567            2410 :     if(impl_)
     568             917 :         return impl_->cs_ +
     569             917 :             impl_->offset(id_frag);
     570            1493 :     return data_ + size_;
     571                 : }
     572                 : 
     573                 : inline
     574                 : std::size_t
     575            9036 : query_ref::
     576                 : nparam() const noexcept
     577                 : {
     578            9036 :     if(impl_)
     579            3171 :         return impl_->nparam_;
     580            5865 :     return nparam_;
     581                 : }
     582                 : 
     583                 : } // detail
     584                 : } // urls
     585                 : } // boost
     586                 : 
     587                 : #endif
        

Generated by: LCOV version 2.3