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.7 % 220 215
Test Date: 2025-11-10 19:06:20 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         2287 : url_impl::
      35              : apply_scheme(
      36              :     core::string_view s) noexcept
      37              : {
      38         2287 :     scheme_ = string_to_scheme(s);
      39         2287 :     set_size(id_scheme, s.size() + 1);
      40         2287 : }
      41              : 
      42              : void
      43          381 : 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          381 :     BOOST_ASSERT(from_ == from::authority);
      51              : 
      52              :     // userinfo
      53          381 :     set_size(id_user, user.size());
      54          381 :     decoded_[id_user] =
      55          381 :         user.decoded_size();
      56          381 :     if(pass)
      57              :     {
      58          252 :         set_size(id_pass,
      59          252 :             pass->size() + 2);
      60          252 :         decoded_[id_pass] =
      61          252 :             pass->decoded_size();
      62              :     }
      63              :     else
      64              :     {
      65              :         // trailing '@'
      66          129 :         set_size(id_pass, 1 );
      67              :     }
      68          381 : }
      69              : 
      70              : void
      71         1888 : url_impl::
      72              : apply_host(
      73              :     host_type ht,
      74              :     pct_string_view s,
      75              :     unsigned char const* addr) noexcept
      76              : {
      77              :     // this function is for
      78              :     // authority_view_rule only
      79         1888 :     BOOST_ASSERT(from_ == from::authority);
      80              : 
      81              :     // host, port
      82         1888 :     host_type_ = ht;
      83         1888 :     set_size(id_host, s.size());
      84         1888 :     decoded_[id_host] =
      85         1888 :         s.decoded_size();
      86         1888 :     std::memcpy(
      87         1888 :         ip_addr_,
      88              :         addr,
      89              :         sizeof(ip_addr_));
      90         1888 : }
      91              : 
      92              : void
      93          260 : url_impl::
      94              : apply_port(
      95              :     core::string_view s,
      96              :     unsigned short pn) noexcept
      97              : {
      98              :     // this function is for
      99              :     // authority_view_rule only
     100          260 :     BOOST_ASSERT(from_ == from::authority);
     101              : 
     102          260 :     port_number_ = pn;
     103          260 :     set_size(id_port, 1 + s.size());
     104          260 : }
     105              : 
     106              : void
     107         1830 : url_impl::
     108              : apply_authority(
     109              :     authority_view const& a) noexcept
     110              : {
     111         1830 :     BOOST_ASSERT(from_ != from::authority);
     112              : 
     113              :     // userinfo
     114         1830 :     set_size(id_user,
     115         1830 :         a.u_.len(id_user) +
     116         1830 :         (from_ == from::authority ? 0 : 2));
     117         1830 :     set_size(id_pass, a.u_.len(id_pass));
     118         1830 :     decoded_[id_user] = a.u_.decoded_[id_user];
     119         1830 :     decoded_[id_pass] = a.u_.decoded_[id_pass];
     120              : 
     121              :     // host, port
     122         1830 :     host_type_ = a.u_.host_type_;
     123         1830 :     port_number_ = a.u_.port_number_;
     124         1830 :     set_size(id_host, a.u_.len(id_host));
     125         1830 :     set_size(id_port, a.u_.len(id_port));
     126         1830 :     std::memcpy(
     127         1830 :         ip_addr_,
     128         1830 :         a.u_.ip_addr_,
     129              :         sizeof(ip_addr_));
     130         1830 :     decoded_[id_host] = a.u_.decoded_[id_host];
     131         1830 : }
     132              : 
     133              : void
     134         3573 : url_impl::
     135              : apply_path(
     136              :     pct_string_view s,
     137              :     std::size_t nseg) noexcept
     138              : {
     139         3573 :     set_size(id_path, s.size());
     140         3573 :     decoded_[id_path] = s.decoded_size();
     141         3573 :     nseg_ = detail::path_segments(s, nseg);
     142         3573 : }
     143              : 
     144              : void
     145          447 : url_impl::
     146              : apply_query(
     147              :     pct_string_view s,
     148              :     std::size_t n) noexcept
     149              : {
     150          447 :     nparam_ = n;
     151          447 :     set_size(id_query, 1 + s.size());
     152          447 :     decoded_[id_query] = s.decoded_size();
     153          447 : }
     154              : 
     155              : void
     156          214 : url_impl::
     157              : apply_frag(
     158              :     pct_string_view s) noexcept
     159              : {
     160          214 :     set_size(id_frag, s.size() + 1);
     161          214 :     decoded_[id_frag] = s.decoded_size();
     162          214 : }
     163              : 
     164              : // return length of [first, last)
     165              : auto
     166        20450 : url_impl::
     167              : len(
     168              :     int first,
     169              :     int last) const noexcept ->
     170              :         std::size_t
     171              : {
     172        20450 :     BOOST_ASSERT(first <= last);
     173        20450 :     BOOST_ASSERT(last <= id_end);
     174        20450 :     return offset(last) - offset(first);
     175              : }
     176              : 
     177              : // return length of part
     178              : auto
     179       269128 : url_impl::
     180              : len(int id) const noexcept ->
     181              :     std::size_t
     182              : {
     183              :     return id == id_end
     184       538256 :         ? zero_
     185       269128 :         : ( offset(id + 1) -
     186       538256 :             offset(id) );
     187              : }
     188              : 
     189              : // return offset of id
     190              : auto
     191       704415 : url_impl::
     192              : offset(int id) const noexcept ->
     193              :     std::size_t
     194              : {
     195              :     return
     196              :         id == id_scheme
     197       704415 :         ? zero_
     198       704415 :         : offset_[id];
     199              : }
     200              : 
     201              : // return id as string
     202              : core::string_view
     203        47922 : url_impl::
     204              : get(int id) const noexcept
     205              : {
     206              :     return {
     207        47922 :         cs_ + offset(id), len(id) };
     208              : }
     209              : 
     210              : // return [first, last) as string
     211              : core::string_view
     212          889 : url_impl::
     213              : get(int first,
     214              :     int last) const noexcept
     215              : {
     216          889 :     return { cs_ + offset(first),
     217          889 :         offset(last) - offset(first) };
     218              : }
     219              : 
     220              : // return id as pct-string
     221              : pct_string_view
     222         2203 : url_impl::
     223              : pct_get(
     224              :     int id) const noexcept
     225              : {
     226         2203 :     return make_pct_string_view_unsafe(
     227         2203 :         cs_ + offset(id),
     228              :         len(id),
     229         4406 :         decoded_[id]);
     230              : }
     231              : 
     232              : // return [first, last) as pct-string
     233              : pct_string_view
     234          120 : url_impl::
     235              : pct_get(
     236              :     int first,
     237              :     int last) const noexcept
     238              : {
     239          120 :     auto const pos = offset(first);
     240          120 :     std::size_t n = 0;
     241          360 :     for(auto i = first; i < last;)
     242          240 :         n += decoded_[i++];
     243          120 :     return make_pct_string_view_unsafe(
     244          120 :         cs_ + pos,
     245          120 :         offset(last) - pos,
     246          120 :         n);
     247              : }
     248              : 
     249              : //------------------------------------------------
     250              : 
     251              : // change id to size n
     252              : void
     253        19467 : url_impl::
     254              : set_size(
     255              :     int id,
     256              :     std::size_t n) noexcept
     257              : {
     258        19467 :     auto d = n - len(id);
     259        19467 :     for(auto i = id + 1;
     260       118243 :         i <= id_end; ++i)
     261        98776 :         offset_[i] += d;
     262        19467 : }
     263              : 
     264              : // trim id to size n,
     265              : // moving excess into id+1
     266              : void
     267          831 : url_impl::
     268              : split(
     269              :     int id,
     270              :     std::size_t n) noexcept
     271              : {
     272          831 :     BOOST_ASSERT(id < id_end - 1);
     273              :     //BOOST_ASSERT(n <= len(id));
     274          831 :     offset_[id + 1] = offset(id) + n;
     275          831 : }
     276              : 
     277              : // add n to [first, last]
     278              : void
     279          921 : url_impl::
     280              : adjust_right(
     281              :     int first,
     282              :     int last,
     283              :     std::size_t n) noexcept
     284              : {
     285          921 :     for(int i = first;
     286         5363 :             i <= last; ++i)
     287         4442 :         offset_[i] += n;
     288          921 : }
     289              : 
     290              : // remove n from [first, last]
     291              : void
     292          690 : url_impl::
     293              : adjust_left(
     294              :     int first,
     295              :     int last,
     296              :     std::size_t n) noexcept
     297              : {
     298          690 :     for(int i = first;
     299         3394 :             i <= last; ++i)
     300         2704 :         offset_[i] -= n;
     301          690 : }
     302              : 
     303              : // set [first, last) offset
     304              : void
     305         1592 : url_impl::
     306              : collapse(
     307              :     int first,
     308              :     int last,
     309              :     std::size_t n) noexcept
     310              : {
     311         1592 :     for(int i = first + 1;
     312         2137 :             i < last; ++i)
     313          545 :         offset_[i] = n;
     314         1592 : }
     315              : 
     316              : 
     317              : //------------------------------------------------
     318              : //
     319              : // path_ref
     320              : //
     321              : //------------------------------------------------
     322              : 
     323         2044 : path_ref::
     324              : path_ref(
     325         2044 :     url_impl const& impl) noexcept
     326              : {
     327         2044 :     if(impl.from_ == url_impl::from::url)
     328              :     {
     329         1587 :         impl_ = &impl;
     330              :     }
     331              :     else
     332              :     {
     333          457 :         core::string_view s = impl.get(id_path);
     334          457 :         data_ = s.data();
     335          457 :         size_ = s.size();
     336          457 :         nseg_ = impl.nseg_;
     337          457 :         dn_ = impl.decoded_[id_path];
     338              :     }
     339         2044 : }
     340              : 
     341          181 : path_ref::
     342              : path_ref(
     343              :     core::string_view s,
     344              :     std::size_t dn,
     345          181 :     std::size_t nseg) noexcept
     346          362 :     : data_(s.data())
     347          181 :     , size_(s.size())
     348          181 :     , nseg_(nseg)
     349          181 :     , dn_(dn)
     350              : {
     351          181 : }
     352              : 
     353              : pct_string_view
     354         4701 : path_ref::
     355              : buffer() const noexcept
     356              : {
     357         4701 :     if(impl_)
     358         2389 :         return make_pct_string_view_unsafe(
     359         2389 :             impl_->cs_ +
     360         2389 :                 impl_->offset(id_path),
     361         2389 :             impl_->len(id_path),
     362         4778 :             impl_->decoded_[id_path]);
     363         2312 :     return make_pct_string_view_unsafe(
     364         2312 :         data_, size_, dn_);
     365              : }
     366              : 
     367              : std::size_t
     368         4431 : path_ref::
     369              : size() const noexcept
     370              : {
     371         4431 :     if(impl_)
     372         3116 :         return impl_->len(id_path);
     373         1315 :     return size_;
     374              : }
     375              : 
     376              : char const*
     377        12801 : path_ref::
     378              : data() const noexcept
     379              : {
     380        12801 :     if(impl_)
     381         7466 :         return impl_->cs_ +
     382         7466 :             impl_->offset(id_path);
     383         5335 :     return data_;
     384              : }
     385              : 
     386              : char const*
     387         4363 : path_ref::
     388              : end() const noexcept
     389              : {
     390         4363 :     if(impl_)
     391         2839 :         return impl_->cs_ +
     392         2839 :             impl_->offset(id_query);
     393         1524 :     return data_ + size_;
     394              : }
     395              : 
     396              : std::size_t
     397         9398 : path_ref::
     398              : nseg() const noexcept
     399              : {
     400         9398 :     if(impl_)
     401         6155 :         return impl_->nseg_;
     402         3243 :     return nseg_;
     403              : }
     404              : 
     405              : std::size_t
     406         2012 : path_ref::
     407              : decoded_size() const noexcept
     408              : {
     409         2012 :     if(impl_)
     410         1359 :         return impl_->decoded_[id_path];
     411          653 :     return dn_;
     412              : }
     413              : 
     414              : //------------------------------------------------
     415              : //
     416              : // query_ref
     417              : //
     418              : //------------------------------------------------
     419              : 
     420          701 : query_ref::
     421              : query_ref(
     422              :     core::string_view s,
     423              :     std::size_t dn,
     424          701 :     std::size_t nparam) noexcept
     425         1402 :     : data_(s.data())
     426          701 :     , size_(s.size())
     427          701 :     , nparam_(nparam)
     428          701 :     , dn_(dn)
     429              : {
     430          701 : }
     431              : 
     432          450 : query_ref::
     433              : query_ref(
     434          450 :     url_impl const& impl) noexcept
     435              : {
     436          450 :     if(impl.from_ == url_impl::from::url)
     437              :     {
     438          353 :         impl_ = &impl;
     439              :     }
     440              :     else
     441              :     {
     442           97 :         core::string_view s = impl.get(id_query);
     443           97 :         if (!s.empty())
     444              :         {
     445           91 :             s.remove_prefix(1);
     446           91 :             question_mark_ = true;
     447              :         }
     448           97 :         data_ = s.data();
     449           97 :         size_ = s.size();
     450           97 :         nparam_ = impl.nparam_;
     451           97 :         dn_ = impl.decoded_[id_query];
     452              :     }
     453          450 : }
     454              : 
     455              : pct_string_view
     456          471 : query_ref::
     457              : buffer() const noexcept
     458              : {
     459          471 :     if(impl_)
     460              :     {
     461            2 :         auto pos = impl_->offset_[id_query];
     462            2 :         auto pos1 = impl_->offset_[id_frag];
     463            2 :         if(pos < pos1)
     464              :         {
     465            0 :             ++pos; // no '?'
     466            0 :             return make_pct_string_view_unsafe(
     467            0 :                 impl_->cs_ + pos,
     468              :                 pos1 - pos,
     469            0 :                 impl_->decoded_[id_query]);
     470              :         }
     471              :         // empty
     472            2 :         return make_pct_string_view_unsafe(
     473            2 :             impl_->cs_ + pos,
     474              :             0,
     475            2 :             0);
     476              :     }
     477              :     // no '?'
     478          469 :     return make_pct_string_view_unsafe(
     479          469 :         data_, size_, dn_);
     480              : }
     481              : 
     482              : // with '?'
     483              : std::size_t
     484         5331 : query_ref::
     485              : size() const noexcept
     486              : {
     487         5331 :     if(impl_)
     488         2011 :         return impl_->len(id_query);
     489         3320 :     if(size_ > 0)
     490         3284 :         return size_ + 1;
     491           36 :     return question_mark_;
     492              : }
     493              : 
     494              : // no '?'
     495              : char const*
     496         5854 : query_ref::
     497              : begin() const noexcept
     498              : {
     499         5854 :     if(impl_)
     500              :     {
     501              :         // using the offset array here
     502         2278 :         auto pos = impl_->offset_[id_query];
     503         2278 :         auto pos1 = impl_->offset_[id_frag];
     504         2278 :         if(pos < pos1)
     505         2278 :             return impl_->cs_ + pos + 1; // no '?'
     506              :         // empty
     507            0 :         return impl_->cs_ + pos;
     508              :     }
     509         3576 :     return data_;
     510              : 
     511              : }
     512              : 
     513              : char const*
     514         2298 : query_ref::
     515              : end() const noexcept
     516              : {
     517         2298 :     if(impl_)
     518          910 :         return impl_->cs_ +
     519          910 :             impl_->offset(id_frag);
     520         1388 :     return data_ + size_;
     521              : }
     522              : 
     523              : std::size_t
     524         8992 : query_ref::
     525              : nparam() const noexcept
     526              : {
     527         8992 :     if(impl_)
     528         3151 :         return impl_->nparam_;
     529         5841 :     return nparam_;
     530              : }
     531              : 
     532              : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
     533              : #pragma GCC diagnostic pop
     534              : #endif
     535              : 
     536              : } // detail
     537              : } // urls
     538              : } // boost
        

Generated by: LCOV version 2.1