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: 203 207 98.1 %
Date: 2024-02-29 20:02:55 Functions: 34 34 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 "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        2249 : url_impl::
      37             : apply_scheme(
      38             :     core::string_view s) noexcept
      39             : {
      40        2249 :     scheme_ = string_to_scheme(s);
      41        2249 :     set_size(id_scheme, s.size() + 1);
      42        2249 : }
      43             : 
      44             : void
      45         380 : 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         380 :     BOOST_ASSERT(from_ == from::authority);
      53             : 
      54             :     // userinfo
      55         380 :     set_size(id_user, user.size());
      56         380 :     decoded_[id_user] =
      57         380 :         user.decoded_size();
      58         380 :     if(pass)
      59             :     {
      60         251 :         set_size(id_pass,
      61         251 :             pass->size() + 2);
      62         251 :         decoded_[id_pass] =
      63         251 :             pass->decoded_size();
      64             :     }
      65             :     else
      66             :     {
      67             :         // trailing '@'
      68         129 :         set_size(id_pass, 1 );
      69             :     }
      70         380 : }
      71             : 
      72             : void
      73        1848 : 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        1848 :     BOOST_ASSERT(from_ == from::authority);
      82             : 
      83             :     // host, port
      84        1848 :     host_type_ = ht;
      85        1848 :     set_size(id_host, s.size());
      86        1848 :     decoded_[id_host] =
      87        1848 :         s.decoded_size();
      88        1848 :     std::memcpy(
      89        1848 :         ip_addr_,
      90             :         addr,
      91             :         sizeof(ip_addr_));
      92        1848 : }
      93             : 
      94             : void
      95         247 : 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         247 :     BOOST_ASSERT(from_ == from::authority);
     103             : 
     104         247 :     port_number_ = pn;
     105         247 :     set_size(id_port, 1 + s.size());
     106         247 : }
     107             : 
     108             : void
     109        1792 : url_impl::
     110             : apply_authority(
     111             :     authority_view const& a) noexcept
     112             : {
     113        1792 :     BOOST_ASSERT(from_ != from::authority);
     114             : 
     115             :     // userinfo
     116        1792 :     set_size(id_user,
     117        1792 :         a.u_.len(id_user) +
     118        1792 :         (from_ == from::authority ? 0 : 2));
     119        1792 :     set_size(id_pass, a.u_.len(id_pass));
     120        1792 :     decoded_[id_user] = a.u_.decoded_[id_user];
     121        1792 :     decoded_[id_pass] = a.u_.decoded_[id_pass];
     122             : 
     123             :     // host, port
     124        1792 :     host_type_ = a.u_.host_type_;
     125        1792 :     port_number_ = a.u_.port_number_;
     126        1792 :     set_size(id_host, a.u_.len(id_host));
     127        1792 :     set_size(id_port, a.u_.len(id_port));
     128        1792 :     std::memcpy(
     129        1792 :         ip_addr_,
     130        1792 :         a.u_.ip_addr_,
     131             :         sizeof(ip_addr_));
     132        1792 :     decoded_[id_host] = a.u_.decoded_[id_host];
     133        1792 : }
     134             : 
     135             : void
     136        3523 : url_impl::
     137             : apply_path(
     138             :     pct_string_view s,
     139             :     std::size_t nseg) noexcept
     140             : {
     141        3523 :     set_size(id_path, s.size());
     142        3523 :     decoded_[id_path] = s.decoded_size();
     143        3523 :     nseg_ = detail::path_segments(s, nseg);
     144        3523 : }
     145             : 
     146             : void
     147         430 : url_impl::
     148             : apply_query(
     149             :     pct_string_view s,
     150             :     std::size_t n) noexcept
     151             : {
     152         430 :     nparam_ = n;
     153         430 :     set_size(id_query, 1 + s.size());
     154         430 :     decoded_[id_query] = s.decoded_size();
     155         430 : }
     156             : 
     157             : void
     158         210 : url_impl::
     159             : apply_frag(
     160             :     pct_string_view s) noexcept
     161             : {
     162         210 :     set_size(id_frag, s.size() + 1);
     163         210 :     decoded_[id_frag] = s.decoded_size();
     164         210 : }
     165             : 
     166             : // return length of [first, last)
     167             : auto
     168       20187 : url_impl::
     169             : len(
     170             :     int first,
     171             :     int last) const noexcept ->
     172             :         std::size_t
     173             : {
     174       20187 :     BOOST_ASSERT(first <= last);
     175       20187 :     BOOST_ASSERT(last <= id_end);
     176       20187 :     return offset(last) - offset(first);
     177             : }
     178             : 
     179             : // return length of part
     180             : auto
     181      262748 : url_impl::
     182             : len(int id) const noexcept ->
     183             :     std::size_t
     184             : {
     185             :     return id == id_end
     186      525496 :         ? zero_
     187      262748 :         : ( offset(id + 1) -
     188      525496 :             offset(id) );
     189             : }
     190             : 
     191             : // return offset of id
     192             : auto
     193      688690 : url_impl::
     194             : offset(int id) const noexcept ->
     195             :     std::size_t
     196             : {
     197             :     return
     198             :         id == id_scheme
     199      688690 :         ? zero_
     200      688690 :         : offset_[id];
     201             : }
     202             : 
     203             : // return id as string
     204             : core::string_view
     205       46519 : url_impl::
     206             : get(int id) const noexcept
     207             : {
     208             :     return {
     209       46519 :         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        2085 : url_impl::
     225             : pct_get(
     226             :     int id) const noexcept
     227             : {
     228             :     return make_pct_string_view_unsafe(
     229        2085 :         cs_ + offset(id),
     230             :         len(id),
     231        4170 :         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       18762 : url_impl::
     256             : set_size(
     257             :     int id,
     258             :     std::size_t n) noexcept
     259             : {
     260       18762 :     auto d = n - len(id);
     261       18762 :     for(auto i = id + 1;
     262      113823 :         i <= id_end; ++i)
     263       95061 :         offset_[i] += d;
     264       18762 : }
     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         911 : url_impl::
     282             : adjust_right(
     283             :     int first,
     284             :     int last,
     285             :     std::size_t n) noexcept
     286             : {
     287         911 :     for(int i = first;
     288        5305 :             i <= last; ++i)
     289        4394 :         offset_[i] += n;
     290         911 : }
     291             : 
     292             : // remove n from [first, last]
     293             : void
     294         676 : url_impl::
     295             : adjust_left(
     296             :     int first,
     297             :     int last,
     298             :     std::size_t n) noexcept
     299             : {
     300         676 :     for(int i = first;
     301        3333 :             i <= last; ++i)
     302        2657 :         offset_[i] -= n;
     303         676 : }
     304             : 
     305             : // set [first, last) offset
     306             : void
     307        1568 : url_impl::
     308             : collapse(
     309             :     int first,
     310             :     int last,
     311             :     std::size_t n) noexcept
     312             : {
     313        1568 :     for(int i = first + 1;
     314        2113 :             i < last; ++i)
     315         545 :         offset_[i] = n;
     316        1568 : }
     317             : 
     318             : 
     319             : //------------------------------------------------
     320             : //
     321             : // path_ref
     322             : //
     323             : //------------------------------------------------
     324             : 
     325        2017 : path_ref::
     326             : path_ref(
     327        2017 :     url_impl const& impl) noexcept
     328             : {
     329        2017 :     if(impl.from_ == url_impl::from::url)
     330             :     {
     331        1569 :         impl_ = &impl;
     332             :     }
     333             :     else
     334             :     {
     335         448 :         core::string_view s = impl.get(id_path);
     336         448 :         data_ = s.data();
     337         448 :         size_ = s.size();
     338         448 :         nseg_ = impl.nseg_;
     339         448 :         dn_ = impl.decoded_[id_path];
     340             :     }
     341        2017 : }
     342             : 
     343         141 : path_ref::
     344             : path_ref(
     345             :     core::string_view s,
     346             :     std::size_t dn,
     347         141 :     std::size_t nseg) noexcept
     348         141 :     : data_(s.data())
     349         141 :     , size_(s.size())
     350             :     , nseg_(nseg)
     351         141 :     , dn_(dn)
     352             : {
     353         141 : }
     354             : 
     355             : pct_string_view
     356        4475 : path_ref::
     357             : buffer() const noexcept
     358             : {
     359        4475 :     if(impl_)
     360             :         return make_pct_string_view_unsafe(
     361        2321 :             impl_->cs_ +
     362        2321 :                 impl_->offset(id_path),
     363        2321 :             impl_->len(id_path),
     364        4642 :             impl_->decoded_[id_path]);
     365             :     return make_pct_string_view_unsafe(
     366        2154 :         data_, size_, dn_);
     367             : }
     368             : 
     369             : std::size_t
     370        3899 : path_ref::
     371             : size() const noexcept
     372             : {
     373        3899 :     if(impl_)
     374        2657 :         return impl_->len(id_path);
     375        1242 :     return size_;
     376             : }
     377             : 
     378             : char const*
     379       12602 : path_ref::
     380             : data() const noexcept
     381             : {
     382       12602 :     if(impl_)
     383        7447 :         return impl_->cs_ +
     384        7447 :             impl_->offset(id_path);
     385        5155 :     return data_;
     386             : }
     387             : 
     388             : char const*
     389        4397 : path_ref::
     390             : end() const noexcept
     391             : {
     392        4397 :     if(impl_)
     393        2945 :         return impl_->cs_ +
     394        2945 :             impl_->offset(id_query);
     395        1452 :     return data_ + size_;
     396             : }
     397             : 
     398             : std::size_t
     399        8630 : path_ref::
     400             : nseg() const noexcept
     401             : {
     402        8630 :     if(impl_)
     403        5508 :         return impl_->nseg_;
     404        3122 :     return nseg_;
     405             : }
     406             : 
     407             : //------------------------------------------------
     408             : //
     409             : // query_ref
     410             : //
     411             : //------------------------------------------------
     412             : 
     413         674 : query_ref::
     414             : query_ref(
     415             :     core::string_view s,
     416             :     std::size_t dn,
     417         674 :     std::size_t nparam) noexcept
     418         674 :     : data_(s.data())
     419         674 :     , size_(s.size())
     420             :     , nparam_(nparam)
     421         674 :     , dn_(dn)
     422             : {
     423         674 : }
     424             : 
     425         425 : query_ref::
     426             : query_ref(
     427         425 :     url_impl const& impl) noexcept
     428             : {
     429         425 :     if(impl.from_ == url_impl::from::url)
     430             :     {
     431         344 :         impl_ = &impl;
     432             :     }
     433             :     else
     434             :     {
     435          81 :         core::string_view s = impl.get(id_query);
     436          81 :         if (!s.empty())
     437             :         {
     438          79 :             s.remove_prefix(1);
     439          79 :             question_mark_ = true;
     440             :         }
     441          81 :         data_ = s.data();
     442          81 :         size_ = s.size();
     443          81 :         nparam_ = impl.nparam_;
     444          81 :         dn_ = impl.decoded_[id_query];
     445             :     }
     446         425 : }
     447             : 
     448             : pct_string_view
     449         454 : query_ref::
     450             : buffer() const noexcept
     451             : {
     452         454 :     if(impl_)
     453             :     {
     454           2 :         auto pos = impl_->offset_[id_query];
     455           2 :         auto pos1 = impl_->offset_[id_frag];
     456           2 :         if(pos < pos1)
     457             :         {
     458           0 :             ++pos; // no '?'
     459             :             return make_pct_string_view_unsafe(
     460           0 :                 impl_->cs_ + pos,
     461             :                 pos1 - pos,
     462           0 :                 impl_->decoded_[id_query]);
     463             :         }
     464             :         // empty
     465             :         return make_pct_string_view_unsafe(
     466           2 :             impl_->cs_ + pos,
     467             :             0,
     468           2 :             0);
     469             :     }
     470             :     // no '?'
     471             :     return make_pct_string_view_unsafe(
     472         452 :         data_, size_, dn_);
     473             : }
     474             : 
     475             : // with '?'
     476             : std::size_t
     477        5282 : query_ref::
     478             : size() const noexcept
     479             : {
     480        5282 :     if(impl_)
     481        1990 :         return impl_->len(id_query);
     482        3292 :     if(size_ > 0)
     483        3264 :         return size_ + 1;
     484          28 :     return question_mark_;
     485             : }
     486             : 
     487             : // no '?'
     488             : char const*
     489        5807 : query_ref::
     490             : begin() const noexcept
     491             : {
     492        5807 :     if(impl_)
     493             :     {
     494             :         // using the offset array here
     495        2267 :         auto pos = impl_->offset_[id_query];
     496        2267 :         auto pos1 = impl_->offset_[id_frag];
     497        2267 :         if(pos < pos1)
     498        2267 :             return impl_->cs_ + pos + 1; // no '?'
     499             :         // empty
     500           0 :         return impl_->cs_ + pos;
     501             :     }
     502        3540 :     return data_;
     503             : 
     504             : }
     505             : 
     506             : char const*
     507        2282 : query_ref::
     508             : end() const noexcept
     509             : {
     510        2282 :     if(impl_)
     511         902 :         return impl_->cs_ +
     512         902 :             impl_->offset(id_frag);
     513        1380 :     return data_ + size_;
     514             : }
     515             : 
     516             : std::size_t
     517        8886 : query_ref::
     518             : nparam() const noexcept
     519             : {
     520        8886 :     if(impl_)
     521        3134 :         return impl_->nparam_;
     522        5752 :     return nparam_;
     523             : }
     524             : 
     525             : #if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__)
     526             : #pragma GCC diagnostic pop
     527             : #endif
     528             : 
     529             : } // detail
     530             : } // urls
     531             : } // boost
     532             : 
     533             : #endif

Generated by: LCOV version 1.15