GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/detail/any_params_iter.hpp
Date: 2025-11-10 19:06:22
Exec Total Coverage
Lines: 61 61 100.0%
Functions: 26 26 100.0%
Branches: 9 10 90.0%

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_PARAMS_ITER_HPP
11 #define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
12
13 #include <boost/url/param.hpp>
14 #include <boost/url/pct_string_view.hpp>
15 #include <boost/core/detail/static_assert.hpp>
16 #include <cstddef>
17 #include <iterator>
18 #include <type_traits>
19
20 namespace boost {
21 namespace urls {
22 namespace detail {
23
24 //------------------------------------------------
25 //
26 // any_params_iter
27 //
28 //------------------------------------------------
29
30 /* An iterator to a type-erased,
31 possibly encoded sequence of
32 query params_ref.
33 */
34 struct BOOST_SYMBOL_VISIBLE
35 any_params_iter
36 {
37 protected:
38 143 any_params_iter(
39 bool empty_,
40 core::string_view s0_ = {},
41 core::string_view s1_ = {}) noexcept
42 143 : s0(s0_)
43 143 , s1(s1_)
44 143 , empty(empty_)
45 {
46 143 }
47
48 public:
49 // these are adjusted
50 // when self-intersecting
51 core::string_view s0;
52 core::string_view s1;
53
54 // True if the sequence is empty
55 bool empty = false;
56
57 BOOST_URL_DECL
58 virtual
59 ~any_params_iter() noexcept = 0;
60
61 // Rewind the iterator to the beginning
62 virtual
63 void
64 rewind() noexcept = 0;
65
66 // Measure and increment current element.
67 // Returns false on end of range.
68 // n is increased by encoded size.
69 // Can throw on bad percent-escape
70 virtual
71 bool
72 measure(std::size_t& n) = 0;
73
74 // Copy and increment the current
75 // element. encoding is performed
76 // if needed.
77 virtual
78 void
79 copy(
80 char*& dest,
81 char const* end) noexcept = 0;
82 };
83
84 //------------------------------------------------
85 //
86 // query_string_iter
87 //
88 //------------------------------------------------
89
90 // A string of plain query params
91 struct BOOST_SYMBOL_VISIBLE
92 query_string_iter
93 : any_params_iter
94 {
95 // ne = never empty
96 BOOST_URL_DECL
97 explicit
98 query_string_iter(
99 core::string_view s,
100 bool ne = false) noexcept;
101
102 private:
103 core::string_view s_;
104 std::size_t n_;
105 char const* p_;
106 bool at_end_;
107
108 void rewind() noexcept override;
109 bool measure(std::size_t&) noexcept override;
110 void copy(char*&, char const*) noexcept override;
111 void increment() noexcept;
112 };
113
114 //------------------------------------------------
115 //
116 // param_iter
117 //
118 //------------------------------------------------
119
120 // A 1-param range allowing
121 // self-intersection
122 struct BOOST_SYMBOL_VISIBLE
123 single_param_iter
124 : any_params_iter
125 {
126 explicit
127 single_param_iter(
128 param_view const&,
129 bool space_as_plus) noexcept;
130
131 private:
132 bool has_value_;
133 bool at_end_ = false;
134 bool space_as_plus_ = false;
135
136 void rewind() noexcept override;
137 bool measure(std::size_t&) noexcept override;
138 void copy(char*&, char const*) noexcept override;
139 };
140
141 //------------------------------------------------
142 //
143 // params_iter_base
144 //
145 //------------------------------------------------
146
147 struct params_iter_base
148 {
149 bool space_as_plus_ = true;
150 protected:
151 32 explicit params_iter_base(
152 bool space_as_plus) noexcept
153 32 : space_as_plus_(space_as_plus)
154 32 {}
155
156 // return encoded size
157 BOOST_URL_DECL
158 void
159 measure_impl(
160 std::size_t& n,
161 param_view const& p) noexcept;
162
163 // encode to dest
164 BOOST_URL_DECL
165 void
166 copy_impl(
167 char*& dest,
168 char const* end,
169 param_view const& v) noexcept;
170 };
171
172 //------------------------------------------------
173
174 // A range of plain query params_ref
175 template<class FwdIt>
176 struct params_iter
177 : any_params_iter
178 , private params_iter_base
179 {
180 BOOST_CORE_STATIC_ASSERT(
181 std::is_convertible<
182 typename std::iterator_traits<
183 FwdIt>::reference,
184 param_view>::value);
185
186 34 params_iter(
187 FwdIt first,
188 FwdIt last,
189 bool space_as_plus) noexcept
190 : any_params_iter(
191 2 first == last)
192 , params_iter_base(space_as_plus)
193 34 , it0_(first)
194 34 , it_(first)
195 36 , end_(last)
196 {
197 34 }
198
199 private:
200 FwdIt it0_;
201 FwdIt it_;
202 FwdIt end_;
203
204 void
205 34 rewind() noexcept override
206 {
207 34 it_ = it0_;
208 34 }
209
210 bool
211 106 measure(
212 std::size_t& n) noexcept override
213 {
214
3/3
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 1 times.
106 if(it_ == end_)
215 34 return false;
216 72 measure_impl(n,
217 74 param_view(*it_++));
218 72 return true;
219 }
220
221 void
222 72 copy(
223 char*& dest,
224 char const* end) noexcept override
225 {
226 72 copy_impl(dest, end,
227 74 param_view(*it_++));
228 72 }
229 };
230
231 //------------------------------------------------
232 //
233 // param_encoded_iter
234 //
235 //------------------------------------------------
236
237 // A 1-param encoded range
238 // allowing self-intersection
239 struct BOOST_SYMBOL_VISIBLE
240 param_encoded_iter
241 : any_params_iter
242 {
243 explicit
244 param_encoded_iter(
245 param_pct_view const&) noexcept;
246
247 private:
248 bool has_value_;
249 bool at_end_ = false;
250
251 void rewind() noexcept override;
252 bool measure(std::size_t&) noexcept override;
253 void copy(char*&, char const*) noexcept override;
254 };
255
256 //------------------------------------------------
257 //
258 // params_encoded_iter
259 //
260 //------------------------------------------------
261
262 // Validating and copying from
263 // a string of encoded params
264 struct params_encoded_iter_base
265 {
266 protected:
267 BOOST_URL_DECL
268 static
269 void
270 measure_impl(
271 std::size_t& n,
272 param_view const& v) noexcept;
273
274 BOOST_URL_DECL
275 static
276 void
277 copy_impl(
278 char*& dest,
279 char const* end,
280 param_view const& v) noexcept;
281 };
282
283 //------------------------------------------------
284
285 // A range of encoded query params_ref
286 template<class FwdIt>
287 struct params_encoded_iter
288 : any_params_iter
289 , private params_encoded_iter_base
290 {
291 BOOST_CORE_STATIC_ASSERT(
292 std::is_convertible<
293 typename std::iterator_traits<
294 FwdIt>::reference,
295 param_view>::value);
296
297 48 params_encoded_iter(
298 FwdIt first,
299 FwdIt last) noexcept
300 : any_params_iter(
301 2 first == last)
302 48 , it0_(first)
303 48 , it_(first)
304 50 , end_(last)
305 {
306 48 }
307
308 private:
309 FwdIt it0_;
310 FwdIt it_;
311 FwdIt end_;
312
313 void
314 43 rewind() noexcept override
315 {
316 43 it_ = it0_;
317 43 }
318
319 bool
320 137 measure(
321 std::size_t& n) override
322 {
323
3/3
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 1 times.
137 if(it_ == end_)
324 43 return false;
325 // throw on invalid input
326 89 measure_impl(n,
327
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
81 param_pct_view(
328
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 5 times.
94 param_view(*it_++)));
329 89 return true;
330 }
331
332 void
333 89 copy(
334 char*& dest,
335 char const* end
336 ) noexcept override
337 {
338 89 copy_impl(dest, end,
339 89 param_view(*it_++));
340 89 }
341 };
342
343 //------------------------------------------------
344 //
345 // param_value_iter
346 //
347 //------------------------------------------------
348
349 // An iterator which outputs
350 // one value on an existing key
351 struct param_value_iter
352 : any_params_iter
353 {
354 9 param_value_iter(
355 std::size_t nk,
356 core::string_view const& value,
357 bool has_value) noexcept
358 9 : any_params_iter(
359 false,
360 value)
361 9 , nk_(nk)
362 9 , has_value_(has_value)
363 {
364 9 }
365
366 private:
367 std::size_t nk_ = 0;
368 bool has_value_ = false;
369 bool at_end_ = false;
370
371 void rewind() noexcept override;
372 bool measure(std::size_t&) noexcept override;
373 void copy(char*&, char const*) noexcept override;
374 };
375
376 //------------------------------------------------
377 //
378 // param_encoded_value_iter
379 //
380 //------------------------------------------------
381
382 // An iterator which outputs one
383 // encoded value on an existing key
384 struct param_encoded_value_iter
385 : any_params_iter
386 {
387 8 param_encoded_value_iter(
388 std::size_t nk,
389 pct_string_view const& value,
390 bool has_value) noexcept
391 8 : any_params_iter(
392 false,
393 value)
394 8 , nk_(nk)
395 8 , has_value_(has_value)
396 {
397 8 }
398
399 private:
400 std::size_t nk_ = 0;
401 bool has_value_ = false;
402 bool at_end_ = false;
403
404 void rewind() noexcept override;
405 bool measure(std::size_t&) noexcept override;
406 void copy(char*&, char const*) noexcept override;
407 };
408
409 //------------------------------------------------
410
411 template<class FwdIt>
412 params_iter<FwdIt>
413 32 make_params_iter(
414 FwdIt first, FwdIt last, bool space_as_plus)
415 {
416 return params_iter<
417 32 FwdIt>(first, last, space_as_plus);
418 }
419
420 template<class FwdIt>
421 params_encoded_iter<FwdIt>
422 29 make_params_encoded_iter(
423 FwdIt first, FwdIt last)
424 {
425 return params_encoded_iter<
426 29 FwdIt>(first, last);
427 }
428
429 } // detail
430 } // urls
431 } // boost
432
433 #endif
434