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 : n += detail::re_encoded_size_unsafe(
304 : s0,
305 : detail::param_key_chars);
306 12 : if(has_value_)
307 12 : n += detail::re_encoded_size_unsafe(
308 : s1,
309 12 : detail::param_value_chars) + 1; // for '='
310 12 : at_end_ = true;
311 12 : return true;
312 : }
313 :
314 : void
315 12 : param_encoded_iter::
316 : copy(
317 : char*& dest,
318 : char const* end) noexcept
319 : {
320 12 : detail::re_encode_unsafe(
321 : dest,
322 : end,
323 : s0,
324 : detail::param_key_chars);
325 12 : if(has_value_)
326 : {
327 12 : *dest++ = '=';
328 12 : detail::re_encode_unsafe(
329 : dest,
330 : end,
331 : s1,
332 : detail::param_value_chars);
333 : }
334 12 : }
335 :
336 :
337 : //------------------------------------------------
338 : //
339 : // params_encoded_iter_base
340 : //
341 : //------------------------------------------------
342 :
343 : void
344 51 : params_encoded_iter_base::
345 : measure_impl(
346 : std::size_t& n,
347 : param_view const& p) noexcept
348 : {
349 51 : n += detail::re_encoded_size_unsafe(
350 : p.key,
351 : detail::param_key_chars);
352 51 : if(p.has_value)
353 42 : n += detail::re_encoded_size_unsafe(
354 : p.value,
355 42 : detail::param_value_chars) + 1; // for '='
356 51 : }
357 :
358 : void
359 51 : params_encoded_iter_base::
360 : copy_impl(
361 : char*& dest,
362 : char const* end,
363 : param_view const& p) noexcept
364 : {
365 51 : detail::re_encode_unsafe(
366 : dest,
367 : end,
368 : p.key,
369 : detail::param_key_chars);
370 51 : if(p.has_value)
371 : {
372 42 : *dest++ = '=';
373 42 : detail::re_encode_unsafe(
374 : dest,
375 : end,
376 : p.value,
377 : detail::param_value_chars);
378 : }
379 51 : }
380 :
381 : //------------------------------------------------
382 : //
383 : // param_value_iter
384 : //
385 : //------------------------------------------------
386 :
387 : void
388 9 : param_value_iter::
389 : rewind() noexcept
390 : {
391 9 : at_end_ = false;
392 9 : }
393 :
394 : bool
395 18 : param_value_iter::
396 : measure(
397 : std::size_t& n) noexcept
398 : {
399 18 : if(at_end_)
400 9 : return false;
401 9 : n += nk_; // skip key
402 9 : if(has_value_)
403 : {
404 5 : encoding_opts opt;
405 5 : opt.space_as_plus = false;
406 5 : n += encoded_size(
407 : s0,
408 : detail::param_value_chars,
409 5 : opt) + 1; // for '='
410 : }
411 9 : at_end_ = true;
412 9 : return true;
413 : }
414 :
415 : void
416 9 : param_value_iter::
417 : copy(char*& it, char const* end) noexcept
418 : {
419 9 : it += nk_; // skip key
420 9 : if(! has_value_)
421 4 : return;
422 5 : *it++ = '=';
423 5 : encoding_opts opt;
424 5 : opt.space_as_plus = false;
425 5 : it += encode(
426 : it,
427 5 : end - it,
428 : s0,
429 : detail::param_value_chars,
430 : opt);
431 : }
432 :
433 : //------------------------------------------------
434 : //
435 : // param_encoded_value_iter
436 : //
437 : //------------------------------------------------
438 :
439 : void
440 8 : param_encoded_value_iter::
441 : rewind() noexcept
442 : {
443 8 : at_end_ = false;
444 8 : }
445 :
446 : bool
447 16 : param_encoded_value_iter::
448 : measure(
449 : std::size_t& n) noexcept
450 : {
451 16 : if(at_end_)
452 8 : return false;
453 8 : n += nk_; // skip key
454 8 : if(has_value_)
455 : {
456 4 : n += detail::re_encoded_size_unsafe(
457 : s0,
458 4 : detail::param_value_chars) + 1; // for '='
459 : }
460 8 : at_end_ = true;
461 8 : return true;
462 : }
463 :
464 : void
465 8 : param_encoded_value_iter::
466 : copy(
467 : char*& dest,
468 : char const* end) noexcept
469 : {
470 8 : dest += nk_; // skip key
471 8 : if(! has_value_)
472 4 : return;
473 4 : *dest++ = '=';
474 4 : detail::re_encode_unsafe(
475 : dest,
476 : end,
477 : s0,
478 : detail::param_value_chars);
479 : }
480 :
481 : } // detail
482 : } // urls
483 : } // boost
484 :
|