LCOV - code coverage report
Current view: top level - boost/url/detail/segments_range.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 45 45
Test Date: 2025-10-23 13:40:31 Functions: 100.0 % 5 5

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2025 Alan de Freitas (alandefreitas@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_SEGMENTS_RANGE_HPP
      11              : #define BOOST_URL_DETAIL_SEGMENTS_RANGE_HPP
      12              : 
      13              : #include <boost/url/detail/config.hpp>
      14              : #include <boost/url/detail/url_impl.hpp>
      15              : #include <boost/url/segments_base.hpp>
      16              : #include <boost/url/segments_encoded_base.hpp>
      17              : #include <boost/core/detail/string_view.hpp>
      18              : #include <boost/assert.hpp>
      19              : 
      20              : namespace boost {
      21              : namespace urls {
      22              : namespace detail {
      23              : 
      24              : struct segments_iter_access
      25              : {
      26              :     static
      27              :     segments_iter_impl const&
      28           36 :     impl(segments_base::iterator const& it) noexcept
      29              :     {
      30           36 :         return it.it_;
      31              :     }
      32              : 
      33              :     static
      34              :     segments_iter_impl const&
      35            2 :     impl(segments_encoded_base::iterator const& it) noexcept
      36              :     {
      37            2 :         return it.it_;
      38              :     }
      39              : };
      40              : 
      41              : inline
      42              : path_ref
      43           19 : make_subref_from_impls(
      44              :     segments_iter_impl const& first,
      45              :     segments_iter_impl const& last) noexcept
      46              : {
      47           19 :     BOOST_ASSERT(first.ref.alias_of(last.ref));
      48           19 :     path_ref const& ref = first.ref;
      49              : 
      50           19 :     std::size_t const i0 = first.index;
      51           19 :     std::size_t const i1 = last.index;
      52           19 :     BOOST_ASSERT(i0 <= i1);
      53           19 :     std::size_t const nseg = i1 - i0;
      54              : 
      55           19 :     bool const absolute = ref.buffer().starts_with('/');
      56              : 
      57              :     // Empty range
      58           19 :     if (nseg == 0)
      59              :     {
      60              :         std::size_t off0;
      61            6 :         if (i0 == 0)
      62              :         {
      63              :             // [begin, begin): don't include the leading '/'
      64              :             // for absolute, start right after the leading '/';
      65            3 :             if (absolute)
      66              :             {
      67            2 :                 off0 = 1;
      68              :             }
      69              :             // for relative, start at the first segment character.
      70              :             else
      71              :             {
      72            1 :                 off0 = first.pos;
      73              :             }
      74              :         }
      75              :         else
      76              :         {
      77              :             // [it, it) in the middle:
      78              :             // skip the separator before segment i0
      79            3 :             off0 = first.pos + 1;
      80              :         }
      81              : 
      82            6 :         core::string_view const sub(ref.data() + off0, 0);
      83            6 :         return {sub, 0, 0};
      84              :     }
      85              : 
      86              :     // General case: non-empty range
      87              :     // Start offset
      88              :     std::size_t off0;
      89           13 :     bool include_leading_slash = false;
      90           13 :     if (i0 == 0)
      91              :     {
      92            8 :         if (absolute)
      93              :         {
      94              :             // include leading '/'
      95            5 :             off0 = 0;
      96            5 :             include_leading_slash = true;
      97              :         }
      98              :         else
      99              :         {
     100              :             // relative: start at first segment
     101            3 :             off0 = first.pos;
     102              :         }
     103              :     }
     104              :     else
     105              :     {
     106              :         // skip slash before segment i0
     107            5 :         off0 = first.pos + 1;
     108              :     }
     109              : 
     110              :     // End offset
     111              :     std::size_t off1;
     112           13 :     if(i1 == ref.nseg())
     113              :     {
     114            7 :         off1 = ref.size();
     115              :     }
     116              :     else
     117              :     {
     118              :         // stop before the slash preceding i1
     119            6 :         off1 = last.pos;
     120              :     }
     121              : 
     122           13 :     BOOST_ASSERT(off1 >= off0);
     123           13 :     core::string_view const sub(ref.data() + off0, off1 - off0);
     124              : 
     125              :     // Decoded-length:
     126              :     // sum per-segment decoded lengths + internal '/' + the leading '/'.
     127           13 :     std::size_t dn_sum = 0;
     128              :     {
     129              :         // copy to iterate
     130           13 :         segments_iter_impl cur = first;
     131           37 :         for (std::size_t k = 0; k < nseg; ++k)
     132              :         {
     133              :             // per-segment decoded length
     134           24 :             dn_sum += cur.dn;
     135           24 :             cur.increment();
     136              :         }
     137              :         // internal '/'s
     138           13 :         dn_sum += (nseg - 1);
     139              :         // leading '/'
     140           13 :         if (include_leading_slash)
     141              :         {
     142            5 :             ++dn_sum;
     143              :         }
     144              :     }
     145              : 
     146           13 :     return {sub, dn_sum, nseg};
     147              : }
     148              : 
     149              : template<class Iter>
     150              : inline
     151              : path_ref
     152           19 : make_subref(Iter const& first, Iter const& last) noexcept
     153              : {
     154           19 :     auto const& f = segments_iter_access::impl(first);
     155           19 :     auto const& l = segments_iter_access::impl(last);
     156           19 :     return make_subref_from_impls(f, l);
     157              : }
     158              : 
     159              : } // detail
     160              : } // urls
     161              : } // boost
     162              : 
     163              : #endif
        

Generated by: LCOV version 2.1