GCC Code Coverage Report


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