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 143 : any_params_iter::
39 : ~any_params_iter() noexcept = default;
40 :
41 : //------------------------------------------------
42 : //
43 : // query_iter
44 : //
45 : //------------------------------------------------
46 :
47 32 : query_string_iter::
48 : query_string_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_string_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_string_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_string_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_string_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 21 : single_param_iter::
150 : single_param_iter(
151 : param_view const& p,
152 21 : bool space_as_plus) noexcept
153 : : any_params_iter(
154 : false,
155 : p.key,
156 : p.value)
157 21 : , has_value_(p.has_value)
158 21 : , space_as_plus_(space_as_plus)
159 : {
160 21 : }
161 :
162 : void
163 21 : single_param_iter::
164 : rewind() noexcept
165 : {
166 21 : at_end_ = false;
167 21 : }
168 :
169 : bool
170 42 : single_param_iter::
171 : measure(std::size_t& n) noexcept
172 : {
173 42 : if(at_end_)
174 21 : return false;
175 21 : encoding_opts opt;
176 21 : opt.space_as_plus = space_as_plus_;
177 21 : n += encoded_size(
178 : s0,
179 : detail::param_key_chars,
180 : opt);
181 21 : if(has_value_)
182 : {
183 21 : ++n; // '='
184 21 : n += encoded_size(
185 : s1,
186 : detail::param_value_chars,
187 : opt);
188 : }
189 21 : at_end_ = true;
190 21 : return true;
191 : }
192 :
193 : void
194 21 : single_param_iter::
195 : copy(
196 : char*& dest,
197 : char const* end) noexcept
198 : {
199 21 : BOOST_ASSERT(! at_end_);
200 21 : encoding_opts opt;
201 21 : opt.space_as_plus = space_as_plus_;
202 42 : dest += encode(
203 : dest,
204 21 : end - dest,
205 : s0,
206 : detail::param_key_chars,
207 : opt);
208 21 : if (has_value_)
209 : {
210 21 : *dest++ = '=';
211 21 : dest += encode(
212 : dest,
213 21 : end - dest,
214 : s1,
215 : detail::param_value_chars,
216 : opt);
217 : }
218 21 : }
219 :
220 : //------------------------------------------------
221 : //
222 : // params_iter_base
223 : //
224 : //------------------------------------------------
225 :
226 : void
227 70 : params_iter_base::
228 : measure_impl(
229 : std::size_t& n,
230 : param_view const& p) noexcept
231 : {
232 70 : encoding_opts opt;
233 70 : opt.space_as_plus = space_as_plus_;
234 70 : n += encoded_size(
235 : p.key,
236 : detail::param_key_chars,
237 : opt);
238 70 : if(p.has_value)
239 : {
240 58 : ++n; // '='
241 58 : n += encoded_size(
242 : p.value,
243 : detail::param_value_chars,
244 : opt);
245 : }
246 70 : }
247 :
248 : void
249 70 : params_iter_base::
250 : copy_impl(
251 : char*& dest,
252 : char const* end,
253 : param_view const& p) noexcept
254 : {
255 70 : encoding_opts opt;
256 70 : opt.space_as_plus = space_as_plus_;
257 140 : dest += encode(
258 : dest,
259 70 : end - dest,
260 : p.key,
261 : detail::param_key_chars,
262 : opt);
263 70 : if(p.has_value)
264 : {
265 58 : *dest++ = '=';
266 58 : dest += encode(
267 : dest,
268 58 : end - dest,
269 : p.value,
270 : detail::param_value_chars,
271 : opt);
272 : }
273 70 : }
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 : n += detail::re_encoded_size_unsafe(
306 : s0,
307 : detail::param_key_chars);
308 12 : if(has_value_)
309 12 : n += detail::re_encoded_size_unsafe(
310 : s1,
311 12 : detail::param_value_chars) + 1; // for '='
312 12 : at_end_ = true;
313 12 : return true;
314 : }
315 :
316 : void
317 12 : param_encoded_iter::
318 : copy(
319 : char*& dest,
320 : char const* end) noexcept
321 : {
322 12 : detail::re_encode_unsafe(
323 : dest,
324 : end,
325 : s0,
326 : detail::param_key_chars);
327 12 : if(has_value_)
328 : {
329 12 : *dest++ = '=';
330 12 : detail::re_encode_unsafe(
331 : dest,
332 : end,
333 : s1,
334 : detail::param_value_chars);
335 : }
336 12 : }
337 :
338 :
339 : //------------------------------------------------
340 : //
341 : // params_encoded_iter_base
342 : //
343 : //------------------------------------------------
344 :
345 : void
346 51 : params_encoded_iter_base::
347 : measure_impl(
348 : std::size_t& n,
349 : param_view const& p) noexcept
350 : {
351 51 : n += detail::re_encoded_size_unsafe(
352 : p.key,
353 : detail::param_key_chars);
354 51 : if(p.has_value)
355 42 : n += detail::re_encoded_size_unsafe(
356 : p.value,
357 42 : detail::param_value_chars) + 1; // for '='
358 51 : }
359 :
360 : void
361 51 : params_encoded_iter_base::
362 : copy_impl(
363 : char*& dest,
364 : char const* end,
365 : param_view const& p) noexcept
366 : {
367 51 : detail::re_encode_unsafe(
368 : dest,
369 : end,
370 : p.key,
371 : detail::param_key_chars);
372 51 : if(p.has_value)
373 : {
374 42 : *dest++ = '=';
375 42 : detail::re_encode_unsafe(
376 : dest,
377 : end,
378 : p.value,
379 : detail::param_value_chars);
380 : }
381 51 : }
382 :
383 : //------------------------------------------------
384 : //
385 : // param_value_iter
386 : //
387 : //------------------------------------------------
388 :
389 : void
390 9 : param_value_iter::
391 : rewind() noexcept
392 : {
393 9 : at_end_ = false;
394 9 : }
395 :
396 : bool
397 18 : param_value_iter::
398 : measure(
399 : std::size_t& n) noexcept
400 : {
401 18 : if(at_end_)
402 9 : return false;
403 9 : n += nk_; // skip key
404 9 : if(has_value_)
405 : {
406 5 : encoding_opts opt;
407 5 : opt.space_as_plus = false;
408 5 : n += encoded_size(
409 : s0,
410 : detail::param_value_chars,
411 5 : opt) + 1; // for '='
412 : }
413 9 : at_end_ = true;
414 9 : return true;
415 : }
416 :
417 : void
418 9 : param_value_iter::
419 : copy(char*& it, char const* end) noexcept
420 : {
421 9 : it += nk_; // skip key
422 9 : if(! has_value_)
423 4 : return;
424 5 : *it++ = '=';
425 5 : encoding_opts opt;
426 5 : opt.space_as_plus = false;
427 5 : it += encode(
428 : it,
429 5 : end - it,
430 : s0,
431 : detail::param_value_chars,
432 : opt);
433 : }
434 :
435 : //------------------------------------------------
436 : //
437 : // param_encoded_value_iter
438 : //
439 : //------------------------------------------------
440 :
441 : void
442 8 : param_encoded_value_iter::
443 : rewind() noexcept
444 : {
445 8 : at_end_ = false;
446 8 : }
447 :
448 : bool
449 16 : param_encoded_value_iter::
450 : measure(
451 : std::size_t& n) noexcept
452 : {
453 16 : if(at_end_)
454 8 : return false;
455 8 : n += nk_; // skip key
456 8 : if(has_value_)
457 : {
458 4 : n += detail::re_encoded_size_unsafe(
459 : s0,
460 4 : detail::param_value_chars) + 1; // for '='
461 : }
462 8 : at_end_ = true;
463 8 : return true;
464 : }
465 :
466 : void
467 8 : param_encoded_value_iter::
468 : copy(
469 : char*& dest,
470 : char const* end) noexcept
471 : {
472 8 : dest += nk_; // skip key
473 8 : if(! has_value_)
474 4 : return;
475 4 : *dest++ = '=';
476 4 : detail::re_encode_unsafe(
477 : dest,
478 : end,
479 : s0,
480 : detail::param_value_chars);
481 : }
482 :
483 : } // detail
484 : } // urls
485 : } // boost
486 :
|