GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/detail/segments_range.hpp
Date: 2025-10-23 13:40:33
Exec Total Coverage
Lines: 45 45 100.0%
Functions: 5 5 100.0%
Branches: 19 22 86.4%

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 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
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
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
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13 times.
19 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 13 bool include_leading_slash = false;
90
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5 times.
13 if (i0 == 0)
91 {
92
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
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
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 6 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
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
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 13 times.
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
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
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
164