GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/detail/segments_range.hpp
Date: 2025-11-10 19:06:22
Exec Total Coverage
Lines: 39 39 100.0%
Functions: 5 5 100.0%
Branches: 18 22 81.8%

Line Branch Exec Source
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
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
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
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 17 times.
23 if (nseg == 0)
59 {
60 std::size_t off0;
61
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (i0 == 0)
62 {
63 // [begin, begin): don't include the leading '/'
64 // for absolute, start right after the leading '/';
65
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
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
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (i0 == 0)
90 {
91
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
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
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 8 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
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
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
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
147