LCOV - code coverage report
Current view: top level - url/detail - segments_range.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 39 39
Test Date: 2026-02-25 21:00:01 Functions: 100.0 % 5 5

           TLA  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 HIT          40 :     impl(segments_base::iterator const& it) noexcept
      29                 :     {
      30              40 :         return it.it_;
      31                 :     }
      32                 : 
      33                 :     static
      34                 :     segments_iter_impl const&
      35               6 :     impl(segments_encoded_base::iterator const& it) noexcept
      36                 :     {
      37               6 :         return it.it_;
      38                 :     }
      39                 : };
      40                 : 
      41                 : inline
      42                 : path_ref
      43              23 : make_subref_from_impls(
      44                 :     segments_iter_impl const& first,
      45                 :     segments_iter_impl const& last) noexcept
      46                 : {
      47              23 :     BOOST_ASSERT(first.ref.alias_of(last.ref));
      48              23 :     path_ref const& ref = first.ref;
      49                 : 
      50              23 :     std::size_t const i0 = first.index;
      51              23 :     std::size_t const i1 = last.index;
      52              23 :     BOOST_ASSERT(i0 <= i1);
      53              23 :     std::size_t const nseg = i1 - i0;
      54                 : 
      55              23 :     bool const absolute = ref.buffer().starts_with('/');
      56                 : 
      57                 :     // Empty range
      58              23 :     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              17 :     if (i0 == 0)
      90                 :     {
      91              10 :         if (absolute)
      92                 :         {
      93                 :             // include leading '/'
      94               5 :             off0 = 0;
      95                 :         }
      96                 :         else
      97                 :         {
      98                 :             // relative: start at first segment
      99               5 :             off0 = first.pos;
     100                 :         }
     101                 :     }
     102                 :     else
     103                 :     {
     104                 :         // include the separator preceding segment i0
     105               7 :         off0 = first.pos;
     106                 :     }
     107                 : 
     108                 :     // End offset
     109                 :     std::size_t off1;
     110              17 :     if(i1 == ref.nseg())
     111                 :     {
     112               9 :         off1 = ref.size();
     113                 :     }
     114                 :     else
     115                 :     {
     116                 :         // stop before the slash preceding i1
     117               8 :         off1 = last.pos;
     118                 :     }
     119                 : 
     120              17 :     BOOST_ASSERT(off1 >= off0);
     121              17 :     core::string_view const sub(ref.data() + off0, off1 - off0);
     122                 : 
     123                 :     // decoded sizes reuse iterator bookkeeping instead of rescanning
     124              17 :     std::size_t start_dn = (i0 == 0) ? 0 : first.decoded_prefix_size();
     125              17 :     std::size_t const end_dn = last.decoded_prefix_size(); // already excludes segment at `last`
     126              17 :     BOOST_ASSERT(end_dn >= start_dn);
     127              17 :     std::size_t const dn_sum = end_dn - start_dn;
     128                 : 
     129              17 :     return {sub, dn_sum, nseg};
     130                 : }
     131                 : 
     132                 : template<class Iter>
     133                 : inline
     134                 : path_ref
     135              23 : make_subref(Iter const& first, Iter const& last) noexcept
     136                 : {
     137              23 :     auto const& f = segments_iter_access::impl(first);
     138              23 :     auto const& l = segments_iter_access::impl(last);
     139              23 :     return make_subref_from_impls(f, l);
     140                 : }
     141                 : 
     142                 : } // detail
     143                 : } // urls
     144                 : } // boost
     145                 : 
     146                 : #endif
        

Generated by: LCOV version 2.3