LCOV - code coverage report
Current view: top level - libs/url/src/detail - url_impl.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 97.4 % 231 225
Test Date: 2026-01-27 21:05:51 Functions: 100.0 % 35 35

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

Generated by: LCOV version 2.3