include/boost/url/detail/any_params_iter.hpp

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