GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/param.hpp
Date: 2025-04-22 15:26:26
Exec Total Coverage
Lines: 90 90 100.0%
Functions: 52 53 98.1%
Branches: 14 16 87.5%

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