include/boost/url/detail/any_params_iter.hpp

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