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