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 % 39 39
Test Date: 2025-11-10 19:06:20 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           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.1