Line | Branch | Exec | Source |
---|---|---|---|
1 | // | ||
2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | ||
3 | // Copyright (c) 2022 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_PARAM_HPP | ||
12 | #define BOOST_URL_PARAM_HPP | ||
13 | |||
14 | #include <boost/url/detail/config.hpp> | ||
15 | #include <boost/url/detail/optional_string.hpp> | ||
16 | #include <boost/url/pct_string_view.hpp> | ||
17 | #include <cstddef> | ||
18 | #include <string> | ||
19 | |||
20 | namespace boost { | ||
21 | namespace urls { | ||
22 | |||
23 | #ifndef BOOST_URL_DOCS | ||
24 | struct param_pct_view; | ||
25 | struct param_view; | ||
26 | #endif | ||
27 | |||
28 | /** The type of no_value | ||
29 | */ | ||
30 | struct no_value_t | ||
31 | { | ||
32 | }; | ||
33 | |||
34 | /** Constant indicating no value in a param | ||
35 | */ | ||
36 | constexpr no_value_t no_value{}; | ||
37 | |||
38 | //------------------------------------------------ | ||
39 | |||
40 | /** A query parameter | ||
41 | |||
42 | Objects of this type represent a single key | ||
43 | and value pair in a query string where a key | ||
44 | is always present and may be empty, while the | ||
45 | presence of a value is indicated by | ||
46 | @ref has_value equal to true. | ||
47 | An empty value is distinct from no value. | ||
48 | |||
49 | Depending on where the object was obtained, | ||
50 | the strings may or may not contain percent | ||
51 | escapes. | ||
52 | |||
53 | For most usages, key comparisons are | ||
54 | case-sensitive and duplicate keys in | ||
55 | a query are possible. However, it is | ||
56 | the authority that has final control | ||
57 | over how the query is interpreted. | ||
58 | |||
59 | @par BNF | ||
60 | @code | ||
61 | query-params = query-param *( "&" query-param ) | ||
62 | query-param = key [ "=" value ] | ||
63 | key = *qpchar | ||
64 | value = *( qpchar / "=" ) | ||
65 | @endcode | ||
66 | |||
67 | @par Specification | ||
68 | @li <a href="https://en.wikipedia.org/wiki/Query_string" | ||
69 | >Query string (Wikipedia)</a> | ||
70 | |||
71 | @see | ||
72 | @ref param_view, | ||
73 | @ref param_pct_view. | ||
74 | */ | ||
75 | struct param | ||
76 | { | ||
77 | /** The key | ||
78 | |||
79 | For most usages, key comparisons are | ||
80 | case-sensitive and duplicate keys in | ||
81 | a query are possible. However, it is | ||
82 | the authority that has final control | ||
83 | over how the query is interpreted. | ||
84 | */ | ||
85 | std::string key; | ||
86 | |||
87 | /** The value | ||
88 | |||
89 | The presence of a value is indicated by | ||
90 | @ref has_value equal to true. | ||
91 | An empty value is distinct from no value. | ||
92 | */ | ||
93 | std::string value; | ||
94 | |||
95 | /** True if a value is present | ||
96 | |||
97 | The presence of a value is indicated by | ||
98 | `has_value == true`. | ||
99 | An empty value is distinct from no value. | ||
100 | */ | ||
101 | bool has_value = false; | ||
102 | |||
103 | /** Constructor | ||
104 | |||
105 | Default constructed query parameters | ||
106 | have an empty key and no value. | ||
107 | |||
108 | @par Example | ||
109 | @code | ||
110 | param qp; | ||
111 | @endcode | ||
112 | |||
113 | @par Postconditions | ||
114 | @code | ||
115 | this->key == "" && this->value == "" && this->has_value == false | ||
116 | @endcode | ||
117 | |||
118 | @par Complexity | ||
119 | Constant. | ||
120 | |||
121 | @par Exception Safety | ||
122 | Throws nothing. | ||
123 | */ | ||
124 | 6 | param() = default; | |
125 | |||
126 | /** Constructor | ||
127 | |||
128 | Upon construction, this acquires | ||
129 | ownership of the members of other | ||
130 | via move construction. The moved | ||
131 | from object is as if default | ||
132 | constructed. | ||
133 | |||
134 | @par Complexity | ||
135 | Constant. | ||
136 | |||
137 | @par Exception Safety | ||
138 | Throws nothing. | ||
139 | |||
140 | @par other The object to construct from. | ||
141 | */ | ||
142 | 1 | param(param&& other) noexcept | |
143 | 1 | : key(std::move(other.key)) | |
144 | 1 | , value(std::move(other.value)) | |
145 | 1 | , has_value(other.has_value) | |
146 | { | ||
147 | #ifdef BOOST_URL_COW_STRINGS | ||
148 | // for copy-on-write std::string | ||
149 | other.key.clear(); | ||
150 | other.value.clear(); | ||
151 | #endif | ||
152 | 1 | other.has_value = false; | |
153 | 1 | } | |
154 | |||
155 | /** Constructor | ||
156 | |||
157 | Upon construction, this becomes a copy | ||
158 | of `other`. | ||
159 | |||
160 | @par Postconditions | ||
161 | @code | ||
162 | this->key == other.key && this->value == other.value && this->has_value == other.has_value | ||
163 | @endcode | ||
164 | |||
165 | @par Complexity | ||
166 | Linear in `other.key.size() + other.value.size()`. | ||
167 | |||
168 | @par Exception Safety | ||
169 | Calls to allocate may throw. | ||
170 | |||
171 | @par other The object to construct from. | ||
172 | */ | ||
173 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | param(param const& other) = default; |
174 | |||
175 | /** Assignment | ||
176 | |||
177 | Upon assignment, this acquires | ||
178 | ownership of the members of other | ||
179 | via move assignment. The moved | ||
180 | from object is as if default | ||
181 | constructed. | ||
182 | |||
183 | @par Complexity | ||
184 | Constant. | ||
185 | |||
186 | @par Exception Safety | ||
187 | Throws nothing. | ||
188 | |||
189 | @par other The object to assign from. | ||
190 | */ | ||
191 | param& | ||
192 | 3 | operator=(param&& other) noexcept | |
193 | { | ||
194 | 3 | key = std::move(other.key); | |
195 | 3 | value = std::move(other.value); | |
196 | 3 | has_value = other.has_value; | |
197 | #ifdef BOOST_URL_COW_STRINGS | ||
198 | // for copy-on-write std::string | ||
199 | other.key.clear(); | ||
200 | other.value.clear(); | ||
201 | #endif | ||
202 | 3 | other.has_value = false; | |
203 | 3 | return *this; | |
204 | } | ||
205 | |||
206 | /** Assignment | ||
207 | |||
208 | Upon assignment, this becomes a copy | ||
209 | of `other`. | ||
210 | |||
211 | @par Postconditions | ||
212 | @code | ||
213 | this->key == other.key && this->value == other.value && this->has_value == other.has_value | ||
214 | @endcode | ||
215 | |||
216 | @par Complexity | ||
217 | Linear in `other.key.size() + other.value.size()`. | ||
218 | |||
219 | @par Exception Safety | ||
220 | Calls to allocate may throw. | ||
221 | |||
222 | @par other The object to assign from. | ||
223 | */ | ||
224 | 1 | param& operator=( | |
225 | param const&) = default; | ||
226 | |||
227 | //-------------------------------------------- | ||
228 | |||
229 | /** Constructor | ||
230 | |||
231 | This constructs a parameter with a key | ||
232 | and value. | ||
233 | |||
234 | No validation is performed on the strings. | ||
235 | Ownership of the key and value is acquired | ||
236 | by making copies. | ||
237 | |||
238 | @par Example | ||
239 | @code | ||
240 | param qp( "key", "value" ); | ||
241 | @endcode | ||
242 | |||
243 | @code | ||
244 | param qp( "key", optional<core::string_view>("value") ); | ||
245 | @endcode | ||
246 | |||
247 | @code | ||
248 | param qp( "key", boost::none ); | ||
249 | @endcode | ||
250 | |||
251 | @code | ||
252 | param qp( "key", nullptr ); | ||
253 | @endcode | ||
254 | |||
255 | @code | ||
256 | param qp( "key", no_value ); | ||
257 | @endcode | ||
258 | |||
259 | @par Postconditions | ||
260 | @code | ||
261 | this->key == key && this->value == value && this->has_value == true | ||
262 | @endcode | ||
263 | |||
264 | @par Complexity | ||
265 | Linear in `key.size() + value.size()`. | ||
266 | |||
267 | @par Exception Safety | ||
268 | Calls to allocate may throw. | ||
269 | |||
270 | @tparam OptionalString An optional string | ||
271 | type, such as `core::string_view`, | ||
272 | `std::nullptr`, @ref no_value_t, or | ||
273 | `optional<core::string_view>`. | ||
274 | |||
275 | @param key, value The key and value to set. | ||
276 | */ | ||
277 | template <class OptionalString> | ||
278 | 32 | param( | |
279 | core::string_view key, | ||
280 | OptionalString const& value) | ||
281 | 32 | : param(key, detail::get_optional_string(value)) | |
282 | { | ||
283 | 32 | } | |
284 | |||
285 | /** Assignment | ||
286 | |||
287 | The members of `other` are copied, | ||
288 | re-using already existing string capacity. | ||
289 | |||
290 | @par Postconditions | ||
291 | @code | ||
292 | this->key == other.key && this->value == other.value && this->has_value == other.has_value | ||
293 | @endcode | ||
294 | |||
295 | @par Complexity | ||
296 | Linear in `other.key.size() + other.value.size()`. | ||
297 | |||
298 | @par Exception Safety | ||
299 | Calls to allocate may throw. | ||
300 | |||
301 | @param other The parameter to copy. | ||
302 | */ | ||
303 | param& | ||
304 | operator=(param_view const& other); | ||
305 | |||
306 | /** Assignment | ||
307 | |||
308 | The members of `other` are copied, | ||
309 | re-using already existing string capacity. | ||
310 | |||
311 | @par Postconditions | ||
312 | @code | ||
313 | this->key == other.key && this->value == other.value && this->has_value == other.has_value | ||
314 | @endcode | ||
315 | |||
316 | @par Complexity | ||
317 | Linear in `other.key.size() + other.value.size()`. | ||
318 | |||
319 | @par Exception Safety | ||
320 | Calls to allocate may throw. | ||
321 | |||
322 | @param other The parameter to copy. | ||
323 | */ | ||
324 | param& | ||
325 | operator=(param_pct_view const& other); | ||
326 | |||
327 | #ifndef BOOST_URL_DOCS | ||
328 | // arrow support | ||
329 | param const* | ||
330 | 1 | operator->() const noexcept | |
331 | { | ||
332 | 1 | return this; | |
333 | } | ||
334 | |||
335 | // aggregate construction | ||
336 | 780 | param( | |
337 | core::string_view key, | ||
338 | core::string_view value, | ||
339 | bool has_value) noexcept | ||
340 | 780 | : key(key) | |
341 | 780 | , value(has_value | |
342 |
2/2✓ Branch 0 taken 610 times.
✓ Branch 1 taken 170 times.
|
780 | ? value |
343 | : core::string_view()) | ||
344 | 780 | , has_value(has_value) | |
345 | { | ||
346 | 780 | } | |
347 | #endif | ||
348 | |||
349 | private: | ||
350 | 16 | param( | |
351 | core::string_view key, | ||
352 | detail::optional_string const& value) | ||
353 | 16 | : param(key, value.s, value.b) | |
354 | { | ||
355 | 16 | } | |
356 | }; | ||
357 | |||
358 | //------------------------------------------------ | ||
359 | |||
360 | /** A query parameter | ||
361 | |||
362 | Objects of this type represent a single key | ||
363 | and value pair in a query string where a key | ||
364 | is always present and may be empty, while the | ||
365 | presence of a value is indicated by | ||
366 | @ref has_value equal to true. | ||
367 | An empty value is distinct from no value. | ||
368 | |||
369 | Depending on where the object was obtained, | ||
370 | the strings may or may not contain percent | ||
371 | escapes. | ||
372 | |||
373 | For most usages, key comparisons are | ||
374 | case-sensitive and duplicate keys in | ||
375 | a query are possible. However, it is | ||
376 | the authority that has final control | ||
377 | over how the query is interpreted. | ||
378 | |||
379 | <br> | ||
380 | |||
381 | Keys and values in this object reference | ||
382 | external character buffers. | ||
383 | Ownership of the buffers is not transferred; | ||
384 | the caller is responsible for ensuring that | ||
385 | the assigned buffers remain valid until | ||
386 | they are no longer referenced. | ||
387 | |||
388 | @par BNF | ||
389 | @code | ||
390 | query-params = query-param *( "&" query-param ) | ||
391 | query-param = key [ "=" value ] | ||
392 | key = *qpchar | ||
393 | value = *( qpchar / "=" ) | ||
394 | @endcode | ||
395 | |||
396 | @par Specification | ||
397 | @li <a href="https://en.wikipedia.org/wiki/Query_string" | ||
398 | >Query string (Wikipedia)</a> | ||
399 | |||
400 | @see | ||
401 | @ref param, | ||
402 | @ref param_pct_view. | ||
403 | */ | ||
404 | struct param_view | ||
405 | { | ||
406 | /** The key | ||
407 | |||
408 | For most usages, key comparisons are | ||
409 | case-sensitive and duplicate keys in | ||
410 | a query are possible. However, it is | ||
411 | the authority that has final control | ||
412 | over how the query is interpreted. | ||
413 | */ | ||
414 | core::string_view key; | ||
415 | |||
416 | /** The value | ||
417 | |||
418 | The presence of a value is indicated by | ||
419 | @ref has_value equal to true. | ||
420 | An empty value is distinct from no value. | ||
421 | */ | ||
422 | core::string_view value; | ||
423 | |||
424 | /** True if a value is present | ||
425 | |||
426 | The presence of a value is indicated by | ||
427 | `has_value == true`. | ||
428 | An empty value is distinct from no value. | ||
429 | */ | ||
430 | bool has_value = false; | ||
431 | |||
432 | //-------------------------------------------- | ||
433 | |||
434 | /** Constructor | ||
435 | |||
436 | Default constructed query parameters | ||
437 | have an empty key and no value. | ||
438 | |||
439 | @par Example | ||
440 | @code | ||
441 | param_view qp; | ||
442 | @endcode | ||
443 | |||
444 | @par Postconditions | ||
445 | @code | ||
446 | this->key == "" && this->value == "" && this->has_value == false | ||
447 | @endcode | ||
448 | |||
449 | @par Complexity | ||
450 | Constant. | ||
451 | |||
452 | @par Exception Safety | ||
453 | Throws nothing. | ||
454 | */ | ||
455 | param_view() = default; | ||
456 | |||
457 | /** Constructor | ||
458 | |||
459 | This constructs a parameter with a key | ||
460 | and value. | ||
461 | No validation is performed on the strings. | ||
462 | The new key and value reference | ||
463 | the same corresponding underlying | ||
464 | character buffers. | ||
465 | Ownership of the buffers is not transferred; | ||
466 | the caller is responsible for ensuring that | ||
467 | the assigned buffers remain valid until | ||
468 | they are no longer referenced. | ||
469 | |||
470 | @par Example | ||
471 | @code | ||
472 | param_view qp( "key", "value" ); | ||
473 | @endcode | ||
474 | |||
475 | @par Postconditions | ||
476 | @code | ||
477 | this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true | ||
478 | @endcode | ||
479 | |||
480 | @par Complexity | ||
481 | Constant. | ||
482 | |||
483 | @par Exception Safety | ||
484 | Throws nothing. | ||
485 | |||
486 | @tparam OptionalString An optional string | ||
487 | type, such as `core::string_view`, | ||
488 | `std::nullptr`, @ref no_value_t, or | ||
489 | `optional<core::string_view>`. | ||
490 | |||
491 | @param key, value The key and value to set. | ||
492 | */ | ||
493 | template <class OptionalString> | ||
494 | 332 | param_view( | |
495 | core::string_view key, | ||
496 | OptionalString const& value) noexcept | ||
497 | 332 | : param_view(key, detail::get_optional_string(value)) | |
498 | { | ||
499 | 332 | } | |
500 | |||
501 | /** Constructor | ||
502 | |||
503 | This function constructs a param | ||
504 | which references the character buffers | ||
505 | representing the key and value in another | ||
506 | container. | ||
507 | Ownership of the buffers is not transferred; | ||
508 | the caller is responsible for ensuring that | ||
509 | the assigned buffers remain valid until | ||
510 | they are no longer referenced. | ||
511 | |||
512 | @par Example | ||
513 | @code | ||
514 | param qp( "key", "value" ); | ||
515 | param_view qpv( qp ); | ||
516 | @endcode | ||
517 | |||
518 | @par Postconditions | ||
519 | @code | ||
520 | this->key == key && this->value == value && this->has_value == other.has_value | ||
521 | @endcode | ||
522 | |||
523 | @par Complexity | ||
524 | Constant. | ||
525 | |||
526 | @par Exception Safety | ||
527 | Throws nothing. | ||
528 | |||
529 | @param other The param to reference | ||
530 | */ | ||
531 | 740 | param_view( | |
532 | param const& other) noexcept | ||
533 | 740 | : param_view( | |
534 | 740 | other.key, | |
535 | 740 | other.value, | |
536 | 740 | other.has_value) | |
537 | { | ||
538 | 740 | } | |
539 | |||
540 | /** Conversion | ||
541 | |||
542 | This function performs a conversion from | ||
543 | a reference-like query parameter to one | ||
544 | retaining ownership of the strings by | ||
545 | making a copy. | ||
546 | No validation is performed on the strings. | ||
547 | |||
548 | @par Complexity | ||
549 | Linear in `this->key.size() + this->value.size()`. | ||
550 | |||
551 | @par Exception Safety | ||
552 | Calls to allocate may throw. | ||
553 | */ | ||
554 | explicit | ||
555 | 4 | operator | |
556 | param() | ||
557 | { | ||
558 | 4 | return { key, value, has_value }; | |
559 | } | ||
560 | |||
561 | #ifndef BOOST_URL_DOCS | ||
562 | // arrow support | ||
563 | param_view const* | ||
564 | operator->() const noexcept | ||
565 | { | ||
566 | return this; | ||
567 | } | ||
568 | |||
569 | // aggregate construction | ||
570 | 1690 | param_view( | |
571 | core::string_view key_, | ||
572 | core::string_view value_, | ||
573 | bool has_value_) noexcept | ||
574 | 1690 | : key(key_) | |
575 |
2/2✓ Branch 0 taken 1331 times.
✓ Branch 1 taken 359 times.
|
1690 | , value(has_value_ |
576 | ? value_ | ||
577 | : core::string_view()) | ||
578 | 1690 | , has_value(has_value_) | |
579 | { | ||
580 | 1690 | } | |
581 | #endif | ||
582 | |||
583 | private: | ||
584 | 167 | param_view( | |
585 | core::string_view key, | ||
586 | detail::optional_string const& value) | ||
587 | 167 | : param_view(key, value.s, value.b) | |
588 | { | ||
589 | 167 | } | |
590 | }; | ||
591 | |||
592 | //------------------------------------------------ | ||
593 | |||
594 | /** A query parameter | ||
595 | |||
596 | Objects of this type represent a single key | ||
597 | and value pair in a query string where a key | ||
598 | is always present and may be empty, while the | ||
599 | presence of a value is indicated by | ||
600 | @ref has_value equal to true. | ||
601 | An empty value is distinct from no value. | ||
602 | |||
603 | The strings may have percent escapes, and | ||
604 | offer an additional invariant: they never | ||
605 | contain an invalid percent-encoding. | ||
606 | |||
607 | For most usages, key comparisons are | ||
608 | case-sensitive and duplicate keys in | ||
609 | a query are possible. However, it is | ||
610 | the authority that has final control | ||
611 | over how the query is interpreted. | ||
612 | |||
613 | <br> | ||
614 | |||
615 | Keys and values in this object reference | ||
616 | external character buffers. | ||
617 | Ownership of the buffers is not transferred; | ||
618 | the caller is responsible for ensuring that | ||
619 | the assigned buffers remain valid until | ||
620 | they are no longer referenced. | ||
621 | |||
622 | @par BNF | ||
623 | @code | ||
624 | query-params = query-param *( "&" query-param ) | ||
625 | query-param = key [ "=" value ] | ||
626 | key = *qpchar | ||
627 | value = *( qpchar / "=" ) | ||
628 | @endcode | ||
629 | |||
630 | @par Specification | ||
631 | @li <a href="https://en.wikipedia.org/wiki/Query_string" | ||
632 | >Query string (Wikipedia)</a> | ||
633 | |||
634 | @see | ||
635 | @ref param, | ||
636 | @ref param_view. | ||
637 | */ | ||
638 | struct param_pct_view | ||
639 | { | ||
640 | /** The key | ||
641 | |||
642 | For most usages, key comparisons are | ||
643 | case-sensitive and duplicate keys in | ||
644 | a query are possible. However, it is | ||
645 | the authority that has final control | ||
646 | over how the query is interpreted. | ||
647 | */ | ||
648 | pct_string_view key; | ||
649 | |||
650 | /** The value | ||
651 | |||
652 | The presence of a value is indicated by | ||
653 | @ref has_value equal to true. | ||
654 | An empty value is distinct from no value. | ||
655 | */ | ||
656 | pct_string_view value; | ||
657 | |||
658 | /** True if a value is present | ||
659 | |||
660 | The presence of a value is indicated by | ||
661 | `has_value == true`. | ||
662 | An empty value is distinct from no value. | ||
663 | */ | ||
664 | bool has_value = false; | ||
665 | |||
666 | //-------------------------------------------- | ||
667 | |||
668 | /** Constructor | ||
669 | |||
670 | Default constructed query parameters | ||
671 | have an empty key and no value. | ||
672 | |||
673 | @par Example | ||
674 | @code | ||
675 | param_pct_view qp; | ||
676 | @endcode | ||
677 | |||
678 | @par Postconditions | ||
679 | @code | ||
680 | this->key == "" && this->value == "" && this->has_value == false | ||
681 | @endcode | ||
682 | |||
683 | @par Complexity | ||
684 | Constant. | ||
685 | |||
686 | @par Exception Safety | ||
687 | Throws nothing. | ||
688 | */ | ||
689 | param_pct_view() = default; | ||
690 | |||
691 | /** Constructor | ||
692 | |||
693 | This constructs a parameter with a key | ||
694 | and value, which may both contain percent | ||
695 | escapes. | ||
696 | The new key and value reference | ||
697 | the same corresponding underlying | ||
698 | character buffers. | ||
699 | Ownership of the buffers is not transferred; | ||
700 | the caller is responsible for ensuring that | ||
701 | the assigned buffers remain valid until | ||
702 | they are no longer referenced. | ||
703 | |||
704 | @par Example | ||
705 | @code | ||
706 | param_pct_view qp( "key", "value" ); | ||
707 | @endcode | ||
708 | |||
709 | @par Postconditions | ||
710 | @code | ||
711 | this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true | ||
712 | @endcode | ||
713 | |||
714 | @par Complexity | ||
715 | Linear in `key.size() + value.size()`. | ||
716 | |||
717 | @par Exception Safety | ||
718 | Exceptions thrown on invalid input. | ||
719 | |||
720 | @throw system_error | ||
721 | `key` or `value` contains an invalid percent-encoding. | ||
722 | |||
723 | @param key, value The key and value to set. | ||
724 | */ | ||
725 | 1086 | param_pct_view( | |
726 | pct_string_view key, | ||
727 | pct_string_view value) noexcept | ||
728 | 1086 | : key(key) | |
729 | 1086 | , value(value) | |
730 | 1086 | , has_value(true) | |
731 | { | ||
732 | 1086 | } | |
733 | |||
734 | /** Constructor | ||
735 | |||
736 | This constructs a parameter with a key | ||
737 | and optional value, which may both | ||
738 | contain percent escapes. | ||
739 | |||
740 | The new key and value reference | ||
741 | the same corresponding underlying | ||
742 | character buffers. | ||
743 | |||
744 | Ownership of the buffers is not transferred; | ||
745 | the caller is responsible for ensuring that | ||
746 | the assigned buffers remain valid until | ||
747 | they are no longer referenced. | ||
748 | |||
749 | @par Example | ||
750 | @code | ||
751 | param_pct_view qp( "key", optional<core::string_view>("value") ); | ||
752 | @endcode | ||
753 | |||
754 | @par Postconditions | ||
755 | @code | ||
756 | this->key.data() == key.data() && this->value->data() == value->data() && this->has_value == true | ||
757 | @endcode | ||
758 | |||
759 | @par Complexity | ||
760 | Linear in `key.size() + value->size()`. | ||
761 | |||
762 | @par Exception Safety | ||
763 | Exceptions thrown on invalid input. | ||
764 | |||
765 | @throw system_error | ||
766 | `key` or `value` contains an invalid percent-encoding. | ||
767 | |||
768 | @tparam OptionalString An optional | ||
769 | `core::string_view` type, such as | ||
770 | `boost::optional<core::string_view>` or | ||
771 | `std::optional<core::string_view>`. | ||
772 | |||
773 | @param key, value The key and value to set. | ||
774 | */ | ||
775 | template <class OptionalString> | ||
776 | 956 | param_pct_view( | |
777 | pct_string_view key, | ||
778 | OptionalString const& value) | ||
779 |
2/2✓ Branch 2 taken 635 times.
✓ Branch 3 taken 3 times.
|
956 | : param_pct_view(key, detail::get_optional_string(value)) |
780 | { | ||
781 | 950 | } | |
782 | |||
783 | /** Construction | ||
784 | |||
785 | This converts a param which may | ||
786 | contain unvalidated percent-escapes into | ||
787 | a param whose key and value are | ||
788 | guaranteed to contain strings with no | ||
789 | invalid percent-escapes, otherwise | ||
790 | an exception is thrown. | ||
791 | |||
792 | The new key and value reference | ||
793 | the same corresponding underlying | ||
794 | character buffers. | ||
795 | Ownership of the buffers is not transferred; | ||
796 | the caller is responsible for ensuring that | ||
797 | the assigned buffers remain valid until | ||
798 | they are no longer referenced. | ||
799 | |||
800 | @par Example | ||
801 | @code | ||
802 | param_pct_view qp( param_view( "key", "value" ) ); | ||
803 | @endcode | ||
804 | |||
805 | @par Complexity | ||
806 | Linear in `key.size() + value.size()`. | ||
807 | |||
808 | @par Exception Safety | ||
809 | Exceptions thrown on invalid input. | ||
810 | |||
811 | @throw system_error | ||
812 | `key` or `value` contains an invalid percent escape. | ||
813 | |||
814 | @param p The param to construct from. | ||
815 | */ | ||
816 | explicit | ||
817 | 56 | param_pct_view( | |
818 | param_view const& p) | ||
819 | 56 | : key(p.key) | |
820 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 9 times.
|
52 | , value(p.has_value |
821 | ? pct_string_view(p.value) | ||
822 | : pct_string_view()) | ||
823 | 51 | , has_value(p.has_value) | |
824 | { | ||
825 | 51 | } | |
826 | |||
827 | /** Conversion | ||
828 | |||
829 | This function performs a conversion from | ||
830 | a reference-like query parameter to one | ||
831 | retaining ownership of the strings by | ||
832 | making a copy. | ||
833 | |||
834 | @par Complexity | ||
835 | Linear in `this->key.size() + this->value.size()`. | ||
836 | |||
837 | @par Exception Safety | ||
838 | Calls to allocate may throw. | ||
839 | */ | ||
840 | explicit | ||
841 | 2 | operator | |
842 | param() const | ||
843 | { | ||
844 | return param( | ||
845 | 2 | static_cast<std::string>(key), | |
846 | 2 | static_cast<std::string>(value), | |
847 | 4 | has_value); | |
848 | } | ||
849 | |||
850 | /** Conversion to param_view | ||
851 | |||
852 | This function performs a conversion from | ||
853 | a pct_string_view query parameter to one | ||
854 | using a simple string_view. | ||
855 | |||
856 | @par Exception Safety | ||
857 | Calls to allocate may throw. | ||
858 | */ | ||
859 | 783 | operator | |
860 | param_view() const noexcept | ||
861 | { | ||
862 | return param_view( | ||
863 | 783 | key, value, has_value); | |
864 | } | ||
865 | |||
866 | #ifndef BOOST_URL_DOCS | ||
867 | /// Arrow support | ||
868 | param_pct_view const* | ||
869 | 21 | operator->() const noexcept | |
870 | { | ||
871 | 21 | return this; | |
872 | } | ||
873 | |||
874 | /// aggregate construction | ||
875 | 635 | param_pct_view( | |
876 | pct_string_view key, | ||
877 | pct_string_view value, | ||
878 | bool has_value) noexcept | ||
879 | 635 | : key(key) | |
880 |
2/2✓ Branch 0 taken 257 times.
✓ Branch 1 taken 378 times.
|
635 | , value(has_value |
881 | ? value | ||
882 | : pct_string_view()) | ||
883 | 635 | , has_value(has_value) | |
884 | { | ||
885 | 635 | } | |
886 | #endif | ||
887 | |||
888 | private: | ||
889 | 638 | param_pct_view( | |
890 | pct_string_view key, | ||
891 | detail::optional_string const& value) | ||
892 | 638 | : param_pct_view(key, value.s, value.b) | |
893 | { | ||
894 | 635 | } | |
895 | }; | ||
896 | |||
897 | //------------------------------------------------ | ||
898 | |||
899 | inline | ||
900 | param& | ||
901 | 1 | param:: | |
902 | operator=( | ||
903 | param_view const& other) | ||
904 | { | ||
905 | // VFALCO operator= assignment | ||
906 | // causes a loss of original capacity: | ||
907 | // https://godbolt.org/z/nYef8445K | ||
908 | // | ||
909 | // key = other.key; | ||
910 | // value = other.value; | ||
911 | |||
912 | // preserve capacity | ||
913 | 1 | key.assign( | |
914 | other.key.data(), | ||
915 | other.key.size()); | ||
916 | 1 | value.assign( | |
917 | other.value.data(), | ||
918 | other.value.size()); | ||
919 | 1 | has_value = other.has_value; | |
920 | 1 | return *this; | |
921 | } | ||
922 | |||
923 | inline | ||
924 | param& | ||
925 | 1 | param:: | |
926 | operator=( | ||
927 | param_pct_view const& other) | ||
928 | { | ||
929 | // preserve capacity | ||
930 | 1 | key.assign( | |
931 | other.key.data(), | ||
932 | other.key.size()); | ||
933 | 1 | value.assign( | |
934 | other.value.data(), | ||
935 | other.value.size()); | ||
936 | 1 | has_value = other.has_value; | |
937 | 1 | return *this; | |
938 | } | ||
939 | |||
940 | } // urls | ||
941 | } // boost | ||
942 | |||
943 | #endif | ||
944 |