Line data Source code
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 @ref 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 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 16 : param(
279 : core::string_view key,
280 : OptionalString const& value)
281 16 : : param(key, detail::get_optional_string(value))
282 : {
283 16 : }
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 : /** Arrow support
328 :
329 : This operator returns the address of the
330 : object so that it can be used in pointer
331 : contexts.
332 :
333 : */
334 : param const*
335 1 : operator->() const noexcept
336 : {
337 1 : return this;
338 : }
339 :
340 : /// Aggregate construction
341 794 : param(
342 : core::string_view key,
343 : core::string_view value,
344 : bool has_value) noexcept
345 794 : : key(key)
346 794 : , value(has_value
347 794 : ? value
348 : : core::string_view())
349 794 : , has_value(has_value)
350 : {
351 794 : }
352 :
353 : private:
354 16 : param(
355 : core::string_view key,
356 : detail::optional_string const& value)
357 16 : : param(key, value.s, value.b)
358 : {
359 16 : }
360 : };
361 :
362 : //------------------------------------------------
363 :
364 : /** A view of a query parameter
365 :
366 : Objects of this type represent a single key
367 : and value pair in a query string where a key
368 : is always present and may be empty, while the
369 : presence of a value is indicated by
370 : @ref has_value equal to true.
371 : An empty value is distinct from no value.
372 :
373 : Depending on where the object was obtained,
374 : the strings may or may not contain percent
375 : escapes.
376 :
377 : For most usages, key comparisons are
378 : case-sensitive and duplicate keys in
379 : a query are possible. However, it is
380 : the authority that has final control
381 : over how the query is interpreted.
382 :
383 : <br>
384 :
385 : Keys and values in this object reference
386 : external character buffers.
387 : Ownership of the buffers is not transferred;
388 : the caller is responsible for ensuring that
389 : the assigned buffers remain valid until
390 : they are no longer referenced.
391 :
392 : @par BNF
393 : @code
394 : query-params = query-param *( "&" query-param )
395 : query-param = key [ "=" value ]
396 : key = *qpchar
397 : value = *( qpchar / "=" )
398 : @endcode
399 :
400 : @par Specification
401 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
402 : >Query string (Wikipedia)</a>
403 :
404 : @see
405 : @ref param,
406 : @ref param_pct_view.
407 : */
408 : struct param_view
409 : {
410 : /** The key
411 :
412 : For most usages, key comparisons are
413 : case-sensitive and duplicate keys in
414 : a query are possible. However, it is
415 : the authority that has final control
416 : over how the query is interpreted.
417 : */
418 : core::string_view key;
419 :
420 : /** The value
421 :
422 : The presence of a value is indicated by
423 : @ref has_value equal to true.
424 : An empty value is distinct from no value.
425 : */
426 : core::string_view value;
427 :
428 : /** True if a value is present
429 :
430 : The presence of a value is indicated by
431 : `has_value == true`.
432 : An empty value is distinct from no value.
433 : */
434 : bool has_value = false;
435 :
436 : //--------------------------------------------
437 :
438 : /** Constructor
439 :
440 : Default constructed query parameters
441 : have an empty key and no value.
442 :
443 : @par Example
444 : @code
445 : param_view qp;
446 : @endcode
447 :
448 : @par Postconditions
449 : @code
450 : this->key == "" && this->value == "" && this->has_value == false
451 : @endcode
452 :
453 : @par Complexity
454 : Constant.
455 :
456 : @par Exception Safety
457 : Throws nothing.
458 : */
459 : param_view() = default;
460 :
461 : /** Constructor
462 :
463 : This constructs a parameter with a key
464 : and value.
465 : No validation is performed on the strings.
466 : The new key and value reference
467 : the same corresponding underlying
468 : character buffers.
469 : Ownership of the buffers is not transferred;
470 : the caller is responsible for ensuring that
471 : the assigned buffers remain valid until
472 : they are no longer referenced.
473 :
474 : @par Example
475 : @code
476 : param_view qp( "key", "value" );
477 : @endcode
478 :
479 : @par Postconditions
480 : @code
481 : this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
482 : @endcode
483 :
484 : @par Complexity
485 : Constant.
486 :
487 : @par Exception Safety
488 : Throws nothing.
489 :
490 : @tparam OptionalString An optional string
491 : type, such as `core::string_view`,
492 : `std::nullptr`, @ref no_value_t, or
493 : `optional<core::string_view>`.
494 :
495 : @param key, value The key and value to set.
496 : */
497 : template <class OptionalString>
498 167 : param_view(
499 : core::string_view key,
500 : OptionalString const& value) noexcept
501 167 : : param_view(key, detail::get_optional_string(value))
502 : {
503 167 : }
504 :
505 : /** Constructor
506 :
507 : This function constructs a param
508 : which references the character buffers
509 : representing the key and value in another
510 : container.
511 : Ownership of the buffers is not transferred;
512 : the caller is responsible for ensuring that
513 : the assigned buffers remain valid until
514 : they are no longer referenced.
515 :
516 : @par Example
517 : @code
518 : param qp( "key", "value" );
519 : param_view qpv( qp );
520 : @endcode
521 :
522 : @par Postconditions
523 : @code
524 : this->key == key && this->value == value && this->has_value == other.has_value
525 : @endcode
526 :
527 : @par Complexity
528 : Constant.
529 :
530 : @par Exception Safety
531 : Throws nothing.
532 :
533 : @param other The param to reference
534 : */
535 754 : param_view(
536 : param const& other) noexcept
537 754 : : param_view(
538 754 : other.key,
539 754 : other.value,
540 754 : other.has_value)
541 : {
542 754 : }
543 :
544 : /** Conversion
545 :
546 : This function performs a conversion from
547 : a reference-like query parameter to one
548 : retaining ownership of the strings by
549 : making a copy.
550 : No validation is performed on the strings.
551 :
552 : @par Complexity
553 : Linear in `this->key.size() + this->value.size()`.
554 :
555 : @par Exception Safety
556 : Calls to allocate may throw.
557 : */
558 : explicit
559 4 : operator
560 : param()
561 : {
562 4 : return { key, value, has_value };
563 : }
564 :
565 : /** Arrow support
566 :
567 : This operator returns the address of the
568 : object so that it can be used in pointer
569 : contexts.
570 :
571 : */
572 : param_view const*
573 : operator->() const noexcept
574 : {
575 : return this;
576 : }
577 :
578 : /// Aggregate construction
579 1718 : param_view(
580 : core::string_view key_,
581 : core::string_view value_,
582 : bool has_value_) noexcept
583 1718 : : key(key_)
584 1718 : , value(has_value_
585 1718 : ? value_
586 : : core::string_view())
587 1718 : , has_value(has_value_)
588 : {
589 1718 : }
590 :
591 : private:
592 167 : param_view(
593 : core::string_view key,
594 : detail::optional_string const& value)
595 167 : : param_view(key, value.s, value.b)
596 : {
597 167 : }
598 : };
599 :
600 : //------------------------------------------------
601 :
602 : /** A view of a percent-encoded query parameter
603 :
604 : Objects of this type represent a single key
605 : and value pair in a query string where a key
606 : is always present and may be empty, while the
607 : presence of a value is indicated by
608 : @ref has_value equal to true.
609 : An empty value is distinct from no value.
610 :
611 : The strings may have percent escapes, and
612 : offer an additional invariant: they never
613 : contain an invalid percent-encoding.
614 :
615 : For most usages, key comparisons are
616 : case-sensitive and duplicate keys in
617 : a query are possible. However, it is
618 : the authority that has final control
619 : over how the query is interpreted.
620 :
621 : <br>
622 :
623 : Keys and values in this object reference
624 : external character buffers.
625 : Ownership of the buffers is not transferred;
626 : the caller is responsible for ensuring that
627 : the assigned buffers remain valid until
628 : they are no longer referenced.
629 :
630 : @par BNF
631 : @code
632 : query-params = query-param *( "&" query-param )
633 : query-param = key [ "=" value ]
634 : key = *qpchar
635 : value = *( qpchar / "=" )
636 : @endcode
637 :
638 : @par Specification
639 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
640 : >Query string (Wikipedia)</a>
641 :
642 : @see
643 : @ref param,
644 : @ref param_view.
645 : */
646 : struct param_pct_view
647 : {
648 : /** The key
649 :
650 : For most usages, key comparisons are
651 : case-sensitive and duplicate keys in
652 : a query are possible. However, it is
653 : the authority that has final control
654 : over how the query is interpreted.
655 : */
656 : pct_string_view key;
657 :
658 : /** The value
659 :
660 : The presence of a value is indicated by
661 : @ref has_value equal to true.
662 : An empty value is distinct from no value.
663 : */
664 : pct_string_view value;
665 :
666 : /** True if a value is present
667 :
668 : The presence of a value is indicated by
669 : `has_value == true`.
670 : An empty value is distinct from no value.
671 : */
672 : bool has_value = false;
673 :
674 : //--------------------------------------------
675 :
676 : /** Constructor
677 :
678 : Default constructed query parameters
679 : have an empty key and no value.
680 :
681 : @par Example
682 : @code
683 : param_pct_view qp;
684 : @endcode
685 :
686 : @par Postconditions
687 : @code
688 : this->key == "" && this->value == "" && this->has_value == false
689 : @endcode
690 :
691 : @par Complexity
692 : Constant.
693 :
694 : @par Exception Safety
695 : Throws nothing.
696 : */
697 : param_pct_view() = default;
698 :
699 : /** Constructor
700 :
701 : This constructs a parameter with a key
702 : and value, which may both contain percent
703 : escapes.
704 : The new key and value reference
705 : the same corresponding underlying
706 : character buffers.
707 : Ownership of the buffers is not transferred;
708 : the caller is responsible for ensuring that
709 : the assigned buffers remain valid until
710 : they are no longer referenced.
711 :
712 : @par Example
713 : @code
714 : param_pct_view qp( "key", "value" );
715 : @endcode
716 :
717 : @par Postconditions
718 : @code
719 : this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
720 : @endcode
721 :
722 : @par Complexity
723 : Linear in `key.size() + value.size()`.
724 :
725 : @par Exception Safety
726 : Exceptions thrown on invalid input.
727 :
728 : @throw system_error
729 : `key` or `value` contains an invalid percent-encoding.
730 :
731 : @param key, value The key and value to set.
732 : */
733 1096 : param_pct_view(
734 : pct_string_view key,
735 : pct_string_view value) noexcept
736 1096 : : key(key)
737 1096 : , value(value)
738 1096 : , has_value(true)
739 : {
740 1096 : }
741 :
742 : /** Constructor
743 :
744 : This constructs a parameter with a key
745 : and optional value, which may both
746 : contain percent escapes.
747 :
748 : The new key and value reference
749 : the same corresponding underlying
750 : character buffers.
751 :
752 : Ownership of the buffers is not transferred;
753 : the caller is responsible for ensuring that
754 : the assigned buffers remain valid until
755 : they are no longer referenced.
756 :
757 : @par Example
758 : @code
759 : param_pct_view qp( "key", optional<core::string_view>("value") );
760 : @endcode
761 :
762 : @par Postconditions
763 : @code
764 : this->key.data() == key.data() && this->value->data() == value->data() && this->has_value == true
765 : @endcode
766 :
767 : @par Complexity
768 : Linear in `key.size() + value->size()`.
769 :
770 : @par Exception Safety
771 : Exceptions thrown on invalid input.
772 :
773 : @throw system_error
774 : `key` or `value` contains an invalid percent-encoding.
775 :
776 : @tparam OptionalString An optional
777 : `core::string_view` type, such as
778 : `boost::optional<core::string_view>` or
779 : `std::optional<core::string_view>`.
780 :
781 : @param key, value The key and value to set.
782 : */
783 : template <class OptionalString>
784 649 : param_pct_view(
785 : pct_string_view key,
786 : OptionalString const& value)
787 649 : : param_pct_view(key, detail::get_optional_string(value))
788 : {
789 646 : }
790 :
791 : /** Construction
792 :
793 : This converts a param which may
794 : contain unvalidated percent-escapes into
795 : a param whose key and value are
796 : guaranteed to contain strings with no
797 : invalid percent-escapes, otherwise
798 : an exception is thrown.
799 :
800 : The new key and value reference
801 : the same corresponding underlying
802 : character buffers.
803 : Ownership of the buffers is not transferred;
804 : the caller is responsible for ensuring that
805 : the assigned buffers remain valid until
806 : they are no longer referenced.
807 :
808 : @par Example
809 : @code
810 : param_pct_view qp( param_view( "key", "value" ) );
811 : @endcode
812 :
813 : @par Complexity
814 : Linear in `key.size() + value.size()`.
815 :
816 : @par Exception Safety
817 : Exceptions thrown on invalid input.
818 :
819 : @throw system_error
820 : `key` or `value` contains an invalid percent escape.
821 :
822 : @param p The param to construct from.
823 : */
824 : explicit
825 56 : param_pct_view(
826 : param_view const& p)
827 56 : : key(p.key)
828 52 : , value(p.has_value
829 52 : ? pct_string_view(p.value)
830 : : pct_string_view())
831 51 : , has_value(p.has_value)
832 : {
833 51 : }
834 :
835 : /** Conversion
836 :
837 : This function performs a conversion from
838 : a reference-like query parameter to one
839 : retaining ownership of the strings by
840 : making a copy.
841 :
842 : @par Complexity
843 : Linear in `this->key.size() + this->value.size()`.
844 :
845 : @par Exception Safety
846 : Calls to allocate may throw.
847 : */
848 : explicit
849 2 : operator
850 : param() const
851 : {
852 : return param(
853 4 : static_cast<std::string>(key),
854 6 : static_cast<std::string>(value),
855 6 : has_value);
856 : }
857 :
858 : /** Conversion to param_view
859 :
860 : This function performs a conversion from
861 : a pct_string_view query parameter to one
862 : using a simple string_view.
863 :
864 : @par Exception Safety
865 : Calls to allocate may throw.
866 : */
867 797 : operator
868 : param_view() const noexcept
869 : {
870 : return param_view(
871 797 : key, value, has_value);
872 : }
873 :
874 : /** Arrow support
875 :
876 : This operator returns the address of the
877 : object so that it can be used in pointer
878 : contexts.
879 :
880 : */
881 : param_pct_view const*
882 21 : operator->() const noexcept
883 : {
884 21 : return this;
885 : }
886 :
887 : /// Aggregate construction
888 646 : param_pct_view(
889 : pct_string_view key,
890 : pct_string_view value,
891 : bool has_value) noexcept
892 646 : : key(key)
893 646 : , value(has_value
894 646 : ? value
895 : : pct_string_view())
896 646 : , has_value(has_value)
897 : {
898 646 : }
899 :
900 : private:
901 649 : param_pct_view(
902 : pct_string_view key,
903 : detail::optional_string const& value)
904 649 : : param_pct_view(key, value.s, value.b)
905 : {
906 646 : }
907 : };
908 :
909 : //------------------------------------------------
910 :
911 : inline
912 : param&
913 1 : param::
914 : operator=(
915 : param_view const& other)
916 : {
917 : // VFALCO operator= assignment
918 : // causes a loss of original capacity:
919 : // https://godbolt.org/z/nYef8445K
920 : //
921 : // key = other.key;
922 : // value = other.value;
923 :
924 : // preserve capacity
925 1 : key.assign(
926 : other.key.data(),
927 : other.key.size());
928 1 : value.assign(
929 : other.value.data(),
930 : other.value.size());
931 1 : has_value = other.has_value;
932 1 : return *this;
933 : }
934 :
935 : inline
936 : param&
937 1 : param::
938 : operator=(
939 : param_pct_view const& other)
940 : {
941 : // preserve capacity
942 1 : key.assign(
943 : other.key.data(),
944 : other.key.size());
945 1 : value.assign(
946 : other.value.data(),
947 : other.value.size());
948 1 : has_value = other.has_value;
949 1 : return *this;
950 : }
951 :
952 : } // urls
953 : } // boost
954 :
955 : #endif
|