GCC Code Coverage Report


Directory: ./
File: libs/url/include/boost/url/param.hpp
Date: 2026-01-20 15:14:26
Exec Total Coverage
Lines: 90 90 100.0%
Functions: 52 53 98.1%
Branches: 12 12 100.0%

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