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