GCC Code Coverage Report


Directory: libs/url/
File: boost/url/detail/any_segments_iter.hpp
Date: 2024-07-10 02:48:28
Exec Total Coverage
Lines: 66 67 98.5%
Functions: 32 33 97.0%
Branches: 19 24 79.2%

Line Branch Exec Source
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@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_ANY_SEGMENTS_ITER_HPP
11 #define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
12
13 #include <boost/url/pct_string_view.hpp>
14 #include <boost/static_assert.hpp>
15 #include <cstddef>
16 #include <iterator>
17 #include <type_traits>
18
19 namespace boost {
20 namespace urls {
21 namespace detail {
22
23 struct BOOST_SYMBOL_VISIBLE
24 any_segments_iter
25 {
26 protected:
27 explicit
28 610 any_segments_iter(
29 core::string_view s_ = {}) noexcept
30 610 : s(s_)
31 {
32 610 }
33
34 1220 virtual ~any_segments_iter() = default;
35
36 public:
37 // this is adjusted
38 // when self-intersecting
39 core::string_view s;
40
41 // the first segment,
42 // to handle special cases
43 core::string_view front;
44
45 // quick number of segments
46 // 0 = zero
47 // 1 = one
48 // 2 = two, or more
49 int fast_nseg = 0;
50
51 // whether the segments should encode colons
52 // when we measure and copy. the calling
53 // function uses this for the first
54 // segment in some cases, such as:
55 // "x:y:z" -> remove_scheme -> "y%3Az"
56 // as "y:z" would no longer represent a path
57 bool encode_colons = false;
58
59 // Rewind the iterator to the beginning
60 virtual void rewind() noexcept = 0;
61
62 // Measure and increment the current
63 // element. n is increased by the
64 // encoded size. Returns false on
65 // end of range.
66 virtual bool measure(std::size_t& n) = 0;
67
68 // Copy and increment the current
69 // element, encoding as needed.
70 virtual void copy(char*& dest,
71 char const* end) noexcept = 0;
72 };
73
74 //------------------------------------------------
75 //
76 // segment_iter
77 //
78 //------------------------------------------------
79
80 // A 1-segment range
81 // allowing self-intersection
82 struct BOOST_SYMBOL_VISIBLE
83 segment_iter
84 : any_segments_iter
85 {
86 148 virtual ~segment_iter() = default;
87
88 explicit
89 segment_iter(
90 core::string_view s) noexcept;
91
92 private:
93 bool at_end_ = false;
94 void rewind() noexcept override;
95 bool measure(std::size_t&) noexcept override;
96 void copy(char*&, char const*) noexcept override;
97 };
98
99 //------------------------------------------------
100 //
101 // segments_iter
102 //
103 //------------------------------------------------
104
105 struct segments_iter_base
106 {
107 protected:
108 BOOST_URL_DECL static void
109 measure_impl(std::size_t&,
110 core::string_view, bool) noexcept;
111 BOOST_URL_DECL static void
112 copy_impl(char*&, char const*,
113 core::string_view, bool) noexcept;
114 };
115
116 // iterates segments in a
117 // plain segment range
118 template<class FwdIt>
119 struct segments_iter
120 : any_segments_iter
121 , segments_iter_base
122 {
123 BOOST_STATIC_ASSERT(
124 std::is_convertible<
125 typename std::iterator_traits<
126 FwdIt>::reference,
127 core::string_view>::value);
128
129 129 segments_iter(
130 FwdIt first,
131 FwdIt last) noexcept
132 129 : it_(first)
133 129 , it0_(first)
134 129 , end_(last)
135 {
136
2/3
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
129 if(first != last)
137 {
138 129 front = *first;
139 129 auto it = first;
140
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
129 if(++it == last)
141 16 fast_nseg = 1;
142 else
143 113 fast_nseg = 2;
144 }
145 else
146 {
147 fast_nseg = 0;
148 }
149 129 }
150
151 private:
152 FwdIt it_;
153 FwdIt it0_;
154 FwdIt end_;
155
156 void
157 129 rewind() noexcept override
158 {
159 129 it_ = it0_;
160 129 }
161
162 bool
163 433 measure(
164 std::size_t& n) noexcept override
165 {
166
3/3
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 184 times.
✓ Branch 2 taken 6 times.
433 if(it_ == end_)
167 129 return false;
168 304 measure_impl(n,
169 292 detail::to_sv(*it_),
170 304 encode_colons);
171 304 ++it_;
172 304 return true;
173 }
174
175 void
176 304 copy(
177 char*& dest,
178 char const* end) noexcept override
179 {
180 304 copy_impl(dest, end,
181 316 detail::to_sv(*it_++),
182 304 encode_colons);
183 304 }
184 };
185
186 //------------------------------------------------
187 //
188 // segment_encoded_iter
189 //
190 //------------------------------------------------
191
192 // A 1-segment range
193 // allowing self-intersection
194 struct BOOST_SYMBOL_VISIBLE
195 segment_encoded_iter
196 : any_segments_iter
197 {
198 144 virtual ~segment_encoded_iter() = default;
199
200 explicit
201 segment_encoded_iter(
202 pct_string_view const& s) noexcept;
203
204 private:
205 bool at_end_ = false;
206 void rewind() noexcept override;
207 bool measure(std::size_t&) noexcept override;
208 void copy(char*&, char const*) noexcept override;
209 };
210
211 //------------------------------------------------
212 //
213 // segments_encoded_iter
214 //
215 //------------------------------------------------
216
217 // Validating and copying from
218 // a string of encoded segments
219 struct segments_encoded_iter_base
220 {
221 protected:
222 BOOST_URL_DECL static void
223 measure_impl(std::size_t&,
224 core::string_view, bool) noexcept;
225 BOOST_URL_DECL static void
226 copy_impl(char*&, char const*,
227 core::string_view, bool) noexcept;
228 };
229
230 // iterates segments in an
231 // encoded segment range
232 template<class FwdIt>
233 struct segments_encoded_iter
234 : public any_segments_iter
235 , public segments_encoded_iter_base
236 {
237 BOOST_STATIC_ASSERT(
238 std::is_convertible<
239 typename std::iterator_traits<
240 FwdIt>::reference,
241 core::string_view>::value);
242
243 415 segments_encoded_iter(
244 FwdIt first,
245 FwdIt last)
246 415 : it_(first)
247 415 , it0_(first)
248 415 , end_(last)
249 {
250
2/3
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 314 times.
✗ Branch 2 not taken.
415 if(it_ != end_)
251 {
252 // throw on invalid input
253
2/2
✓ Branch 2 taken 183 times.
✓ Branch 3 taken 13 times.
226 front = pct_string_view(
254 125 detail::to_sv(*first));
255 213 auto it = first;
256
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 60 times.
213 if(++it == last)
257 65 fast_nseg = 1;
258 else
259 148 fast_nseg = 2;
260 }
261 else
262 {
263 189 fast_nseg = 0;
264 }
265 415 }
266
267 private:
268 FwdIt it_;
269 FwdIt it0_;
270 FwdIt end_;
271
272 void
273 400 rewind() noexcept override
274 {
275 400 it_ = it0_;
276 400 }
277
278 bool
279 876 measure(
280 std::size_t& n) override
281 {
282
3/3
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 268 times.
✓ Branch 2 taken 258 times.
876 if(it_ == end_)
283 400 return false;
284 // throw on invalid input
285 474 measure_impl(n,
286
1/2
✓ Branch 2 taken 258 times.
✗ Branch 3 not taken.
476 pct_string_view(
287 476 detail::to_sv(*it_++)),
288 476 encode_colons);
289 474 return true;
290 }
291
292 void
293 472 copy(
294 char*& dest,
295 char const* end) noexcept override
296 {
297 472 copy_impl(dest, end,
298 472 detail::to_sv(*it_++),
299 472 encode_colons);
300 472 }
301 };
302
303 //------------------------------------------------
304
305 template<class FwdIt>
306 segments_iter<FwdIt>
307 129 make_segments_iter(
308 FwdIt first, FwdIt last)
309 {
310 return segments_iter<
311 129 FwdIt>(first, last);
312 }
313
314 template<class FwdIt>
315 segments_encoded_iter<FwdIt>
316 385 make_segments_encoded_iter(
317 FwdIt first, FwdIt last)
318 {
319 return segments_encoded_iter<
320 385 FwdIt>(first, last);
321 }
322
323 } // detail
324 } // urls
325 } // boost
326
327 #endif
328