TLA Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_DETAIL_IMPL_ANY_PARAMS_ITER_HPP
12 : #define BOOST_URL_DETAIL_IMPL_ANY_PARAMS_ITER_HPP
13 :
14 : #include <boost/url/encode.hpp>
15 : #include <boost/url/rfc/detail/charsets.hpp>
16 : #include <boost/assert.hpp>
17 :
18 : namespace boost {
19 : namespace urls {
20 : namespace detail {
21 :
22 : /*
23 : When a string is transformed into a range of
24 : params, the empty string becomes ambiguous:
25 : it can be an empty range, or a range with
26 : one param. The value `not_empty` is used on
27 : construction to inform the transformation
28 : that the empty string should be treated as
29 : a one-element range. This simplifies
30 : edit_params().
31 : */
32 :
33 : //------------------------------------------------
34 : //
35 : // any_params_iter
36 : //
37 : //------------------------------------------------
38 :
39 : inline
40 HIT 147 : any_params_iter::
41 : ~any_params_iter() noexcept = default;
42 :
43 : //------------------------------------------------
44 : //
45 : // query_iter
46 : //
47 : //------------------------------------------------
48 :
49 : inline
50 33 : query_string_iter::
51 : query_string_iter(
52 : core::string_view s,
53 33 : bool ne) noexcept
54 : : any_params_iter(
55 33 : s.empty() && ! ne, s)
56 : {
57 33 : rewind();
58 33 : }
59 :
60 : inline
61 : void
62 44 : query_string_iter::
63 : rewind() noexcept
64 : {
65 44 : if(empty)
66 : {
67 22 : at_end_ = true;
68 22 : return;
69 : }
70 22 : p_ = s0.begin();
71 22 : if(! s0.empty())
72 : {
73 : auto pos =
74 16 : s0.find_first_of('&');
75 16 : if(pos != core::string_view::npos)
76 4 : n_ = pos;
77 : else
78 12 : n_ = s0.size();
79 : }
80 : else
81 : {
82 6 : n_ = 0;
83 : }
84 22 : at_end_ = false;
85 : }
86 :
87 : inline
88 : bool
89 46 : query_string_iter::
90 : measure(
91 : std::size_t& n) noexcept
92 : {
93 46 : if(at_end_)
94 33 : return false;
95 : // When interacting with the query as
96 : // an intact string, we do not treat
97 : // the plus sign as an encoded space.
98 13 : encoding_opts opt;
99 13 : opt.space_as_plus = false;
100 13 : n += encoded_size(
101 : core::string_view(p_, n_),
102 : query_chars,
103 : opt);
104 13 : increment();
105 13 : return true;
106 : }
107 :
108 : inline
109 : void
110 13 : query_string_iter::
111 : copy(
112 : char*& dest,
113 : char const* end) noexcept
114 : {
115 13 : BOOST_ASSERT(! at_end_);
116 : // When interacting with the query as
117 : // an intact string, we do not treat
118 : // the plus sign as an encoded space.
119 13 : encoding_opts opt;
120 13 : opt.space_as_plus = false;
121 13 : dest += encode_unsafe(
122 : dest,
123 13 : end - dest,
124 : core::string_view(p_, n_),
125 : query_chars,
126 : opt);
127 13 : increment();
128 13 : }
129 :
130 : inline
131 : void
132 26 : query_string_iter::
133 : increment() noexcept
134 : {
135 26 : p_ += n_;
136 26 : if(p_ == s0.end())
137 : {
138 22 : at_end_ = true;
139 22 : return;
140 : }
141 4 : ++p_;
142 4 : core::string_view s(p_, s0.end() - p_);
143 4 : auto pos = s.find_first_of('&');
144 4 : if(pos != core::string_view::npos)
145 MIS 0 : n_ = pos;
146 : else
147 HIT 4 : n_ = s.size();
148 : }
149 :
150 : //------------------------------------------------
151 : //
152 : // param_iter
153 : //
154 : //------------------------------------------------
155 :
156 : inline
157 24 : single_param_iter::
158 : single_param_iter(
159 : param_view const& p,
160 24 : bool space_as_plus) noexcept
161 : : any_params_iter(
162 : false,
163 : p.key,
164 : p.value)
165 24 : , has_value_(p.has_value)
166 24 : , space_as_plus_(space_as_plus)
167 : {
168 24 : }
169 :
170 : inline
171 : void
172 24 : single_param_iter::
173 : rewind() noexcept
174 : {
175 24 : at_end_ = false;
176 24 : }
177 :
178 : inline
179 : bool
180 48 : single_param_iter::
181 : measure(std::size_t& n) noexcept
182 : {
183 48 : if(at_end_)
184 24 : return false;
185 24 : encoding_opts opt;
186 24 : opt.space_as_plus = space_as_plus_;
187 24 : n += encoded_size(
188 : s0,
189 : detail::param_key_chars,
190 : opt);
191 24 : if(has_value_)
192 : {
193 24 : ++n; // '='
194 24 : n += encoded_size(
195 : s1,
196 : detail::param_value_chars,
197 : opt);
198 : }
199 24 : at_end_ = true;
200 24 : return true;
201 : }
202 :
203 : inline
204 : void
205 24 : single_param_iter::
206 : copy(
207 : char*& dest,
208 : char const* end) noexcept
209 : {
210 24 : BOOST_ASSERT(! at_end_);
211 24 : encoding_opts opt;
212 24 : opt.space_as_plus = space_as_plus_;
213 48 : dest += encode(
214 : dest,
215 24 : end - dest,
216 : s0,
217 : detail::param_key_chars,
218 : opt);
219 24 : if (has_value_)
220 : {
221 24 : *dest++ = '=';
222 24 : dest += encode(
223 : dest,
224 24 : end - dest,
225 : s1,
226 : detail::param_value_chars,
227 : opt);
228 : }
229 24 : }
230 :
231 : //------------------------------------------------
232 : //
233 : // params_iter_base
234 : //
235 : //------------------------------------------------
236 :
237 : inline
238 : void
239 70 : params_iter_base::
240 : measure_impl(
241 : std::size_t& n,
242 : param_view const& p) noexcept
243 : {
244 70 : encoding_opts opt;
245 70 : opt.space_as_plus = space_as_plus_;
246 70 : n += encoded_size(
247 : p.key,
248 : detail::param_key_chars,
249 : opt);
250 70 : if(p.has_value)
251 : {
252 58 : ++n; // '='
253 58 : n += encoded_size(
254 : p.value,
255 : detail::param_value_chars,
256 : opt);
257 : }
258 70 : }
259 :
260 : inline
261 : void
262 70 : params_iter_base::
263 : copy_impl(
264 : char*& dest,
265 : char const* end,
266 : param_view const& p) noexcept
267 : {
268 70 : encoding_opts opt;
269 70 : opt.space_as_plus = space_as_plus_;
270 140 : dest += encode(
271 : dest,
272 70 : end - dest,
273 : p.key,
274 : detail::param_key_chars,
275 : opt);
276 70 : if(p.has_value)
277 : {
278 58 : *dest++ = '=';
279 58 : dest += encode(
280 : dest,
281 58 : end - dest,
282 : p.value,
283 : detail::param_value_chars,
284 : opt);
285 : }
286 70 : }
287 :
288 : //------------------------------------------------
289 : //
290 : // param_encoded_iter
291 : //
292 : //------------------------------------------------
293 :
294 : inline
295 12 : param_encoded_iter::
296 : param_encoded_iter(
297 12 : param_pct_view const& p) noexcept
298 : : any_params_iter(
299 : false,
300 : p.key,
301 : p.value)
302 12 : , has_value_(p.has_value)
303 : {
304 12 : }
305 :
306 : inline
307 : void
308 12 : param_encoded_iter::
309 : rewind() noexcept
310 : {
311 12 : at_end_ = false;
312 12 : }
313 :
314 : inline
315 : bool
316 24 : param_encoded_iter::
317 : measure(std::size_t& n) noexcept
318 : {
319 24 : if(at_end_)
320 12 : return false;
321 12 : n += detail::re_encoded_size_unsafe(
322 : s0,
323 : detail::param_key_chars);
324 12 : if(has_value_)
325 12 : n += detail::re_encoded_size_unsafe(
326 : s1,
327 12 : detail::param_value_chars) + 1; // for '='
328 12 : at_end_ = true;
329 12 : return true;
330 : }
331 :
332 : inline
333 : void
334 12 : param_encoded_iter::
335 : copy(
336 : char*& dest,
337 : char const* end) noexcept
338 : {
339 12 : detail::re_encode_unsafe(
340 : dest,
341 : end,
342 : s0,
343 : detail::param_key_chars);
344 12 : if(has_value_)
345 : {
346 12 : *dest++ = '=';
347 12 : detail::re_encode_unsafe(
348 : dest,
349 : end,
350 : s1,
351 : detail::param_value_chars);
352 : }
353 12 : }
354 :
355 :
356 : //------------------------------------------------
357 : //
358 : // params_encoded_iter_base
359 : //
360 : //------------------------------------------------
361 :
362 : inline
363 : void
364 51 : params_encoded_iter_base::
365 : measure_impl(
366 : std::size_t& n,
367 : param_view const& p) noexcept
368 : {
369 51 : n += detail::re_encoded_size_unsafe(
370 : p.key,
371 : detail::param_key_chars);
372 51 : if(p.has_value)
373 42 : n += detail::re_encoded_size_unsafe(
374 : p.value,
375 42 : detail::param_value_chars) + 1; // for '='
376 51 : }
377 :
378 : inline
379 : void
380 51 : params_encoded_iter_base::
381 : copy_impl(
382 : char*& dest,
383 : char const* end,
384 : param_view const& p) noexcept
385 : {
386 51 : detail::re_encode_unsafe(
387 : dest,
388 : end,
389 : p.key,
390 : detail::param_key_chars);
391 51 : if(p.has_value)
392 : {
393 42 : *dest++ = '=';
394 42 : detail::re_encode_unsafe(
395 : dest,
396 : end,
397 : p.value,
398 : detail::param_value_chars);
399 : }
400 51 : }
401 :
402 : //------------------------------------------------
403 : //
404 : // param_value_iter
405 : //
406 : //------------------------------------------------
407 :
408 : inline
409 : void
410 9 : param_value_iter::
411 : rewind() noexcept
412 : {
413 9 : at_end_ = false;
414 9 : }
415 :
416 : inline
417 : bool
418 18 : param_value_iter::
419 : measure(
420 : std::size_t& n) noexcept
421 : {
422 18 : if(at_end_)
423 9 : return false;
424 9 : n += nk_; // skip key
425 9 : if(has_value_)
426 : {
427 5 : encoding_opts opt;
428 5 : opt.space_as_plus = false;
429 5 : n += encoded_size(
430 : s0,
431 : detail::param_value_chars,
432 5 : opt) + 1; // for '='
433 : }
434 9 : at_end_ = true;
435 9 : return true;
436 : }
437 :
438 : inline
439 : void
440 9 : param_value_iter::
441 : copy(char*& it, char const* end) noexcept
442 : {
443 9 : it += nk_; // skip key
444 9 : if(! has_value_)
445 4 : return;
446 5 : *it++ = '=';
447 5 : encoding_opts opt;
448 5 : opt.space_as_plus = false;
449 5 : it += encode(
450 : it,
451 5 : end - it,
452 : s0,
453 : detail::param_value_chars,
454 : opt);
455 : }
456 :
457 : //------------------------------------------------
458 : //
459 : // param_encoded_value_iter
460 : //
461 : //------------------------------------------------
462 :
463 : inline
464 : void
465 8 : param_encoded_value_iter::
466 : rewind() noexcept
467 : {
468 8 : at_end_ = false;
469 8 : }
470 :
471 : inline
472 : bool
473 16 : param_encoded_value_iter::
474 : measure(
475 : std::size_t& n) noexcept
476 : {
477 16 : if(at_end_)
478 8 : return false;
479 8 : n += nk_; // skip key
480 8 : if(has_value_)
481 : {
482 4 : n += detail::re_encoded_size_unsafe(
483 : s0,
484 4 : detail::param_value_chars) + 1; // for '='
485 : }
486 8 : at_end_ = true;
487 8 : return true;
488 : }
489 :
490 : inline
491 : void
492 8 : param_encoded_value_iter::
493 : copy(
494 : char*& dest,
495 : char const* end) noexcept
496 : {
497 8 : dest += nk_; // skip key
498 8 : if(! has_value_)
499 4 : return;
500 4 : *dest++ = '=';
501 4 : detail::re_encode_unsafe(
502 : dest,
503 : end,
504 : s0,
505 : detail::param_value_chars);
506 : }
507 :
508 : } // detail
509 : } // urls
510 : } // boost
511 :
512 : #endif
|