GCC Code Coverage Report


Directory: libs/url/
File: include/boost/url/params_ref.hpp
Date: 2025-11-13 05:23:43
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 1 1 100.0%
Branches: 0 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_PARAMS_REF_HPP
12 #define BOOST_URL_PARAMS_REF_HPP
13
14 #include <boost/url/detail/config.hpp>
15 #include <boost/url/ignore_case.hpp>
16 #include <boost/url/params_base.hpp>
17 #include <initializer_list>
18 #include <iterator>
19
20 namespace boost {
21 namespace urls {
22
23 #ifndef BOOST_URL_DOCS
24 class url_base;
25 class params_view;
26 #endif
27
28 /** Mutable decoded query parameter proxy
29
30 This container presents the decoded query
31 parameters of a @ref url_base as a bidirectional
32 range whose modifying operations update the
33 underlying URL in-place. It references (but
34 does not own) the character buffer, so the
35 referenced URL must stay alive while the proxy
36 is used.
37
38 <br>
39
40 Percent escapes in strings returned when
41 dereferencing iterators are automatically
42 decoded.
43 Reserved characters in strings supplied
44 to modifier functions are automatically
45 percent-escaped.
46
47 @par Example
48 @code
49 url u( "?first=John&last=Doe" );
50
51 params_ref p = u.params();
52 @endcode
53
54 @par Iterator Invalidation
55 Changes to the underlying character buffer
56 can invalidate iterators which reference it.
57 Modifications made through the container
58 invalidate some or all iterators:
59 <br>
60
61 @li @ref append : Only `end()`.
62
63 @li @ref assign, @ref clear,
64 `operator=` : All elements.
65
66 @li @ref erase : Erased elements and all
67 elements after (including `end()`).
68
69 @li @ref insert : All elements at or after
70 the insertion point (including `end()`).
71
72 @li @ref replace, @ref set : Modified
73 elements and all elements
74 after (including `end()`).
75
76 @par Reads vs. writes
77 Although this is a mutable proxy, all
78 observer helpers inherited from
79 @ref params_base (such as @ref contains,
80 @ref find, and @ref get_or) operate in the
81 same way as they do on @ref params_view:
82 they perform their lookup against the
83 current contents of the referenced URL
84 without modifying it.
85 */
86 class BOOST_URL_DECL params_ref
87 : public params_base
88 {
89 friend class url_base;
90
91 url_base* u_ = nullptr;
92
93 params_ref(
94 url_base& u,
95 encoding_opts opt) noexcept;
96
97 public:
98 //--------------------------------------------
99 //
100 // Special Members
101 //
102 //--------------------------------------------
103
104 /** Constructor
105
106 After construction, both views
107 reference the same url. Ownership is not
108 transferred; the caller is responsible
109 for ensuring the lifetime of the url
110 extends until it is no longer
111 referenced.
112
113 @par Postconditions
114 @code
115 &this->url() == &other.url()
116 @endcode
117
118 @par Complexity
119 Constant.
120
121 @par Exception Safety
122 Throws nothing.
123
124 @param other The other view.
125 */
126 params_ref(
127 params_ref const& other) = default;
128
129 /** Constructor
130
131 After construction, both views will
132 reference the same url but this
133 instance will use the specified
134 @ref encoding_opts when the values
135 are decoded.
136
137 Ownership is not transferred; the
138 caller is responsible for ensuring
139 the lifetime of the url extends
140 until it is no longer referenced.
141
142 @par Postconditions
143 @code
144 &this->url() == &other.url()
145 @endcode
146
147 @par Complexity
148 Constant.
149
150 @par Exception Safety
151 Throws nothing.
152
153 @param other The other view.
154 @param opt The options for decoding. If
155 this parameter is omitted, `space_as_plus`
156 is used.
157
158 */
159 params_ref(
160 params_ref const& other,
161 encoding_opts opt) noexcept;
162
163 /** Assignment
164
165 The previous contents of this are
166 replaced by the contents of `other.
167
168 <br>
169 All iterators are invalidated.
170
171 @note
172 The strings referenced by `other`
173 must not come from the underlying url,
174 or else the behavior is undefined.
175
176 @par Effects
177 @code
178 this->assign( other.begin(), other.end() );
179 @endcode
180
181 @par Complexity
182 Linear in `other.buffer().size()`.
183
184 @par Exception Safety
185 Strong guarantee.
186 Calls to allocate may throw.
187
188 @param other The params to assign.
189 @return `*this`
190 */
191 params_ref&
192 operator=(
193 params_ref const& other);
194
195 /** Assignment
196
197 After assignment, the previous contents
198 of the query parameters are replaced by
199 the contents of the initializer-list.
200
201 @par Preconditions
202 None of character buffers referenced by
203 `init` may overlap the character buffer of
204 the underlying url, or else the behavior
205 is undefined.
206
207 @par Effects
208 @code
209 this->assign( init );
210 @endcode
211
212 @par Complexity
213 Linear in `init.size()`.
214
215 @par Exception Safety
216 Strong guarantee.
217 Calls to allocate may throw.
218
219 @param init The list of params to assign.
220 @return `*this`
221 */
222 params_ref&
223 operator=(
224 std::initializer_list<
225 param_view> init);
226
227 /** Conversion
228
229 @return A view of the query parameters.
230 */
231 operator
232 params_view() const noexcept;
233
234 //--------------------------------------------
235 //
236 // Observers
237 //
238 //--------------------------------------------
239
240 /** Return the referenced url
241
242 This function returns the url referenced
243 by the view.
244
245 @par Example
246 @code
247 url u( "?key=value" );
248
249 assert( &u.segments().url() == &u );
250 @endcode
251
252 @par Exception Safety
253 @code
254 Throws nothing.
255 @endcode
256
257 @return A reference to the url.
258 */
259 url_base&
260 10 url() const noexcept
261 {
262 10 return *u_;
263 }
264
265 //--------------------------------------------
266 //
267 // Modifiers
268 //
269 //--------------------------------------------
270
271 /** Clear the contents of the container
272
273 <br>
274 All iterators are invalidated.
275
276 @par Effects
277 @code
278 this->url().remove_query();
279 @endcode
280
281 @par Postconditions
282 @code
283 this->empty() == true && this->url().has_query() == false
284 @endcode
285
286 @par Complexity
287 Constant.
288
289 @par Exception Safety
290 Throws nothing.
291 */
292 void
293 clear() noexcept;
294
295 //--------------------------------------------
296
297 /** Assign elements
298
299 This function replaces the entire
300 contents of the view with the params
301 in the <em>initializer-list</em>.
302
303 <br>
304 All iterators are invalidated.
305
306 @note
307 The strings referenced by the inputs
308 must not come from the underlying url,
309 or else the behavior is undefined.
310
311 @par Example
312 @code
313 url u;
314
315 u.params().assign( {{ "first", "John" }, { "last", "Doe" }} );
316 @endcode
317
318 @par Complexity
319 Linear in `init.size()`.
320
321 @par Exception Safety
322 Strong guarantee.
323 Calls to allocate may throw.
324
325 @param init The list of params to assign.
326 */
327 void
328 assign(
329 std::initializer_list<
330 param_view> init);
331
332 /** Assign elements
333
334 This function replaces the entire
335 contents of the view with the params
336 in the range.
337
338 <br>
339 All iterators are invalidated.
340
341 @note
342 The strings referenced by the inputs
343 must not come from the underlying url,
344 or else the behavior is undefined.
345
346 @par Mandates
347 @code
348 std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true
349 @endcode
350
351 @par Complexity
352 Linear in the size of the range.
353
354 @par Exception Safety
355 Strong guarantee.
356 Calls to allocate may throw.
357
358 @param first The first element to assign.
359 @param last One past the last element to assign.
360 */
361 template<class FwdIt>
362 void
363 assign(FwdIt first, FwdIt last);
364
365 //--------------------------------------------
366
367 /** Append elements
368
369 This function appends a param to the view.
370
371 <br>
372 The `end()` iterator is invalidated.
373
374 @par Example
375 @code
376 url u;
377
378 u.params().append( { "first", "John" } );
379 @endcode
380
381 @par Complexity
382 Linear in `this->url().encoded_query().size()`.
383
384 @par Exception Safety
385 Strong guarantee.
386 Calls to allocate may throw.
387
388 @return An iterator to the new element.
389
390 @param p The param to append.
391 */
392 iterator
393 append(
394 param_view const& p);
395
396 /** Append elements
397
398 This function appends the params in
399 an <em>initializer-list</em> to the view.
400
401 <br>
402 The `end()` iterator is invalidated.
403
404 @par Example
405 @code
406 url u;
407
408 u.params().append({ { "first", "John" }, { "last", "Doe" } });
409 @endcode
410
411 @par Complexity
412 Linear in `this->url().encoded_query().size()`.
413
414 @par Exception Safety
415 Strong guarantee.
416 Calls to allocate may throw.
417
418 @return An iterator to the first new element.
419
420 @param init The list of params to append.
421 */
422 iterator
423 append(
424 std::initializer_list<
425 param_view> init);
426
427 /** Append elements
428
429 This function appends a range of params
430 to the view.
431
432 <br>
433 The `end()` iterator is invalidated.
434
435 @note
436 The strings referenced by the inputs
437 must not come from the underlying url,
438 or else the behavior is undefined.
439
440 @par Mandates
441 @code
442 std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true
443 @endcode
444
445 @par Complexity
446 Linear in `this->url().encoded_query().size()`.
447
448 @par Exception Safety
449 Strong guarantee.
450 Calls to allocate may throw.
451
452 @param first The first element to append.
453 @param last One past the last element to append.
454 @return An iterator to the first new element.
455 */
456 template<class FwdIt>
457 iterator
458 append(
459 FwdIt first, FwdIt last);
460
461 //--------------------------------------------
462
463 /** Insert elements
464
465 This function inserts a param
466 before the specified position.
467
468 <br>
469 All iterators that are equal to
470 `before` or come after are invalidated.
471
472 @par Complexity
473 Linear in `this->url().encoded_query().size()`.
474
475 @par Exception Safety
476 Strong guarantee.
477 Calls to allocate may throw.
478
479 @return An iterator to the inserted
480 element.
481
482 @param before An iterator before which
483 the param is inserted. This may
484 be equal to `end()`.
485
486 @param p The param to insert.
487 */
488 iterator
489 insert(
490 iterator before,
491 param_view const& p);
492
493 /** Insert elements
494
495 This function inserts the params in
496 an <em>initializer-list</em> before
497 the specified position.
498
499 <br>
500 All iterators that are equal to
501 `before` or come after are invalidated.
502
503 @note
504 The strings referenced by the inputs
505 must not come from the underlying url,
506 or else the behavior is undefined.
507
508 @par Complexity
509 Linear in `this->url().encoded_query().size()`.
510
511 @par Exception Safety
512 Strong guarantee.
513 Calls to allocate may throw.
514
515 @return An iterator to the first
516 element inserted, or `before` if
517 `init.size() == 0`.
518
519 @param before An iterator before which
520 the element is inserted. This may
521 be equal to `end()`.
522
523 @param init The list of params to insert.
524 */
525 iterator
526 insert(
527 iterator before,
528 std::initializer_list<
529 param_view> init);
530
531 /** Insert elements
532
533 This function inserts a range of
534 params before the specified position.
535
536 <br>
537 All iterators that are equal to
538 `before` or come after are invalidated.
539
540 @note
541 The strings referenced by the inputs
542 must not come from the underlying url,
543 or else the behavior is undefined.
544
545 @par Mandates
546 @code
547 std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true
548 @endcode
549
550 @par Complexity
551 Linear in `this->url().encoded_query().size()`.
552
553 @par Exception Safety
554 Strong guarantee.
555 Calls to allocate may throw.
556
557 @return An iterator to the first
558 element inserted, or `before` if
559 `first == last`.
560
561 @param before An iterator before which
562 the element is inserted. This may
563 be equal to `end()`.
564 @param first The first element to insert.
565 @param last One past the last element to insert.
566 @return An iterator to the first element inserted, or `before` if `first == last`.
567 */
568 template<class FwdIt>
569 iterator
570 insert(
571 iterator before,
572 FwdIt first,
573 FwdIt last);
574
575 //--------------------------------------------
576
577 /** Erase elements
578
579 This function removes an element from
580 the container.
581
582 <br>
583 All iterators that are equal to
584 `pos` or come after are invalidated.
585
586 @par Example
587 @code
588 url u( "?first=John&last=Doe" );
589
590 params_ref::iterator it = u.params().erase( u.params().begin() );
591
592 assert( u.encoded_query() == "last=Doe" );
593 @endcode
594
595 @par Complexity
596 Linear in `this->url().encoded_query().size()`.
597
598 @par Exception Safety
599 Throws nothing.
600
601 @return An iterator to one past
602 the removed element.
603
604 @param pos An iterator to the element.
605 */
606 iterator
607 erase(iterator pos) noexcept;
608
609 /** Erase elements
610
611 This function removes a range of elements
612 from the container.
613
614 <br>
615 All iterators that are equal to
616 `first` or come after are invalidated.
617
618 @par Complexity
619 Linear in `this->url().encoded_query().size()`.
620
621 @par Exception Safety
622 Throws nothing.
623
624 @param first The first element to remove.
625 @param last One past the last element to remove.
626 @return An iterator to one past the removed range.
627 */
628 iterator
629 erase(
630 iterator first,
631 iterator last) noexcept;
632
633 /** Erase elements
634
635 <br>
636 All iterators are invalidated.
637
638 @par Postconditions
639 @code
640 this->count( key, ic ) == 0
641 @endcode
642
643 @par Complexity
644 Linear in `this->url().encoded_query().size()`.
645
646 @par Exception Safety
647 Throws nothing.
648
649 @return The number of elements removed
650 from the container.
651
652 @param key The key to match.
653 By default, a case-sensitive
654 comparison is used.
655
656 @param ic An optional parameter. If
657 the value @ref ignore_case is passed
658 here, the comparison is
659 case-insensitive.
660 */
661 std::size_t
662 erase(
663 core::string_view key,
664 ignore_case_param ic = {}) noexcept;
665
666 //--------------------------------------------
667
668 /** Replace elements
669
670 This function replaces the contents
671 of the element at `pos` with the
672 specified param.
673
674 <br>
675 All iterators that are equal to
676 `pos` or come after are invalidated.
677
678 @par Example
679 @code
680 url u( "?first=John&last=Doe" );
681
682 u.params().replace( u.params().begin(), { "title", "Mr" });
683
684 assert( u.encoded_query() == "title=Mr&last=Doe" );
685 @endcode
686
687 @par Complexity
688 Linear in `this->url().encoded_query().size()`.
689
690 @par Exception Safety
691 Strong guarantee.
692 Calls to allocate may throw.
693
694 @return An iterator to the element.
695
696 @param pos An iterator to the element.
697
698 @param p The param to assign.
699 */
700 iterator
701 replace(
702 iterator pos,
703 param_view const& p);
704
705 /** Replace elements
706
707 This function replaces a range of
708 elements with the params in an
709 <em>initializer-list</em>.
710
711 <br>
712 All iterators that are equal to
713 `from` or come after are invalidated.
714
715 @note
716 The strings referenced by the inputs
717 must not come from the underlying url,
718 or else the behavior is undefined.
719
720 @par Complexity
721 Linear in `this->url().encoded_query().size()`.
722
723 @par Exception Safety
724 Strong guarantee.
725 Calls to allocate may throw.
726
727 @return An iterator to the first
728 element inserted, or one past `to` if
729 `init.size() == 0`.
730
731 @param from,to The range of elements
732 to replace.
733
734 @param init The list of params to assign.
735 */
736 iterator
737 replace(
738 iterator from,
739 iterator to,
740 std::initializer_list<
741 param_view> init);
742
743 /** Replace elements
744
745 This function replaces a range of
746 elements with a range of params.
747
748 <br>
749 All iterators that are equal to
750 `from` or come after are invalidated.
751
752 @note
753 The strings referenced by the inputs
754 must not come from the underlying url,
755 or else the behavior is undefined.
756
757 @par Mandates
758 @code
759 std::is_convertible< std::iterator_traits< FwdIt >::reference_type, param_view >::value == true
760 @endcode
761
762 @par Complexity
763 Linear in `this->url().encoded_query().size()`.
764
765 @par Exception Safety
766 Strong guarantee.
767 Calls to allocate may throw.
768
769 @return An iterator to the first
770 element inserted, or one past `to` if
771 `first == last`.
772
773 @param from The first element to replace.
774 @param to One past the last element to replace.
775 @param first The first element to insert.
776 @param last One past the last element to insert.
777 @return An iterator to the first element inserted, or one past `to` if `first == last`.
778 */
779 template<class FwdIt>
780 iterator
781 replace(
782 iterator from,
783 iterator to,
784 FwdIt first,
785 FwdIt last);
786
787 //--------------------------------------------
788
789 /** Remove the value on an element
790
791 This function removes the value of
792 an element at the specified position.
793 After the call returns, `has_value`
794 for the element is false.
795
796 <br>
797 All iterators that are equal to
798 `pos` or come after are invalidated.
799
800 @par Example
801 @code
802 url u( "?first=John&last=Doe" );
803
804 u.params().unset( u.params().begin() );
805
806 assert( u.encoded_query() == "first&last=Doe" );
807 @endcode
808
809 @par Complexity
810 Linear in `this->url().encoded_query().size()`.
811
812 @par Exception Safety
813 Throws nothing.
814
815 @return An iterator to the element.
816
817 @param pos An iterator to the element.
818 */
819 iterator
820 unset(
821 iterator pos) noexcept;
822
823 /** Set a value
824
825 This function replaces the value of an
826 element at the specified position.
827
828 <br>
829 All iterators that are equal to
830 `pos` or come after are invalidated.
831
832 @par Example
833 @code
834 url u( "?id=42&id=69" );
835
836 u.params().set( u.params().begin(), "none" );
837
838 assert( u.encoded_query() == "id=none&id=69" );
839 @endcode
840
841 @par Complexity
842 Linear in `this->url().encoded_query().size()`.
843
844 @par Exception Safety
845 Strong guarantee.
846 Calls to allocate may throw.
847
848 @return An iterator to the element.
849
850 @param pos An iterator to the element.
851
852 @param value The value to assign. The
853 empty string still counts as a value.
854 That is, `has_value` for the element
855 is true.
856 */
857 iterator
858 set(
859 iterator pos,
860 core::string_view value);
861
862 /** Set a value
863
864 This function performs one of two
865 actions depending on the value of
866 `this->contains( key, ic )`.
867
868 @li If key is contained in the view
869 then one of the matching elements has
870 its value changed to the specified value.
871 The remaining elements with a matching
872 key are erased. Otherwise,
873
874 @li If `key` is not contained in the
875 view, then the function apppends the
876 param `{ key, value }`.
877
878 <br>
879 All iterators are invalidated.
880
881 @par Example
882 @code
883 url u( "?id=42&id=69" );
884
885 u.params().set( "id", "none" );
886
887 assert( u.params().count( "id" ) == 1 );
888 @endcode
889
890 @par Postconditions
891 @code
892 this->count( key, ic ) == 1 && this->find( key, ic )->value == value
893 @endcode
894
895 @par Complexity
896 Linear in `this->url().encoded_query().size()`.
897
898 @par Exception Safety
899 Strong guarantee.
900 Calls to allocate may throw.
901
902 @return An iterator to the appended
903 or modified element.
904
905 @param key The key to match.
906 By default, a case-sensitive
907 comparison is used.
908
909 @param value The value to assign. The
910 empty string still counts as a value.
911 That is, `has_value` for the element
912 is true.
913
914 @param ic An optional parameter. If
915 the value @ref ignore_case is passed
916 here, the comparison is
917 case-insensitive.
918 */
919 iterator
920 set(
921 core::string_view key,
922 core::string_view value,
923 ignore_case_param ic = {});
924
925 //--------------------------------------------
926
927 private:
928 template<class FwdIt>
929 void
930 assign(FwdIt first, FwdIt last,
931 std::forward_iterator_tag);
932
933 // Doxygen cannot render ` = delete`
934 template<class FwdIt>
935 void
936 assign(FwdIt first, FwdIt last,
937 std::input_iterator_tag) = delete;
938
939 template<class FwdIt>
940 iterator
941 insert(
942 iterator before,
943 FwdIt first,
944 FwdIt last,
945 std::forward_iterator_tag);
946
947 // Doxygen cannot render ` = delete`
948 template<class FwdIt>
949 iterator
950 insert(
951 iterator before,
952 FwdIt first,
953 FwdIt last,
954 std::input_iterator_tag) = delete;
955 };
956
957 } // urls
958 } // boost
959
960 // This is in <boost/url/url_base.hpp>
961 //
962 // #include <boost/url/impl/params_ref.hpp>
963
964 #endif
965