GCC Code Coverage Report


Directory: libs/url/
File: boost/url/param.hpp
Date: 2024-03-15 21:27:27
Exec Total Coverage
Lines: 83 83 100.0%
Functions: 52 53 98.1%
Branches: 11 12 91.7%

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 1 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 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 , value(has_value
342
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 170 times.
780 ? value
343 : core::string_view())
344 1560 , 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 , value(has_value_
576 ? value_
577 : core::string_view())
578
2/2
✓ Branch 0 taken 1331 times.
✓ Branch 1 taken 359 times.
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 , 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 52 , value(p.has_value
821 ? pct_string_view(p.value)
822 : pct_string_view())
823
2/2
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 9 times.
56 , 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 783 operator
851 param_view() const noexcept
852 {
853 return param_view(
854 783 key, value, has_value);
855 }
856
857 #ifndef BOOST_URL_DOCS
858 // arrow support
859 param_pct_view const*
860 21 operator->() const noexcept
861 {
862 21 return this;
863 }
864
865 // aggregate construction
866 635 param_pct_view(
867 pct_string_view key,
868 pct_string_view value,
869 bool has_value) noexcept
870 635 : key(key)
871 , value(has_value
872 ? value
873 : pct_string_view())
874
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 378 times.
635 , has_value(has_value)
875 {
876 635 }
877 #endif
878
879 private:
880 638 param_pct_view(
881 pct_string_view key,
882 detail::optional_string const& value)
883 638 : param_pct_view(key, value.s, value.b)
884 {
885 635 }
886 };
887
888 //------------------------------------------------
889
890 inline
891 param&
892 1 param::
893 operator=(
894 param_view const& other)
895 {
896 // VFALCO operator= assignment
897 // causes a loss of original capacity:
898 // https://godbolt.org/z/nYef8445K
899 //
900 // key = other.key;
901 // value = other.value;
902
903 // preserve capacity
904 key.assign(
905 other.key.data(),
906 1 other.key.size());
907 value.assign(
908 other.value.data(),
909 1 other.value.size());
910 1 has_value = other.has_value;
911 1 return *this;
912 }
913
914 inline
915 param&
916 1 param::
917 operator=(
918 param_pct_view const& other)
919 {
920 // preserve capacity
921 key.assign(
922 other.key.data(),
923 1 other.key.size());
924 value.assign(
925 other.value.data(),
926 1 other.value.size());
927 1 has_value = other.has_value;
928 1 return *this;
929 }
930
931 } // urls
932 } // boost
933
934 #endif
935