LCOV - code coverage report
Current view: top level - libs/url/src/detail - url_impl.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 198 202 98.0 %
Date: 2023-12-15 15:31:48 Functions: 33 33 100.0 %

          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             : #ifndef BOOST_URL_DETAIL_IMPL_URL_IMPL_IPP
      11             : #define BOOST_URL_DETAIL_IMPL_URL_IMPL_IPP
      12             : 
      13             : #include <boost/url/detail/config.hpp>
      14             : #include <boost/url/detail/path.hpp>
      15             : #include <boost/url/detail/url_impl.hpp>
      16             : #include <boost/url/authority_view.hpp>
      17             : #include <boost/assert.hpp>
      18             : #include <cstring>
      19             : 
      20             : namespace boost {
      21             : namespace urls {
      22             : namespace detail {
      23             : 
      24             : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
      25             : #pragma GCC diagnostic push
      26             : #pragma GCC diagnostic ignored "-Warray-bounds"
      27             : #endif
      28             : 
      29             : //------------------------------------------------
      30             : //
      31             : // url_impl
      32             : //
      33             : //------------------------------------------------
      34             : 
      35             : void
      36        2233 : url_impl::
      37             : apply_scheme(
      38             :     core::string_view s) noexcept
      39             : {
      40        2233 :     scheme_ = string_to_scheme(s);
      41        2233 :     set_size(id_scheme, s.size() + 1);
      42        2233 : }
      43             : 
      44             : void
      45         372 : url_impl::
      46             : apply_userinfo(
      47             :     pct_string_view const& user,
      48             :     pct_string_view const* pass) noexcept
      49             : {
      50             :     // this function is for
      51             :     // authority_view_rule only
      52         372 :     BOOST_ASSERT(from_ == from::authority);
      53             : 
      54             :     // userinfo
      55         372 :     set_size(id_user, user.size());
      56         372 :     decoded_[id_user] =
      57         372 :         user.decoded_size();
      58         372 :     if(pass)
      59             :     {
      60         243 :         set_size(id_pass,
      61         243 :             pass->size() + 2);
      62         243 :         decoded_[id_pass] =
      63         243 :             pass->decoded_size();
      64             :     }
      65             :     else
      66             :     {
      67             :         // trailing '@'
      68         129 :         set_size(id_pass, 1 );
      69             :     }
      70         372 : }
      71             : 
      72             : void
      73        1840 : 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        1840 :     BOOST_ASSERT(from_ == from::authority);
      82             : 
      83             :     // host, port
      84        1840 :     host_type_ = ht;
      85        1840 :     set_size(id_host, s.size());
      86        1840 :     decoded_[id_host] =
      87        1840 :         s.decoded_size();
      88        1840 :     std::memcpy(
      89        1840 :         ip_addr_,
      90             :         addr,
      91             :         sizeof(ip_addr_));
      92        1840 : }
      93             : 
      94             : void
      95         239 : url_impl::
      96             : apply_port(
      97             :     core::string_view s,
      98             :     unsigned short pn) noexcept
      99             : {
     100             :     // this function is for
     101             :     // authority_view_rule only
     102         239 :     BOOST_ASSERT(from_ == from::authority);
     103             : 
     104         239 :     port_number_ = pn;
     105         239 :     set_size(id_port, 1 + s.size());
     106         239 : }
     107             : 
     108             : void
     109        1784 : url_impl::
     110             : apply_authority(
     111             :     authority_view const& a) noexcept
     112             : {
     113        1784 :     BOOST_ASSERT(from_ != from::authority);
     114             : 
     115             :     // userinfo
     116        1784 :     set_size(id_user,
     117        1784 :         a.u_.len(id_user) +
     118        1784 :         (from_ == from::authority ? 0 : 2));
     119        1784 :     set_size(id_pass, a.u_.len(id_pass));
     120        1784 :     decoded_[id_user] = a.u_.decoded_[id_user];
     121        1784 :     decoded_[id_pass] = a.u_.decoded_[id_pass];
     122             : 
     123             :     // host, port
     124        1784 :     host_type_ = a.u_.host_type_;
     125        1784 :     port_number_ = a.u_.port_number_;
     126        1784 :     set_size(id_host, a.u_.len(id_host));
     127        1784 :     set_size(id_port, a.u_.len(id_port));
     128        1784 :     std::memcpy(
     129        1784 :         ip_addr_,
     130        1784 :         a.u_.ip_addr_,
     131             :         sizeof(ip_addr_));
     132        1784 :     decoded_[id_host] = a.u_.decoded_[id_host];
     133        1784 : }
     134             : 
     135             : void
     136        3499 : url_impl::
     137             : apply_path(
     138             :     pct_string_view s,
     139             :     std::size_t nseg) noexcept
     140             : {
     141        3499 :     set_size(id_path, s.size());
     142        3499 :     decoded_[id_path] = s.decoded_size();
     143        3499 :     nseg_ = detail::path_segments(s, nseg);
     144        3499 : }
     145             : 
     146             : void
     147         422 : url_impl::
     148             : apply_query(
     149             :     pct_string_view s,
     150             :     std::size_t n) noexcept
     151             : {
     152         422 :     nparam_ = n;
     153         422 :     set_size(id_query, 1 + s.size());
     154         422 :     decoded_[id_query] = s.decoded_size();
     155         422 : }
     156             : 
     157             : void
     158         202 : url_impl::
     159             : apply_frag(
     160             :     pct_string_view s) noexcept
     161             : {
     162         202 :     set_size(id_frag, s.size() + 1);
     163         202 :     decoded_[id_frag] = s.decoded_size();
     164         202 : }
     165             : 
     166             : // return length of [first, last)
     167             : auto
     168       19899 : url_impl::
     169             : len(
     170             :     int first,
     171             :     int last) const noexcept ->
     172             :         std::size_t
     173             : {
     174       19899 :     BOOST_ASSERT(first <= last);
     175       19899 :     BOOST_ASSERT(last <= id_end);
     176       19899 :     return offset(last) - offset(first);
     177             : }
     178             : 
     179             : // return length of part
     180             : auto
     181      259476 : url_impl::
     182             : len(int id) const noexcept ->
     183             :     std::size_t
     184             : {
     185             :     return id == id_end
     186      518952 :         ? zero_
     187      259476 :         : ( offset(id + 1) -
     188      518952 :             offset(id) );
     189             : }
     190             : 
     191             : // return offset of id
     192             : auto
     193      680082 : url_impl::
     194             : offset(int id) const noexcept ->
     195             :     std::size_t
     196             : {
     197             :     return
     198             :         id == id_scheme
     199      680082 :         ? zero_
     200      680082 :         : offset_[id];
     201             : }
     202             : 
     203             : // return id as string
     204             : core::string_view
     205       46071 : url_impl::
     206             : get(int id) const noexcept
     207             : {
     208             :     return {
     209       46071 :         cs_ + offset(id), len(id) };
     210             : }
     211             : 
     212             : // return [first, last) as string
     213             : core::string_view
     214         791 : url_impl::
     215             : get(int first,
     216             :     int last) const noexcept
     217             : {
     218         791 :     return { cs_ + offset(first),
     219         791 :         offset(last) - offset(first) };
     220             : }
     221             : 
     222             : // return id as pct-string
     223             : pct_string_view
     224        2053 : url_impl::
     225             : pct_get(
     226             :     int id) const noexcept
     227             : {
     228             :     return make_pct_string_view_unsafe(
     229        2053 :         cs_ + offset(id),
     230             :         len(id),
     231        4106 :         decoded_[id]);
     232             : }
     233             : 
     234             : // return [first, last) as pct-string
     235             : pct_string_view
     236         120 : url_impl::
     237             : pct_get(
     238             :     int first,
     239             :     int last) const noexcept
     240             : {
     241         120 :     auto const pos = offset(first);
     242         120 :     std::size_t n = 0;
     243         360 :     for(auto i = first; i < last;)
     244         240 :         n += decoded_[i++];
     245             :     return make_pct_string_view_unsafe(
     246         120 :         cs_ + pos,
     247         120 :         offset(last) - pos,
     248         120 :         n);
     249             : }
     250             : 
     251             : //------------------------------------------------
     252             : 
     253             : // change id to size n
     254             : void
     255       18610 : url_impl::
     256             : set_size(
     257             :     int id,
     258             :     std::size_t n) noexcept
     259             : {
     260       18610 :     auto d = n - len(id);
     261       18610 :     for(auto i = id + 1;
     262      112999 :         i <= id_end; ++i)
     263       94389 :         offset_[i] += d;
     264       18610 : }
     265             : 
     266             : // trim id to size n,
     267             : // moving excess into id+1
     268             : void
     269         811 : url_impl::
     270             : split(
     271             :     int id,
     272             :     std::size_t n) noexcept
     273             : {
     274         811 :     BOOST_ASSERT(id < id_end - 1);
     275             :     //BOOST_ASSERT(n <= len(id));
     276         811 :     offset_[id + 1] = offset(id) + n;
     277         811 : }
     278             : 
     279             : // add n to [first, last]
     280             : void
     281        1571 : url_impl::
     282             : adjust(
     283             :     int first,
     284             :     int last,
     285             :     std::size_t n) noexcept
     286             : {
     287        1571 :     for(int i = first;
     288        8574 :             i <= last; ++i)
     289        7003 :         offset_[i] += n;
     290        1571 : }
     291             : 
     292             : // set [first, last) offset
     293             : void
     294        1552 : url_impl::
     295             : collapse(
     296             :     int first,
     297             :     int last,
     298             :     std::size_t n) noexcept
     299             : {
     300        1552 :     for(int i = first + 1;
     301        2097 :             i < last; ++i)
     302         545 :         offset_[i] = n;
     303        1552 : }
     304             : 
     305             : 
     306             : //------------------------------------------------
     307             : //
     308             : // path_ref
     309             : //
     310             : //------------------------------------------------
     311             : 
     312        1937 : path_ref::
     313             : path_ref(
     314        1937 :     url_impl const& impl) noexcept
     315             : {
     316        1937 :     if(impl.from_ == url_impl::from::url)
     317             :     {
     318        1521 :         impl_ = &impl;
     319             :     }
     320             :     else
     321             :     {
     322         416 :         core::string_view s = impl.get(id_path);
     323         416 :         data_ = s.data();
     324         416 :         size_ = s.size();
     325         416 :         nseg_ = impl.nseg_;
     326         416 :         dn_ = impl.decoded_[id_path];
     327             :     }
     328        1937 : }
     329             : 
     330         141 : path_ref::
     331             : path_ref(
     332             :     core::string_view s,
     333             :     std::size_t dn,
     334         141 :     std::size_t nseg) noexcept
     335         141 :     : data_(s.data())
     336         141 :     , size_(s.size())
     337             :     , nseg_(nseg)
     338         141 :     , dn_(dn)
     339             : {
     340         141 : }
     341             : 
     342             : pct_string_view
     343        4443 : path_ref::
     344             : buffer() const noexcept
     345             : {
     346        4443 :     if(impl_)
     347             :         return make_pct_string_view_unsafe(
     348        2305 :             impl_->cs_ +
     349        2305 :                 impl_->offset(id_path),
     350        2305 :             impl_->len(id_path),
     351        4610 :             impl_->decoded_[id_path]);
     352             :     return make_pct_string_view_unsafe(
     353        2138 :         data_, size_, dn_);
     354             : }
     355             : 
     356             : std::size_t
     357        3771 : path_ref::
     358             : size() const noexcept
     359             : {
     360        3771 :     if(impl_)
     361        2561 :         return impl_->len(id_path);
     362        1210 :     return size_;
     363             : }
     364             : 
     365             : char const*
     366       12186 : path_ref::
     367             : data() const noexcept
     368             : {
     369       12186 :     if(impl_)
     370        7319 :         return impl_->cs_ +
     371        7319 :             impl_->offset(id_path);
     372        4867 :     return data_;
     373             : }
     374             : 
     375             : char const*
     376        4221 : path_ref::
     377             : end() const noexcept
     378             : {
     379        4221 :     if(impl_)
     380        2913 :         return impl_->cs_ +
     381        2913 :             impl_->offset(id_query);
     382        1308 :     return data_ + size_;
     383             : }
     384             : 
     385             : std::size_t
     386        8214 : path_ref::
     387             : nseg() const noexcept
     388             : {
     389        8214 :     if(impl_)
     390        5428 :         return impl_->nseg_;
     391        2786 :     return nseg_;
     392             : }
     393             : 
     394             : //------------------------------------------------
     395             : //
     396             : // query_ref
     397             : //
     398             : //------------------------------------------------
     399             : 
     400         666 : query_ref::
     401             : query_ref(
     402             :     core::string_view s,
     403             :     std::size_t dn,
     404         666 :     std::size_t nparam) noexcept
     405         666 :     : data_(s.data())
     406         666 :     , size_(s.size())
     407             :     , nparam_(nparam)
     408         666 :     , dn_(dn)
     409             : {
     410         666 : }
     411             : 
     412         425 : query_ref::
     413             : query_ref(
     414         425 :     url_impl const& impl) noexcept
     415             : {
     416         425 :     if(impl.from_ == url_impl::from::url)
     417             :     {
     418         344 :         impl_ = &impl;
     419             :     }
     420             :     else
     421             :     {
     422          81 :         core::string_view s = impl.get(id_query);
     423          81 :         if (!s.empty())
     424             :         {
     425          79 :             s.remove_prefix(1);
     426          79 :             question_mark_ = true;
     427             :         }
     428          81 :         data_ = s.data();
     429          81 :         size_ = s.size();
     430          81 :         nparam_ = impl.nparam_;
     431          81 :         dn_ = impl.decoded_[id_query];
     432             :     }
     433         425 : }
     434             : 
     435             : pct_string_view
     436         446 : query_ref::
     437             : buffer() const noexcept
     438             : {
     439         446 :     if(impl_)
     440             :     {
     441           2 :         auto pos = impl_->offset_[id_query];
     442           2 :         auto pos1 = impl_->offset_[id_frag];
     443           2 :         if(pos < pos1)
     444             :         {
     445           0 :             ++pos; // no '?'
     446             :             return make_pct_string_view_unsafe(
     447           0 :                 impl_->cs_ + pos,
     448             :                 pos1 - pos,
     449           0 :                 impl_->decoded_[id_query]);
     450             :         }
     451             :         // empty
     452             :         return make_pct_string_view_unsafe(
     453           2 :             impl_->cs_ + pos,
     454             :             0,
     455           2 :             0);
     456             :     }
     457             :     // no '?'
     458             :     return make_pct_string_view_unsafe(
     459         444 :         data_, size_, dn_);
     460             : }
     461             : 
     462             : // with '?'
     463             : std::size_t
     464        5282 : query_ref::
     465             : size() const noexcept
     466             : {
     467        5282 :     if(impl_)
     468        1990 :         return impl_->len(id_query);
     469        3292 :     if(size_ > 0)
     470        3264 :         return size_ + 1;
     471          28 :     return question_mark_;
     472             : }
     473             : 
     474             : // no '?'
     475             : char const*
     476        5807 : query_ref::
     477             : begin() const noexcept
     478             : {
     479        5807 :     if(impl_)
     480             :     {
     481             :         // using the offset array here
     482        2267 :         auto pos = impl_->offset_[id_query];
     483        2267 :         auto pos1 = impl_->offset_[id_frag];
     484        2267 :         if(pos < pos1)
     485        2267 :             return impl_->cs_ + pos + 1; // no '?'
     486             :         // empty
     487           0 :         return impl_->cs_ + pos;
     488             :     }
     489        3540 :     return data_;
     490             : 
     491             : }
     492             : 
     493             : char const*
     494        2282 : query_ref::
     495             : end() const noexcept
     496             : {
     497        2282 :     if(impl_)
     498         902 :         return impl_->cs_ +
     499         902 :             impl_->offset(id_frag);
     500        1380 :     return data_ + size_;
     501             : }
     502             : 
     503             : std::size_t
     504        8878 : query_ref::
     505             : nparam() const noexcept
     506             : {
     507        8878 :     if(impl_)
     508        3134 :         return impl_->nparam_;
     509        5744 :     return nparam_;
     510             : }
     511             : 
     512             : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
     513             : #pragma GCC diagnostic pop
     514             : #endif
     515             : 
     516             : } // detail
     517             : } // urls
     518             : } // boost
     519             : 
     520             : #endif

Generated by: LCOV version 1.15