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